Add foundational components and logic for migration, UI design, and input handling
- Introduced foundational UI components (`Badge`, `LockCard`, `SectionHeader`, `AvatarIcon`, etc.) for flexible layouts and consistent design. - Added migration support with the `MigrationModal` component and backend integration for exporting/importing data between Electron and Tauri. - Extended form components with `TextAreaInput`, `OrderInput`, `ToggleField`, and `ToolbarSelect` for improved input handling. - Updated `ScribeShell` with migration popup logic to prompt users for data migration. - Integrated `AlertStack` for better alert handling and notification management. - Enhanced Rust/Tauri services with migration command implementations. - Added translations and styles for new components.
This commit is contained in:
102
components/ui/Modal.tsx
Normal file
102
components/ui/Modal.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
'use client';
|
||||
import React, {ReactNode, useEffect, useState} from 'react';
|
||||
import {createPortal} from 'react-dom';
|
||||
import {LucideIcon, X} from "lucide-react";
|
||||
import Button from "@/components/ui/Button";
|
||||
import IconButton from "@/components/ui/IconButton";
|
||||
|
||||
type ModalSize = 'sm' | 'md' | 'lg';
|
||||
|
||||
interface ModalProps {
|
||||
title: string;
|
||||
icon?: LucideIcon;
|
||||
children: ReactNode;
|
||||
size?: ModalSize;
|
||||
onClose: () => void;
|
||||
onConfirm?: () => void;
|
||||
confirmText?: string;
|
||||
cancelText?: string;
|
||||
footer?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
enableOverflow?: boolean;
|
||||
}
|
||||
|
||||
const sizeClasses: Record<ModalSize, string> = {
|
||||
sm: 'md:w-3/4 xl:w-1/4 lg:w-2/4 sm:w-11/12',
|
||||
md: 'md:w-3/4 xl:w-2/5 lg:w-2/4 sm:w-11/12',
|
||||
lg: 'md:w-3/4 xl:w-3/5 lg:w-3/4 sm:w-11/12',
|
||||
};
|
||||
|
||||
export default function Modal(
|
||||
{
|
||||
title,
|
||||
icon: Icon,
|
||||
children,
|
||||
size = 'md',
|
||||
onClose,
|
||||
onConfirm,
|
||||
confirmText = 'Confirmer',
|
||||
cancelText = 'Annuler',
|
||||
footer,
|
||||
actions,
|
||||
enableOverflow = true,
|
||||
}: ModalProps) {
|
||||
const [mounted, setMounted] = useState<boolean>(false);
|
||||
|
||||
useEffect((): (() => void) => {
|
||||
setMounted(true);
|
||||
document.body.style.overflow = 'hidden';
|
||||
return (): void => {
|
||||
setMounted(false);
|
||||
document.body.style.overflow = 'auto';
|
||||
};
|
||||
}, []);
|
||||
|
||||
const hasFooter: boolean = !!footer || !!onConfirm;
|
||||
|
||||
const modalContent: React.JSX.Element = (
|
||||
<div
|
||||
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-darkest-background/60 backdrop-blur-md animate-fadeIn">
|
||||
<div
|
||||
className={`relative bg-tertiary text-text-primary rounded-xl max-h-[90vh] overflow-hidden flex flex-col ${sizeClasses[size]}`}>
|
||||
<div className="flex justify-between items-center px-6 py-4">
|
||||
<h2 className="flex items-center gap-3 font-['ADLaM_Display'] text-xl tracking-wide">
|
||||
{Icon && <Icon className="w-6 h-6" strokeWidth={1.75}/>}
|
||||
{title}
|
||||
</h2>
|
||||
<div className="flex items-center gap-2">
|
||||
{actions}
|
||||
<IconButton icon={X} variant="light" onClick={onClose}/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`flex-1 min-h-0 bg-darkest-background rounded-xl mx-2 flex flex-col overflow-hidden ${!hasFooter ? 'mb-2' : ''}`}>
|
||||
<div
|
||||
className={`flex-1 min-h-0 ${enableOverflow ? 'overflow-auto custom-scrollbar' : 'overflow-hidden'}`}>
|
||||
<div className="p-5 space-y-6">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{hasFooter && (
|
||||
<div className="flex justify-end gap-3 px-6 py-4">
|
||||
{footer ? footer : (
|
||||
<>
|
||||
<Button variant="secondary" onClick={onClose}>
|
||||
{cancelText}
|
||||
</Button>
|
||||
<Button variant="primary" onClick={onConfirm}>
|
||||
{confirmText}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
return createPortal(modalContent, document.body);
|
||||
}
|
||||
Reference in New Issue
Block a user