69 lines
2.5 KiB
TypeScript
69 lines
2.5 KiB
TypeScript
export interface Step {
|
|
key: string;
|
|
title: string;
|
|
}
|
|
|
|
/**
|
|
* نوار مراحلِ یک فرمِ چندمرحلهای — «کجای کارم و چقدر مانده».
|
|
*
|
|
* فرمهای بلندِ مودال (ثبت نوبت، قطعی کردن نوبت) همهٔ تصمیمها را با هم نشان میدادند
|
|
* و از ارتفاع صفحه بلندتر میشدند. حالا هر بار یک مرحله دیده میشود و این نوار تنها
|
|
* چیزی است که کلِ مسیر را میگوید.
|
|
*
|
|
* فقط نمایش است: پیمایش با دکمههای فوتر انجام میشود، نه با کلیک روی مراحل — پرشِ
|
|
* دلخواه یعنی رسیدن به مرحلهای که پیشنیازش پر نشده.
|
|
*/
|
|
export default function Stepper({
|
|
steps, current, ariaLabel,
|
|
}: { steps: Step[]; current: string; ariaLabel: string }) {
|
|
const activeIdx = steps.findIndex(s => s.key === current);
|
|
|
|
return (
|
|
<ol
|
|
aria-label={ariaLabel}
|
|
style={{
|
|
display: 'flex', alignItems: 'center', gap: 8, listStyle: 'none',
|
|
margin: '0 0 18px', padding: 0,
|
|
}}
|
|
>
|
|
{steps.map((step, idx) => {
|
|
const done = idx < activeIdx;
|
|
const active = idx === activeIdx;
|
|
|
|
return (
|
|
<li
|
|
key={step.key}
|
|
aria-current={active ? 'step' : undefined}
|
|
style={{
|
|
display: 'flex', alignItems: 'center', gap: 8,
|
|
flex: idx === steps.length - 1 ? '0 0 auto' : 1,
|
|
}}
|
|
>
|
|
<span style={{
|
|
display: 'grid', placeItems: 'center', width: 22, height: 22, borderRadius: 999,
|
|
flexShrink: 0, fontSize: 11.5, fontWeight: 700,
|
|
background: active || done ? 'var(--primary)' : 'var(--surface-3)',
|
|
color: active || done ? 'var(--on-primary)' : 'var(--text-3)',
|
|
}}>
|
|
{idx + 1}
|
|
</span>
|
|
<span style={{
|
|
fontSize: 12.5, whiteSpace: 'nowrap',
|
|
fontWeight: active ? 700 : 500,
|
|
color: active ? 'var(--text)' : 'var(--text-3)',
|
|
}}>
|
|
{step.title}
|
|
</span>
|
|
{idx < steps.length - 1 && (
|
|
<span style={{
|
|
flex: 1, height: 1, minWidth: 12,
|
|
background: done ? 'var(--primary)' : 'var(--border)',
|
|
}} />
|
|
)}
|
|
</li>
|
|
);
|
|
})}
|
|
</ol>
|
|
);
|
|
}
|