/* * : M3's switch (resources/views/components/toggle.blade.php), on the row the selection * controls share (components/selection.css). The hooks say `switch` because `toggle` is daisyUI's * class, which the design guard rejects. * * SwitchTokens (androidx Compose Material 3, Apache-2.0): a 52×32 track with a 2px outline, in * surface-container-highest when off and primary when on. The handle's centre is 16px from the * track's start off and 36px on; it is 16px across off, 24px with an icon or on, and 28px while * pressed, moving and growing on the fast spatial spring. Off it is outline, on-surface-variant * while hovered, focused or pressed; on it is on-primary, primary-container in those states. The * state layer is a 40px circle around the handle. Its icons are 16px, on-primary-container when on. * Disabled, the track is on-surface at 12% and the handle on-surface at 38% (surface when on). * * [data-md-switch] the track; `data-md-icons` = "both" or "selected" * input, [data-md-switch-handle] (with [data-md-switch-on] and [data-md-switch-off] icons) */ @layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; @import './selection.css'; @import './icon.css'; @layer material.components { /* The positions below are the handle's centres less half its size, measured inside the track's 2px outline. */ [data-md-switch] { position: relative; display: grid; flex: none; width: 52px; height: 32px; } [data-md-switch] input { width: 100%; height: 100%; border: 2px solid var(--md-sys-color-outline); border-radius: var(--md-sys-shape-corner-full); background-color: var(--md-sys-color-surface-container-highest); } [data-md-switch] input:focus-visible { outline: 3px solid var(--md-sys-color-secondary); outline-offset: 2px; } [data-md-switch-handle] { --handle: 16px; position: absolute; top: 50%; inset-inline-start: calc(16px - var(--handle) / 2); display: grid; place-items: center; width: var(--handle); height: var(--handle); translate: 0 -50%; border-radius: var(--md-sys-shape-corner-full); background-color: var(--md-sys-color-outline); color: var(--md-sys-color-surface-container-highest); pointer-events: none; transition-property: inset-inline-start, width, height, background-color; transition-duration: var(--md-sys-motion-spatial-fast-duration); transition-timing-function: var(--md-sys-motion-spatial-fast); } [data-md-switch-handle]::before { inset: 50% auto auto 50%; width: 40px; height: 40px; translate: -50% -50%; } [data-md-switch-handle] > svg { grid-area: 1 / 1; opacity: 0; transition: opacity var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } [data-md-switch][data-md-icons='both'] [data-md-switch-handle] { --handle: 24px; } [data-md-switch][data-md-icons='both'] input:not(:checked) ~ [data-md-switch-handle] [data-md-switch-off], [data-md-switch][data-md-icons] input:checked ~ [data-md-switch-handle] [data-md-switch-on] { opacity: 1; } [data-md-switch] input:checked { border-color: var(--md-sys-color-primary); background-color: var(--md-sys-color-primary); } [data-md-switch] input:checked ~ [data-md-switch-handle] { --handle: 24px; inset-inline-start: calc(36px - var(--handle) / 2); background-color: var(--md-sys-color-on-primary); color: var(--md-sys-color-on-primary-container); } [data-md-selection-row]:active [data-md-switch] input:not(:disabled) ~ [data-md-switch-handle] { --handle: 28px; } @media (hover: hover) { [data-md-selection-row]:hover [data-md-switch] input:not(:disabled) ~ [data-md-switch-handle] { background-color: var(--md-sys-color-on-surface-variant); } [data-md-selection-row]:hover [data-md-switch] input:checked:not(:disabled) ~ [data-md-switch-handle] { background-color: var(--md-sys-color-primary-container); } } [data-md-switch] input:focus-visible ~ [data-md-switch-handle], [data-md-selection-row]:active [data-md-switch] input:not(:disabled) ~ [data-md-switch-handle] { background-color: var(--md-sys-color-on-surface-variant); } [data-md-switch] input:checked:focus-visible ~ [data-md-switch-handle], [data-md-selection-row]:active [data-md-switch] input:checked:not(:disabled) ~ [data-md-switch-handle] { background-color: var(--md-sys-color-primary-container); } [data-md-switch] input:disabled { border-color: color-mix(in srgb, var(--md-sys-color-on-surface) calc(var(--md-sys-state-disabled-container-opacity) * 100%), transparent); background-color: color-mix(in srgb, var(--md-sys-color-surface-container-highest) calc(var(--md-sys-state-disabled-container-opacity) * 100%), transparent); } [data-md-switch] input:disabled ~ [data-md-switch-handle] { background-color: color-mix(in srgb, var(--md-sys-color-on-surface) calc(var(--md-sys-state-disabled-content-opacity) * 100%), transparent); color: color-mix(in srgb, var(--md-sys-color-surface-container-highest) calc(var(--md-sys-state-disabled-content-opacity) * 100%), transparent); } [data-md-switch] input:disabled:checked { border-color: transparent; background-color: color-mix(in srgb, var(--md-sys-color-on-surface) calc(var(--md-sys-state-disabled-container-opacity) * 100%), transparent); } [data-md-switch] input:disabled:checked ~ [data-md-switch-handle] { background-color: var(--md-sys-color-surface); color: color-mix(in srgb, var(--md-sys-color-on-surface) calc(var(--md-sys-state-disabled-content-opacity) * 100%), transparent); } }