Files
Stirling-PDF/frontend/shared/components/ToggleSwitch.tsx
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

60 lines
1.5 KiB
TypeScript
Raw Normal View History

2026-06-02 17:08:24 +01:00
import { useId } from "react";
import "@shared/components/ToggleSwitch.css";
export interface ToggleSwitchProps {
checked: boolean;
onChange: (checked: boolean) => void;
/** Accessible label associated to the control. */
label?: string;
/** Optional helper text rendered next to the label. */
description?: string;
disabled?: boolean;
size?: "sm" | "md";
id?: string;
}
/**
* 36×20 pill toggle, matched to the prototype's SettingsRow control.
*
* Pair with the {@link SettingsRow} component (or a custom row) when you need
* a label + description layout. Standalone, this is just the switch itself.
*/
export function ToggleSwitch({
checked,
onChange,
label,
description,
disabled,
size = "md",
id,
}: ToggleSwitchProps) {
const autoId = useId();
const controlId = id ?? autoId;
return (
<label
className={`sui-toggle sui-toggle--${size}${disabled ? " is-disabled" : ""}`}
htmlFor={controlId}
>
<input
id={controlId}
type="checkbox"
role="switch"
checked={checked}
disabled={disabled}
onChange={(e) => onChange(e.target.checked)}
/>
<span className="sui-toggle__track" aria-hidden>
<span className="sui-toggle__thumb" />
</span>
{(label || description) && (
<span className="sui-toggle__text">
{label && <span className="sui-toggle__label">{label}</span>}
{description && (
<span className="sui-toggle__desc">{description}</span>
)}
</span>
)}
</label>
);
}