Switch
Switchは、有効または無効の状態を表示したり切り替えたりするために使用されるコンポーネントです。
<script lang="ts">
import Switch from '$lib/components/ui/atoms/Switch.svelte';
let checked = $state(false);
</script>
<Switch bind:checked />
プロパティ
Switchは、以下のプロパティをサポートしています。
| 名前 | 型 | デフォルト値 | 説明 |
|---|---|---|---|
checked |
boolean |
false |
チェック状態の値、bind:checked による双方向バインディングが可能です |
disabled |
boolean |
false |
指定するとグレーアウトされ、クリック不可になります。 |
インストールの手順
以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。
パスは実際のプロジェクトの構成にあわせて更新します。
atoms/Switch.svelte
<!--
@component
## 概要
- checkboxをベースにした、ON/OFF の状態を切り替えるための汎用的なスイッチコンポーネントです
## 機能
- トグルスイッチをベースにしており、クリックやキーボード操作で状態を切り替えられます
- 操作状態・チェック状況を管理するPropsが追加されています(詳細はPropsセクションを参照)
## Props
- checked: チェック状態の値、`bind:checked` による双方向バインディングが可能です
- disabled: 指定するとグレーアウトされ、クリック不可になります
## Usage
```svelte
<Switch bind:checked></Switch>
```
-->
<script module lang="ts">
import type { ClassValue, HTMLInputAttributes } from 'svelte/elements';
import { cva, type VariantProps } from 'class-variance-authority';
export const switchVariants = cva('relative w-11 h-6 bg-base-stroke-default rounded-full group outline-primary transition-shadow focus-visible:outline-[0.125rem] focus-visible:outline-offset-[0.125rem] focus-visible:outline-primary', {
variants: {
/** チェック状態 */
checked: {
true: ['bg-primary'],
false: ['bg-base-stroke-default'],
},
/** 操作できるかどうか */
disabled: {
true: ['opacity-50 !pointer-events-none'],
false: ['cursor-pointer'],
},
},
defaultVariants: {
checked: false,
},
});
export const knobVariants = cva('size-5 bg-base-container-default rounded-full transition group-hover:ring-[0.25rem] group-hover:ring-primary/20', {
variants: {
/** チェック状態 */
checked: {
true: ['translate-x-[calc(1.375rem)] translate-y-0.5'],
false: ['translate-0.5 translate-y-0.5'],
},
/** 操作できるかどうか */
disabled: {
true: ['opacity-95 !pointer-events-none'],
false: [],
},
},
defaultVariants: {
checked: false,
},
});
export type SwitchVariants = VariantProps<typeof switchVariants>;
export interface SwitchProps extends SwitchVariants, HTMLInputAttributes {
/** クラス */
class?: ClassValue;
}
</script>
<script lang="ts">
let { checked = $bindable(false), disabled = false, class: className, ...inputAttributes }: SwitchProps = $props();
let switchVariantClass = $derived(switchVariants({ checked, disabled }));
let knobVariantClass = $derived(knobVariants({ checked, disabled }));
function onKeyDown(e: KeyboardEvent) {
if (disabled) return;
const SPACE = ' ';
if (e.key === 'Enter' || e.key === SPACE) {
e.preventDefault();
checked = !checked;
}
}
</script>
<label class={[className, 'flex w-fit']}>
<input class="sr-only" type="checkbox" {disabled} tabindex="-1" {...inputAttributes} bind:checked />
<div class={switchVariantClass} tabindex="0" role="switch" aria-checked={checked} onkeydown={onKeyDown}>
<div class={knobVariantClass}></div>
</div>
</label>
使い方
<script lang="ts">
import Switch from '$lib/components/ui/atoms/Switch.svelte';
let checked = $state(false);
</script>
<Switch bind:checked />
サンプル
Default
特に操作が行われていない、デフォルトの状態です。
<script lang="ts">
import Switch from '$lib/components/ui/atoms/Switch.svelte';
let checked = $state(false);
</script>
<Switch bind:checked />
Disabled
利用不可の状態です。
<script lang="ts">
import Switch from '$lib/components/ui/atoms/Switch.svelte';
let checked = $state(false);
</script>
<Switch disabled bind:checked />