<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"
}
  • Content:
    @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);
    }
    
  • URL: /components/raw/switch/switch.scss
  • Filesystem Path: src/components/2-atoms/switch/switch.scss
  • Size: 2.2 KB
  • Content:
    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;
      }
    });
    
  • URL: /components/raw/switch/switch.ts
  • Filesystem Path: src/components/2-atoms/switch/switch.ts
  • Size: 284 Bytes

No notes defined.