<div id="switch-74629-93238-container" class="switch">
<input id="switch-74629-93238" type="checkbox" role="switch" class="switch__input" name="switch" value="1" aria-checked="false">
<span class="switch__switch"></span>
<span class="switch__label" aria-hidden="true">
<span class="switch__label-on u-line-clamp">On</span>
<span class="switch__label-off u-line-clamp">Off</span>
</span>
</div>
{% set id = id ??? html_id('switch') %}
{% set descriptionId = descriptionId ?? '' %}
{% set errorId = errorId ?? '' %}
{% set describedBy = html_classes(errorId, descriptionId) | trim | default(false) -%}
<div {{ html_attributes({
id: containerId ??? ('container' | namespaceInputId(id)),
class: 'switch',
}, attrs ?? {}) }}>
<input {{ html_attributes({
id: id,
type: 'checkbox',
role: 'switch',
class: 'switch__input',
name: name ?? null,
value: value ?? null,
disabled: disabled ?? false,
checked: checked ?? false,
'aria-checked': checked|default ? 'true' : 'false',
'aria-invalid': invalid|default ? 'true' : null,
'aria-describedby': describedBy,
}, inputAttrs ?? {}) }}>
<span class="switch__switch"></span>
{% if on|default or off|default %}
<span class="switch__label" aria-hidden="true">
{% if on|default %}
<span class="switch__label-on u-line-clamp">
{{- on -}}
</span>
{% endif %}
{% if off|default %}
<span class="switch__label-off u-line-clamp">
{{- off -}}
</span>
{% endif %}
</span>
{% endif %}
</div>
{
"name": "switch",
"value": 1,
"label": "This is a switch",
"on": "On",
"off": "Off"
}
@use 'a11y';
.switch {
align-items: center;
display: flex;
gap: var(--switch-gap, 1.5rem);
user-select: none;
&:has([disabled]) {
cursor: default;
filter: grayscale(1);
opacity: 0.2;
}
&:has(:focus-visible:not(:any-link)) {
@include a11y.outline();
}
&:has(.switch__input:checked) {
--_switch-label-state-off: none;
--_switch-label-state-on: block;
}
}
.switch__input {
opacity: 0;
pointer-events: none;
position: absolute;
z-index: -1;
}
.switch__switch {
--_switch-size: var(--switch-size, 2.8rem);
--_switch-inner-padding: var(--switch-inner-padding, 0.5rem);
--_switch-bullet-size: calc(var(--_switch-size) - var(--_switch-inner-padding) * 2);
background-color: var(--switch-background-color, var(--color-gray-200));
block-size: var(--_switch-size);
border-radius: calc(var(--_switch-size) / 2);
cursor: pointer;
display: block;
inline-size: calc(var(--_switch-bullet-size) * 2 + var(--_switch-inner-padding) * 2);
position: relative;
transition-property: background-color;
&::before {
background-color: var(--switch-foreground-color, var(--color-gray-600));
block-size: var(--_switch-bullet-size);
border-radius: 50%;
content: '';
inline-size: var(--_switch-bullet-size);
inset-block-start: var(--_switch-inner-padding);
inset-inline-start: var(--_switch-inner-padding);
position: absolute;
transition-property: background-color, translate;
translate: 0 0;
}
}
.switch__input:checked ~ .switch__switch {
background-color: var(--switch-background-color--checked, var(--color-green-100));
&::before {
background-color: var(--switch-foreground-color--checked, var(--color-green-700));
translate: 100% 0;
}
}
.switch__label {
--line-clamp: 1;
color: var(--switch-text-color, inherit);
font-size: var(--switch-font-size, inherit);
line-height: var(--switch-line-height, var(--line-height-wide));
margin-block-start: calc((var(--_switch-size) - 1lh) / 2);
text-align: start;
}
.switch__label-off {
display: var(--_switch-label-state-off, block);
}
.switch__label-on {
display: var(--_switch-label-state-on, none);
}
import { on } from 'delegated-events';
on('click', '.switch__switch', (event) => {
const { currentTarget } = event;
const $input = currentTarget.closest('.switch')?.querySelector<HTMLInputElement>('.switch__input');
if ($input) {
$input.checked = !$input.checked;
}
});
No notes defined.