bugfix: FDI tooth chart is now compatible with RTL direction.
This commit is contained in:
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user