A control that indicates whether a setting is on or off.
Installation
npx shadcn@latest add @caprice/switchpnpm dlx shadcn@latest add @caprice/switchyarn dlx shadcn@latest add @caprice/switchbunx shadcn@latest add @caprice/switchnpm install @caprice-ui/reactpnpm add @caprice-ui/reactyarn add @caprice-ui/reactbun add @caprice-ui/reactInstall the following dependencies:
npm install @base-ui/react lucide-reactpnpm add @base-ui/react lucide-reactyarn add @base-ui/react lucide-reactbun add @base-ui/react lucide-reactAdd a cn helper
import { defineConfig, getSchema, type VariantProps } from 'cva';
import { twMerge } from 'tailwind-merge';
export const { cva, cx: cn } = defineConfig({
hooks: {
onComplete: (className: string) => twMerge(className),
},
});
export type { VariantProps };
export { getSchema };
Copy and paste the following code into your project.
'use client';
import { mergeProps } from '@base-ui/react';
import { Switch as SwitchPrimitive } from '@base-ui/react/switch';
import { type PressEvents, usePress } from 'react-aria';
import { cva, type VariantProps } from '@/lib/utils';
const switchVariants = cva({
base: 'group/switch peer inline-flex shrink-0 items-center rounded-full shadow-xs transition-[shadow,background-color] focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2 data-unchecked:data-pressed:bg-primary/25 data-disabled:cursor-not-allowed data-checked:bg-primary data-unchecked:bg-input/80 data-disabled:opacity-50 data-unchecked:hover:bg-input',
variants: {
size: {
sm: 'h-6 w-12',
md: 'h-8 w-16',
},
},
defaultVariants: {
size: 'sm',
},
});
export const switchThumbVariants = cva({
base: 'pointer-events-none block rounded-full border-2 border-ring/80 bg-background shadow-sm transition-[translate,transform,width,border-color] data-unchecked:translate-x-0 data-checked:border-primary',
variants: {
size: {
sm: 'size-6 data-checked:translate-x-6 group-data-pressed/switch:not-data-disabled:w-6.5 data-checked:group-data-pressed/switch:translate-x-5.5',
md: 'size-8 data-checked:translate-x-8 group-data-pressed/switch:not-data-disabled:w-8.5 data-checked:group-data-pressed/switch:translate-x-7.5',
},
},
defaultVariants: {
size: 'sm',
},
});
/**
* Represents the switch itself.
* Renders a `<span>` element and a hidden `<input>` beside.
*
* Documentation: [Caprice UI Switch](https://caprice-ui.com/docs/components/switch)
*
* API Reference: [Base UI Switch](https://base-ui.com/react/components/switch)
*/
export namespace Switch {
export type Variants = VariantProps<typeof switchVariants>;
export type Props = React.ComponentProps<typeof SwitchPrimitive.Root> &
PressEvents &
Switch.Variants;
export type State = SwitchPrimitive.Root.State;
export type ChangeEventDetails = SwitchPrimitive.Root.ChangeEventDetails;
export type ChangeEventReason = SwitchPrimitive.Root.ChangeEventReason;
}
export function Switch({
className,
size = 'sm',
// PressEvents
onPress,
onPressStart,
onPressChange,
onPressEnd,
onPressUp,
onClick,
...props
}: Switch.Props) {
const { pressProps, isPressed } = usePress({
onPress,
onPressStart,
onPressChange,
onPressEnd,
onPressUp,
onClick,
isDisabled: props.disabled,
});
const defaultProps: Switch.Props & { 'data-slot'?: string } = {
'data-slot': 'button',
className: switchVariants({ size, className }),
};
return (
<SwitchPrimitive.Root
data-pressed={isPressed ? '' : undefined}
{...mergeProps(defaultProps, pressProps, props)}
>
<SwitchPrimitive.Thumb className={switchThumbVariants({ size })} data-slot="switch-thumb" />
</SwitchPrimitive.Root>
);
}
Update the import paths to match your project setup.
Usage
import { Switch } from "@/components/caprice-ui/switch"import { Switch } from "@caprice-ui/react/switch"<Switch />Examples
Size
Disabled
Card Label
Last updated on