Start time grid #62

Merged
stne3960 merged 30 commits from start_time_grid into main 2026-01-16 14:17:09 +01:00
Showing only changes of commit 5c36cf840c - Show all commits

View File

@ -0,0 +1,89 @@
import type { InputHTMLAttributes } from "react";
import clsx from "clsx";
export interface ChoiceboxProps
extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
primaryText: string;
secondaryText?: string;
unavailable?: boolean;
fitContent?: boolean;
}
const baseClasses = clsx(
"flex items-center gap-(--spacing-md)",
"border-[length:var(--border-width-sm)]",
"rounded-(--border-radius-md)",
"p-(--padding-md)",
);
const availableClasses = clsx(
"bg-sky-20 border-sky-100",
"cursor-pointer",
// Hover
"hover:bg-sky-35",
// Focus
"focus-within:bg-sky-20 focus-within:border-primary",
"focus-within:outline focus-within:outline-sky-100 focus-within:outline-[length:var(--border-width-lg)]",
// Selected
"has-[:checked]:bg-sky-70 has-[:checked]:border-secondary",
// Selected + Focus
"has-[:checked]:focus-within:bg-sky-35",
);
const unavailableClasses = clsx(
"bg-base-canvas border-base-ink-soft",
"cursor-not-allowed",
);
const radioClasses = clsx(
"appearance-none shrink-0",
"w-[var(--font-size-body-md)] h-[var(--font-size-body-md)]",
"rounded-full",
"border-[length:var(--border-width-sm)] border-base-ink-medium",
"bg-base-canvas",
"outline-none",
// Selected
"checked:border-primary",
"checked:bg-[radial-gradient(circle,var(--color-primary)_50%,var(--color-base-canvas)_50%)]",
);
export default function Choicebox({
primaryText,
secondaryText,
unavailable = false,
fitContent = false,
className = "",
disabled,
...props
}: ChoiceboxProps) {
const isDisabled = unavailable || disabled;
const textColorClass = unavailable ? "text-base-ink-placeholder" : "text-primary";
return (
<label
className={clsx(
baseClasses,
unavailable ? unavailableClasses : availableClasses,
fitContent ? "w-fit" : "w-full",
className,
)}
>
<div className="flex flex-col flex-1 min-w-0">
<span className={clsx("body-bold-lg break-words", textColorClass)}>
{primaryText}
</span>
{secondaryText && (
<span className={clsx("body-light-sm break-words", textColorClass)}>
{secondaryText}
</span>
)}
</div>
<input
type="radio"
className={radioClasses}
disabled={isDisabled}
{...props}
/>
</label>
);
}