/* ── Provider — variant-shared base ─────────────────────────────────────── */ [data-checkbox] { --_checkbox-box-size: var(--checkbox-size-md-box-size); --_checkbox-indicator-size: var(--checkbox-size-md-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-md-indicator-stroke); /* `--_checkbox-palette-*` are private TSC tokens emitted by the * generator from `lib/recipes/base.ts > checkbox._palette-*`. * Per-color cascade is config-owned via `declarations[]`. */ display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; inline-size: var(--_checkbox-box-size); block-size: var(--_checkbox-box-size); padding: 0; border: var(--checkbox-border-width) solid var(--checkbox-border-off); border-radius: var(--checkbox-radius); background: var(--checkbox-bg-off); box-shadow: none; cursor: pointer; outline: none; transition: background var(--checkbox-transition-duration) var(--checkbox-transition-ease), border-color var(--checkbox-transition-duration) var(--checkbox-transition-ease), box-shadow var(--checkbox-transition-duration) var(--checkbox-transition-ease), opacity var(--checkbox-transition-duration) var(--checkbox-transition-ease); } /* ── Sizes ──────────────────────────────────────────────────────────────── */ [data-checkbox][data-size='xs'] { --_checkbox-box-size: var(--checkbox-size-xs-box-size); --_checkbox-indicator-size: var(--checkbox-size-xs-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-xs-indicator-stroke); } [data-checkbox][data-size='sm'] { --_checkbox-box-size: var(--checkbox-size-sm-box-size); --_checkbox-indicator-size: var(--checkbox-size-sm-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-sm-indicator-stroke); } [data-checkbox][data-size='md'] { --_checkbox-box-size: var(--checkbox-size-md-box-size); --_checkbox-indicator-size: var(--checkbox-size-md-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-md-indicator-stroke); } [data-checkbox][data-size='lg'] { --_checkbox-box-size: var(--checkbox-size-lg-box-size); --_checkbox-indicator-size: var(--checkbox-size-lg-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-lg-indicator-stroke); } [data-checkbox][data-size='xl'] { --_checkbox-box-size: var(--checkbox-size-xl-box-size); --_checkbox-indicator-size: var(--checkbox-size-xl-indicator-size); --_checkbox-indicator-stroke: var(--checkbox-size-xl-indicator-stroke); } /* ── Color subset cascade — config-owned by recipes/base.ts ────────────── * Subset: primary | secondary | neutral | affirm. Per-color override * blocks emitted by the generator at `[data-checkbox][data-color='X']`. */ /* ── Hover / focus ─────────────────────────────────────────────────────── */ [data-checkbox]:hover:not([data-disabled]):not([data-readonly]) { background: var(--checkbox-bg-off-hover); border-color: var(--checkbox-border-off-hover); } [data-checkbox]:focus-visible { box-shadow: var(--checkbox-focus-ring); } /* ── States: checked / indeterminate ───────────────────────────────────── * Solid variant (default): filled with the colour palette. */ [data-checkbox][data-variant='solid'][data-state='checked'], [data-checkbox][data-variant='solid'][data-state='indeterminate'], [data-checkbox]:not([data-variant])[data-state='checked'], [data-checkbox]:not([data-variant])[data-state='indeterminate'] { background: var(--_checkbox-palette-solid); border-color: var(--_checkbox-palette-solid); --_checkbox-palette-text: var(--color-content-on-solid); } [data-checkbox][data-variant='solid'][data-state='checked']:hover:not([data-disabled]):not([data-readonly]), [data-checkbox][data-variant='solid'][data-state='indeterminate']:hover:not([data-disabled]):not([data-readonly]), [data-checkbox]:not([data-variant])[data-state='checked']:hover:not([data-disabled]):not([data-readonly]), [data-checkbox]:not([data-variant])[data-state='indeterminate']:hover:not([data-disabled]):not([data-readonly]) { background: var(--_checkbox-palette-solid-hover); border-color: var(--_checkbox-palette-solid-hover); } /* Outline variant: transparent fill, border carries the active colour. */ [data-checkbox][data-variant='outline'][data-state='checked'], [data-checkbox][data-variant='outline'][data-state='indeterminate'] { background: transparent; border-color: var(--_checkbox-palette-solid); --_checkbox-palette-text: var(--_checkbox-palette-solid); } /* Ghost variant: minimal chrome, faint tint when active. */ [data-checkbox][data-variant='ghost'] { border-color: transparent; background: transparent; } [data-checkbox][data-variant='ghost']:hover:not([data-disabled]):not([data-readonly]) { background: color-mix(in srgb, var(--_checkbox-palette-solid) 8%, transparent); border-color: transparent; } [data-checkbox][data-variant='ghost'][data-state='checked'], [data-checkbox][data-variant='ghost'][data-state='indeterminate'] { background: color-mix(in srgb, var(--_checkbox-palette-solid) 18%, transparent); border-color: transparent; --_checkbox-palette-text: var(--_checkbox-palette-solid); } /* ── Invalid state (form validation) ──────────────────────────────────── * Threat-coloured border across ALL variants. Wins over the active color * because invalid signals priority. */ [data-checkbox][data-invalid] { border-color: var(--color-threat-element); } [data-checkbox][data-invalid]:focus-visible { box-shadow: 0 0 0 2px var(--color-surface-default), 0 0 0 4px var(--color-threat-element); } /* ── Disabled / readonly ────────────────────────────────────────────────── */ [data-checkbox][data-disabled] { background: var(--checkbox-bg-disabled); border-color: var(--checkbox-border-disabled); cursor: not-allowed; opacity: var(--checkbox-disabled-opacity); } [data-checkbox][data-readonly] { cursor: default; } /* ── Indicator ──────────────────────────────────────────────────────────── */ [data-checkbox-indicator] { display: inline-flex; align-items: center; justify-content: center; inline-size: var(--_checkbox-indicator-size); block-size: var(--_checkbox-indicator-size); flex: 0 0 auto; color: var(--_checkbox-palette-text); pointer-events: none; } /* SVG glyph from `$uix/eidos/components/svg`. Uses currentColor so it * inherits the indicator's colour, which is set per-variant above. */ [data-checkbox-indicator] svg { inline-size: 100%; block-size: 100%; stroke-width: var(--_checkbox-indicator-stroke); } /* ── Animation: stroke-dasharray draw on check + dash grow ─────────────── */ [data-checkbox-indicator] svg[data-svg='check'] path, [data-checkbox-indicator] svg[data-svg='dash'] path { stroke-dasharray: 100; stroke-dashoffset: 100; transition: stroke-dashoffset var(--checkbox-stroke-duration) var(--checkbox-stroke-ease); } [data-checkbox][data-state='checked'] [data-checkbox-indicator] svg[data-svg='check'] path, [data-checkbox][data-state='indeterminate'] [data-checkbox-indicator] svg[data-svg='dash'] path { stroke-dashoffset: 0; } /* ── Disabled indicator colour ──────────────────────────────────────────── */ [data-checkbox][data-disabled] [data-checkbox-indicator] { color: var(--checkbox-indicator-color-disabled); } /* ── Group ──────────────────────────────────────────────────────────────── */ [data-checkbox-group] { display: flex; flex-direction: column; gap: var(--checkbox-group-gap); } [data-checkbox-group][data-orientation='horizontal'] { flex-direction: row; flex-wrap: wrap; align-items: center; } /* Grid layout when `columns` is set on the wrapper. The wrapper publishes * `--_checkbox-group-columns` inline + `data-columns` for the selector. */ [data-checkbox-group][data-columns] { display: grid; grid-template-columns: repeat(var(--_checkbox-group-columns, 2), minmax(0, 1fr)); align-items: start; } [data-checkbox-group-label] { display: inline-flex; align-items: center; width: fit-content; font-family: var(--checkbox-group-label-font-family); font-size: var(--checkbox-group-label-font-size); font-weight: var(--checkbox-group-label-font-weight); line-height: var(--checkbox-group-label-line-height); color: var(--checkbox-group-label-color); } [data-checkbox-group-label][data-disabled] { color: var(--checkbox-group-label-color-disabled); } /* ── Reduced motion ───────────────────────────────────────────────────────── * Honour the user's OS preference: skip the stroke draw + state * transition. Indicator just snaps in / out. */ @media (prefers-reduced-motion: reduce) { [data-checkbox] { transition: none; } [data-checkbox-indicator] svg path { transition: none; } }