feat(simulations): composant clavier caractères spéciaux français

This commit is contained in:
Hermann_Kitio 2026-04-20 23:37:58 +03:00
parent 6a40e9a4c0
commit 4f786dd44b

View file

@ -0,0 +1,47 @@
/**
* Clavier de caractères spéciaux français pour la zone de saisie.
*
* Affiche une rangée horizontale scrollable de 30 caractères accentués
* (15 minuscules + 15 majuscules). Un clic insère le caractère à la
* position du curseur via le callback `onInsert`.
*
* Règle H : purement présentationnel, la logique d'insertion est dans le parent.
* Règle L : tokens Direction H exclusivement.
*
* `onMouseDown preventDefault` empêche le textarea de perdre le focus au clic,
* ce qui permet de conserver la position du curseur lors de l'insertion.
*/
const SPECIAL_CHARS = [
'à', 'â', 'é', 'è', 'ê', 'ë', 'î', 'ï', 'ô', 'ù', 'û', 'ü', 'ç', 'œ', 'æ',
'À', 'Â', 'É', 'È', 'Ê', 'Ë', 'Î', 'Ï', 'Ô', 'Ù', 'Û', 'Ü', 'Ç', 'Œ', 'Æ',
] as const
interface Props {
onInsert: (char: string) => void
disabled?: boolean
}
export function SpecialCharsKeyboard({ onInsert, disabled = false }: Props) {
return (
<div
role="toolbar"
aria-label="Caractères spéciaux"
className="flex gap-1.5 overflow-x-auto rounded-md border border-line bg-canvas-2 p-2"
>
{SPECIAL_CHARS.map((char) => (
<button
key={char}
type="button"
disabled={disabled}
onMouseDown={(e) => e.preventDefault()}
onClick={() => onInsert(char)}
aria-label={`Insérer le caractère ${char}`}
className="size-10 shrink-0 rounded-md border border-line bg-surface text-sm font-medium text-ink-1 transition-colors hover:border-expria hover:bg-expria-50 hover:text-expria focus:border-expria focus:outline-none focus:ring-2 focus:ring-expria/20 disabled:cursor-not-allowed disabled:opacity-50"
>
{char}
</button>
))}
</div>
)
}