fix(ui): thème, textes et lisibilité restants de la revue
All checks were successful
CI / Lint, Unit Tests & Build (push) Successful in 6m57s
CI / Deploy production (on server) (push) Successful in 24s

Les boutons suivent la couleur d’apparence, les libellés trop petits ou trop techniques sont clarifiés, et le catalogue des fournisseurs se met à jour tout seul.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Antigravity
2026-08-30 21:13:07 +00:00
parent ebf6f16fde
commit afbb0dfc2d
77 changed files with 2842 additions and 1546 deletions

View File

@@ -6,6 +6,7 @@ import { useLanguage } from '@/lib/i18n'
import { RevisionHeatmap } from '@/components/flashcards/revision-heatmap'
import { UsageMeter } from '@/components/usage-meter'
import { DashboardWidgetTitleRow } from '@/components/dashboard-widget-title-row'
import { pathNoteTitle } from '@/lib/dashboard/path-title'
import type { DashboardWidgetId } from '@/lib/dashboard/layout'
interface DashboardWidgetShellProps {
@@ -41,21 +42,40 @@ export function DashboardWidgetShell({
)
}
function inboxDisplayTitle(
note: { title: string | null; excerpt?: string },
fallback: string,
): string {
const titled = note.title?.trim()
if (titled) return titled
const excerpt = note.excerpt?.trim()
if (!excerpt) return fallback
return excerpt.length > 80 ? `${excerpt.slice(0, 80).trim()}` : excerpt
}
export function DashboardInboxWidget({
count,
notes,
loading,
onOpen,
onSelect,
formatRelativeTime,
}: {
count: number
notes: Array<{ id: string; title: string | null; notebookId: string | null }>
notes: Array<{
id: string
title: string | null
excerpt?: string
notebookId: string | null
updatedAt?: string
}>
loading: boolean
onOpen: () => void
onSelect: (id: string, notebookId: string | null) => void
formatRelativeTime?: (date: string) => string
}) {
const { t } = useLanguage()
const reduced = !!useReducedMotion()
const untitled = t('homeDashboard.untitled')
return (
<DashboardWidgetShell
widgetId="inbox"
@@ -83,21 +103,22 @@ export function DashboardInboxWidget({
className="w-full text-start p-2.5 rounded-xl border border-border/20 hover:border-brand-accent/30 hover:bg-brand-accent/[0.03] transition-all"
>
<p className="text-[11px] text-ink dark:text-dark-ink truncate">
{note.title || t('homeDashboard.untitled')}
{inboxDisplayTitle(note, untitled)}
</p>
<p className="text-[9px] text-concrete truncate mt-0.5">
{t('homeDashboard.inbox')}
{note.updatedAt && formatRelativeTime
? ` · ${formatRelativeTime(note.updatedAt)}`
: ''}
</p>
</motion.button>
))}
<button
type="button"
onClick={onOpen}
className="w-full flex items-center justify-between gap-2 px-1 pt-1 text-start"
className="w-full text-start px-1 pt-1 text-[9px] font-mono uppercase font-bold text-brand-accent hover:underline"
>
<span className="text-[9px] font-mono uppercase font-bold text-concrete">
{t('homeDashboard.inboxSeeAll', { count })}
</span>
<span className="text-[9px] font-mono uppercase font-bold text-brand-accent">
{t('homeDashboard.widgetOpen')}
</span>
{t('homeDashboard.inboxOpenList')}
</button>
</div>
)}
@@ -278,12 +299,22 @@ export function DashboardPinnedWidget({
notes,
loading,
onSelect,
formatRelativeTime,
}: {
notes: { id: string; title: string | null; notebookId: string | null }[]
notes: {
id: string
title: string | null
excerpt?: string
notebookId: string | null
updatedAt?: string
notebook?: { name: string; color: string | null } | null
}[]
loading: boolean
onSelect: (id: string, notebookId: string | null) => void
formatRelativeTime?: (date: string) => string
}) {
const { t } = useLanguage()
const untitled = t('homeDashboard.untitled')
return (
<DashboardWidgetShell
widgetId="pinned"
@@ -298,17 +329,37 @@ export function DashboardPinnedWidget({
) : notes.length === 0 ? (
<p className="text-[10px] text-concrete italic py-2">{t('homeDashboard.widgetPinnedEmpty')}</p>
) : (
<div className="space-y-1">
{notes.map(n => (
<button
key={n.id}
type="button"
onClick={() => onSelect(n.id, n.notebookId)}
className="w-full text-[10px] text-ink dark:text-dark-ink truncate text-start p-2 rounded-lg hover:bg-brand-accent/[0.04] transition-colors"
>
{n.title || t('homeDashboard.untitled')}
</button>
))}
<div className="space-y-1.5">
{notes.map(n => {
const displayTitle = pathNoteTitle(n.title, n.excerpt) || untitled
const notebookName = n.notebook?.name || t('homeDashboard.pinnedNoNotebook')
const notebookColor = n.notebook?.color || '#C4A574'
return (
<button
key={n.id}
type="button"
onClick={() => onSelect(n.id, n.notebookId)}
className="w-full flex items-center gap-2.5 p-2 rounded-xl border border-border/20 hover:border-brand-accent/30 hover:bg-brand-accent/[0.03] transition-all text-start group"
>
<span
className="w-1 h-7 rounded-full shrink-0"
style={{ backgroundColor: notebookColor }}
aria-hidden
/>
<div className="min-w-0 flex-1">
<p className="text-[11px] text-ink dark:text-dark-ink truncate group-hover:text-brand-accent transition-colors">
{displayTitle}
</p>
<p className="text-[9px] text-concrete truncate mt-0.5">
{notebookName}
{n.updatedAt && formatRelativeTime
? ` · ${formatRelativeTime(n.updatedAt)}`
: ''}
</p>
</div>
</button>
)
})}
</div>
)}
</DashboardWidgetShell>
@@ -338,8 +389,7 @@ export function DashboardActivityWidget({
</div>
) : (
<>
<RevisionHeatmap data={data} />
<p className="text-[9px] text-concrete mt-2">{t('homeDashboard.widgetActivityHint')}</p>
<RevisionHeatmap data={data} kind="edits" />
</>
)}
</DashboardWidgetShell>
@@ -426,15 +476,12 @@ export function DashboardFlashcardsProgressWidget({
style={{ width: `${retention}%` }}
/>
</div>
{dueCount > 0 ? (
<p className="text-[10px] font-medium text-brand-accent group-hover:underline">
{t('homeDashboard.flashDueCta', { count: dueCount })}
</p>
) : (
<p className="text-[9px] text-concrete group-hover:text-brand-accent transition-colors">
{t('homeDashboard.flashOpenCta')}
</p>
)}
<p className="text-[9px] text-concrete leading-relaxed mb-2">
{t('homeDashboard.flashRetentionHint')}
</p>
<p className="text-[10px] font-medium text-brand-accent group-hover:underline">
{dueCount > 0 ? t('homeDashboard.flashDueCta') : t('homeDashboard.flashOpenCta')}
</p>
</button>
)}
</DashboardWidgetShell>