Switch

Un contrôle qui bascule entre deux états.

Utilisation

Utilisez la directive v-model pour contrôler l'état vérifié du commutateur.

<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>

Utilisez la prop default-value pour définir la valeur initiale lorsque vous n'avez pas besoin de contrôler son état.

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

étiquette

Utilisez le prop label pour définir l'étiquette du Switch.

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

Lorsque vous utilisez le prop required, un astérisque est ajouté à côté de l'étiquette.

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

Description

Utilisez le prop description pour définir la description du Switch.

This is a checkbox.

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

icône

Utilisez les accessoires checked-icon et unchecked-icon pour définir les icônes du commutateur lorsqu 'elles sont cochées ou non.

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

Loading

Utilisez le prop loading pour afficher une icône de chargement sur le Switch.

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

Icône de chargement

Utilisez la prop loading-icon pour personnaliser l'icône de chargement. Par défaut, i-lucide-loader-circle.

<template>
  <USwitch loading loading-icon="i-lucide-loader" default-value label="Check me" />
</template>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la clé ui.icons.loading.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.loading.

Couleur

Utilisez le prop color pour changer la couleur du Switch.

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

Size

Utilisez le prop size pour modifier la taille du commutateur.

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

Désactivé

Utilisez le prop disabled pour désactiver le Switch.

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

API

Props équipements

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; }
Ce composant prend également en charge tous les attributs HTML natifs <button>.

Slots

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

Emits

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

Thème

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