Replace the hello-world shell with the elevated design system, bilingual screens, recipe/extras data, and the interactive Mein Teller view. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
1.6 KiB
TypeScript
63 lines
1.6 KiB
TypeScript
import { cx } from "@/lib/cx"
|
|
|
|
export interface SegOption<T extends string> {
|
|
value: T
|
|
label: string
|
|
}
|
|
|
|
export interface SegControlProps<T extends string> {
|
|
value: T
|
|
options: SegOption<T>[]
|
|
onChange: (value: T) => void
|
|
className?: string
|
|
/** Accessible name for the control group. */
|
|
"aria-label"?: string
|
|
}
|
|
|
|
/**
|
|
* Segmented control — same interaction pattern as the prototype `.segctl`.
|
|
* Soft track + elevated active pill. Touch targets ≥48px.
|
|
*/
|
|
export function SegControl<T extends string>({
|
|
value,
|
|
options,
|
|
onChange,
|
|
className,
|
|
"aria-label": ariaLabel,
|
|
}: SegControlProps<T>) {
|
|
return (
|
|
<div
|
|
role="tablist"
|
|
aria-label={ariaLabel}
|
|
className={cx(
|
|
"flex rounded-[var(--radius-pill)] p-1",
|
|
className,
|
|
)}
|
|
style={{ background: "var(--green-soft)" }}
|
|
>
|
|
{options.map((option) => {
|
|
const active = option.value === value
|
|
return (
|
|
<button
|
|
key={option.value}
|
|
type="button"
|
|
role="tab"
|
|
aria-selected={active}
|
|
onClick={() => onChange(option.value)}
|
|
className={cx(
|
|
"type-button-secondary flex-1 min-h-[48px] rounded-[var(--radius-pill)] px-3",
|
|
"no-select [-webkit-tap-highlight-color:transparent]",
|
|
"elevation-transition",
|
|
active
|
|
? "bg-[var(--glass-fill)] text-[var(--ink)] shadow-[var(--shadow-resting)]"
|
|
: "text-[var(--ink-soft)] active:brightness-95",
|
|
)}
|
|
>
|
|
{option.label}
|
|
</button>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|