or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-system.mddata-display.mddate-time.mdfeedback.mdforms.mdindex.mdinputs.mdinteractions.mdlayout.mdnavigation.mdoverlays.mdutilities.md

inputs.mddocs/

0

# Input Components

1

2

NextUI provides a comprehensive set of form input components with built-in validation, accessibility support, and consistent styling across different input types.

3

4

## Capabilities

5

6

### Input

7

8

A versatile text input component with support for labels, validation, helper text, and various visual states.

9

10

```typescript { .api }

11

interface InputProps {

12

/** Input content and elements */

13

children?: React.ReactNode;

14

/** Input label */

15

label?: React.ReactNode;

16

/** Current input value */

17

value?: string;

18

/** Default value for uncontrolled mode */

19

defaultValue?: string;

20

/** Placeholder text */

21

placeholder?: string;

22

/** Helper description text */

23

description?: React.ReactNode;

24

/** Error message content */

25

errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);

26

/** Validation function */

27

validate?: (value: string) => ValidationError | true | null | undefined;

28

/** Validation behavior */

29

validationBehavior?: "aria" | "native";

30

/** Validation state */

31

validationState?: "valid" | "invalid";

32

/** Whether input is required */

33

isRequired?: boolean;

34

/** Whether input is read-only */

35

isReadOnly?: boolean;

36

/** Whether input is disabled */

37

isDisabled?: boolean;

38

/** Whether input is invalid */

39

isInvalid?: boolean;

40

/** Base container ref */

41

baseRef?: React.RefObject<HTMLDivElement>;

42

/** Whether to show helper content */

43

hasHelper?: boolean;

44

/** Input size variant */

45

size?: "sm" | "md" | "lg";

46

/** Border radius */

47

radius?: "none" | "sm" | "md" | "lg" | "full";

48

/** Visual variant */

49

variant?: "flat" | "bordered" | "underlined" | "faded";

50

/** Color theme */

51

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

52

/** Label placement */

53

labelPlacement?: "inside" | "outside" | "outside-left";

54

/** Whether input takes full width */

55

fullWidth?: boolean;

56

/** Whether to show clear button */

57

isClearable?: boolean;

58

/** Disable animations */

59

disableAnimation?: boolean;

60

/** Input type */

61

type?: "text" | "email" | "password" | "search" | "tel" | "url" | "number";

62

/** Start content (icon, etc.) */

63

startContent?: React.ReactNode;

64

/** End content (icon, button, etc.) */

65

endContent?: React.ReactNode;

66

/** Custom CSS class */

67

className?: string;

68

/** Slot-based styling */

69

classNames?: SlotsToClasses<InputSlots>;

70

/** Value change handler */

71

onValueChange?: (value: string) => void;

72

/** Clear button press handler */

73

onClear?: () => void;

74

}

75

76

type InputSlots =

77

| "base" | "mainWrapper" | "inputWrapper" | "innerWrapper"

78

| "input" | "clearButton" | "label" | "description"

79

| "errorMessage" | "helperWrapper";

80

81

function Input(props: InputProps): JSX.Element;

82

83

/**

84

* Hook for Input state management

85

*/

86

function useInput(props: InputProps): {

87

Component: React.ElementType;

88

label?: React.ReactNode;

89

description?: React.ReactNode;

90

errorMessage?: React.ReactNode;

91

isInvalid: boolean;

92

validationErrors: string[];

93

validationDetails: ValidationDetails;

94

slots: Record<InputSlots, string>;

95

classNames: SlotsToClasses<InputSlots>;

96

getBaseProps: () => any;

97

getLabelProps: () => any;

98

getInputProps: () => any;

99

getInputWrapperProps: () => any;

100

getInnerWrapperProps: () => any;

101

getMainWrapperProps: () => any;

102

getClearButtonProps: () => any;

103

getDescriptionProps: () => any;

104

getErrorMessageProps: () => any;

105

};

106

```

107

108

**Input Usage Examples:**

109

110

```typescript

111

import { Input } from "@nextui-org/react";

112

import { SearchIcon, EyeFilledIcon, EyeSlashFilledIcon } from "@heroicons/react/24/solid";

113

114

function InputExamples() {

115

const [isVisible, setIsVisible] = useState(false);

116

const [value, setValue] = useState("");

117

118

const toggleVisibility = () => setIsVisible(!isVisible);

119

120

const validateEmail = (value: string) => {

121

return value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i);

122

};

123

124

const isInvalid = useMemo(() => {

125

if (value === "") return false;

126

return validateEmail(value) ? false : true;

127

}, [value]);

128

129

return (

130

<div className="space-y-4">

131

{/* Basic input */}

132

<Input

133

type="text"

134

label="Name"

135

placeholder="Enter your name"

136

labelPlacement="outside"

137

/>

138

139

{/* Email input with validation */}

140

<Input

141

value={value}

142

onValueChange={setValue}

143

isInvalid={isInvalid}

144

label="Email"

145

variant="bordered"

146

placeholder="Enter your email"

147

description="We'll never share your email with anyone else."

148

errorMessage={isInvalid && "Please enter a valid email"}

149

color={isInvalid ? "danger" : "success"}

150

className="max-w-xs"

151

/>

152

153

{/* Password input with toggle visibility */}

154

<Input

155

label="Password"

156

variant="bordered"

157

placeholder="Enter your password"

158

endContent={

159

<button className="focus:outline-none" type="button" onClick={toggleVisibility}>

160

{isVisible ? (

161

<EyeSlashFilledIcon className="text-2xl text-default-400 pointer-events-none" />

162

) : (

163

<EyeFilledIcon className="text-2xl text-default-400 pointer-events-none" />

164

)}

165

</button>

166

}

167

type={isVisible ? "text" : "password"}

168

className="max-w-xs"

169

/>

170

171

{/* Search input with icon */}

172

<Input

173

label="Search"

174

isClearable

175

radius="lg"

176

placeholder="Type to search..."

177

startContent={

178

<SearchIcon className="text-black/50 mb-0.5 dark:text-white/90 text-slate-400 pointer-events-none flex-shrink-0" />

179

}

180

/>

181

</div>

182

);

183

}

184

```

185

186

### Textarea

187

188

Multi-line text input component with automatic resizing and validation support.

189

190

```typescript { .api }

191

interface TextAreaProps {

192

/** Textarea content */

193

children?: React.ReactNode;

194

/** Textarea label */

195

label?: React.ReactNode;

196

/** Current textarea value */

197

value?: string;

198

/** Default value for uncontrolled mode */

199

defaultValue?: string;

200

/** Placeholder text */

201

placeholder?: string;

202

/** Helper description text */

203

description?: React.ReactNode;

204

/** Error message content */

205

errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);

206

/** Validation function */

207

validate?: (value: string) => ValidationError | true | null | undefined;

208

/** Validation behavior */

209

validationBehavior?: "aria" | "native";

210

/** Validation state */

211

validationState?: "valid" | "invalid";

212

/** Whether textarea is required */

213

isRequired?: boolean;

214

/** Whether textarea is read-only */

215

isReadOnly?: boolean;

216

/** Whether textarea is disabled */

217

isDisabled?: boolean;

218

/** Whether textarea is invalid */

219

isInvalid?: boolean;

220

/** Textarea size variant */

221

size?: "sm" | "md" | "lg";

222

/** Border radius */

223

radius?: "none" | "sm" | "md" | "lg" | "full";

224

/** Visual variant */

225

variant?: "flat" | "bordered" | "underlined" | "faded";

226

/** Color theme */

227

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

228

/** Label placement */

229

labelPlacement?: "inside" | "outside" | "outside-left";

230

/** Whether textarea takes full width */

231

fullWidth?: boolean;

232

/** Disable animations */

233

disableAnimation?: boolean;

234

/** Minimum number of rows */

235

minRows?: number;

236

/** Maximum number of rows */

237

maxRows?: number;

238

/** Whether to cache height for performance */

239

cacheMeasurements?: boolean;

240

/** Custom CSS class */

241

className?: string;

242

/** Slot-based styling */

243

classNames?: SlotsToClasses<InputSlots>;

244

/** Value change handler */

245

onValueChange?: (value: string) => void;

246

}

247

248

function Textarea(props: TextAreaProps): JSX.Element;

249

```

250

251

**Textarea Usage Example:**

252

253

```typescript

254

import { Textarea } from "@nextui-org/react";

255

256

function TextareaExample() {

257

return (

258

<div className="space-y-4">

259

<Textarea

260

label="Description"

261

placeholder="Enter your description"

262

description="Provide a detailed description of your project"

263

className="max-w-xs"

264

/>

265

266

<Textarea

267

isRequired

268

label="Feedback"

269

labelPlacement="outside"

270

placeholder="Share your feedback..."

271

variant="bordered"

272

minRows={3}

273

maxRows={8}

274

className="max-w-lg"

275

/>

276

</div>

277

);

278

}

279

```

280

281

### Select

282

283

Dropdown selection component with search, multiple selection, and custom item rendering support.

284

285

```typescript { .api }

286

interface SelectProps<T = object> {

287

/** Select content and options */

288

children?: React.ReactNode;

289

/** Data items for dynamic rendering */

290

items?: Iterable<T>;

291

/** Select label */

292

label?: React.ReactNode;

293

/** Placeholder text when no selection */

294

placeholder?: string;

295

/** Helper description text */

296

description?: React.ReactNode;

297

/** Error message content */

298

errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);

299

/** Validation function */

300

validate?: (value: SelectValue<T>) => ValidationError | true | null | undefined;

301

/** Selection mode */

302

selectionMode?: "single" | "multiple";

303

/** Currently selected keys */

304

selectedKeys?: "all" | Iterable<React.Key>;

305

/** Default selected keys for uncontrolled mode */

306

defaultSelectedKeys?: "all" | Iterable<React.Key>;

307

/** Prevent empty selection */

308

disallowEmptySelection?: boolean;

309

/** Whether popover should flip to fit */

310

shouldFlip?: boolean;

311

/** Whether select is required */

312

isRequired?: boolean;

313

/** Whether select is invalid */

314

isInvalid?: boolean;

315

/** Whether select is disabled */

316

isDisabled?: boolean;

317

/** Whether select is in loading state */

318

isLoading?: boolean;

319

/** Select size variant */

320

size?: "sm" | "md" | "lg";

321

/** Border radius */

322

radius?: "none" | "sm" | "md" | "lg" | "full";

323

/** Visual variant */

324

variant?: "flat" | "bordered" | "underlined" | "faded";

325

/** Color theme */

326

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

327

/** Label placement */

328

labelPlacement?: "inside" | "outside" | "outside-left";

329

/** Whether select takes full width */

330

fullWidth?: boolean;

331

/** Popover placement */

332

placement?: Placement;

333

/** Start content (icon, etc.) */

334

startContent?: React.ReactNode;

335

/** End content (icon, button, etc.) */

336

endContent?: React.ReactNode;

337

/** Selector icon (dropdown arrow) */

338

selectorIcon?: React.ReactNode;

339

/** Disable animations */

340

disableAnimation?: boolean;

341

/** Disable selector icon animation */

342

disableSelectorIconRotation?: boolean;

343

/** Custom scroll reference */

344

scrollRef?: React.RefObject<HTMLElement>;

345

/** Listbox props */

346

listboxProps?: Partial<ListboxProps>;

347

/** Popover props */

348

popoverProps?: Partial<PopoverProps>;

349

/** Spinner props for loading state */

350

spinnerProps?: Partial<SpinnerProps>;

351

/** Custom CSS class */

352

className?: string;

353

/** Slot-based styling */

354

classNames?: SlotsToClasses<SelectSlots>;

355

/** Selection change handler */

356

onSelectionChange?: (keys: Selection) => void;

357

/** Open state change handler */

358

onOpenChange?: (isOpen: boolean) => void;

359

/** Close handler */

360

onClose?: () => void;

361

}

362

363

type SelectSlots =

364

| "base" | "label" | "trigger" | "innerWrapper" | "selectorIcon"

365

| "value" | "listboxWrapper" | "listbox" | "popoverContent"

366

| "helperWrapper" | "description" | "errorMessage";

367

368

type SelectValue<T> = T | null | undefined;

369

370

function Select<T = object>(props: SelectProps<T>): JSX.Element;

371

372

/**

373

* Hook for Select state management

374

*/

375

function useSelect<T = object>(props: UseSelectProps<T>): {

376

Component: React.ElementType;

377

state: SelectState<T>;

378

slots: Record<SelectSlots, string>;

379

classNames: SlotsToClasses<SelectSlots>;

380

isOpen: boolean;

381

isLoading?: boolean;

382

getSelectProps: () => any;

383

getTriggerProps: () => any;

384

getValueProps: () => any;

385

getListboxProps: () => any;

386

getPopoverProps: () => any;

387

};

388

389

interface UseSelectProps<T> extends Omit<SelectProps<T>, 'children'> {

390

/** Trigger ref */

391

triggerRef?: React.RefObject<HTMLElement>;

392

/** Value ref */

393

valueRef?: React.RefObject<HTMLElement>;

394

/** Listbox ref */

395

listboxRef?: React.RefObject<HTMLElement>;

396

/** Popover ref */

397

popoverRef?: React.RefObject<HTMLDivElement>;

398

}

399

```

400

401

### Select Items

402

403

Components for defining select options and sections.

404

405

```typescript { .api }

406

// SelectItem is an alias for ListboxItem

407

interface SelectItemProps {

408

/** Item key identifier */

409

key?: React.Key;

410

/** Item text content */

411

children?: React.ReactNode;

412

/** Item text value for controlled components */

413

textValue?: string;

414

/** Whether item is disabled */

415

isDisabled?: boolean;

416

/** Whether to hide selected indicator */

417

hideSelectedIcon?: boolean;

418

/** Item start content (icon, avatar, etc.) */

419

startContent?: React.ReactNode;

420

/** Item end content (icon, badge, etc.) */

421

endContent?: React.ReactNode;

422

/** Item description text */

423

description?: React.ReactNode;

424

/** Custom CSS class */

425

className?: string;

426

/** Slot-based styling */

427

classNames?: SlotsToClasses<ListboxItemSlots>;

428

}

429

430

// SelectSection is an alias for ListboxSection

431

interface SelectSectionProps {

432

/** Section title */

433

title?: React.ReactNode;

434

/** Section items */

435

children?: React.ReactNode;

436

/** Whether to hide divider */

437

hideDivider?: boolean;

438

/** Whether to show divider */

439

showDivider?: boolean;

440

/** Divider props */

441

dividerProps?: DividerProps;

442

/** Item heading */

443

heading?: React.ReactNode;

444

/** Custom CSS class */

445

className?: string;

446

/** Slot-based styling */

447

classNames?: SlotsToClasses<ListboxSectionSlots>;

448

}

449

450

const SelectItem: React.FC<SelectItemProps>;

451

const SelectSection: React.FC<SelectSectionProps>;

452

```

453

454

**Select Usage Examples:**

455

456

```typescript

457

import { Select, SelectItem, SelectSection } from "@nextui-org/react";

458

459

function SelectExamples() {

460

const animals = [

461

{key: "cat", label: "Cat"},

462

{key: "dog", label: "Dog"},

463

{key: "elephant", label: "Elephant"},

464

{key: "lion", label: "Lion"},

465

{key: "tiger", label: "Tiger"},

466

];

467

468

const [selectedValue, setSelectedValue] = useState(new Set(["cat"]));

469

470

return (

471

<div className="space-y-4">

472

{/* Basic select */}

473

<Select

474

label="Favorite Animal"

475

placeholder="Select an animal"

476

className="max-w-xs"

477

>

478

{animals.map((animal) => (

479

<SelectItem key={animal.key}>

480

{animal.label}

481

</SelectItem>

482

))}

483

</Select>

484

485

{/* Multiple selection */}

486

<Select

487

label="Animals"

488

selectionMode="multiple"

489

placeholder="Select animals"

490

selectedKeys={selectedValue}

491

onSelectionChange={setSelectedValue}

492

className="max-w-xs"

493

>

494

{animals.map((animal) => (

495

<SelectItem key={animal.key}>

496

{animal.label}

497

</SelectItem>

498

))}

499

</Select>

500

501

{/* Select with sections */}

502

<Select

503

label="Pets by category"

504

placeholder="Select a pet"

505

className="max-w-xs"

506

>

507

<SelectSection title="Mammals">

508

<SelectItem key="cat">Cat</SelectItem>

509

<SelectItem key="dog">Dog</SelectItem>

510

</SelectSection>

511

<SelectSection title="Birds">

512

<SelectItem key="parrot">Parrot</SelectItem>

513

<SelectItem key="canary">Canary</SelectItem>

514

</SelectSection>

515

</Select>

516

517

{/* Dynamic items */}

518

<Select

519

items={animals}

520

label="Dynamic Animals"

521

placeholder="Select an animal"

522

className="max-w-xs"

523

>

524

{(item) => <SelectItem key={item.key}>{item.label}</SelectItem>}

525

</Select>

526

</div>

527

);

528

}

529

```

530

531

### Checkbox

532

533

Individual checkbox component with indeterminate state support and custom styling.

534

535

```typescript { .api }

536

interface CheckboxProps {

537

/** Checkbox label content */

538

children?: React.ReactNode;

539

/** Checkbox value */

540

value?: string;

541

/** Whether checkbox is selected */

542

isSelected?: boolean;

543

/** Default selection state */

544

defaultSelected?: boolean;

545

/** Whether checkbox is indeterminate */

546

isIndeterminate?: boolean;

547

/** Whether checkbox is required */

548

isRequired?: boolean;

549

/** Whether checkbox is read-only */

550

isReadOnly?: boolean;

551

/** Whether checkbox is disabled */

552

isDisabled?: boolean;

553

/** Whether checkbox is invalid */

554

isInvalid?: boolean;

555

/** Validation state */

556

validationState?: "valid" | "invalid";

557

/** Checkbox size */

558

size?: "sm" | "md" | "lg";

559

/** Color theme */

560

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

561

/** Border radius */

562

radius?: "none" | "sm" | "md" | "lg" | "full";

563

/** Line through text when selected */

564

lineThrough?: boolean;

565

/** Disable animations */

566

disableAnimation?: boolean;

567

/** Custom icon for checkbox */

568

icon?: React.ReactNode | ((props: CheckboxIconProps) => React.ReactNode);

569

/** Custom CSS class */

570

className?: string;

571

/** Slot-based styling */

572

classNames?: SlotsToClasses<CheckboxSlots>;

573

/** Selection change handler */

574

onValueChange?: (isSelected: boolean) => void;

575

}

576

577

type CheckboxSlots = "base" | "wrapper" | "icon" | "label";

578

579

function Checkbox(props: CheckboxProps): JSX.Element;

580

581

/**

582

* Hook for Checkbox state management

583

*/

584

function useCheckbox(props: CheckboxProps): {

585

Component: React.ElementType;

586

slots: Record<CheckboxSlots, string>;

587

classNames: SlotsToClasses<CheckboxSlots>;

588

isSelected: boolean;

589

isPressed: boolean;

590

isFocused: boolean;

591

isInvalid: boolean;

592

getBaseProps: () => any;

593

getWrapperProps: () => any;

594

getInputProps: () => any;

595

getLabelProps: () => any;

596

getIconProps: () => any;

597

};

598

```

599

600

### Checkbox Icon

601

602

Customizable icon component for checkbox states.

603

604

```typescript { .api }

605

interface CheckboxIconProps {

606

/** Icon data attributes */

607

"data-checked"?: string;

608

/** Whether checkbox is selected */

609

isSelected?: boolean;

610

/** Whether checkbox is indeterminate */

611

isIndeterminate?: boolean;

612

/** Disable animations */

613

disableAnimation?: boolean;

614

/** Custom CSS class */

615

className?: string;

616

}

617

618

function CheckboxIcon(props: CheckboxIconProps): JSX.Element;

619

```

620

621

### Checkbox Group

622

623

Container for managing groups of related checkboxes with shared state and validation.

624

625

```typescript { .api }

626

interface CheckboxGroupProps {

627

/** Group label */

628

label?: React.ReactNode;

629

/** Checkbox items */

630

children?: React.ReactNode;

631

/** Currently selected values */

632

value?: string[];

633

/** Default selected values */

634

defaultValue?: string[];

635

/** Group name attribute */

636

name?: string;

637

/** Group size */

638

size?: "sm" | "md" | "lg";

639

/** Color theme */

640

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

641

/** Border radius for all checkboxes */

642

radius?: "none" | "sm" | "md" | "lg" | "full";

643

/** Group orientation */

644

orientation?: "horizontal" | "vertical";

645

/** Whether group is required */

646

isRequired?: boolean;

647

/** Whether group is read-only */

648

isReadOnly?: boolean;

649

/** Whether group is disabled */

650

isDisabled?: boolean;

651

/** Whether group is invalid */

652

isInvalid?: boolean;

653

/** Validation state */

654

validationState?: "valid" | "invalid";

655

/** Helper description text */

656

description?: React.ReactNode;

657

/** Error message content */

658

errorMessage?: React.ReactNode;

659

/** Disable animations */

660

disableAnimation?: boolean;

661

/** Custom CSS class */

662

className?: string;

663

/** Slot-based styling */

664

classNames?: SlotsToClasses<CheckboxGroupSlots>;

665

/** Value change handler */

666

onValueChange?: (value: string[]) => void;

667

}

668

669

type CheckboxGroupSlots = "base" | "label" | "wrapper" | "description" | "errorMessage";

670

671

function CheckboxGroup(props: CheckboxGroupProps): JSX.Element;

672

673

/**

674

* Hook for CheckboxGroup state management

675

*/

676

function useCheckboxGroup(props: CheckboxGroupProps): {

677

Component: React.ElementType;

678

slots: Record<CheckboxGroupSlots, string>;

679

classNames: SlotsToClasses<CheckboxGroupSlots>;

680

groupState: CheckboxGroupState;

681

getGroupProps: () => any;

682

getLabelProps: () => any;

683

getWrapperProps: () => any;

684

getDescriptionProps: () => any;

685

getErrorMessageProps: () => any;

686

};

687

```

688

689

**Checkbox Usage Examples:**

690

691

```typescript

692

import { Checkbox, CheckboxGroup } from "@nextui-org/react";

693

694

function CheckboxExamples() {

695

const [selected, setSelected] = useState(["argentina"]);

696

697

return (

698

<div className="space-y-6">

699

{/* Individual checkboxes */}

700

<div className="space-y-2">

701

<Checkbox defaultSelected>Option 1</Checkbox>

702

<Checkbox isIndeterminate>Option 2</Checkbox>

703

<Checkbox isDisabled>Option 3</Checkbox>

704

</div>

705

706

{/* Checkbox group */}

707

<CheckboxGroup

708

label="Select countries"

709

color="secondary"

710

value={selected}

711

onValueChange={setSelected}

712

description="Choose your favorite countries"

713

>

714

<Checkbox value="argentina">Argentina</Checkbox>

715

<Checkbox value="venezuela">Venezuela</Checkbox>

716

<Checkbox value="brazil">Brazil</Checkbox>

717

<Checkbox value="colombia">Colombia</Checkbox>

718

</CheckboxGroup>

719

720

{/* Custom icon checkbox */}

721

<Checkbox

722

icon={<HeartIcon />}

723

color="danger"

724

defaultSelected

725

>

726

Add to favorites

727

</Checkbox>

728

</div>

729

);

730

}

731

```

732

733

### Checkbox Group Context

734

735

Context system for sharing checkbox group state.

736

737

```typescript { .api }

738

interface CheckboxGroupProviderProps {

739

children: React.ReactNode;

740

value: CheckboxGroupContextValue;

741

}

742

743

interface CheckboxGroupContextValue {

744

groupState: CheckboxGroupState;

745

size?: "sm" | "md" | "lg";

746

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

747

radius?: "none" | "sm" | "md" | "lg" | "full";

748

isInvalid?: boolean;

749

isReadOnly?: boolean;

750

isDisabled?: boolean;

751

disableAnimation?: boolean;

752

}

753

754

const CheckboxGroupProvider: React.FC<CheckboxGroupProviderProps>;

755

756

/**

757

* Hook to access checkbox group context

758

* @throws Error if used outside CheckboxGroupProvider

759

*/

760

function useCheckboxGroupContext(): CheckboxGroupContextValue | undefined;

761

```

762

763

### Radio

764

765

Individual radio button component for single selection within groups.

766

767

```typescript { .api }

768

interface RadioProps {

769

/** Radio label content */

770

children?: React.ReactNode;

771

/** Radio value */

772

value: string;

773

/** Radio size */

774

size?: "sm" | "md" | "lg";

775

/** Color theme */

776

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

777

/** Whether radio is disabled */

778

isDisabled?: boolean;

779

/** Whether radio is invalid */

780

isInvalid?: boolean;

781

/** Custom description */

782

description?: React.ReactNode;

783

/** Disable animations */

784

disableAnimation?: boolean;

785

/** Custom CSS class */

786

className?: string;

787

/** Slot-based styling */

788

classNames?: SlotsToClasses<RadioSlots>;

789

}

790

791

type RadioSlots = "base" | "wrapper" | "labelWrapper" | "control" | "label" | "description";

792

793

function Radio(props: RadioProps): JSX.Element;

794

795

/**

796

* Hook for Radio state management

797

*/

798

function useRadio(props: RadioProps): {

799

Component: React.ElementType;

800

slots: Record<RadioSlots, string>;

801

classNames: SlotsToClasses<RadioSlots>;

802

isSelected: boolean;

803

isPressed: boolean;

804

isFocused: boolean;

805

isInvalid: boolean;

806

getBaseProps: () => any;

807

getWrapperProps: () => any;

808

getInputProps: () => any;

809

getLabelWrapperProps: () => any;

810

getLabelProps: () => any;

811

getControlProps: () => any;

812

getDescriptionProps: () => any;

813

};

814

```

815

816

### Radio Group

817

818

Container for managing groups of radio buttons with single selection state.

819

820

```typescript { .api }

821

interface RadioGroupProps {

822

/** Group label */

823

label?: React.ReactNode;

824

/** Radio items */

825

children?: React.ReactNode;

826

/** Currently selected value */

827

value?: string;

828

/** Default selected value */

829

defaultValue?: string;

830

/** Group name attribute */

831

name?: string;

832

/** Group size */

833

size?: "sm" | "md" | "lg";

834

/** Color theme */

835

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

836

/** Group orientation */

837

orientation?: "horizontal" | "vertical";

838

/** Whether group is required */

839

isRequired?: boolean;

840

/** Whether group is read-only */

841

isReadOnly?: boolean;

842

/** Whether group is disabled */

843

isDisabled?: boolean;

844

/** Whether group is invalid */

845

isInvalid?: boolean;

846

/** Validation state */

847

validationState?: "valid" | "invalid";

848

/** Helper description text */

849

description?: React.ReactNode;

850

/** Error message content */

851

errorMessage?: React.ReactNode;

852

/** Disable animations */

853

disableAnimation?: boolean;

854

/** Custom CSS class */

855

className?: string;

856

/** Slot-based styling */

857

classNames?: SlotsToClasses<RadioGroupSlots>;

858

/** Value change handler */

859

onValueChange?: (value: string) => void;

860

}

861

862

type RadioGroupSlots = "base" | "label" | "wrapper" | "description" | "errorMessage";

863

864

function RadioGroup(props: RadioGroupProps): JSX.Element;

865

866

/**

867

* Hook for RadioGroup state management

868

*/

869

function useRadioGroup(props: RadioGroupProps): {

870

Component: React.ElementType;

871

slots: Record<RadioGroupSlots, string>;

872

classNames: SlotsToClasses<RadioGroupSlots>;

873

groupState: RadioGroupState;

874

getGroupProps: () => any;

875

getLabelProps: () => any;

876

getWrapperProps: () => any;

877

getDescriptionProps: () => any;

878

getErrorMessageProps: () => any;

879

};

880

```

881

882

**Radio Usage Example:**

883

884

```typescript

885

import { RadioGroup, Radio } from "@nextui-org/react";

886

887

function RadioExample() {

888

const [selected, setSelected] = useState("london");

889

890

return (

891

<RadioGroup

892

label="Select your favorite city"

893

value={selected}

894

onValueChange={setSelected}

895

orientation="horizontal"

896

>

897

<Radio value="buenos-aires">Buenos Aires</Radio>

898

<Radio value="sydney">Sydney</Radio>

899

<Radio value="san-francisco">San Francisco</Radio>

900

<Radio value="london">London</Radio>

901

<Radio value="tokyo">Tokyo</Radio>

902

</RadioGroup>

903

);

904

}

905

```

906

907

### Switch

908

909

Toggle switch component for boolean states with customizable appearance and behavior.

910

911

```typescript { .api }

912

interface SwitchProps {

913

/** Switch label content */

914

children?: React.ReactNode;

915

/** Whether switch is selected */

916

isSelected?: boolean;

917

/** Default selection state */

918

defaultSelected?: boolean;

919

/** Switch value */

920

value?: string;

921

/** Switch name attribute */

922

name?: string;

923

/** Switch size */

924

size?: "sm" | "md" | "lg";

925

/** Color theme */

926

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

927

/** Custom start content */

928

startContent?: React.ReactNode;

929

/** Custom end content */

930

endContent?: React.ReactNode;

931

/** Custom thumb icon */

932

thumbIcon?: React.ReactNode | ((props: SwitchThumbIconProps) => React.ReactNode);

933

/** Whether switch is required */

934

isRequired?: boolean;

935

/** Whether switch is read-only */

936

isReadOnly?: boolean;

937

/** Whether switch is disabled */

938

isDisabled?: boolean;

939

/** Disable animations */

940

disableAnimation?: boolean;

941

/** Custom CSS class */

942

className?: string;

943

/** Slot-based styling */

944

classNames?: SlotsToClasses<SwitchSlots>;

945

/** Selection change handler */

946

onValueChange?: (isSelected: boolean) => void;

947

}

948

949

type SwitchSlots =

950

| "base" | "wrapper" | "thumb" | "startContent"

951

| "endContent" | "thumbIcon" | "label";

952

953

interface SwitchThumbIconProps {

954

/** Icon data attributes */

955

"data-selected"?: string;

956

/** Whether switch is selected */

957

isSelected?: boolean;

958

/** Custom CSS class */

959

className?: string;

960

}

961

962

function Switch(props: SwitchProps): JSX.Element;

963

964

/**

965

* Hook for Switch state management

966

*/

967

function useSwitch(props: SwitchProps): {

968

Component: React.ElementType;

969

slots: Record<SwitchSlots, string>;

970

classNames: SlotsToClasses<SwitchSlots>;

971

isSelected: boolean;

972

isPressed: boolean;

973

isFocused: boolean;

974

getBaseProps: () => any;

975

getWrapperProps: () => any;

976

getInputProps: () => any;

977

getLabelProps: () => any;

978

getThumbProps: () => any;

979

getStartContentProps: () => any;

980

getEndContentProps: () => any;

981

getThumbIconProps: () => any;

982

};

983

```

984

985

**Switch Usage Examples:**

986

987

```typescript

988

import { Switch } from "@nextui-org/react";

989

import { MoonIcon, SunIcon } from "@heroicons/react/24/solid";

990

991

function SwitchExamples() {

992

return (

993

<div className="space-y-4">

994

{/* Basic switch */}

995

<Switch defaultSelected>Airplane mode</Switch>

996

997

{/* Switch with icons */}

998

<Switch

999

defaultSelected

1000

size="lg"

1001

color="success"

1002

startContent={<SunIcon />}

1003

endContent={<MoonIcon />}

1004

>

1005

Dark mode

1006

</Switch>

1007

1008

{/* Switch with custom thumb icon */}

1009

<Switch

1010

defaultSelected

1011

size="lg"

1012

color="secondary"

1013

thumbIcon={({ isSelected, className }) =>

1014

isSelected ? (

1015

<SunIcon className={className} />

1016

) : (

1017

<MoonIcon className={className} />

1018

)

1019

}

1020

>

1021

Theme toggle

1022

</Switch>

1023

</div>

1024

);

1025

}

1026

```

1027

1028

### Slider

1029

1030

Range slider component for selecting numeric values within a defined range.

1031

1032

```typescript { .api }

1033

interface SliderProps {

1034

/** Slider label */

1035

label?: React.ReactNode;

1036

/** Current slider value(s) */

1037

value?: SliderValue;

1038

/** Default value for uncontrolled mode */

1039

defaultValue?: SliderValue;

1040

/** Minimum value */

1041

minValue?: number;

1042

/** Maximum value */

1043

maxValue?: number;

1044

/** Step increment */

1045

step?: number;

1046

/** Format options for value display */

1047

formatOptions?: Intl.NumberFormatOptions;

1048

/** Slider size */

1049

size?: "sm" | "md" | "lg";

1050

/** Color theme */

1051

color?: "foreground" | "primary" | "secondary" | "success" | "warning" | "danger";

1052

/** Fill offset for range sliders */

1053

fillOffset?: number;

1054

/** Step marks configuration */

1055

marks?: SliderStepMark[];

1056

/** Whether to hide thumb labels */

1057

hideThumb?: boolean;

1058

/** Whether to hide value label */

1059

hideValue?: boolean;

1060

/** Show steps as marks */

1061

showSteps?: boolean;

1062

/** Show tooltip on hover/focus */

1063

showTooltip?: boolean;

1064

/** Show outline on focus */

1065

showOutline?: boolean;

1066

/** Disable thumb scale animation */

1067

disableThumbScale?: boolean;

1068

/** Whether slider is required */

1069

isRequired?: boolean;

1070

/** Whether slider is disabled */

1071

isDisabled?: boolean;

1072

/** Slider orientation */

1073

orientation?: "horizontal" | "vertical";

1074

/** Tooltip properties */

1075

tooltipProps?: Partial<TooltipProps>;

1076

/** Custom thumb renderer */

1077

renderThumb?: (props: SliderRenderThumbProps) => React.ReactNode;

1078

/** Custom label renderer */

1079

renderLabel?: (props: SliderRenderLabelProps) => React.ReactNode;

1080

/** Custom value renderer */

1081

renderValue?: (props: SliderRenderValueProps) => React.ReactNode;

1082

/** Custom CSS class */

1083

className?: string;

1084

/** Slot-based styling */

1085

classNames?: SlotsToClasses<SliderSlots>;

1086

/** Value change handler */

1087

onChange?: (value: SliderValue) => void;

1088

/** Value change end handler */

1089

onChangeEnd?: (value: SliderValue) => void;

1090

}

1091

1092

type SliderValue = number | number[];

1093

1094

interface SliderStepMark {

1095

/** Step value */

1096

value: number;

1097

/** Step label */

1098

label?: React.ReactNode;

1099

}

1100

1101

interface SliderRenderThumbProps {

1102

/** Thumb index for multi-thumb sliders */

1103

index?: number;

1104

/** Current value */

1105

value?: number;

1106

/** Value as percentage */

1107

valueLabel?: string;

1108

/** Whether thumb has focus */

1109

isFocused?: boolean;

1110

/** Whether thumb is being dragged */

1111

isDragging?: boolean;

1112

/** Whether slider is disabled */

1113

isDisabled?: boolean;

1114

/** Thumb props */

1115

getThumbProps: (props?: any) => any;

1116

}

1117

1118

interface SliderRenderLabelProps {

1119

/** Current value(s) */

1120

value?: SliderValue;

1121

/** Formatted value text */

1122

valueLabel?: string;

1123

/** Whether slider has focus */

1124

isFocused?: boolean;

1125

/** Whether slider is disabled */

1126

isDisabled?: boolean;

1127

}

1128

1129

interface SliderRenderValueProps extends SliderRenderLabelProps {}

1130

1131

type SliderSlots =

1132

| "base" | "labelWrapper" | "label" | "value" | "trackWrapper"

1133

| "track" | "filler" | "thumb" | "mark" | "step";

1134

1135

function Slider(props: SliderProps): JSX.Element;

1136

1137

/**

1138

* Hook for Slider state management

1139

*/

1140

function useSlider(props: SliderProps): {

1141

Component: React.ElementType;

1142

slots: Record<SliderSlots, string>;

1143

classNames: SlotsToClasses<SliderSlots>;

1144

state: SliderState;

1145

getBaseProps: () => any;

1146

getLabelWrapperProps: () => any;

1147

getLabelProps: () => any;

1148

getValueProps: () => any;

1149

getTrackWrapperProps: () => any;

1150

getTrackProps: () => any;

1151

getFillerProps: () => any;

1152

getThumbProps: (index?: number) => any;

1153

getMarkProps: (mark: SliderStepMark, index: number) => any;

1154

getStepProps: (step: number, index: number) => any;

1155

};

1156

```

1157

1158

**Slider Usage Examples:**

1159

1160

```typescript

1161

import { Slider } from "@nextui-org/react";

1162

1163

function SliderExamples() {

1164

const [value, setValue] = useState(40);

1165

const [rangeValue, setRangeValue] = useState([100, 500]);

1166

1167

return (

1168

<div className="space-y-8">

1169

{/* Basic slider */}

1170

<Slider

1171

label="Temperature"

1172

step={1}

1173

minValue={0}

1174

maxValue={100}

1175

value={value}

1176

onChange={setValue}

1177

className="max-w-md"

1178

formatOptions={{style: "unit", unit: "celsius"}}

1179

/>

1180

1181

{/* Range slider */}

1182

<Slider

1183

label="Price Range"

1184

step={50}

1185

minValue={0}

1186

maxValue={1000}

1187

value={rangeValue}

1188

onChange={setRangeValue}

1189

className="max-w-md"

1190

formatOptions={{style: "currency", currency: "USD"}}

1191

/>

1192

1193

{/* Slider with steps */}

1194

<Slider

1195

label="Volume"

1196

step={10}

1197

minValue={0}

1198

maxValue={100}

1199

defaultValue={30}

1200

showSteps

1201

showTooltip

1202

showOutline

1203

className="max-w-md"

1204

marks={[

1205

{value: 20, label: "20%"},

1206

{value: 50, label: "50%"},

1207

{value: 80, label: "80%"},

1208

]}

1209

/>

1210

</div>

1211

);

1212

}

1213

```

1214

1215

### Textarea

1216

1217

A multi-line text input component with auto-resize capabilities and enhanced styling options.

1218

1219

```typescript { .api }

1220

interface TextAreaProps {

1221

/** Input label */

1222

label?: React.ReactNode;

1223

/** Current textarea value */

1224

value?: string;

1225

/** Default textarea value */

1226

defaultValue?: string;

1227

/** Input placeholder text */

1228

placeholder?: string;

1229

/** Helper description text */

1230

description?: React.ReactNode;

1231

/** Error message */

1232

errorMessage?: React.ReactNode | ((v: ValidationResult) => React.ReactNode);

1233

/** Validation function */

1234

validate?: (value: string) => ValidationError | true | null | undefined;

1235

/** Validation behavior */

1236

validationBehavior?: "aria" | "native";

1237

/** Whether textarea is required */

1238

isRequired?: boolean;

1239

/** Whether textarea is read-only */

1240

isReadOnly?: boolean;

1241

/** Whether textarea is disabled */

1242

isDisabled?: boolean;

1243

/** Whether textarea is invalid */

1244

isInvalid?: boolean;

1245

/** Auto focus on mount */

1246

autoFocus?: boolean;

1247

/** Textarea size */

1248

size?: "sm" | "md" | "lg";

1249

/** Border radius */

1250

radius?: "none" | "sm" | "md" | "lg" | "full";

1251

/** Visual variant */

1252

variant?: "flat" | "bordered" | "underlined" | "faded";

1253

/** Color theme */

1254

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

1255

/** Label placement */

1256

labelPlacement?: "inside" | "outside" | "outside-left";

1257

/** Whether textarea takes full width */

1258

fullWidth?: boolean;

1259

/** Minimum number of visible text lines */

1260

minRows?: number;

1261

/** Maximum number of visible text lines */

1262

maxRows?: number;

1263

/** Show clear button */

1264

isClearable?: boolean;

1265

/** Disable animations */

1266

disableAnimation?: boolean;

1267

/** Disable auto resize */

1268

disableAutosize?: boolean;

1269

/** Cached row height for performance */

1270

cacheMeasurements?: boolean;

1271

/** Custom CSS class */

1272

className?: string;

1273

/** Slot-based styling */

1274

classNames?: SlotsToClasses<InputSlots>;

1275

/** Value change handler */

1276

onValueChange?: (value: string) => void;

1277

/** Clear handler */

1278

onClear?: () => void;

1279

}

1280

1281

function Textarea(props: TextAreaProps): JSX.Element;

1282

```

1283

1284

**Textarea Usage Examples:**

1285

1286

```typescript

1287

import { Textarea, Button, Card, CardBody } from "@nextui-org/react";

1288

1289

function TextareaExamples() {

1290

const [value, setValue] = useState("");

1291

const [message, setMessage] = useState("");

1292

1293

return (

1294

<Card className="max-w-lg">

1295

<CardBody className="space-y-4">

1296

{/* Basic textarea */}

1297

<Textarea

1298

label="Description"

1299

placeholder="Enter your description"

1300

value={value}

1301

onValueChange={setValue}

1302

/>

1303

1304

{/* Textarea with validation */}

1305

<Textarea

1306

isRequired

1307

label="Message"

1308

placeholder="Write your message here..."

1309

description="Minimum 10 characters required"

1310

value={message}

1311

onValueChange={setMessage}

1312

minRows={3}

1313

maxRows={8}

1314

validate={(value) => {

1315

if (value.length < 10) {

1316

return "Message must be at least 10 characters long";

1317

}

1318

return true;

1319

}}

1320

errorMessage={(validation) =>

1321

validation.isInvalid ? validation.validationErrors[0] : undefined

1322

}

1323

/>

1324

1325

{/* Disabled auto-resize textarea */}

1326

<Textarea

1327

label="Fixed Size"

1328

placeholder="This textarea doesn't auto-resize"

1329

disableAutosize

1330

minRows={4}

1331

variant="bordered"

1332

color="secondary"

1333

/>

1334

1335

{/* Textarea with clear functionality */}

1336

<Textarea

1337

label="Clearable Content"

1338

placeholder="Type something and clear it"

1339

isClearable

1340

variant="underlined"

1341

/>

1342

1343

<Button

1344

color="primary"

1345

isDisabled={message.length < 10}

1346

className="w-full"

1347

>

1348

Submit Message

1349

</Button>

1350

</CardBody>

1351

</Card>

1352

);

1353

}

1354

```

1355

1356

### Input OTP

1357

1358

A specialized input component for One-Time Password entry with individual character segments.

1359

1360

```typescript { .api }

1361

interface InputOTPProps {

1362

/** Number of OTP digits */

1363

length?: number;

1364

/** Current OTP value */

1365

value?: string;

1366

/** Default OTP value */

1367

defaultValue?: string;

1368

/** Input placeholder for each digit */

1369

placeholder?: string;

1370

/** Whether input is required */

1371

isRequired?: boolean;

1372

/** Whether input is disabled */

1373

isDisabled?: boolean;

1374

/** Whether input is invalid */

1375

isInvalid?: boolean;

1376

/** Input size */

1377

size?: "sm" | "md" | "lg";

1378

/** Border radius */

1379

radius?: "none" | "sm" | "md" | "lg" | "full";

1380

/** Visual variant */

1381

variant?: "flat" | "bordered" | "underlined" | "faded";

1382

/** Color theme */

1383

color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger";

1384

/** Whether to allow only numeric input */

1385

allowedKeys?: RegExp;

1386

/** Custom CSS class */

1387

className?: string;

1388

/** Slot-based styling */

1389

classNames?: SlotsToClasses<InputOTPSlots>;

1390

/** Value change handler */

1391

onValueChange?: (value: string) => void;

1392

/** Complete handler (when all digits filled) */

1393

onComplete?: (value: string) => void;

1394

}

1395

1396

type InputOTPSlots = "base" | "segmentWrapper" | "segment" | "helperWrapper";

1397

1398

function InputOTP(props: InputOTPProps): JSX.Element;

1399

1400

/**

1401

* Hook for InputOTP state management

1402

*/

1403

function useInputOTP(props: InputOTPProps): {

1404

Component: React.ElementType;

1405

slots: Record<InputOTPSlots, string>;

1406

classNames: SlotsToClasses<InputOTPSlots>;

1407

getInputOTPProps: () => any;

1408

getSegmentProps: (index: number) => any;

1409

};

1410

```

1411

1412

**Input OTP Usage Examples:**

1413

1414

```typescript

1415

import { InputOTP, Card, CardHeader, CardBody, Button } from "@nextui-org/react";

1416

1417

function InputOTPExamples() {

1418

const [otp, setOtp] = useState("");

1419

const [verificationOTP, setVerificationOTP] = useState("");

1420

1421

const handleComplete = (value: string) => {

1422

console.log("OTP completed:", value);

1423

// Handle OTP verification

1424

};

1425

1426

return (

1427

<div className="space-y-6 max-w-sm mx-auto">

1428

<Card>

1429

<CardHeader>

1430

<h3>Email Verification</h3>

1431

</CardHeader>

1432

<CardBody className="space-y-4">

1433

<p className="text-sm text-default-500">

1434

Enter the 6-digit code sent to your email

1435

</p>

1436

1437

<InputOTP

1438

length={6}

1439

value={otp}

1440

onValueChange={setOtp}

1441

onComplete={handleComplete}

1442

placeholder="0"

1443

/>

1444

1445

<Button

1446

color="primary"

1447

isDisabled={otp.length !== 6}

1448

className="w-full"

1449

>

1450

Verify Code

1451

</Button>

1452

</CardBody>

1453

</Card>

1454

1455

<Card>

1456

<CardHeader>

1457

<h3>Custom Styled OTP</h3>

1458

</CardHeader>

1459

<CardBody className="space-y-4">

1460

<InputOTP

1461

length={4}

1462

value={verificationOTP}

1463

onValueChange={setVerificationOTP}

1464

variant="bordered"

1465

color="secondary"

1466

size="lg"

1467

radius="sm"

1468

allowedKeys={/^[0-9]$/}

1469

/>

1470

1471

<p className="text-xs text-default-400">

1472

Only numeric digits allowed

1473

</p>

1474

</CardBody>

1475

</Card>

1476

</div>

1477

);

1478

}

1479

```

1480

1481

## Input Component Types

1482

1483

```typescript { .api }

1484

// Common input types

1485

type InputSize = "sm" | "md" | "lg";

1486

type InputVariant = "flat" | "bordered" | "underlined" | "faded";

1487

type InputColor = "default" | "primary" | "secondary" | "success" | "warning" | "danger";

1488

type LabelPlacement = "inside" | "outside" | "outside-left";

1489

type ValidationBehavior = "aria" | "native";

1490

1491

// Validation types

1492

type ValidationError = string | string[];

1493

1494

interface ValidationResult {

1495

isInvalid: boolean;

1496

validationErrors: string[];

1497

validationDetails: ValidationDetails;

1498

}

1499

1500

interface ValidationDetails {

1501

[key: string]: any;

1502

}

1503

1504

// Selection types

1505

type Selection = "all" | Set<React.Key>;

1506

1507

// Group state interfaces

1508

interface CheckboxGroupState {

1509

readonly selectedKeys: Set<string>;

1510

readonly isDisabled: boolean;

1511

readonly isReadOnly: boolean;

1512

readonly isRequired: boolean;

1513

readonly isInvalid: boolean;

1514

readonly value: string[];

1515

addValue(value: string): void;

1516

removeValue(value: string): void;

1517

toggleValue(value: string): void;

1518

clearValue(): void;

1519

}

1520

1521

interface RadioGroupState {

1522

readonly selectedValue: string | null;

1523

readonly isDisabled: boolean;

1524

readonly isReadOnly: boolean;

1525

readonly isRequired: boolean;

1526

readonly isInvalid: boolean;

1527

setSelectedValue(value: string): void;

1528

}

1529

1530

interface SliderState {

1531

readonly values: number[];

1532

readonly focusedThumb: number | undefined;

1533

readonly isDisabled: boolean;

1534

getThumbValue(index: number): number;

1535

setThumbValue(index: number, value: number): void;

1536

incrementThumb(index: number, stepSize?: number): void;

1537

decrementThumb(index: number, stepSize?: number): void;

1538

}

1539

```