๐ข Switch
Basic
use NSwitch to create a switch input.
Label
You can use the
NFormGroupcomponent to create a label for the switch.
NFormGroup component here.Outset
By default, the switch is in inset mode. You can change it to outset mode using the
outsetprop.
outset - force the switch to be outset mode.
Color
switch="{color}" - change the color of the switch.
primary. You can also add your own colors to the palette through the Configuration section.Focus
switch="focus" - add a focus color to the switch.
Size
size="{size}" - change the size of the switch.
๐ You can freely adjust the size of the switch using any size imaginable. No limits exist, and you can use
breakpointssuch assm:sm, xs:lgto change size based on screen size orstatessuch ashover:lg, focus:3xlto change size based on input state and more.
height and width of the switch scale depends on the switch-size. If you want to change the height and width simultaneously, you can always customize it using utility classes.Icon
icon - add an icon to the switch.
Disabled
disabled - disable the switch.
Loading
loading - set the switch to loading state.
Customization
You can customize the switch using the
unaprop and utility classes.
Slots
You can use the following slots to customize the switch.
| Name | Description | Props |
|---|---|---|
icon | The on and off icons of the switch. | on |
loading-icon | The loading icon slot. | on |
Props
export interface NSwitchProps {
/**
* Value of the switch.
*
* @default null
*/
modelValue?: boolean
/**
* Disable the switch from being clicked.
*
* @default false
*/
disabled?: boolean
/**
* Add a loading indicator to the switch.
* This will also disable the switch.
*
* @default false
*/
loading?: boolean
/**
* Display the slider thumb outside of the track.
*
* @default false
*/
outset?: boolean
/**
* Allows you to add `UnaUI` switch preset properties,
* Think of it as a shortcut for adding options or variants to the preset if available.
*
* @example
* switch="xl green focus"
*/
switch?: string
/**
* Allows you to display an icon when the switch is on.
* Accepts icon name and utility classes
*
* @example
* icon="i-heroicons-check-20-solid text-white"
*/
onIcon?: string
/**
* Allows you to display an icon when the switch is off.
* Accepts icon name and utility classes
*
* @example
* icon="i-heroicons-x-mark-20-solid text-white"
*/
offIcon?: string
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/switch.ts
*/
una?: {
switchThumb?: string
switchThumbOn?: string
switchThumbOff?: string
switchTrack?: string
switchTrackOn?: string
switchTrackOff?: string
switchIconBase?: string
switchIconOn?: string
switchIconOff?: string
switchLoading?: string
switchloadingicon?: string
}
}
Presets
import type { RuleContext } from '@unocss/core'
import type { Theme } from '@unocss/preset-uno'
import { parseColor } from '@unocss/preset-mini/utils'
type SwitchPrefix = 'switch'
export const staticSwitch: Record<`${SwitchPrefix}-${string}` | SwitchPrefix, string> = {
// base
'switch': 'switch-primary bg-transparent relative inline-flex items-center justify-center flex-shrink-0 cursor-pointer rounded-full',
'switch-disabled': 'n-disabled',
'switch-focus': 'focus:outline-none focus:ring-2 focus:ring-offset-2 ring-offset-base focus:ring-brand',
// inset
'switch-inset': 'h-1.5em w-2.75em',
'switch-track-inset': 'h-1.5em w-2.75em',
// outset
'switch-outset': 'h-1.25em w-2.5em',
'switch-track-outset': 'h-1em w-2.25em',
// thumb
'switch-thumb': 'flex items-center justify-center h-1.25em w-1.25em absolute bg-base pointer-events-none inline-block transform rounded-full shadow transition-base',
'switch-thumb-on': 'translate-x-1.25em',
'switch-thumb-off': 'translate-x-0',
// track
'switch-track': 'pointer-events-none absolute mx-auto rounded-full transition-base',
'switch-track-on': 'bg-brand',
'switch-track-off': 'bg-$c-gray-200',
// icon
'switch-icon-base': 'text-0.8em',
'switch-icon-off': 'text-muted',
'switch-icon-on': 'text-muted',
// loading
'switch-loading-icon': 'i-loading',
'switch-loading': 'text-gray animate-spin text-0.8em',
}
export const dynamicSwitch = [
[/^switch-(.*)$/, ([, body]: string[], { theme }: RuleContext<Theme>) => {
const color = parseColor(body, theme)
if ((color?.cssColor?.type === 'rgb' || color?.cssColor?.type === 'rgba') && color.cssColor.components)
return `n-${body}-600 dark:n-${body}-500`
}],
]
export const _switch = [
...dynamicSwitch,
staticSwitch,
]
Component
<script setup lang="ts">
import type { NSwitchProps } from '../../types'
import { Switch } from '@headlessui/vue'
import { useVModel } from '@vueuse/core'
import { computed } from 'vue'
import NIcon from '../elements/Icon.vue'
defineOptions({
inheritAttrs: false,
})
const props = defineProps<NSwitchProps>()
const emit = defineEmits<{ (...args: any): void }>()
const on = useVModel(props, 'modelValue', emit, { passive: true })
const _switch = computed(() => props.switch)
const outsetClassVariants = computed(() => {
const switchWrapper = {
false: 'switch-inset',
true: 'switch-outset',
}
const switchTrack = {
false: 'switch-track-inset',
true: 'switch-track-outset',
}
const switchThumb = {
false: 'left-0.125em',
true: 'left-0 border-base border',
}
return {
switchWrapper: switchWrapper[!props.outset ? 'false' : 'true'],
switchTrack: switchTrack[!props.outset ? 'false' : 'true'],
switchThumb: switchThumb[!props.outset ? 'false' : 'true'],
}
})
const onClassVariants = computed(() => {
const switchTrack = {
true: `${props.una?.switchTrackOn ?? ''} switch-track-on`,
false: `${props.una?.switchTrackOff ?? ''} switch-track-off`,
}
const switchThumb = {
true: `${props.una?.switchThumbOn ?? ''} switch-thumb-on`,
false: `${props.una?.switchThumbOff ?? ''} switch-thumb-off`,
}
const switchIcon = {
true: `${props.onIcon ?? ''} switch-icon-on`,
false: `${props.offIcon ?? ''} switch-icon-off`,
}
return {
switchTrack: switchTrack[on.value ? 'true' : 'false'],
switchThumb: switchThumb[on.value ? 'true' : 'false'],
switchIcon: switchIcon[on.value ? 'true' : 'false'],
}
})
</script>
<template>
<Switch
v-model="on"
class="switch"
:class="[
{ 'switch-disabled': disabled || loading },
outsetClassVariants?.switchWrapper,
]"
:switch="_switch"
v-bind="$attrs"
:disabled="disabled"
>
<span class="sr-only">Track</span>
<span
aria-hidden="true"
switch="track"
:class="[
una?.switchTrack,
onClassVariants?.switchTrack,
outsetClassVariants?.switchTrack,
]"
/>
<span class="sr-only">Thumb</span>
<span
aria-hidden="true"
switch="thumb"
:class="[
una?.switchThumb,
onClassVariants?.switchThumb,
outsetClassVariants?.switchThumb,
]"
>
<span class="sr-only">Icon</span>
<slot v-if="!loading" name="icon" :on="on">
<NIcon
switch="icon-base"
:name="onClassVariants?.switchIcon"
:class="una?.switchIconBase"
/>
</slot>
<slot v-else name="loading-icon" :on="on">
<NIcon
switch="loading"
:class="una?.switchLoading"
:name="una?.switchloadingicon ?? 'switch-loading-icon'"
/>
</slot>
</span>
</Switch>
</template>