Toggle

A two-state button that can be either on or off.

Examples

Basic

PropDefaultTypeDescription
defaultValue-booleanThe initial pressed state of the toggle when it is first rendered. Use this when you don't need to manage its open state manually.
disabledfalsebooleanWhen set to true, disables user interaction with the toggle.
pressed-booleanThe controlled pressed state of the toggle, which can be bound using v-model.
Preview
Code

Variant and Color

PropDefaultTypeDescription
toggle-onsoft-accent{variant}-{color}Change the color of the toggle when it is on.
toggle-offghost-gray{variant}-{color}Change the color of the toggle when it is off.
Preview
Code

Slots

Preview
Code

Presets

shortcuts/toggle.ts
type TogglePrefix = 'toggle'

export const staticToggle: Record<`${TogglePrefix}-${string}` | TogglePrefix, string> = {
  // configurations
  toggle: '',
}

export const dynamicToggle = [
  [
    /^toggle-on(?:-([^-]+))?(?:-([^-]+))?$/,
    ([, variant = 'soft', color = 'accent']) =>
      `data-[state=on]:btn-${variant}-${color}`,
  ],
  [
    /^toggle-off(?:-([^-]+))?(?:-([^-]+))?$/,
    ([, variant = 'ghost', color = 'muted']) =>
      `data-[state=off]:btn-${variant}-${color}`,
  ],
]

export const toggle = [
  ...dynamicToggle,
  staticToggle,
]

Props

types/toggle.ts
import type { ToggleProps } from 'radix-vue'
import type { NButtonProps } from './button'

export interface NToggleProps extends ToggleProps, NButtonProps {
  /**
   * Allows you to add `UnaUI` badge preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/toggle.ts
   * @example
   * toggle-on="soft-accent"
   */
  toggleOn?: string

  /**
   * Allows you to add `UnaUI` badge preset properties,
   * Think of it as a shortcut for adding options or variants to the preset if available.
   *
   * @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/toggle.ts
   * @example
   * toggle-off="ghost-gray"
   */
  toggleOff?: string
}

Components

Toggle.vue
<script setup lang="ts">
import type { NToggleProps } from '../../types'
import { Toggle, type ToggleEmits, useForwardPropsEmits } from 'radix-vue'
import { computed } from 'vue'
import { cn } from '../../utils'
import Button from './Button.vue'

const props = withDefaults(defineProps<NToggleProps>(), {
  icon: true,
  square: true,
  toggleOff: '~',
  toggleOn: '~',
})

const emits = defineEmits<ToggleEmits>()

const delegatedProps = computed(() => {
  const { class: _, ...delegated } = props

  return delegated
})

const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
  <Toggle
    :class="cn(
      'toggle',
      props.class,
    )"
    v-bind="forwarded"
    :toggle-off
    :toggle-on
    :as="Button"
  >
    <template v-for="(_, name) in $slots" #[name]="slotData">
      <slot :name="name" v-bind="slotData" />
    </template>
  </Toggle>
</template>