feat: standardize UI theme, fix dark mode consistency, and implement editorial tags
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 1m24s

This commit is contained in:
Antigravity
2026-05-10 18:43:13 +00:00
parent f6880bd0e1
commit 330c0c61b6
25 changed files with 640 additions and 503 deletions

View File

@@ -11,7 +11,7 @@ import {
DialogTitle,
DialogTrigger,
} from './ui/dialog'
import { Settings, Plus, Palette, Trash2, Tag } from 'lucide-react'
import { Settings, Plus, Palette, Trash2, Sparkles } from 'lucide-react'
import { LABEL_COLORS, LabelColorName } from '@/lib/types'
import { cn } from '@/lib/utils'
import { useNotebooks } from '@/context/notebooks-context'
@@ -19,7 +19,6 @@ import { useLanguage } from '@/lib/i18n'
import { useRefresh } from '@/lib/use-refresh'
export interface LabelManagementDialogProps {
/** Mode contrôlé (ex. ouverture depuis la liste des carnets) */
open?: boolean
onOpenChange?: (open: boolean) => void
}
@@ -77,9 +76,7 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
className="max-w-md"
dir={language === 'fa' || language === 'ar' ? 'rtl' : 'ltr'}
onInteractOutside={(event) => {
// Prevent dialog from closing when interacting with Sonner toasts
const target = event.target as HTMLElement;
const isSonnerElement =
target.closest('[data-sonner-toast]') ||
target.closest('[data-sonner-toaster]') ||
@@ -88,12 +85,10 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
target.closest('[data-description]') ||
target.closest('[data-title]') ||
target.closest('[data-button]');
if (isSonnerElement) {
event.preventDefault();
return;
}
if (target.getAttribute('data-sonner-toaster') !== null) {
event.preventDefault();
return;
@@ -108,7 +103,6 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
</DialogHeader>
<div className="space-y-4 py-4">
{/* Add new label */}
<div className="flex gap-2">
<Input
placeholder={t('labels.newLabelPlaceholder')}
@@ -126,7 +120,6 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
</Button>
</div>
{/* List labels */}
<div className="max-h-[60vh] overflow-y-auto space-y-2">
{loading ? (
<p className="text-sm text-muted-foreground">{t('labels.loading')}</p>
@@ -136,14 +129,21 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
labels.map((label) => {
const colorClasses = LABEL_COLORS[label.color]
const isEditing = editingColorId === label.id
const isAI = label.type === 'ai'
return (
<div key={label.id} className="flex items-center justify-between p-2 rounded-md hover:bg-accent/50 group">
<div className="flex items-center gap-3 flex-1 relative">
<Tag className={cn("h-4 w-4", colorClasses.text)} />
{isAI ? (
<Sparkles className={cn("h-4 w-4", "text-memento-blue")} />
) : (
<div className={cn("h-3 w-3 rounded-full", colorClasses.bg)} />
)}
<span className="font-medium text-sm">{label.name}</span>
{isAI && (
<span className="text-[8px] px-1.5 py-0.5 rounded-full bg-memento-blue/10 text-memento-blue font-bold uppercase">IA</span>
)}
{/* Color Picker Popover */}
{isEditing && (
<div className="absolute z-20 top-8 left-0 bg-popover text-popover-foreground border border-border rounded-lg shadow-xl p-3 animate-in fade-in zoom-in-95 w-48">
<div className="grid grid-cols-5 gap-2">
@@ -155,7 +155,7 @@ export function LabelManagementDialog(props: LabelManagementDialogProps = {}) {
className={cn(
'h-7 w-7 rounded-full border-2 transition-all hover:scale-110',
classes.bg,
label.color === color ? 'border-gray-900 dark:border-gray-100 ring-2 ring-offset-1' : 'border-transparent'
label.color === color ? 'border-foreground dark:border-foreground ring-2 ring-offset-1' : 'border-transparent'
)}
onClick={() => handleChangeColor(label.id, color)}
title={color}