diff --git a/_bmad-output/implementation-artifacts/spec-align-create-glossary-dialog-design.md b/_bmad-output/implementation-artifacts/spec-align-create-glossary-dialog-design.md new file mode 100644 index 0000000..47725d1 --- /dev/null +++ b/_bmad-output/implementation-artifacts/spec-align-create-glossary-dialog-design.md @@ -0,0 +1,22 @@ +--- +title: 'Aligner le design du CreateGlossaryDialog avec le design system éditorial' +type: 'refactor' +created: '2026-06-20' +status: 'done' +route: 'one-shot' +context: [] +--- + +# Aligner le design du CreateGlossaryDialog avec le design system éditorial + +## Intent + +**Problem:** Le dialog `CreateGlossaryDialog` utilisait le style shadcn/ui générique (boutons gris, tabs Radix standard, couleurs template Tailwind) alors que le reste de l'application — et notamment la page Glossaires elle-même — utilise un design éditorial premium avec typography serif Playfair Display, boutons `premium-button` dorés, cartes `editorial-card`, palette brand (#C5A17A), et micro-typographie soignée. De plus, les labels de langue étaient hardcodés en français au lieu d'utiliser le système i18n. + +**Approach:** Refactoriser le composant pour adopter le même vocabulaire visuel (editorial-card, premium-button, accent-pill, font-serif, brand colors), remplacer les labels hardcodés par des clés i18n existantes, et ajouter les attributs ARIA manquants sur les tabs custom. + +## Suggested Review Order + +1. [CreateGlossaryDialog.tsx](file:///d:/dev1405/office_translator/frontend/src/app/dashboard/glossaries/CreateGlossaryDialog.tsx) — Composant refactorisé : vérifier la cohérence visuelle avec la page parent +2. [page.tsx](file:///d:/dev1405/office_translator/frontend/src/app/dashboard/glossaries/page.tsx) — Page Glossaires (référence design — non modifiée) +3. [globals.css](file:///d:/dev1405/office_translator/frontend/src/app/globals.css) — Design tokens (référence — non modifié) diff --git a/frontend/src/app/dashboard/glossaries/CreateGlossaryDialog.tsx b/frontend/src/app/dashboard/glossaries/CreateGlossaryDialog.tsx index 9f03c55..86bb856 100644 --- a/frontend/src/app/dashboard/glossaries/CreateGlossaryDialog.tsx +++ b/frontend/src/app/dashboard/glossaries/CreateGlossaryDialog.tsx @@ -7,13 +7,9 @@ import { DialogHeader, DialogTitle, DialogDescription, - DialogFooter, } from '@/components/ui/dialog'; -import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Badge } from '@/components/ui/badge'; import { TermEditor } from './TermEditor'; import { parseFileToTerms } from './csvUtils'; import { useGlossaryTemplates } from './useGlossaries'; @@ -62,17 +58,6 @@ const TEMPLATE_ICONS: Record = { ecommerce: , }; -const TEMPLATE_COLORS: Record = { - legal: 'bg-purple-50 text-purple-700 border-purple-200 hover:bg-purple-100', - technology: 'bg-blue-50 text-blue-700 border-blue-200 hover:bg-blue-100', - finance: 'bg-green-50 text-green-700 border-green-200 hover:bg-green-100', - medical: 'bg-red-50 text-red-700 border-red-200 hover:bg-red-100', - marketing: 'bg-orange-50 text-orange-700 border-orange-200 hover:bg-orange-100', - hr: 'bg-teal-50 text-teal-700 border-teal-200 hover:bg-teal-100', - scientific: 'bg-indigo-50 text-indigo-700 border-indigo-200 hover:bg-indigo-100', - ecommerce: 'bg-pink-50 text-pink-700 border-pink-200 hover:bg-pink-100', -}; - type FileStatus = 'idle' | 'parsing' | 'success' | 'error'; const MAX_FILE_SIZE_MB = 5; @@ -81,15 +66,16 @@ function TemplateCard({ template, onSelect, isLoading, + isSelected, termsLabel, }: { template: GlossaryTemplate; onSelect: (t: GlossaryTemplate) => void; isLoading: boolean; + isSelected: boolean; termsLabel: string; }) { const icon = TEMPLATE_ICONS[template.id] ?? ; - const colorClass = TEMPLATE_COLORS[template.id] ?? 'bg-muted text-foreground border-border hover:bg-muted/80'; return ( ); } @@ -182,18 +180,18 @@ function FileUploadZone({ }; return ( -
+
{ e.preventDefault(); setIsDragging(true); }} onDragLeave={() => setIsDragging(false)} onDrop={handleDrop} onClick={() => !disabled && fileInputRef.current?.click()} className={cn( - 'relative flex flex-col items-center justify-center gap-3 rounded-lg border-2 border-dashed p-8 text-center transition-colors cursor-pointer', - isDragging ? 'border-primary bg-primary/5' : 'border-muted-foreground/25 hover:border-primary/50 hover:bg-muted/30', + 'relative flex flex-col items-center justify-center gap-3 rounded-2xl border-2 border-dashed p-8 text-center transition-all cursor-pointer', + isDragging ? 'border-brand-accent bg-brand-accent/5' : 'border-brand-dark/10 dark:border-white/10 hover:border-brand-accent/50 hover:bg-brand-muted/30 dark:hover:bg-white/[0.02]', disabled && 'opacity-50 cursor-not-allowed', - status === 'success' && 'border-green-400 bg-green-50', - status === 'error' && 'border-destructive/50 bg-destructive/5' + status === 'success' && 'border-emerald-400/50 bg-emerald-50 dark:bg-emerald-900/10', + status === 'error' && 'border-destructive/30 bg-destructive/5' )} > - -

{t('glossaries.dialog.parsing')}

+ +

{t('glossaries.dialog.parsing')}

)} {status === 'success' && parsedFile && ( <> - +
-

+

{t('glossaries.dialog.termsImported', { count: String(parsedFile.count) })}

-

{parsedFile.name}

+

{parsedFile.name}

- + {t('glossaries.dialog.changeFile')} + )} {status === 'error' && ( <> -
-

{errorMsg}

-
- + {t('glossaries.dialog.retry')} + )} {status === 'idle' && ( <> -
- +
+
-

{t('glossaries.dialog.dropTitle')}

-

{t('glossaries.dialog.dropOr')}

+

{t('glossaries.dialog.dropTitle')}

+

{t('glossaries.dialog.dropOr')}

-

{t('glossaries.dialog.dropFormats')}

+

{t('glossaries.dialog.dropFormats')}

)}
-
-

{t('glossaries.dialog.formatTitle')}

-

{t('glossaries.dialog.formatDesc')}

-
-
source,target
-
server,server
-
database,database
+
+

{t('glossaries.dialog.formatTitle')}

+

{t('glossaries.dialog.formatDesc')}

+
+
source,target
+
server,server
+
database,database
-

{t('glossaries.dialog.formatNote')}

+

{t('glossaries.dialog.formatNote')}

); @@ -379,49 +371,70 @@ export function CreateGlossaryDialog({ : t('glossaries.dialog.createEmpty'); })(); + const tabs = [ + { id: 'templates' as const, label: t('glossaries.dialog.tabTemplates'), icon: }, + { id: 'file' as const, label: t('glossaries.dialog.tabFile'), icon: }, + { id: 'manual' as const, label: t('glossaries.dialog.tabManual'), icon: }, + ]; + return ( - - - {t('glossaries.dialog.title')} - {t('glossaries.dialog.description')} + + + {/* ── Header ────────────────────────────────────── */} + + + {t('glossaries.dialog.title')} + + + {t('glossaries.dialog.description')} + -
+ {/* ── Name + Languages ──────────────────────────── */} +
- + { setName(e.target.value); setNameAutoFilled(false); }} placeholder={t('glossaries.dialog.namePlaceholder')} disabled={isProcessing} - className="mt-1" + className="mt-1.5 bg-brand-muted/30 dark:bg-white/[0.03] border-black/5 dark:border-white/10 rounded-xl focus:ring-brand-accent/20 focus:border-brand-accent/30" />
- {/* Language pair selector */} -
+ +
- +
-
+
- +