# Switch

> A control that toggles between two states.

## Usage

Use the `v-model` directive to control the checked state of the Switch.

```vue
<template>
  <PSwitch model-value />
</template>
```

Use the `default-value` prop to set the initial value when you do not need to control its state.

```vue
<template>
  <PSwitch default-value />
</template>
```

### Label

Use the `label` prop to set the label of the Switch.

```vue
<template>
  <PSwitch label="Check me" />
</template>
```

When using the `required` prop, an asterisk is added next to the label.

```vue
<template>
  <PSwitch required label="Check me" />
</template>
```

### Description

Use the `description` prop to set the description of the Switch.

```vue
<template>
  <PSwitch label="Check me" description="This is a checkbox." />
</template>
```

### Icon

Use the `checked-icon` and `unchecked-icon` props to set the icons of the Switch when checked and unchecked.

```vue
<template>
  <PSwitch unchecked-icon="i-lucide:x" checked-icon="i-lucide:check" default-value label="Check me" />
</template>
```

### Loading

Use the `loading` prop to show a loading icon on the Switch.

```vue
<template>
  <PSwitch loading default-value label="Check me" />
</template>
```

### Loading Icon

Use the `loading-icon` prop to customize the loading icon. Defaults to `i-lucide:loader-circle`.

```vue
<template>
  <PSwitch loading loading-icon="i-lucide:loader" default-value label="Check me" />
</template>
```

<docs-framework-only>
<template v-slot:nuxt="">
<tip to="/docs/pohon/getting-started/integrations/icons/nuxt#theme">

You can customize this icon globally in your `app.config.ts` under `pohon.icons.loading` key.

</tip>
</template>

<template v-slot:vue="">
<tip to="/docs/pohon/getting-started/integrations/icons/vue#theme">

You can customize this icon globally in your `vite.config.ts` under `pohon.icons.loading` key.

</tip>
</template>
</docs-framework-only>

### Color

Use the `color` prop to change the color of the Switch.

```vue
<template>
  <PSwitch color="neutral" default-value label="Check me" />
</template>
```

### Size

Use the `size` prop to change the size of the Switch.

```vue
<template>
  <PSwitch size="xl" default-value label="Check me" />
</template>
```

### Disabled

Use the `disabled` prop to disable the Switch.

```vue
<template>
  <PSwitch disabled label="Check me" />
</template>
```

## API

### Props

```ts
/**
 * Props for the Switch component
 */
interface SwitchProps {
  /**
   * The element or component this component should render as.
   */
  as?: any;
  size?: "md" | "xs" | "sm" | "lg" | "xl";
  color?: "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral";
  pohon?: { root?: ClassValue; base?: ClassValue; container?: ClassValue; thumb?: ClassValue; icon?: ClassValue; wrapper?: ClassValue; label?: ClassValue; description?: ClassValue; };
  description?: string;
  /**
   * The value given as data when submitted with a `name`.
   */
  value?: string;
  /**
   * The name of the field. Submitted with its owning form as part of a name/value pair.
   */
  name?: string;
  id?: string;
  autofocus?: Booleanish;
  form?: string;
  formaction?: string;
  formenctype?: string;
  formmethod?: string;
  formnovalidate?: Booleanish;
  formtarget?: string;
  /**
   * The icon when the `loading` prop is `true`.
   */
  loadingIcon?: string | object;
  /**
   * Display an icon when the switch is checked.
   */
  checkedIcon?: string | object;
  /**
   * Display an icon when the switch is unchecked.
   */
  uncheckedIcon?: string | object;
  label?: string;
  /**
   * The state of the switch when it is initially rendered. Use when you do not need to control its state.
   */
  defaultValue?: boolean;
  /**
   * When `true`, prevents the user from interacting with the switch.
   */
  disabled?: boolean;
  /**
   * @default "undefined"
   */
  modelValue?: boolean;
  /**
   * When `true`, indicates that the user must set the value before the owning form can be submitted.
   */
  required?: boolean;
  /**
   * When `true`, the loading icon will be displayed.
   */
  loading?: boolean;
}
```

<callout icon="i-simple-icons:mdnwebdocs" target="_blank" to="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes">

This component also supports all native `<button>` HTML attributes.

</callout>

### Slots

```ts
/**
 * Slots for the Switch component
 */
interface SwitchSlots {
  label(): any;
  description(): any;
}
```

### Emits

```ts
/**
 * Emitted events for the Switch component
 */
interface SwitchEmits {
  update:modelValue: (payload: [value: boolean]) => void;
  change: (payload: [event: Event]) => void;
}
```

## Theme

```ts [app.config.ts]
export default defineAppConfig({
  pohon: {
    switch: {
      slots: {
        root: 'flex items-start relative',
        base: 'border-2 border-transparent rounded-full inline-flex shrink-0 transition-colors-280 items-center focus-visible:(outline-2 outline-offset-2) data-[state=unchecked]:bg-background-accented',
        container: 'flex items-center',
        thumb: 'group rounded-full bg-background flex pointer-events-none ring-0 shadow-lg transition-transform-280 items-center justify-center data-[state=unchecked]:translate-x-0 data-[state=unchecked]:rtl:-translate-x-0',
        icon: 'opacity-0 shrink-0 size-10/12 transition-[color,opacity]-280 absolute group-data-[state=unchecked]:color-text-dimmed',
        wrapper: 'ms-2',
        label: 'color-text font-medium block',
        description: 'color-text-muted'
      },
      variants: {
        color: {
          primary: {
            base: 'data-[state=checked]:bg-primary focus-visible:outline-primary',
            icon: 'group-data-[state=checked]:color-primary'
          },
          secondary: {
            base: 'data-[state=checked]:bg-secondary focus-visible:outline-secondary',
            icon: 'group-data-[state=checked]:color-secondary'
          },
          success: {
            base: 'data-[state=checked]:bg-success focus-visible:outline-success',
            icon: 'group-data-[state=checked]:color-success'
          },
          info: {
            base: 'data-[state=checked]:bg-info focus-visible:outline-info',
            icon: 'group-data-[state=checked]:color-info'
          },
          warning: {
            base: 'data-[state=checked]:bg-warning focus-visible:outline-warning',
            icon: 'group-data-[state=checked]:color-warning'
          },
          error: {
            base: 'data-[state=checked]:bg-error focus-visible:outline-error',
            icon: 'group-data-[state=checked]:color-error'
          },
          neutral: {
            base: 'focus-visible:outline-outline-inverted data-[state=checked]:bg-background-inverted',
            icon: 'group-data-[state=checked]:color-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'
          }
        },
        required: {
          true: {
            label: 'after:(text-error ms-0.5 content-["*"])'
          }
        },
        disabled: {
          true: {
            root: 'opacity-75',
            base: 'cursor-not-allowed',
            label: 'cursor-not-allowed',
            description: 'cursor-not-allowed'
          }
        }
      }
    }
  }
})
```

## Akar

<docs-akar-to-pohon mode="pohon" to="/docs/akar/components/slider">



</docs-akar-to-pohon>

## Changelog

<docs-component-changelog>



</docs-component-changelog>
