forked from cerc-io/snowballtools-base
* ⚡️ feat: create switch component * 📝 docs: add switch to the example page * 🔧 chore: install `@radix-ui/react-switch` * 🎨 style: add inset shadow * 🎨 style: addjust input outline when error and focus
86 lines
1.9 KiB
TypeScript
86 lines
1.9 KiB
TypeScript
import React, { type ComponentPropsWithoutRef } from 'react';
|
|
import { type SwitchProps as SwitchRadixProps } from '@radix-ui/react-switch';
|
|
import * as SwitchRadix from '@radix-ui/react-switch';
|
|
|
|
import { switchTheme, type SwitchVariants } from './Switch.theme';
|
|
|
|
interface SwitchProps
|
|
extends Omit<SwitchRadixProps, 'checked'>,
|
|
SwitchVariants {
|
|
/**
|
|
* The label of the switch.
|
|
*/
|
|
label?: string;
|
|
/**
|
|
* The description of the switch.
|
|
*/
|
|
description?: string;
|
|
/**
|
|
* Custom wrapper props for the switch.
|
|
*/
|
|
wrapperProps?: ComponentPropsWithoutRef<'div'>;
|
|
/**
|
|
* Function that is called when the checked state of the switch changes.
|
|
* @param checked The new checked state of the switch.
|
|
*/
|
|
onCheckedChange?(checked: boolean): void;
|
|
}
|
|
|
|
/**
|
|
* A switch is a component used for toggling between two states.
|
|
*/
|
|
export const Switch = ({
|
|
className,
|
|
checked,
|
|
label,
|
|
description,
|
|
disabled,
|
|
name,
|
|
wrapperProps,
|
|
fullWidth,
|
|
...props
|
|
}: SwitchProps) => {
|
|
const {
|
|
wrapper,
|
|
switch: switchClass,
|
|
thumb,
|
|
label: labelClass,
|
|
description: descriptionClass,
|
|
} = switchTheme({
|
|
checked,
|
|
disabled,
|
|
fullWidth,
|
|
});
|
|
|
|
const switchComponent = (
|
|
<SwitchRadix.Root
|
|
{...props}
|
|
checked={checked}
|
|
disabled={disabled}
|
|
className={switchClass({ className })}
|
|
>
|
|
<SwitchRadix.Thumb className={thumb()} />
|
|
</SwitchRadix.Root>
|
|
);
|
|
|
|
// If a label is provided, wrap the switch in a label element.
|
|
if (label) {
|
|
return (
|
|
<div
|
|
{...wrapperProps}
|
|
className={wrapper({ className: wrapperProps?.className })}
|
|
>
|
|
<label className={labelClass()} htmlFor={name}>
|
|
{label}
|
|
{description && (
|
|
<span className={descriptionClass()}>{description}</span>
|
|
)}
|
|
</label>
|
|
{switchComponent}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return switchComponent;
|
|
};
|