Files
ersatztv/design-system/components/forms/Checkbox.jsx
T
2026-07-02 07:37:00 +02:00

38 lines
1.6 KiB
React

import React from "react";
/**
* Checkbox with label. Controlled via checked/onChange.
*/
export function Checkbox({ checked = false, onChange, disabled = false, label, indeterminate = false, style = {} }) {
const toggle = () => { if (!disabled && onChange) onChange(!checked); };
const on = checked || indeterminate;
return (
<label style={{ display: "inline-flex", alignItems: "center", gap: "8px", cursor: disabled ? "not-allowed" : "pointer", opacity: disabled ? 0.5 : 1, ...style }}>
<span
role="checkbox"
aria-checked={indeterminate ? "mixed" : checked}
onClick={toggle}
style={{
display: "inline-flex",
alignItems: "center",
justifyContent: "center",
width: 17,
height: 17,
flex: "0 0 auto",
borderRadius: "var(--radius-xs)",
background: on ? "var(--action-primary)" : "var(--ctv-bg-sunken)",
border: `1px solid ${on ? "transparent" : "var(--border-control)"}`,
transition: "background var(--dur-fast), border-color var(--dur-fast)",
}}
>
{indeterminate ? (
<svg width="11" height="11" viewBox="0 0 24 24"><path d="M6 12h12" stroke="#fff" strokeWidth="3" strokeLinecap="round" /></svg>
) : checked ? (
<svg width="12" height="12" viewBox="0 0 24 24" fill="none"><path d="M5 12.5l4.5 4.5L19 7" stroke="#fff" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" /></svg>
) : null}
</span>
{label && <span style={{ font: "var(--text-sm)/1 var(--font-sans)", color: "var(--text-primary)" }}>{label}</span>}
</label>
);
}