Toggle Group
Installation
Add the following Soul components
The toggle-group component uses the field-error and label components. Make sure you have added them to your project.
Install the following dependencies
npm install clsx @radix-ui/react-toggle-group
Copy and paste the following code into your project
form/toggle-group/index.tsx
'use client';import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';import { clsx } from 'clsx';import { ComponentPropsWithoutRef, useId } from 'react';import { FieldError } from '@/vibes/soul/form/field-error';import { Label } from '@/vibes/soul/form/label';export type ToggleGroupProps = ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> & { label?: string; options: Option[]; errors?: string[] | null; colorScheme?: 'light' | 'dark'; hideLabel?: boolean;};interface Option { value: string; label: string; disabled?: boolean;}/** * This component supports various CSS variables for theming. Here's a comprehensive list, along * with their default values: * * ```css * :root { * --toggle-group-light-focus: hsl(var(--primary)); * --toggle-group-light-border: hsl(var(--contrast-100)); * --toggle-group-light-on-border: hsl(var(--foreground)); * --toggle-group-light-on-background: hsl(var(--foreground)); * --toggle-group-light-off-background: hsl(var(--background)); * --toggle-group-light-off-text: hsl(var(--foreground)); * --toggle-group-light-on-text: hsl(var(--background)); * --toggle-group-light-off-border-hover: hsl(var(--contrast-200)); * --toggle-group-light-off-background-hover: hsl(var(--contrast-100)); * --toggle-group-dark-focus: hsl(var(--primary)); * --toggle-group-dark-border: hsl(var(--contrast-500)); * --toggle-group-dark-on-border: hsl(var(--background)); * --toggle-group-dark-on-background: hsl(var(--background)); * --toggle-group-dark-off-background: hsl(var(--foreground)); * --toggle-group-dark-off-text: hsl(var(--background)); * --toggle-group-dark-on-text: hsl(var(--foreground)); * --toggle-group-dark-off-border-hover: hsl(var(--contrast-400)); * --toggle-group-dark-off-background-hover: hsl(var(--contrast-500)); * } * ``` */export const ToggleGroup = ({ label, options, errors = null, className = '', colorScheme = 'light', hideLabel = true, ...rest}: ToggleGroupProps) => { const id = useId(); return ( <div className={clsx('w-full', className)}> {label !== undefined && label !== '' && ( <Label className={clsx(hideLabel ? 'sr-only' : 'mb-2')} colorScheme={colorScheme} id={id}> {label} </Label> )} <ToggleGroupPrimitive.Root {...rest} aria-labelledby={id} className="flex flex-wrap gap-2"> {options.map((option) => ( <ToggleGroupPrimitive.Item aria-label={option.label} className={clsx( 'h-12 whitespace-nowrap rounded-full border px-4 font-body text-sm font-normal leading-normal transition-colors focus-visible:outline-0 focus-visible:ring-2 data-[disabled]:pointer-events-none data-[disabled]:opacity-50', { light: 'border-[var(--toggle-group-light-border,hsl(var(--contrast-100)))] ring-[var(--toggle-group-light-focus,hsl(var(--primary)))] data-[state=on]:border-[var(--toggle-group-light-on-border,hsl(var(--foreground)))] data-[state=off]:bg-[var(--toggle-group-light-off-background,hsl(var(--background)))] data-[state=on]:bg-[var(--toggle-group-light-on-background,hsl(var(--foreground)))] data-[state=off]:text-[var(--toggle-group-light-off-text,hsl(var(--foreground)))] data-[state=on]:text-[var(--toggle-group-light-on-text,hsl(var(--background)))] data-[state=off]:hover:border-[var(--toggle-group-light-off-border-hover,hsl(var(--contrast-200)))] data-[state=off]:hover:bg-[var(--toggle-group-light-off-background-hover,hsl(var(--contrast-100)))]', dark: 'border-[var(--toggle-group-dark-border,hsl(var(--contrast-500)))] ring-[var(--toggle-group-dark-focus,hsl(var(--primary)))] data-[state=on]:border-[var(--toggle-group-dark-on-border,hsl(var(--background)))] data-[state=off]:bg-[var(--toggle-group-dark-off-background,hsl(var(--foreground)))] data-[state=on]:bg-[var(--toggle-group-dark-on-background,hsl(var(--background)))] data-[state=off]:text-[var(--toggle-group-dark-off-text,hsl(var(--background)))] data-[state=on]:text-[var(--toggle-group-dark-on-text,hsl(var(--foreground)))] data-[state=off]:hover:border-[var(--toggle-group-dark-off-border-hover,hsl(var(--contrast-400)))] data-[state=off]:hover:bg-[var(--toggle-group-dark-off-background-hover,hsl(var(--contrast-500)))]', }[colorScheme], )} disabled={option.disabled} key={option.value} value={option.value} > {option.label} </ToggleGroupPrimitive.Item> ))} </ToggleGroupPrimitive.Root> {errors?.map((error) => ( <FieldError className="mt-2" key={error}> {error} </FieldError> ))} </div> );};
Usage
import { ToggleGroup } from '@/vibes/soul/form/toggle-group';function Usage() { return ( <ToggleGroup label="Options" options={[ { value: 'option-1', label: ' Option 1' }, { value: 'option-2', label: ' Option 2' }, { value: 'option-3', label: ' Option 3' }, ]} type="multiple" /> );}
API Reference
This component uses the Toggle Group component from Radix UI. Refer to the Radix Toggle Group documentation for more information.
ToggleGroupProps
Prop | Type | Default |
---|---|---|
label | string | |
options* | Option[] | |
errors | string[] | null | null |
colorScheme | 'light' | 'dark' | 'light' |
hideLabel | boolean | false |
Option
Prop | Type | Default |
---|---|---|
value* | string | |
label* | string | |
disabled | boolean |
CSS Variables
This component supports various CSS variables for theming. Here's a comprehensive list.
:root { --toggle-group-light-focus: hsl(var(--primary)); --toggle-group-light-border: hsl(var(--border-contrast-100)); --toggle-group-light-on-border: hsl(var(--foreground)); --toggle-group-light-on-background: hsl(var(--foreground)); --toggle-group-light-off-background: hsl(var(--background)); --toggle-group-light-off-text: hsl(var(--foreground)); --toggle-group-light-on-text: hsl(var(--background)); --toggle-group-light-off-border-hover: hsl(var(--contrast-200)); --toggle-group-light-off-background-hover: hsl(var(--contrast-100)); --toggle-group-dark-focus: hsl(var(--primary)); --toggle-group-dark-border: hsl(var(--border-contrast-500)); --toggle-group-dark-on-border: hsl(var(--background)); --toggle-group-dark-on-background: hsl(var(--background)); --toggle-group-dark-off-background: hsl(var(--foreground)); --toggle-group-dark-off-text: hsl(var(--background)); --toggle-group-dark-on-text: hsl(var(--foreground)); --toggle-group-dark-off-border-hover: hsl(var(--contrast-400)); --toggle-group-dark-off-background-hover: hsl(var(--contrast-500));}