2つの状態を切り替えるコントロール。

使用法

v-modelディレクティブを使用して、Switchのチェック状態を制御します。

<script setup lang="ts">
const value = ref(true)
</script>

<template>
  <USwitch v-model="value" />
</template>
<script setup lang="ts">
import { ref } from 'vue'

const value = ref(true)
</script>

<template>
  <USwitch v-model="value" />
</template>

状態を制御する必要がない場合は、default-valueプロパティを使用して初期値を設定します。

<template>
  <USwitch default-value />
</template>

Label

labelプロパティを使用して、Switchのラベルを設定します。

<template>
  <USwitch label="Check me" />
</template>

requiredプロパティを使用する場合、ラベルの横にアスタリスクが追加されます。

<template>
  <USwitch required label="Check me" />
</template>

Description

descriptionプロパティを使用して、Switchの説明を設定します。

This is a checkbox.

<template>
  <USwitch label="Check me" description="This is a checkbox." />
</template>

Icon

checked-iconとunchecked-iconのプロップを使用して、スイッチのアイコンをチェックしたりオフにしたりします。

<template>
  <USwitch
    unchecked-icon="i-lucide-x"
    checked-icon="i-lucide-check"
    default-value
    label="Check me"
  />
</template>

読み込み中

loadingプロパティを使用して、Switchにロードアイコンを表示します。

<template>
  <USwitch loading default-value label="Check me" />
</template>

Loadingアイコン

loading-iconプロパティを使用して、ロードアイコンをカスタマイズします。デフォルトはi-lucide-loader-circleです。

<template>
  <USwitch loading loading-icon="i-lucide-loader" default-value label="Check me" />
</template>
このアイコンはapp.config.tsのui.icons.loadingキーでグローバルにカスタマイズできます。
このアイコンはvite.config.tsのui.icons.loadingキーでグローバルにカスタマイズできます。

Color

colorプロパティを使用してSwitchの色を変更します。

<template>
  <USwitch color="neutral" default-value label="Check me" />
</template>

サイズ

sizeプロパティを使用してSwitchのサイズを変更します。

<template>
  <USwitch size="xl" default-value label="Check me" />
</template>

無効

disabledプロパティを使用してSwitchを無効にします。

<template>
  <USwitch disabled label="Check me" />
</template>

API

Props

Prop Default Type
as
'div'
any

The element or component this component should render as.

color
'primary'
"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"
size
'md'
"md" | "xs" | "sm" | "lg" | "xl"
highlight
boolean

Highlight the ring color like a focus state.

loading
boolean

When true, the loading icon will be displayed.

loadingIcon
appConfig.ui.icons.loading
any

The icon when the loading prop is true.

checkedIcon
any

Display an icon when the switch is checked.

uncheckedIcon
any

Display an icon when the switch is unchecked.

label
string
description
string
disabled
boolean

When true, prevents the user from interacting with the switch.

id
string
name
string

The name of the field. Submitted with its owning form as part of a name/value pair.

required
boolean

When true, indicates that the user must set the value before the owning form can be submitted.

value
string

The value given as data when submitted with a name.

defaultValue
T

The state of the switch when it is initially rendered. Use when you do not need to control its state.

modelValue
null | T

The controlled state of the switch. Can be bind as v-model.

trueValue
T

The value used when the switch is on. Defaults to true.

falseValue
T

The value used when the switch is off. Defaults to false.

autofocus
false | true | "true" | "false"
ui
{ root?: SlotClass; base?: SlotClass; container?: SlotClass; thumb?: SlotClass; icon?: SlotClass; wrapper?: SlotClass; label?: SlotClass; description?: SlotClass; }
このコンポーネントはすべてのネイティブ<button> HTML属性もサポートします。

スロット

Slot Type
label
{ label: string | undefined; }
description
{ description: string | undefined; }

Emits

Event Type
change
[event: Event]
update:modelValue
[payload: T]

Theme

app.config.ts
export default defineAppConfig({
  ui: {
    switch: {
      slots: {
        root: 'relative flex items-start',
        base: [
          'inline-flex items-center shrink-0 rounded-full border-2 border-transparent focus-visible:outline-3 data-[state=unchecked]:bg-accented',
          'transition-[background] duration-200 ease-out'
        ],
        container: 'flex items-center',
        thumb: 'group pointer-events-none rounded-full bg-default shadow-lg ring-0 transition-transform duration-200 ease-out motion-reduce:transition-none data-[state=unchecked]:translate-x-0 data-[state=unchecked]:rtl:-translate-x-0 flex items-center justify-center',
        icon: [
          'absolute shrink-0 group-data-[state=unchecked]:text-dimmed opacity-0 size-10/12',
          'transition-[color,opacity] duration-200 ease-out'
        ],
        wrapper: 'ms-2',
        label: 'block font-medium text-default',
        description: 'text-muted'
      },
      variants: {
        color: {
          primary: {
            base: 'data-[state=checked]:bg-primary outline-primary/25',
            icon: 'group-data-[state=checked]:text-primary'
          },
          secondary: {
            base: 'data-[state=checked]:bg-secondary outline-secondary/25',
            icon: 'group-data-[state=checked]:text-secondary'
          },
          success: {
            base: 'data-[state=checked]:bg-success outline-success/25',
            icon: 'group-data-[state=checked]:text-success'
          },
          info: {
            base: 'data-[state=checked]:bg-info outline-info/25',
            icon: 'group-data-[state=checked]:text-info'
          },
          warning: {
            base: 'data-[state=checked]:bg-warning outline-warning/25',
            icon: 'group-data-[state=checked]:text-warning'
          },
          error: {
            base: 'data-[state=checked]:bg-error outline-error/25',
            icon: 'group-data-[state=checked]:text-error'
          },
          neutral: {
            base: 'data-[state=checked]:bg-inverted outline-inverted/25',
            icon: 'group-data-[state=checked]:text-highlighted'
          }
        },
        size: {
          xs: {
            base: 'w-7',
            container: 'h-4',
            thumb: 'size-3 data-[state=checked]:translate-x-3 data-[state=checked]:rtl:-translate-x-3',
            wrapper: 'text-xs'
          },
          sm: {
            base: 'w-8',
            container: 'h-4',
            thumb: 'size-3.5 data-[state=checked]:translate-x-3.5 data-[state=checked]:rtl:-translate-x-3.5',
            wrapper: 'text-xs'
          },
          md: {
            base: 'w-9',
            container: 'h-5',
            thumb: 'size-4 data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4',
            wrapper: 'text-sm'
          },
          lg: {
            base: 'w-10',
            container: 'h-5',
            thumb: 'size-4.5 data-[state=checked]:translate-x-4.5 data-[state=checked]:rtl:-translate-x-4.5',
            wrapper: 'text-sm'
          },
          xl: {
            base: 'w-11',
            container: 'h-6',
            thumb: 'size-5 data-[state=checked]:translate-x-5 data-[state=checked]:rtl:-translate-x-5',
            wrapper: 'text-base'
          }
        },
        checked: {
          true: {
            icon: 'group-data-[state=checked]:opacity-100'
          }
        },
        unchecked: {
          true: {
            icon: 'group-data-[state=unchecked]:opacity-100'
          }
        },
        loading: {
          true: {
            icon: 'animate-spin'
          }
        },
        highlight: {
          true: ''
        },
        required: {
          true: {
            label: "after:content-['*'] after:ms-0.5 after:text-error"
          }
        },
        disabled: {
          true: {
            root: 'opacity-75',
            base: 'cursor-not-allowed',
            label: 'cursor-not-allowed',
            description: 'cursor-not-allowed'
          }
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          highlight: true,
          class: {
            base: 'ring ring-primary'
          }
        },
        {
          color: 'neutral',
          highlight: true,
          class: {
            base: 'ring ring-inverted'
          }
        }
      ],
      defaultVariants: {
        color: 'primary',
        size: 'md'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        switch: {
          slots: {
            root: 'relative flex items-start',
            base: [
              'inline-flex items-center shrink-0 rounded-full border-2 border-transparent focus-visible:outline-3 data-[state=unchecked]:bg-accented',
              'transition-[background] duration-200 ease-out'
            ],
            container: 'flex items-center',
            thumb: 'group pointer-events-none rounded-full bg-default shadow-lg ring-0 transition-transform duration-200 ease-out motion-reduce:transition-none data-[state=unchecked]:translate-x-0 data-[state=unchecked]:rtl:-translate-x-0 flex items-center justify-center',
            icon: [
              'absolute shrink-0 group-data-[state=unchecked]:text-dimmed opacity-0 size-10/12',
              'transition-[color,opacity] duration-200 ease-out'
            ],
            wrapper: 'ms-2',
            label: 'block font-medium text-default',
            description: 'text-muted'
          },
          variants: {
            color: {
              primary: {
                base: 'data-[state=checked]:bg-primary outline-primary/25',
                icon: 'group-data-[state=checked]:text-primary'
              },
              secondary: {
                base: 'data-[state=checked]:bg-secondary outline-secondary/25',
                icon: 'group-data-[state=checked]:text-secondary'
              },
              success: {
                base: 'data-[state=checked]:bg-success outline-success/25',
                icon: 'group-data-[state=checked]:text-success'
              },
              info: {
                base: 'data-[state=checked]:bg-info outline-info/25',
                icon: 'group-data-[state=checked]:text-info'
              },
              warning: {
                base: 'data-[state=checked]:bg-warning outline-warning/25',
                icon: 'group-data-[state=checked]:text-warning'
              },
              error: {
                base: 'data-[state=checked]:bg-error outline-error/25',
                icon: 'group-data-[state=checked]:text-error'
              },
              neutral: {
                base: 'data-[state=checked]:bg-inverted outline-inverted/25',
                icon: 'group-data-[state=checked]:text-highlighted'
              }
            },
            size: {
              xs: {
                base: 'w-7',
                container: 'h-4',
                thumb: 'size-3 data-[state=checked]:translate-x-3 data-[state=checked]:rtl:-translate-x-3',
                wrapper: 'text-xs'
              },
              sm: {
                base: 'w-8',
                container: 'h-4',
                thumb: 'size-3.5 data-[state=checked]:translate-x-3.5 data-[state=checked]:rtl:-translate-x-3.5',
                wrapper: 'text-xs'
              },
              md: {
                base: 'w-9',
                container: 'h-5',
                thumb: 'size-4 data-[state=checked]:translate-x-4 data-[state=checked]:rtl:-translate-x-4',
                wrapper: 'text-sm'
              },
              lg: {
                base: 'w-10',
                container: 'h-5',
                thumb: 'size-4.5 data-[state=checked]:translate-x-4.5 data-[state=checked]:rtl:-translate-x-4.5',
                wrapper: 'text-sm'
              },
              xl: {
                base: 'w-11',
                container: 'h-6',
                thumb: 'size-5 data-[state=checked]:translate-x-5 data-[state=checked]:rtl:-translate-x-5',
                wrapper: 'text-base'
              }
            },
            checked: {
              true: {
                icon: 'group-data-[state=checked]:opacity-100'
              }
            },
            unchecked: {
              true: {
                icon: 'group-data-[state=unchecked]:opacity-100'
              }
            },
            loading: {
              true: {
                icon: 'animate-spin'
              }
            },
            highlight: {
              true: ''
            },
            required: {
              true: {
                label: "after:content-['*'] after:ms-0.5 after:text-error"
              }
            },
            disabled: {
              true: {
                root: 'opacity-75',
                base: 'cursor-not-allowed',
                label: 'cursor-not-allowed',
                description: 'cursor-not-allowed'
              }
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              highlight: true,
              class: {
                base: 'ring ring-primary'
              }
            },
            {
              color: 'neutral',
              highlight: true,
              class: {
                base: 'ring ring-inverted'
              }
            }
          ],
          defaultVariants: {
            color: 'primary',
            size: 'md'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.

Changelog

No recent changes