Kosorikōsori alpha

Toggle

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

Installation

Install the primitive

Install the @radix-ui/react-toggle package.

npm install @radix-ui/react-toggle

Copy-paste the component

Copy and paste the component code in a .tsx file.

import type { VariantProps } from 'tailwind-variants';
import { forwardRef } from 'react';
import { Root } from '@radix-ui/react-toggle';
import { clsx } from 'clsx/lite';
import { tv } from 'tailwind-variants';
 
export const toggleStyles = tv({
  base: clsx(
    'inline-flex items-center justify-center font-medium outline-none transition-colors duration-200',
    'focus-visible:ring-4',
    'disabled:cursor-not-allowed',
  ),
  variants: {
    variant: {
      ghost: clsx(
        'hover:bg-grey-bg-hover',
        'active:bg-grey-bg-active',
        'data-[state=on]:bg-grey-bg-active',
        'focus-visible:ring-grey-focus-ring',
        'disabled:text-grey-solid',
        'disabled:hover:bg-transparent',
      ),
      outline: clsx(
        'border border-grey-border',
        'hover:border-grey-border-hover hover:bg-grey-bg-hover',
        'hover:border-grey-border-hover active:bg-grey-bg-active',
        'data-[state=on]:border-grey-border-hover data-[state=on]:bg-grey-bg-active',
        'focus-visible:ring-grey-focus-ring',
        'disabled:border-grey-line disabled:bg-grey-bg disabled:text-grey-solid',
      ),
    },
    size: {
      small: clsx('h-8 gap-x-1.5 rounded-lg px-2 text-xs', '[&_svg]:size-3.5'),
      medium: clsx('h-9 gap-x-2 rounded-lg px-3 text-sm', '[&_svg]:size-4'),
      large: clsx('h-10 gap-x-2.5 rounded-xl px-3 text-md', '[_&svg]:size-5'),
    },
    icon: {
      true: '',
    },
  },
  compoundVariants: [
    {
      size: 'small',
      icon: true,
      class: 'w-8 px-0',
    },
    {
      size: 'medium',
      icon: true,
      class: 'w-9 px-0',
    },
    {
      size: 'large',
      icon: true,
      class: 'w-10 px-0',
    },
  ],
  defaultVariants: {
    variant: 'ghost',
    size: 'medium',
  },
});
 
type ToggleRef = React.ElementRef<typeof Root>;
type ToggleRadixProps = React.ComponentPropsWithoutRef<typeof Root>;
export type ToggleVariants = VariantProps<typeof toggleStyles>;
type ToggleProps = object & ToggleRadixProps & ToggleVariants;
 
/**
 * Toggle component that allows users to switch between on and off states.
 *
 * @param {ToggleProps} props - The props for the Toggle component.
 * @param {'ghost' | 'outline'} [variant='ghost'] - The variant style of the toggle (e.g. 'ghost', 'outline').
 * @param {'small' | 'medium' | 'large'} [size='medium'] - The size of the toggle (e.g. 'small', 'medium', 'large').
 * @param {boolean} [icon=false] - If true, adjusts the button size for icon-only usage.
 *
 * @example
 * <Toggle>Toggle</Toggle>
 *
 * @see {@link https://dub.sh/ui-toggle Toggle Docs} for further information.
 */
export const Toggle = forwardRef<ToggleRef, ToggleProps>(
  ({ className, variant, size, icon, ...props }, ref) => (
    <Root
      ref={ref}
      className={toggleStyles({ className, size, variant, icon })}
      {...props}
    />
  ),
);
 
Toggle.displayName = Root.displayName;

Update import paths

Update the @kosori/ui import paths to fit your project structure, for example, using ~/components/ui.

Usage

import { Toggle } from '~/components/ui/toggle';
<Toggle>Toggle</Toggle>

Reference

PropTypeDefault
size
enum
medium
variant
enum
ghost
icon
boolean
false

Examples

Variants

Sizes

With Text

Disabled

On this page