feature: Phase4 - Clinic two-step treatment UI
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
|
||||
import { useId } from 'react';
|
||||
import { useId, type KeyboardEvent } from 'react';
|
||||
import { Check } from 'lucide-react';
|
||||
|
||||
type CheckboxProps = {
|
||||
@@ -14,6 +14,7 @@ type CheckboxProps = {
|
||||
|
||||
/**
|
||||
* App design-system checkbox: primary fill when checked, rounded, focus-visible ring.
|
||||
* Uses a button-like label toggle so mouse clicks do not focus a hidden input (scroll jumps).
|
||||
*/
|
||||
export function Checkbox({
|
||||
checked,
|
||||
@@ -26,25 +27,42 @@ export function Checkbox({
|
||||
const genId = useId();
|
||||
const inputId = id ?? genId;
|
||||
|
||||
const toggle = () => {
|
||||
if (!disabled) onChange(!checked);
|
||||
};
|
||||
|
||||
const onKeyDown = (event: KeyboardEvent<HTMLLabelElement>) => {
|
||||
if (disabled) return;
|
||||
if (event.key === ' ' || event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
toggle();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<label
|
||||
htmlFor={inputId}
|
||||
id={inputId}
|
||||
role="checkbox"
|
||||
aria-checked={checked}
|
||||
aria-disabled={disabled}
|
||||
tabIndex={disabled ? -1 : 0}
|
||||
onKeyDown={onKeyDown}
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
toggle();
|
||||
}}
|
||||
onMouseDown={(event) => {
|
||||
// Avoid focus-driven scroll-into-view in overflow panels.
|
||||
if (event.button === 0) event.preventDefault();
|
||||
}}
|
||||
className={`
|
||||
inline-flex items-center gap-2.5 cursor-pointer select-none rounded-[var(--radius-sm)] -m-0.5 p-0.5
|
||||
has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-primary/45 has-[:focus-visible]:ring-offset-2
|
||||
has-[:focus-visible]:ring-offset-background-secondary
|
||||
focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/45 focus-visible:ring-offset-2
|
||||
focus-visible:ring-offset-background-secondary
|
||||
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
|
||||
${className}
|
||||
`}
|
||||
>
|
||||
<input
|
||||
id={inputId}
|
||||
type="checkbox"
|
||||
className="sr-only"
|
||||
checked={checked}
|
||||
disabled={disabled}
|
||||
onChange={(e) => onChange(e.target.checked)}
|
||||
/>
|
||||
<span
|
||||
className={`
|
||||
flex h-5 w-5 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border-2 transition-all duration-200
|
||||
|
||||
Reference in New Issue
Block a user