Specialized input and selection components providing advanced interaction patterns, file handling, and binary controls with consistent Carbon Design System styling.
Binary state control component distinct from Switch, offering user-friendly on/off selection with customizable labels.
/**
* Binary toggle component with custom labels for on/off states
*/
interface ToggleProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'aria-labelledby' | 'aria-checked' | 'type' | 'role' | 'id' | 'size' | 'onClick' | 'onToggle'> {
/** Reference another element's id for labeling this toggle */
'aria-labelledby'?: string;
/** Unique identifier for the underlying button (required) */
id: string;
/** Label for the "off" position */
labelA?: string;
/** Label for the "on" position */
labelB?: string;
/** Main label text for screen readers */
labelText?: string;
/** Hide label but replace side labels with labelText */
hideLabel?: boolean;
/** Click/keyboard event handler */
onClick?: React.MouseEventHandler<HTMLDivElement> | React.KeyboardEventHandler<HTMLDivElement>;
/** Toggle state change callback */
onToggle?: (checked: boolean) => void;
/** Toggle size variant */
size?: 'sm' | 'md';
/** Read-only state */
readOnly?: boolean;
/** Default toggle state */
defaultToggled?: boolean;
/** Controlled toggle state */
toggled?: boolean;
/** Disabled state */
disabled?: boolean;
/** Additional CSS classes */
className?: string;
}Usage Examples:
import { Toggle } from "@carbon/react";
// Basic toggle
<Toggle
id="basic-toggle"
labelText="Enable notifications"
defaultToggled={false}
/>
// Custom labels
<Toggle
id="feature-toggle"
labelA="Disabled"
labelB="Enabled"
labelText="Feature toggle"
onToggle={(checked) => console.log('Toggled:', checked)}
/>
// Small size with controlled state
<Toggle
id="small-toggle"
size="sm"
toggled={isEnabled}
onToggle={setIsEnabled}
readOnly={isReadOnly}
/>Range input component with single or dual handle support, validation, and customizable formatting.
/**
* Range slider with single or dual handle support
*/
interface SliderProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'onBlur'>, TranslateWithId<TranslationKey, { correctedValue?: string }> {
/** Aria label for the input */
ariaLabelInput?: string;
/** Aria label for upper handle (dual handle mode) */
unstable_ariaLabelInputUpper?: string;
/** Child elements */
children?: React.ReactNode;
/** CSS class name */
className?: string;
/** Disabled state */
disabled?: boolean;
/** Label formatter function */
formatLabel?: (value: number, label: string | undefined) => string;
/** Hide number input box */
hideTextInput?: boolean;
/** Input element ID */
id?: string;
/** Input type attribute */
inputType?: string;
/** Invalid state */
invalid?: boolean;
/** Invalid state message */
invalidText?: React.ReactNode;
/** Slider label */
labelText?: React.ReactNode;
/** Hide label visually */
hideLabel?: boolean;
/** Maximum value (required) */
max: number;
/** Maximum value label */
maxLabel?: string;
/** Minimum value (required) */
min: number;
/** Minimum value label */
minLabel?: string;
/** Input name attribute */
name?: string;
/** Upper handle name (dual handle mode) */
unstable_nameUpper?: string;
/** Blur event handler */
onBlur?: (data: { value: string; handlePosition: HandlePosition | undefined }) => void;
/** Value change callback */
onChange?: (data: { value: SliderProps['value']; valueUpper: SliderProps['unstable_valueUpper'] }) => void;
/** Input key up handler */
onInputKeyUp?: React.KeyboardEventHandler<HTMLInputElement>;
/** Handle release callback */
onRelease?: (data: { value: SliderProps['value']; valueUpper: SliderProps['unstable_valueUpper'] }) => void;
/** Read-only state */
readOnly?: boolean;
/** Required field */
required?: boolean;
/** Step increment */
step?: number;
/** Shift+arrow key step multiplier */
stepMultiplier?: number;
/** Current value (required) */
value: number;
/** Upper bound value (dual handle mode) */
unstable_valueUpper?: number;
/** Warning state */
warn?: boolean;
/** Warning message */
warnText?: React.ReactNode;
}
/**
* Slider loading skeleton
*/
interface SliderSkeletonProps {
/** Hide text input in skeleton */
hideLabel?: boolean;
}Usage Examples:
import { Slider, SliderSkeleton } from "@carbon/react";
// Basic slider
<Slider
min={0}
max={100}
value={25}
labelText="Volume"
onChange={({ value }) => setValue(value)}
/>
// Range slider with dual handles
<Slider
min={0}
max={1000}
value={200}
unstable_valueUpper={800}
labelText="Price range"
minLabel="$0"
maxLabel="$1000"
formatLabel={(value, label) => `$${value}${label ? ` ${label}` : ''}`}
onChange={({ value, valueUpper }) => setPriceRange([value, valueUpper])}
/>
// Slider with validation
<Slider
min={0}
max={10}
value={value}
step={0.5}
invalid={value < 2}
invalidText="Minimum value is 2"
hideTextInput={true}
/>
// Loading skeleton
<SliderSkeleton />Search component with expand/collapse behavior for space-efficient interfaces.
/**
* Search component with expandable behavior
*/
interface ExpandableSearchProps extends SearchProps {
/** Blur event handler */
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
/** Value change handler */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/** Expand event handler */
onExpand?: () => void;
/** Key down handler */
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
/** Default input value */
defaultValue?: string;
/** Controlled expanded state */
isExpanded?: boolean;
}Usage Examples:
import { ExpandableSearch } from "@carbon/react";
// Basic expandable search
<ExpandableSearch
labelText="Search products"
placeholder="Type to search..."
onChange={(event) => setSearchValue(event.target.value)}
/>
// Controlled expanded state
<ExpandableSearch
isExpanded={isSearchExpanded}
onExpand={() => setIsSearchExpanded(true)}
onBlur={() => setIsSearchExpanded(false)}
defaultValue={initialSearchTerm}
/>Comprehensive file upload system with drag-and-drop support, validation, and progress tracking.
/**
* Complete file upload component with integrated file management
*/
interface FileUploaderProps extends React.HTMLAttributes<HTMLSpanElement> {
/** Accepted file types */
accept?: string[];
/** Upload button style */
buttonKind?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'danger--primary' | 'danger--ghost' | 'danger--tertiary' | 'tertiary';
/** Button label for screen readers */
buttonLabel?: string;
/** CSS class name */
className?: string;
/** Disabled state */
disabled?: boolean;
/** File status indicator (required) */
filenameStatus: 'edit' | 'complete' | 'uploading';
/** Icon description for screen readers */
iconDescription?: string;
/** Description text */
labelDescription?: string;
/** Title text */
labelTitle?: string;
/** Multiple file selection */
multiple?: boolean;
/** Input name attribute */
name?: string;
/** File change event handler */
onChange?: (event: any, data?: FileChangeData) => void;
/** Click event handler */
onClick?: (event: any) => void;
/** File deletion handler */
onDelete?: (event: any, data?: FileDeleteData) => void;
/** Component size */
size?: 'sm' | 'small' | 'md' | 'field' | 'lg';
}
/**
* File upload button component
*/
interface FileUploaderButtonProps extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'onChange' | 'tabIndex'> {
/** Accepted file types */
accept?: string[];
/** Button style variant */
buttonKind?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'danger--primary' | 'danger--ghost' | 'danger--tertiary' | 'tertiary';
/** CSS class name */
className?: string;
/** Disable label updates */
disableLabelChanges?: boolean;
/** Disabled state */
disabled?: boolean;
/** Input ID */
id?: string;
/** Button label text */
labelText?: React.ReactNode;
/** Multiple file selection */
multiple?: boolean;
/** Input name */
name?: string;
/** Change handler */
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/** Click handler */
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
/** Accessibility role */
role?: string;
/** Button size */
size?: 'sm' | 'small' | 'field' | 'md' | 'lg';
}
/**
* Drag-and-drop file upload container
*/
interface FileUploaderDropContainerProps extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'tabIndex'> {
/** Accepted file types */
accept?: string[];
/** CSS class name */
className?: string;
/** Disabled state */
disabled?: boolean;
/** Input ID */
id?: string;
/** Label text */
labelText?: string;
/** Multiple file selection */
multiple?: boolean;
/** Input name */
name?: string;
/** File addition handler */
onAddFiles?: (event: React.SyntheticEvent<HTMLElement>, content: { addedFiles: File[] }) => void;
/** Click handler */
onClick?: () => void;
/** File type validation pattern */
pattern?: string;
/** Inner button ref */
innerRef?: React.Ref<HTMLButtonElement>;
}
/**
* Individual file item component
*/
interface FileUploaderItemProps extends React.HTMLAttributes<HTMLSpanElement> {
/** Error message body */
errorBody?: string;
/** Error message subject */
errorSubject?: string;
/** Status icon description */
iconDescription?: string;
/** Invalid file state */
invalid?: boolean;
/** File name */
name?: string;
/** File addition handler */
onAddFiles?: (event: React.ChangeEvent<HTMLInputElement>) => void;
/** File deletion handler */
onDelete?: (event: React.SyntheticEvent<HTMLElement>, opts: { uuid: string }) => void;
/** Component size */
size?: 'sm' | 'md' | 'lg';
/** File status */
status?: 'uploading' | 'edit' | 'complete';
/** Unique identifier */
uuid?: string;
}
/**
* File status indicator component
*/
interface FilenameProps extends Omit<React.HTMLAttributes<HTMLElement> & React.SVGAttributes<React.ReactSVGElement>, 'tabIndex' | 'type'> {
/** Error description ID */
'aria-describedby'?: string;
/** Icon description */
iconDescription?: string;
/** Invalid state */
invalid?: boolean;
/** File name */
name?: string;
/** Upload status */
status?: 'edit' | 'complete' | 'uploading';
/** Tab index */
tabIndex?: number;
}
/**
* File uploader handle for imperative operations
*/
interface FileUploaderHandle {
/** Clear all files */
clearFiles: () => void;
/** Get current files (with feature flag) */
getCurrentFiles?: () => FileItem[];
}
/**
* File change data structure
*/
interface FileChangeData {
/** Newly added files */
addedFiles: FileItem[];
/** Removed files */
removedFiles: FileItem[];
/** Current file list */
currentFiles: FileItem[];
/** Type of change */
action: 'add' | 'remove' | 'clear';
}
/**
* File deletion data structure
*/
interface FileDeleteData {
/** Deleted file info */
deletedFile: FileItem;
/** Remaining files */
remainingFiles: FileItem[];
}Usage Examples:
import {
FileUploader,
FileUploaderButton,
FileUploaderDropContainer,
FileUploaderItem,
Filename
} from "@carbon/react";
// Complete file uploader
<FileUploader
accept={['.jpg', '.png', '.pdf']}
buttonLabel="Add files"
labelTitle="Upload documents"
labelDescription="Only .jpg, .png and .pdf files at 500mb or less"
filenameStatus="edit"
multiple
onChange={(event, data) => {
console.log('Files changed:', data?.currentFiles);
}}
onDelete={(event, data) => {
console.log('File deleted:', data?.deletedFile);
}}
/>
// Standalone upload button
<FileUploaderButton
buttonKind="primary"
labelText="Choose files"
multiple
accept={['image/*']}
onChange={(event) => {
const files = Array.from(event.target.files || []);
handleFileSelection(files);
}}
/>
// Drag-and-drop container
<FileUploaderDropContainer
accept={['.csv', '.xlsx']}
labelText="Drag and drop files here or click to upload"
multiple
onAddFiles={(event, { addedFiles }) => {
setFiles(prevFiles => [...prevFiles, ...addedFiles]);
}}
/>
// Individual file item
<FileUploaderItem
name="document.pdf"
status="complete"
uuid="file-123"
invalid={false}
onDelete={(event, { uuid }) => {
removeFile(uuid);
}}
/>
// File status indicator
<Filename
name="upload.jpg"
status="uploading"
iconDescription="Uploading file"
/>// Main components
import {
Toggle,
Slider,
SliderSkeleton,
ExpandableSearch,
FileUploader,
FileUploaderButton,
FileUploaderDropContainer,
FileUploaderItem,
Filename
} from "@carbon/react";
// Type definitions
import type {
ToggleProps,
SliderProps,
SliderSkeletonProps,
FileUploaderProps,
FileUploaderButtonProps,
FileUploaderDropContainerProps,
FileUploaderItemProps,
FilenameProps,
FileUploaderHandle,
FileChangeData,
FileDeleteData
} from "@carbon/react";File Upload System: FileUploader orchestrates FileUploaderButton, FileUploaderItem, and Filename components. FileUploaderDropContainer provides an alternative drag-and-drop interface.
Toggle vs Switch: Toggle is a binary control with customizable labels and different interaction patterns compared to Switch, which is a simple on/off control.
Slider Capabilities: Supports both single-value and range (dual-handle) modes with extensive validation and formatting options.
ExpandableSearch Behavior: Automatically expands on focus and collapses when empty and loses focus, with escape key support for clearing/collapsing.