38 lines
1.6 KiB
React
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>
|
|
);
|
|
}
|