- Remplacement intégral index.css par palette Charcoal (DESIGN_SYSTEM.md v2.0)
- Dark = thème par défaut, .light = override via @custom-variant light
- Sidebar navy #0C1528 permanent (identique dark+light)
- Script anti-FOUC inline dans index.html
- Layout : radial-gradient sur <main>, sidebar 230px, max-w-[1100px]
- Renommage tokens Boréal→Charcoal sur ~45 composants
- Inversion dark: → baseline + light: sur primitives shadcn
- Fix logo blanc forcé dans sidebar
- ADR 006 mis à jour
Typecheck: OK · Tests: 122/122 ✅
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
2.7 KiB
TypeScript
80 lines
2.7 KiB
TypeScript
/**
|
|
* CritereCard — Sprint 3.6b.
|
|
*
|
|
* Carte critère enrichie : nom, score /5, commentaire, exemple, suggestion,
|
|
* astuce + badges des codes d'erreurs taxonomie correspondants.
|
|
*
|
|
* Visible pour Standard et Premium (gate `detailed_report`). Le floutage est
|
|
* géré par le parent via BlurredSection — CritereCard ne connaît pas le plan.
|
|
*
|
|
* Règle L : tokens Direction H exclusivement.
|
|
* Règle H : purement présentationnel — aucune logique plan ici.
|
|
*/
|
|
|
|
import ReactMarkdown from 'react-markdown'
|
|
import { Card } from '@/shared/ui/Card'
|
|
import { Badge } from '@/shared/ui/Badge'
|
|
import type { Critere, ErreurCode } from '@/entities/report/types'
|
|
|
|
interface Props {
|
|
critere: Critere
|
|
erreursCodes: ErreurCode[]
|
|
}
|
|
|
|
export function CritereCard({ critere, erreursCodes }: Props) {
|
|
return (
|
|
<Card variant="default" className="space-y-3 p-4">
|
|
<div className="flex items-start justify-between gap-3">
|
|
<h3 className="text-sm font-semibold text-ink-primary">{critere.nom}</h3>
|
|
<Badge variant="nclc" className="shrink-0 tabular-nums">
|
|
{critere.score}/5
|
|
</Badge>
|
|
</div>
|
|
|
|
{critere.commentaire && (
|
|
<div className="text-sm leading-relaxed text-ink-primary">
|
|
<ReactMarkdown disallowedElements={['script', 'iframe']}>
|
|
{critere.commentaire}
|
|
</ReactMarkdown>
|
|
</div>
|
|
)}
|
|
|
|
{critere.exemple && (
|
|
<div className="space-y-1.5 rounded-md border border-border bg-surface p-3">
|
|
<p className="text-[11px] font-semibold uppercase tracking-widest text-ink-tertiary">
|
|
Exemple tiré de votre texte
|
|
</p>
|
|
<p className="italic text-sm leading-relaxed text-ink-primary">« {critere.exemple} »</p>
|
|
</div>
|
|
)}
|
|
|
|
{critere.suggestion && (
|
|
<div className="space-y-1.5 rounded-md border border-brand/30 bg-brand-soft p-3">
|
|
<p className="text-[11px] font-semibold uppercase tracking-widest text-brand-text">
|
|
Reformulation suggérée
|
|
</p>
|
|
<p className="text-sm leading-relaxed text-ink-primary">{critere.suggestion}</p>
|
|
</div>
|
|
)}
|
|
|
|
{critere.astuce && (
|
|
<div className="flex gap-2 text-sm text-ink-secondary">
|
|
<span className="shrink-0 text-brand-text" aria-hidden="true">
|
|
💡
|
|
</span>
|
|
<span>{critere.astuce}</span>
|
|
</div>
|
|
)}
|
|
|
|
{erreursCodes.length > 0 && (
|
|
<div className="flex flex-wrap gap-1.5 border-t border-border pt-3">
|
|
{erreursCodes.map((e) => (
|
|
<Badge key={`${e.code}-${e.description ?? ''}`} variant="neutral">
|
|
{e.description ?? e.code.replace(/_/g, ' ')}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
</Card>
|
|
)
|
|
}
|