Switch
A control element that allows for a binary selection.
import { Switch, type SwitchProps } from '~/components/ui/switch'
export const Demo = (props: SwitchProps) => {
  return (
    <Switch defaultChecked {...props}>
      Label
    </Switch>
  )
}
import { Switch, type SwitchProps } from '~/components/ui/switch'
export const Demo = (props: SwitchProps) => {
  return (
    <Switch defaultChecked {...props}>
      Label
    </Switch>
  )
}
Usage
import { Switch } from '~/components/ui/switch'Installation
npx @park-ui/cli components add switch1
Add Styled Primitive
Copy the code snippet below into ~/components/ui/styled/switch.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { Switch } from '@ark-ui/react/switch'
import { type SwitchRecipeVariantProps, switchRecipe } from 'styled-system/recipes'
import type { ComponentProps, HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(switchRecipe)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
  HTMLLabelElement,
  Assign<Assign<HTMLStyledProps<'label'>, Switch.RootProviderBaseProps>, SwitchRecipeVariantProps>
>(Switch.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
  HTMLLabelElement,
  Assign<Assign<HTMLStyledProps<'label'>, Switch.RootBaseProps>, SwitchRecipeVariantProps>
>(Switch.Root, 'root')
export const Control = withContext<
  HTMLSpanElement,
  Assign<HTMLStyledProps<'span'>, Switch.ControlBaseProps>
>(Switch.Control, 'control')
export const Label = withContext<
  HTMLSpanElement,
  Assign<HTMLStyledProps<'span'>, Switch.LabelBaseProps>
>(Switch.Label, 'label')
export const Thumb = withContext<
  HTMLSpanElement,
  Assign<HTMLStyledProps<'span'>, Switch.ThumbBaseProps>
>(Switch.Thumb, 'thumb')
export {
  SwitchContext as Context,
  SwitchHiddenInput as HiddenInput,
} from '@ark-ui/react/switch'
import { type Assign, Switch } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { type SwitchRecipeVariantProps, switchRecipe } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from './utils/create-style-context'
const { withProvider, withContext } = createStyleContext(switchRecipe)
export type RootProviderProps = ComponentProps<typeof RootProvider>
export const RootProvider = withProvider<
  Assign<Assign<HTMLStyledProps<'label'>, Switch.RootProviderBaseProps>, SwitchRecipeVariantProps>
>(Switch.RootProvider, 'root')
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<
  Assign<Assign<HTMLStyledProps<'label'>, Switch.RootBaseProps>, SwitchRecipeVariantProps>
>(Switch.Root, 'root')
export const Control = withContext<Assign<HTMLStyledProps<'span'>, Switch.ControlBaseProps>>(
  Switch.Control,
  'control',
)
export const Label = withContext<Assign<HTMLStyledProps<'span'>, Switch.LabelBaseProps>>(
  Switch.Label,
  'label',
)
export const Thumb = withContext<Assign<HTMLStyledProps<'span'>, Switch.ThumbBaseProps>>(
  Switch.Thumb,
  'thumb',
)
export {
  SwitchContext as Context,
  SwitchHiddenInput as HiddenInput,
} from '@ark-ui/solid'
No snippet found2
Add Composition
Copy the composition snippet below into ~/components/ui/switch.tsx
import { forwardRef } from 'react'
import * as StyledSwitch from './styled/switch'
export interface SwitchProps extends StyledSwitch.RootProps {}
export const Switch = forwardRef<HTMLLabelElement, SwitchProps>((props, ref) => {
  const { children, ...rootProps } = props
  return (
    <StyledSwitch.Root ref={ref} {...rootProps}>
      <StyledSwitch.Control>
        <StyledSwitch.Thumb />
      </StyledSwitch.Control>
      {children && <StyledSwitch.Label>{children}</StyledSwitch.Label>}
      <StyledSwitch.HiddenInput />
    </StyledSwitch.Root>
  )
})
Switch.displayName = 'Switch'
import { Show, children } from 'solid-js'
import * as StyledSwitch from './styled/switch'
export interface SwitchProps extends StyledSwitch.RootProps {}
export const Switch = (props: SwitchProps) => {
  const getChildren = children(() => props.children)
  return (
    <StyledSwitch.Root {...props}>
      <StyledSwitch.Control>
        <StyledSwitch.Thumb />
      </StyledSwitch.Control>
      <Show when={getChildren()}>
        <StyledSwitch.Label>{getChildren()}</StyledSwitch.Label>
      </Show>
      <StyledSwitch.HiddenInput />
    </StyledSwitch.Root>
  )
}
3
Integrate Recipe
If you're not using @park-ui/preset, add the following recipe to yourpanda.config.ts:
import { switchAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const switchRecipe = defineSlotRecipe({
  className: 'switchRecipe',
  jsx: ['Switch', /Switch\.+/],
  slots: switchAnatomy.keys(),
  base: {
    root: {
      alignItems: 'center',
      display: 'flex',
      position: 'relative',
    },
    control: {
      alignItems: 'center',
      background: 'bg.emphasized',
      borderRadius: 'full',
      cursor: 'pointer',
      display: 'inline-flex',
      flexShrink: '0',
      transitionDuration: 'normal',
      transitionProperty: 'background',
      transitionTimingFunction: 'default',
      _checked: {
        background: 'colorPalette.default',
      },
    },
    label: {
      color: 'fg.default',
      fontWeight: 'medium',
    },
    thumb: {
      background: 'bg.default',
      borderRadius: 'full',
      boxShadow: 'xs',
      transitionDuration: 'normal',
      transitionProperty: 'transform, background',
      transitionTimingFunction: 'default',
      _checked: {
        transform: 'translateX(100%)',
        background: { _light: 'bg.default', _dark: 'colorPalette.fg' },
      },
    },
  },
  defaultVariants: {
    size: 'md',
  },
  variants: {
    size: {
      sm: {
        root: {
          gap: '2',
        },
        control: {
          width: '7',
          p: '0.5',
        },
        thumb: {
          width: '3',
          height: '3',
        },
        label: {
          textStyle: 'sm',
        },
      },
      md: {
        root: {
          gap: '3',
        },
        control: {
          width: '9',
          p: '0.5',
        },
        thumb: {
          width: '4',
          height: '4',
        },
        label: {
          textStyle: 'md',
        },
      },
      lg: {
        root: {
          gap: '4',
        },
        control: {
          width: '11',
          p: '0.5',
        },
        thumb: {
          width: '5',
          height: '5',
        },
        label: {
          textStyle: 'lg',
        },
      },
    },
  },
})