Beautiful and modern React UI library with comprehensive components, theming, and accessibility support.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
NextUI provides a comprehensive set of form input components with built-in validation, accessibility support, and consistent styling across different input types.
A versatile text input component with support for labels, validation, helper text, and various visual states.
interface InputProps {
/** Input content and elements */
children?: React.ReactNode;
/** Input label */
label?: React.ReactNode;
/** Current input value */
value?: string;
/** Default value for uncontrolled mode */
defaultValue?: string;
/** Placeholder text */
placeholder?: string;
/** Helper description text */
description?: React.ReactNode;
/** Error message content */
errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);
/** Validation function */
validate?: (value: string) => ValidationError | true | null | undefined;
/** Validation behavior */
validationBehavior?: "aria" | "native";
/** Validation state */
validationState?: "valid" | "invalid";
/** Whether input is required */
isRequired?: boolean;
/** Whether input is read-only */
isReadOnly?: boolean;
/** Whether input is disabled */
isDisabled?: boolean;
/** Whether input is invalid */
isInvalid?: boolean;
/** Base container ref */
baseRef?: React.RefObject<HTMLDivElement>;
/** Whether to show helper content */
hasHelper?: boolean;
/** Input size variant */
size?: "sm" | "md" | "lg";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Visual variant */
variant?: "flat" | "bordered" | "underlined" | "faded";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Label placement */
labelPlacement?: "inside" | "outside" | "outside-left";
/** Whether input takes full width */
fullWidth?: boolean;
/** Whether to show clear button */
isClearable?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Input type */
type?: "text" | "email" | "password" | "search" | "tel" | "url" | "number";
/** Start content (icon, etc.) */
startContent?: React.ReactNode;
/** End content (icon, button, etc.) */
endContent?: React.ReactNode;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<InputSlots>;
/** Value change handler */
onValueChange?: (value: string) => void;
/** Clear button press handler */
onClear?: () => void;
}
type InputSlots =
| "base" | "mainWrapper" | "inputWrapper" | "innerWrapper"
| "input" | "clearButton" | "label" | "description"
| "errorMessage" | "helperWrapper";
function Input(props: InputProps): JSX.Element;
/**
* Hook for Input state management
*/
function useInput(props: InputProps): {
Component: React.ElementType;
label?: React.ReactNode;
description?: React.ReactNode;
errorMessage?: React.ReactNode;
isInvalid: boolean;
validationErrors: string[];
validationDetails: ValidationDetails;
slots: Record<InputSlots, string>;
classNames: SlotsToClasses<InputSlots>;
getBaseProps: () => any;
getLabelProps: () => any;
getInputProps: () => any;
getInputWrapperProps: () => any;
getInnerWrapperProps: () => any;
getMainWrapperProps: () => any;
getClearButtonProps: () => any;
getDescriptionProps: () => any;
getErrorMessageProps: () => any;
};Input Usage Examples:
import { Input } from "@nextui-org/react";
import { SearchIcon, EyeFilledIcon, EyeSlashFilledIcon } from "@heroicons/react/24/solid";
function InputExamples() {
const [isVisible, setIsVisible] = useState(false);
const [value, setValue] = useState("");
const toggleVisibility = () => setIsVisible(!isVisible);
const validateEmail = (value: string) => {
return value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i);
};
const isInvalid = useMemo(() => {
if (value === "") return false;
return validateEmail(value) ? false : true;
}, [value]);
return (
<div className="space-y-4">
{/* Basic input */}
<Input
type="text"
label="Name"
placeholder="Enter your name"
labelPlacement="outside"
/>
{/* Email input with validation */}
<Input
value={value}
onValueChange={setValue}
isInvalid={isInvalid}
label="Email"
variant="bordered"
placeholder="Enter your email"
description="We'll never share your email with anyone else."
errorMessage={isInvalid && "Please enter a valid email"}
color={isInvalid ? "danger" : "success"}
className="max-w-xs"
/>
{/* Password input with toggle visibility */}
<Input
label="Password"
variant="bordered"
placeholder="Enter your password"
endContent={
<button className="focus:outline-none" type="button" onClick={toggleVisibility}>
{isVisible ? (
<EyeSlashFilledIcon className="text-2xl text-default-400 pointer-events-none" />
) : (
<EyeFilledIcon className="text-2xl text-default-400 pointer-events-none" />
)}
</button>
}
type={isVisible ? "text" : "password"}
className="max-w-xs"
/>
{/* Search input with icon */}
<Input
label="Search"
isClearable
radius="lg"
placeholder="Type to search..."
startContent={
<SearchIcon className="text-black/50 mb-0.5 dark:text-white/90 text-slate-400 pointer-events-none flex-shrink-0" />
}
/>
</div>
);
}Multi-line text input component with automatic resizing and validation support.
interface TextAreaProps {
/** Textarea content */
children?: React.ReactNode;
/** Textarea label */
label?: React.ReactNode;
/** Current textarea value */
value?: string;
/** Default value for uncontrolled mode */
defaultValue?: string;
/** Placeholder text */
placeholder?: string;
/** Helper description text */
description?: React.ReactNode;
/** Error message content */
errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);
/** Validation function */
validate?: (value: string) => ValidationError | true | null | undefined;
/** Validation behavior */
validationBehavior?: "aria" | "native";
/** Validation state */
validationState?: "valid" | "invalid";
/** Whether textarea is required */
isRequired?: boolean;
/** Whether textarea is read-only */
isReadOnly?: boolean;
/** Whether textarea is disabled */
isDisabled?: boolean;
/** Whether textarea is invalid */
isInvalid?: boolean;
/** Textarea size variant */
size?: "sm" | "md" | "lg";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Visual variant */
variant?: "flat" | "bordered" | "underlined" | "faded";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Label placement */
labelPlacement?: "inside" | "outside" | "outside-left";
/** Whether textarea takes full width */
fullWidth?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Minimum number of rows */
minRows?: number;
/** Maximum number of rows */
maxRows?: number;
/** Whether to cache height for performance */
cacheMeasurements?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<InputSlots>;
/** Value change handler */
onValueChange?: (value: string) => void;
}
function Textarea(props: TextAreaProps): JSX.Element;Textarea Usage Example:
import { Textarea } from "@nextui-org/react";
function TextareaExample() {
return (
<div className="space-y-4">
<Textarea
label="Description"
placeholder="Enter your description"
description="Provide a detailed description of your project"
className="max-w-xs"
/>
<Textarea
isRequired
label="Feedback"
labelPlacement="outside"
placeholder="Share your feedback..."
variant="bordered"
minRows={3}
maxRows={8}
className="max-w-lg"
/>
</div>
);
}Dropdown selection component with search, multiple selection, and custom item rendering support.
interface SelectProps<T = object> {
/** Select content and options */
children?: React.ReactNode;
/** Data items for dynamic rendering */
items?: Iterable<T>;
/** Select label */
label?: React.ReactNode;
/** Placeholder text when no selection */
placeholder?: string;
/** Helper description text */
description?: React.ReactNode;
/** Error message content */
errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);
/** Validation function */
validate?: (value: SelectValue<T>) => ValidationError | true | null | undefined;
/** Selection mode */
selectionMode?: "single" | "multiple";
/** Currently selected keys */
selectedKeys?: "all" | Iterable<React.Key>;
/** Default selected keys for uncontrolled mode */
defaultSelectedKeys?: "all" | Iterable<React.Key>;
/** Prevent empty selection */
disallowEmptySelection?: boolean;
/** Whether popover should flip to fit */
shouldFlip?: boolean;
/** Whether select is required */
isRequired?: boolean;
/** Whether select is invalid */
isInvalid?: boolean;
/** Whether select is disabled */
isDisabled?: boolean;
/** Whether select is in loading state */
isLoading?: boolean;
/** Select size variant */
size?: "sm" | "md" | "lg";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Visual variant */
variant?: "flat" | "bordered" | "underlined" | "faded";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Label placement */
labelPlacement?: "inside" | "outside" | "outside-left";
/** Whether select takes full width */
fullWidth?: boolean;
/** Popover placement */
placement?: Placement;
/** Start content (icon, etc.) */
startContent?: React.ReactNode;
/** End content (icon, button, etc.) */
endContent?: React.ReactNode;
/** Selector icon (dropdown arrow) */
selectorIcon?: React.ReactNode;
/** Disable animations */
disableAnimation?: boolean;
/** Disable selector icon animation */
disableSelectorIconRotation?: boolean;
/** Custom scroll reference */
scrollRef?: React.RefObject<HTMLElement>;
/** Listbox props */
listboxProps?: Partial<ListboxProps>;
/** Popover props */
popoverProps?: Partial<PopoverProps>;
/** Spinner props for loading state */
spinnerProps?: Partial<SpinnerProps>;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<SelectSlots>;
/** Selection change handler */
onSelectionChange?: (keys: Selection) => void;
/** Open state change handler */
onOpenChange?: (isOpen: boolean) => void;
/** Close handler */
onClose?: () => void;
}
type SelectSlots =
| "base" | "label" | "trigger" | "innerWrapper" | "selectorIcon"
| "value" | "listboxWrapper" | "listbox" | "popoverContent"
| "helperWrapper" | "description" | "errorMessage";
type SelectValue<T> = T | null | undefined;
function Select<T = object>(props: SelectProps<T>): JSX.Element;
/**
* Hook for Select state management
*/
function useSelect<T = object>(props: UseSelectProps<T>): {
Component: React.ElementType;
state: SelectState<T>;
slots: Record<SelectSlots, string>;
classNames: SlotsToClasses<SelectSlots>;
isOpen: boolean;
isLoading?: boolean;
getSelectProps: () => any;
getTriggerProps: () => any;
getValueProps: () => any;
getListboxProps: () => any;
getPopoverProps: () => any;
};
interface UseSelectProps<T> extends Omit<SelectProps<T>, 'children'> {
/** Trigger ref */
triggerRef?: React.RefObject<HTMLElement>;
/** Value ref */
valueRef?: React.RefObject<HTMLElement>;
/** Listbox ref */
listboxRef?: React.RefObject<HTMLElement>;
/** Popover ref */
popoverRef?: React.RefObject<HTMLDivElement>;
}Components for defining select options and sections.
// SelectItem is an alias for ListboxItem
interface SelectItemProps {
/** Item key identifier */
key?: React.Key;
/** Item text content */
children?: React.ReactNode;
/** Item text value for controlled components */
textValue?: string;
/** Whether item is disabled */
isDisabled?: boolean;
/** Whether to hide selected indicator */
hideSelectedIcon?: boolean;
/** Item start content (icon, avatar, etc.) */
startContent?: React.ReactNode;
/** Item end content (icon, badge, etc.) */
endContent?: React.ReactNode;
/** Item description text */
description?: React.ReactNode;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<ListboxItemSlots>;
}
// SelectSection is an alias for ListboxSection
interface SelectSectionProps {
/** Section title */
title?: React.ReactNode;
/** Section items */
children?: React.ReactNode;
/** Whether to hide divider */
hideDivider?: boolean;
/** Whether to show divider */
showDivider?: boolean;
/** Divider props */
dividerProps?: DividerProps;
/** Item heading */
heading?: React.ReactNode;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<ListboxSectionSlots>;
}
const SelectItem: React.FC<SelectItemProps>;
const SelectSection: React.FC<SelectSectionProps>;Select Usage Examples:
import { Select, SelectItem, SelectSection } from "@nextui-org/react";
function SelectExamples() {
const animals = [
{key: "cat", label: "Cat"},
{key: "dog", label: "Dog"},
{key: "elephant", label: "Elephant"},
{key: "lion", label: "Lion"},
{key: "tiger", label: "Tiger"},
];
const [selectedValue, setSelectedValue] = useState(new Set(["cat"]));
return (
<div className="space-y-4">
{/* Basic select */}
<Select
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.key}>
{animal.label}
</SelectItem>
))}
</Select>
{/* Multiple selection */}
<Select
label="Animals"
selectionMode="multiple"
placeholder="Select animals"
selectedKeys={selectedValue}
onSelectionChange={setSelectedValue}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.key}>
{animal.label}
</SelectItem>
))}
</Select>
{/* Select with sections */}
<Select
label="Pets by category"
placeholder="Select a pet"
className="max-w-xs"
>
<SelectSection title="Mammals">
<SelectItem key="cat">Cat</SelectItem>
<SelectItem key="dog">Dog</SelectItem>
</SelectSection>
<SelectSection title="Birds">
<SelectItem key="parrot">Parrot</SelectItem>
<SelectItem key="canary">Canary</SelectItem>
</SelectSection>
</Select>
{/* Dynamic items */}
<Select
items={animals}
label="Dynamic Animals"
placeholder="Select an animal"
className="max-w-xs"
>
{(item) => <SelectItem key={item.key}>{item.label}</SelectItem>}
</Select>
</div>
);
}Individual checkbox component with indeterminate state support and custom styling.
interface CheckboxProps {
/** Checkbox label content */
children?: React.ReactNode;
/** Checkbox value */
value?: string;
/** Whether checkbox is selected */
isSelected?: boolean;
/** Default selection state */
defaultSelected?: boolean;
/** Whether checkbox is indeterminate */
isIndeterminate?: boolean;
/** Whether checkbox is required */
isRequired?: boolean;
/** Whether checkbox is read-only */
isReadOnly?: boolean;
/** Whether checkbox is disabled */
isDisabled?: boolean;
/** Whether checkbox is invalid */
isInvalid?: boolean;
/** Validation state */
validationState?: "valid" | "invalid";
/** Checkbox size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Line through text when selected */
lineThrough?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Custom icon for checkbox */
icon?: React.ReactNode | ((props: CheckboxIconProps) => React.ReactNode);
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<CheckboxSlots>;
/** Selection change handler */
onValueChange?: (isSelected: boolean) => void;
}
type CheckboxSlots = "base" | "wrapper" | "icon" | "label";
function Checkbox(props: CheckboxProps): JSX.Element;
/**
* Hook for Checkbox state management
*/
function useCheckbox(props: CheckboxProps): {
Component: React.ElementType;
slots: Record<CheckboxSlots, string>;
classNames: SlotsToClasses<CheckboxSlots>;
isSelected: boolean;
isPressed: boolean;
isFocused: boolean;
isInvalid: boolean;
getBaseProps: () => any;
getWrapperProps: () => any;
getInputProps: () => any;
getLabelProps: () => any;
getIconProps: () => any;
};Customizable icon component for checkbox states.
interface CheckboxIconProps {
/** Icon data attributes */
"data-checked"?: string;
/** Whether checkbox is selected */
isSelected?: boolean;
/** Whether checkbox is indeterminate */
isIndeterminate?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Custom CSS class */
className?: string;
}
function CheckboxIcon(props: CheckboxIconProps): JSX.Element;Container for managing groups of related checkboxes with shared state and validation.
interface CheckboxGroupProps {
/** Group label */
label?: React.ReactNode;
/** Checkbox items */
children?: React.ReactNode;
/** Currently selected values */
value?: string[];
/** Default selected values */
defaultValue?: string[];
/** Group name attribute */
name?: string;
/** Group size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Border radius for all checkboxes */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Group orientation */
orientation?: "horizontal" | "vertical";
/** Whether group is required */
isRequired?: boolean;
/** Whether group is read-only */
isReadOnly?: boolean;
/** Whether group is disabled */
isDisabled?: boolean;
/** Whether group is invalid */
isInvalid?: boolean;
/** Validation state */
validationState?: "valid" | "invalid";
/** Helper description text */
description?: React.ReactNode;
/** Error message content */
errorMessage?: React.ReactNode;
/** Disable animations */
disableAnimation?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<CheckboxGroupSlots>;
/** Value change handler */
onValueChange?: (value: string[]) => void;
}
type CheckboxGroupSlots = "base" | "label" | "wrapper" | "description" | "errorMessage";
function CheckboxGroup(props: CheckboxGroupProps): JSX.Element;
/**
* Hook for CheckboxGroup state management
*/
function useCheckboxGroup(props: CheckboxGroupProps): {
Component: React.ElementType;
slots: Record<CheckboxGroupSlots, string>;
classNames: SlotsToClasses<CheckboxGroupSlots>;
groupState: CheckboxGroupState;
getGroupProps: () => any;
getLabelProps: () => any;
getWrapperProps: () => any;
getDescriptionProps: () => any;
getErrorMessageProps: () => any;
};Checkbox Usage Examples:
import { Checkbox, CheckboxGroup } from "@nextui-org/react";
function CheckboxExamples() {
const [selected, setSelected] = useState(["argentina"]);
return (
<div className="space-y-6">
{/* Individual checkboxes */}
<div className="space-y-2">
<Checkbox defaultSelected>Option 1</Checkbox>
<Checkbox isIndeterminate>Option 2</Checkbox>
<Checkbox isDisabled>Option 3</Checkbox>
</div>
{/* Checkbox group */}
<CheckboxGroup
label="Select countries"
color="secondary"
value={selected}
onValueChange={setSelected}
description="Choose your favorite countries"
>
<Checkbox value="argentina">Argentina</Checkbox>
<Checkbox value="venezuela">Venezuela</Checkbox>
<Checkbox value="brazil">Brazil</Checkbox>
<Checkbox value="colombia">Colombia</Checkbox>
</CheckboxGroup>
{/* Custom icon checkbox */}
<Checkbox
icon={<HeartIcon />}
color="danger"
defaultSelected
>
Add to favorites
</Checkbox>
</div>
);
}Context system for sharing checkbox group state.
interface CheckboxGroupProviderProps {
children: React.ReactNode;
value: CheckboxGroupContextValue;
}
interface CheckboxGroupContextValue {
groupState: CheckboxGroupState;
size?: "sm" | "md" | "lg";
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
radius?: "none" | "sm" | "md" | "lg" | "full";
isInvalid?: boolean;
isReadOnly?: boolean;
isDisabled?: boolean;
disableAnimation?: boolean;
}
const CheckboxGroupProvider: React.FC<CheckboxGroupProviderProps>;
/**
* Hook to access checkbox group context
* @throws Error if used outside CheckboxGroupProvider
*/
function useCheckboxGroupContext(): CheckboxGroupContextValue | undefined;Individual radio button component for single selection within groups.
interface RadioProps {
/** Radio label content */
children?: React.ReactNode;
/** Radio value */
value: string;
/** Radio size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Whether radio is disabled */
isDisabled?: boolean;
/** Whether radio is invalid */
isInvalid?: boolean;
/** Custom description */
description?: React.ReactNode;
/** Disable animations */
disableAnimation?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<RadioSlots>;
}
type RadioSlots = "base" | "wrapper" | "labelWrapper" | "control" | "label" | "description";
function Radio(props: RadioProps): JSX.Element;
/**
* Hook for Radio state management
*/
function useRadio(props: RadioProps): {
Component: React.ElementType;
slots: Record<RadioSlots, string>;
classNames: SlotsToClasses<RadioSlots>;
isSelected: boolean;
isPressed: boolean;
isFocused: boolean;
isInvalid: boolean;
getBaseProps: () => any;
getWrapperProps: () => any;
getInputProps: () => any;
getLabelWrapperProps: () => any;
getLabelProps: () => any;
getControlProps: () => any;
getDescriptionProps: () => any;
};Container for managing groups of radio buttons with single selection state.
interface RadioGroupProps {
/** Group label */
label?: React.ReactNode;
/** Radio items */
children?: React.ReactNode;
/** Currently selected value */
value?: string;
/** Default selected value */
defaultValue?: string;
/** Group name attribute */
name?: string;
/** Group size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Group orientation */
orientation?: "horizontal" | "vertical";
/** Whether group is required */
isRequired?: boolean;
/** Whether group is read-only */
isReadOnly?: boolean;
/** Whether group is disabled */
isDisabled?: boolean;
/** Whether group is invalid */
isInvalid?: boolean;
/** Validation state */
validationState?: "valid" | "invalid";
/** Helper description text */
description?: React.ReactNode;
/** Error message content */
errorMessage?: React.ReactNode;
/** Disable animations */
disableAnimation?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<RadioGroupSlots>;
/** Value change handler */
onValueChange?: (value: string) => void;
}
type RadioGroupSlots = "base" | "label" | "wrapper" | "description" | "errorMessage";
function RadioGroup(props: RadioGroupProps): JSX.Element;
/**
* Hook for RadioGroup state management
*/
function useRadioGroup(props: RadioGroupProps): {
Component: React.ElementType;
slots: Record<RadioGroupSlots, string>;
classNames: SlotsToClasses<RadioGroupSlots>;
groupState: RadioGroupState;
getGroupProps: () => any;
getLabelProps: () => any;
getWrapperProps: () => any;
getDescriptionProps: () => any;
getErrorMessageProps: () => any;
};Radio Usage Example:
import { RadioGroup, Radio } from "@nextui-org/react";
function RadioExample() {
const [selected, setSelected] = useState("london");
return (
<RadioGroup
label="Select your favorite city"
value={selected}
onValueChange={setSelected}
orientation="horizontal"
>
<Radio value="buenos-aires">Buenos Aires</Radio>
<Radio value="sydney">Sydney</Radio>
<Radio value="san-francisco">San Francisco</Radio>
<Radio value="london">London</Radio>
<Radio value="tokyo">Tokyo</Radio>
</RadioGroup>
);
}Toggle switch component for boolean states with customizable appearance and behavior.
interface SwitchProps {
/** Switch label content */
children?: React.ReactNode;
/** Whether switch is selected */
isSelected?: boolean;
/** Default selection state */
defaultSelected?: boolean;
/** Switch value */
value?: string;
/** Switch name attribute */
name?: string;
/** Switch size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Custom start content */
startContent?: React.ReactNode;
/** Custom end content */
endContent?: React.ReactNode;
/** Custom thumb icon */
thumbIcon?: React.ReactNode | ((props: SwitchThumbIconProps) => React.ReactNode);
/** Whether switch is required */
isRequired?: boolean;
/** Whether switch is read-only */
isReadOnly?: boolean;
/** Whether switch is disabled */
isDisabled?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<SwitchSlots>;
/** Selection change handler */
onValueChange?: (isSelected: boolean) => void;
}
type SwitchSlots =
| "base" | "wrapper" | "thumb" | "startContent"
| "endContent" | "thumbIcon" | "label";
interface SwitchThumbIconProps {
/** Icon data attributes */
"data-selected"?: string;
/** Whether switch is selected */
isSelected?: boolean;
/** Custom CSS class */
className?: string;
}
function Switch(props: SwitchProps): JSX.Element;
/**
* Hook for Switch state management
*/
function useSwitch(props: SwitchProps): {
Component: React.ElementType;
slots: Record<SwitchSlots, string>;
classNames: SlotsToClasses<SwitchSlots>;
isSelected: boolean;
isPressed: boolean;
isFocused: boolean;
getBaseProps: () => any;
getWrapperProps: () => any;
getInputProps: () => any;
getLabelProps: () => any;
getThumbProps: () => any;
getStartContentProps: () => any;
getEndContentProps: () => any;
getThumbIconProps: () => any;
};Switch Usage Examples:
import { Switch } from "@nextui-org/react";
import { MoonIcon, SunIcon } from "@heroicons/react/24/solid";
function SwitchExamples() {
return (
<div className="space-y-4">
{/* Basic switch */}
<Switch defaultSelected>Airplane mode</Switch>
{/* Switch with icons */}
<Switch
defaultSelected
size="lg"
color="success"
startContent={<SunIcon />}
endContent={<MoonIcon />}
>
Dark mode
</Switch>
{/* Switch with custom thumb icon */}
<Switch
defaultSelected
size="lg"
color="secondary"
thumbIcon={({ isSelected, className }) =>
isSelected ? (
<SunIcon className={className} />
) : (
<MoonIcon className={className} />
)
}
>
Theme toggle
</Switch>
</div>
);
}Range slider component for selecting numeric values within a defined range.
interface SliderProps {
/** Slider label */
label?: React.ReactNode;
/** Current slider value(s) */
value?: SliderValue;
/** Default value for uncontrolled mode */
defaultValue?: SliderValue;
/** Minimum value */
minValue?: number;
/** Maximum value */
maxValue?: number;
/** Step increment */
step?: number;
/** Format options for value display */
formatOptions?: Intl.NumberFormatOptions;
/** Slider size */
size?: "sm" | "md" | "lg";
/** Color theme */
color?: "foreground" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Fill offset for range sliders */
fillOffset?: number;
/** Step marks configuration */
marks?: SliderStepMark[];
/** Whether to hide thumb labels */
hideThumb?: boolean;
/** Whether to hide value label */
hideValue?: boolean;
/** Show steps as marks */
showSteps?: boolean;
/** Show tooltip on hover/focus */
showTooltip?: boolean;
/** Show outline on focus */
showOutline?: boolean;
/** Disable thumb scale animation */
disableThumbScale?: boolean;
/** Whether slider is required */
isRequired?: boolean;
/** Whether slider is disabled */
isDisabled?: boolean;
/** Slider orientation */
orientation?: "horizontal" | "vertical";
/** Tooltip properties */
tooltipProps?: Partial<TooltipProps>;
/** Custom thumb renderer */
renderThumb?: (props: SliderRenderThumbProps) => React.ReactNode;
/** Custom label renderer */
renderLabel?: (props: SliderRenderLabelProps) => React.ReactNode;
/** Custom value renderer */
renderValue?: (props: SliderRenderValueProps) => React.ReactNode;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<SliderSlots>;
/** Value change handler */
onChange?: (value: SliderValue) => void;
/** Value change end handler */
onChangeEnd?: (value: SliderValue) => void;
}
type SliderValue = number | number[];
interface SliderStepMark {
/** Step value */
value: number;
/** Step label */
label?: React.ReactNode;
}
interface SliderRenderThumbProps {
/** Thumb index for multi-thumb sliders */
index?: number;
/** Current value */
value?: number;
/** Value as percentage */
valueLabel?: string;
/** Whether thumb has focus */
isFocused?: boolean;
/** Whether thumb is being dragged */
isDragging?: boolean;
/** Whether slider is disabled */
isDisabled?: boolean;
/** Thumb props */
getThumbProps: (props?: any) => any;
}
interface SliderRenderLabelProps {
/** Current value(s) */
value?: SliderValue;
/** Formatted value text */
valueLabel?: string;
/** Whether slider has focus */
isFocused?: boolean;
/** Whether slider is disabled */
isDisabled?: boolean;
}
interface SliderRenderValueProps extends SliderRenderLabelProps {}
type SliderSlots =
| "base" | "labelWrapper" | "label" | "value" | "trackWrapper"
| "track" | "filler" | "thumb" | "mark" | "step";
function Slider(props: SliderProps): JSX.Element;
/**
* Hook for Slider state management
*/
function useSlider(props: SliderProps): {
Component: React.ElementType;
slots: Record<SliderSlots, string>;
classNames: SlotsToClasses<SliderSlots>;
state: SliderState;
getBaseProps: () => any;
getLabelWrapperProps: () => any;
getLabelProps: () => any;
getValueProps: () => any;
getTrackWrapperProps: () => any;
getTrackProps: () => any;
getFillerProps: () => any;
getThumbProps: (index?: number) => any;
getMarkProps: (mark: SliderStepMark, index: number) => any;
getStepProps: (step: number, index: number) => any;
};Slider Usage Examples:
import { Slider } from "@nextui-org/react";
function SliderExamples() {
const [value, setValue] = useState(40);
const [rangeValue, setRangeValue] = useState([100, 500]);
return (
<div className="space-y-8">
{/* Basic slider */}
<Slider
label="Temperature"
step={1}
minValue={0}
maxValue={100}
value={value}
onChange={setValue}
className="max-w-md"
formatOptions={{style: "unit", unit: "celsius"}}
/>
{/* Range slider */}
<Slider
label="Price Range"
step={50}
minValue={0}
maxValue={1000}
value={rangeValue}
onChange={setRangeValue}
className="max-w-md"
formatOptions={{style: "currency", currency: "USD"}}
/>
{/* Slider with steps */}
<Slider
label="Volume"
step={10}
minValue={0}
maxValue={100}
defaultValue={30}
showSteps
showTooltip
showOutline
className="max-w-md"
marks={[
{value: 20, label: "20%"},
{value: 50, label: "50%"},
{value: 80, label: "80%"},
]}
/>
</div>
);
}A multi-line text input component with auto-resize capabilities and enhanced styling options.
interface TextAreaProps {
/** Input label */
label?: React.ReactNode;
/** Current textarea value */
value?: string;
/** Default textarea value */
defaultValue?: string;
/** Input placeholder text */
placeholder?: string;
/** Helper description text */
description?: React.ReactNode;
/** Error message */
errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);
/** Validation function */
validate?: (value: string) => ValidationError | true | null | undefined;
/** Validation behavior */
validationBehavior?: "aria" | "native";
/** Whether textarea is required */
isRequired?: boolean;
/** Whether textarea is read-only */
isReadOnly?: boolean;
/** Whether textarea is disabled */
isDisabled?: boolean;
/** Whether textarea is invalid */
isInvalid?: boolean;
/** Auto focus on mount */
autoFocus?: boolean;
/** Textarea size */
size?: "sm" | "md" | "lg";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Visual variant */
variant?: "flat" | "bordered" | "underlined" | "faded";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Label placement */
labelPlacement?: "inside" | "outside" | "outside-left";
/** Whether textarea takes full width */
fullWidth?: boolean;
/** Minimum number of visible text lines */
minRows?: number;
/** Maximum number of visible text lines */
maxRows?: number;
/** Show clear button */
isClearable?: boolean;
/** Disable animations */
disableAnimation?: boolean;
/** Disable auto resize */
disableAutosize?: boolean;
/** Cached row height for performance */
cacheMeasurements?: boolean;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<InputSlots>;
/** Value change handler */
onValueChange?: (value: string) => void;
/** Clear handler */
onClear?: () => void;
}
function Textarea(props: TextAreaProps): JSX.Element;Textarea Usage Examples:
import { Textarea, Button, Card, CardBody } from "@nextui-org/react";
function TextareaExamples() {
const [value, setValue] = useState("");
const [message, setMessage] = useState("");
return (
<Card className="max-w-lg">
<CardBody className="space-y-4">
{/* Basic textarea */}
<Textarea
label="Description"
placeholder="Enter your description"
value={value}
onValueChange={setValue}
/>
{/* Textarea with validation */}
<Textarea
isRequired
label="Message"
placeholder="Write your message here..."
description="Minimum 10 characters required"
value={message}
onValueChange={setMessage}
minRows={3}
maxRows={8}
validate={(value) => {
if (value.length < 10) {
return "Message must be at least 10 characters long";
}
return true;
}}
errorMessage={(validation) =>
validation.isInvalid ? validation.validationErrors[0] : undefined
}
/>
{/* Disabled auto-resize textarea */}
<Textarea
label="Fixed Size"
placeholder="This textarea doesn't auto-resize"
disableAutosize
minRows={4}
variant="bordered"
color="secondary"
/>
{/* Textarea with clear functionality */}
<Textarea
label="Clearable Content"
placeholder="Type something and clear it"
isClearable
variant="underlined"
/>
<Button
color="primary"
isDisabled={message.length < 10}
className="w-full"
>
Submit Message
</Button>
</CardBody>
</Card>
);
}A specialized input component for One-Time Password entry with individual character segments.
interface InputOTPProps {
/** Number of OTP digits */
length?: number;
/** Current OTP value */
value?: string;
/** Default OTP value */
defaultValue?: string;
/** Input placeholder for each digit */
placeholder?: string;
/** Whether input is required */
isRequired?: boolean;
/** Whether input is disabled */
isDisabled?: boolean;
/** Whether input is invalid */
isInvalid?: boolean;
/** Input size */
size?: "sm" | "md" | "lg";
/** Border radius */
radius?: "none" | "sm" | "md" | "lg" | "full";
/** Visual variant */
variant?: "flat" | "bordered" | "underlined" | "faded";
/** Color theme */
color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Whether to allow only numeric input */
allowedKeys?: RegExp;
/** Custom CSS class */
className?: string;
/** Slot-based styling */
classNames?: SlotsToClasses<InputOTPSlots>;
/** Value change handler */
onValueChange?: (value: string) => void;
/** Complete handler (when all digits filled) */
onComplete?: (value: string) => void;
}
type InputOTPSlots = "base" | "segmentWrapper" | "segment" | "helperWrapper";
function InputOTP(props: InputOTPProps): JSX.Element;
/**
* Hook for InputOTP state management
*/
function useInputOTP(props: InputOTPProps): {
Component: React.ElementType;
slots: Record<InputOTPSlots, string>;
classNames: SlotsToClasses<InputOTPSlots>;
getInputOTPProps: () => any;
getSegmentProps: (index: number) => any;
};Input OTP Usage Examples:
import { InputOTP, Card, CardHeader, CardBody, Button } from "@nextui-org/react";
function InputOTPExamples() {
const [otp, setOtp] = useState("");
const [verificationOTP, setVerificationOTP] = useState("");
const handleComplete = (value: string) => {
console.log("OTP completed:", value);
// Handle OTP verification
};
return (
<div className="space-y-6 max-w-sm mx-auto">
<Card>
<CardHeader>
<h3>Email Verification</h3>
</CardHeader>
<CardBody className="space-y-4">
<p className="text-sm text-default-500">
Enter the 6-digit code sent to your email
</p>
<InputOTP
length={6}
value={otp}
onValueChange={setOtp}
onComplete={handleComplete}
placeholder="0"
/>
<Button
color="primary"
isDisabled={otp.length !== 6}
className="w-full"
>
Verify Code
</Button>
</CardBody>
</Card>
<Card>
<CardHeader>
<h3>Custom Styled OTP</h3>
</CardHeader>
<CardBody className="space-y-4">
<InputOTP
length={4}
value={verificationOTP}
onValueChange={setVerificationOTP}
variant="bordered"
color="secondary"
size="lg"
radius="sm"
allowedKeys={/^[0-9]$/}
/>
<p className="text-xs text-default-400">
Only numeric digits allowed
</p>
</CardBody>
</Card>
</div>
);
}// Common input types
type InputSize = "sm" | "md" | "lg";
type InputVariant = "flat" | "bordered" | "underlined" | "faded";
type InputColor = "default" | "primary" | "secondary" | "success" | "warning" | "danger";
type LabelPlacement = "inside" | "outside" | "outside-left";
type ValidationBehavior = "aria" | "native";
// Validation types
type ValidationError = string | string[];
interface ValidationResult {
isInvalid: boolean;
validationErrors: string[];
validationDetails: ValidationDetails;
}
interface ValidationDetails {
[key: string]: any;
}
// Selection types
type Selection = "all" | Set<React.Key>;
// Group state interfaces
interface CheckboxGroupState {
readonly selectedKeys: Set<string>;
readonly isDisabled: boolean;
readonly isReadOnly: boolean;
readonly isRequired: boolean;
readonly isInvalid: boolean;
readonly value: string[];
addValue(value: string): void;
removeValue(value: string): void;
toggleValue(value: string): void;
clearValue(): void;
}
interface RadioGroupState {
readonly selectedValue: string | null;
readonly isDisabled: boolean;
readonly isReadOnly: boolean;
readonly isRequired: boolean;
readonly isInvalid: boolean;
setSelectedValue(value: string): void;
}
interface SliderState {
readonly values: number[];
readonly focusedThumb: number | undefined;
readonly isDisabled: boolean;
getThumbValue(index: number): number;
setThumbValue(index: number, value: number): void;
incrementThumb(index: number, stepSize?: number): void;
decrementThumb(index: number, stepSize?: number): void;
}