improvement: treatment plan turned into a wizard. shift+click control added to FDI tooth chart for cunnected prosthesises.

This commit is contained in:
2026-07-17 00:39:32 +03:30
parent cf07b4d8a8
commit 68fc9d5d6d
28 changed files with 1461 additions and 477 deletions

View File

@@ -0,0 +1,100 @@
'use client';
export type WizardStepItem = {
id: string;
label: string;
};
type WizardStepperProps = {
steps: WizardStepItem[];
currentStepId: string;
onStepChange: (stepId: string) => void;
/** Accessible name for the stepper. */
'aria-label': string;
className?: string;
};
/**
* Compact horizontal progress stepper — numbered nodes + connector rail.
* Distinct from chip/tab row patterns used elsewhere (e.g. treatment detail chips).
*/
export function WizardStepper({
steps,
currentStepId,
onStepChange,
'aria-label': ariaLabel,
className,
}: WizardStepperProps) {
const currentIndex = Math.max(
0,
steps.findIndex((step) => step.id === currentStepId),
);
return (
<nav aria-label={ariaLabel} className={className}>
<ol className="flex items-center gap-0 min-w-0">
{steps.map((step, index) => {
const isCurrent = index === currentIndex;
const isComplete = index < currentIndex;
const isUpcoming = index > currentIndex;
return (
<li key={step.id} className="flex items-center min-w-0 flex-1 last:flex-none">
<button
type="button"
aria-current={isCurrent ? 'step' : undefined}
onClick={() => onStepChange(step.id)}
className={`
group inline-flex items-center gap-1.5 shrink-0 rounded-[var(--radius-sm)]
py-0.5 pe-1 ps-0.5 transition-colors
focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/45
${isUpcoming ? 'opacity-70 hover:opacity-100' : ''}
`}
>
<span
className={`
inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full
text-[10px] font-semibold leading-none tabular-nums transition-colors
${
isCurrent
? 'bg-primary text-primary-contrast shadow-[0_0_0_2px_var(--color-primary-soft)]'
: isComplete
? 'bg-primary-soft text-primary'
: 'bg-background-secondary text-text-muted ring-1 ring-inset ring-border'
}
`}
>
{index + 1}
</span>
<span
className={`
text-[11px] leading-none whitespace-nowrap transition-colors
${
isCurrent
? 'font-semibold text-text-primary'
: isComplete
? 'font-medium text-text-secondary'
: 'font-medium text-text-muted'
}
`}
>
{step.label}
</span>
</button>
{index < steps.length - 1 ? (
<span
aria-hidden
className={`
mx-1.5 h-px min-w-[0.75rem] flex-1 rounded-full
${isComplete ? 'bg-primary/55' : 'bg-border'}
`}
/>
) : null}
</li>
);
})}
</ol>
</nav>
);
}