bugfix: FDI tooth chart is now compatible with RTL direction.

This commit is contained in:
2026-08-22 17:49:38 +03:30
parent 94b010ccfc
commit de46da216f

View File

@@ -24,6 +24,12 @@ const TOOTH_NUMBER_GAP = 'mt-1';
const REALISTIC_NUMBER_GAP = '2mm'; const REALISTIC_NUMBER_GAP = '2mm';
/** Tight interproximal gap between tooth columns. */ /** Tight interproximal gap between tooth columns. */
const TOOTH_GAP = 'gap-x-px'; const TOOTH_GAP = 'gap-x-px';
/**
* Centers a mark on the inline-end edge of a tooth column (between this tooth
* and the next in flex order). Logical `end` + 0-width flex stays correct in LTR and RTL.
*/
const EDGE_MARK_ANCHOR =
'absolute inset-y-0 end-0 z-10 w-0 flex items-center justify-center';
function quadrantMirrored(fdi: FdiToothId): boolean { function quadrantMirrored(fdi: FdiToothId): boolean {
const q = fdi[0]; const q = fdi[0];
@@ -285,40 +291,42 @@ export function FdiToothChart({
/> />
) : null} ) : null}
{renderEdge ? ( {renderEdge ? (
linkInteractive ? ( <div className={EDGE_MARK_ANCHOR}>
<button {linkInteractive ? (
type="button" <button
disabled={isDisabled} type="button"
title={linked ? t('toothUnlinkHint') : t('toothLinkHint')} disabled={isDisabled}
aria-label={ title={linked ? t('toothUnlinkHint') : t('toothLinkHint')}
linked aria-label={
? t('toothUnlinkAria', { a: fdi, b: next! })
: t('toothLinkAria', { a: fdi, b: next! })
}
aria-pressed={linked}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
onToggleLink?.(fdi, next!);
}}
className={`
absolute right-0 z-10 translate-x-1/2 h-3.5 w-3.5 rounded-full border-2 transition-colors
focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50
${
linked linked
? 'border-primary bg-primary shadow-sm' ? t('toothUnlinkAria', { a: fdi, b: next! })
: 'border-primary bg-background-secondary hover:bg-primary/15' : t('toothLinkAria', { a: fdi, b: next! })
} }
${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'} aria-pressed={linked}
`} onClick={(e) => {
/> e.preventDefault();
) : ( e.stopPropagation();
<span onToggleLink?.(fdi, next!);
className="absolute right-0 z-10 translate-x-1/2 h-2.5 w-2.5 rounded-full bg-primary shadow-sm" }}
title={t('toothConnectedHint')} className={`
aria-hidden h-3.5 w-3.5 shrink-0 rounded-full border-2 transition-colors
/> focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50
) ${
linked
? 'border-primary bg-primary shadow-sm'
: 'border-primary bg-background-secondary hover:bg-primary/15'
}
${isDisabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
`}
/>
) : (
<span
className="h-2.5 w-2.5 shrink-0 rounded-full bg-primary shadow-sm"
title={t('toothConnectedHint')}
aria-hidden
/>
)}
</div>
) : null} ) : null}
</div> </div>
); );