or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

data-display.mdform-controls.mdhooks-utilities.mdindex.mdlayout-positioning.mdselection-navigation.md

form-controls.mddocs/

0

# Form Controls

1

2

Core form elements providing accessible, headless components for user input including buttons, inputs, switches, sliders, and form control context management.

3

4

## Capabilities

5

6

### Button Component

7

8

Headless button component with built-in accessibility features and polymorphic support.

9

10

```typescript { .api }

11

/**

12

* Headless button component with accessibility and polymorphic support

13

* @param props - Button properties including styling slots and behavior options

14

* @returns Button element with proper accessibility attributes

15

*/

16

function Button<RootComponentType extends React.ElementType = "button">(

17

props: ButtonProps<RootComponentType>

18

): JSX.Element;

19

20

interface ButtonProps<RootComponentType extends React.ElementType = "button">

21

extends PolymorphicProps<ButtonTypeMap, RootComponentType> {

22

/** Ref for imperative actions like focusVisible() */

23

action?: React.Ref<ButtonActions>;

24

/** Button content */

25

children?: React.ReactNode;

26

/** Props for customizing button slots */

27

slotProps?: {

28

root?: SlotComponentProps<ButtonSlots["root"], {}, ButtonOwnerState>;

29

};

30

/** Components used for button slots */

31

slots?: ButtonSlots;

32

/** HTML element name for root (default: 'button') */

33

rootElementName?: keyof HTMLElementTagNameMap;

34

/** Whether button is disabled */

35

disabled?: boolean;

36

/** Whether button is focusable when disabled */

37

focusableWhenDisabled?: boolean;

38

/** Href for link-style buttons */

39

href?: string;

40

/** Tab index override */

41

tabIndex?: number;

42

/** Router link destination */

43

to?: string;

44

/** Button type attribute */

45

type?: "button" | "submit" | "reset";

46

}

47

48

interface ButtonSlots {

49

/** Root button element */

50

root?: React.ElementType;

51

}

52

53

interface ButtonActions {

54

/** Focus the button and show focus visible indicator */

55

focusVisible(): void;

56

}

57

58

interface ButtonOwnerState {

59

active: boolean;

60

disabled: boolean;

61

focusVisible: boolean;

62

}

63

```

64

65

**Usage Examples:**

66

67

```typescript

68

import { Button } from "@mui/base/Button";

69

70

// Basic button

71

<Button onClick={() => console.log("clicked")}>

72

Click me

73

</Button>

74

75

// Custom styled button

76

<Button

77

className="btn btn-primary"

78

slotProps={{

79

root: { className: "custom-root" }

80

}}

81

>

82

Styled Button

83

</Button>

84

85

// Link-style button

86

<Button href="/dashboard" component="a">

87

Go to Dashboard

88

</Button>

89

90

// Disabled but focusable button

91

<Button disabled focusableWhenDisabled>

92

Disabled but Focusable

93

</Button>

94

```

95

96

**Button Classes:**

97

98

```typescript { .api }

99

// CSS classes for Button component styling

100

interface ButtonClasses {

101

/** Class name applied to the root element */

102

root: string;

103

/** State class applied if active={true} */

104

active: string;

105

/** State class applied if disabled={true} */

106

disabled: string;

107

/** State class applied if focusVisible={true} */

108

focusVisible: string;

109

}

110

111

// Button classes object

112

declare const buttonClasses: ButtonClasses;

113

114

// Utility function for Button class generation

115

function getButtonUtilityClass(slot: string): string;

116

```

117

118

### Input Component

119

120

Headless input component with form control integration and validation support.

121

122

```typescript { .api }

123

/**

124

* Headless input component with form control integration

125

* @param props - Input properties including value, validation, and styling

126

* @returns Input element with proper form control integration

127

*/

128

function Input<RootComponentType extends React.ElementType = "div">(

129

props: InputProps<RootComponentType>

130

): JSX.Element;

131

132

interface InputProps<RootComponentType extends React.ElementType = "div">

133

extends PolymorphicProps<InputTypeMap, RootComponentType> {

134

/** Default input value */

135

defaultValue?: unknown;

136

/** Whether input is disabled */

137

disabled?: boolean;

138

/** Whether input has validation error */

139

error?: boolean;

140

/** Change event handler */

141

onChange?: React.ChangeEventHandler<HTMLInputElement>;

142

/** Whether input is required */

143

required?: boolean;

144

/** Current input value */

145

value?: unknown;

146

/** Props for customizing input slots */

147

slotProps?: {

148

root?: SlotComponentProps<InputSlots["root"], {}, InputOwnerState>;

149

input?: SlotComponentProps<InputSlots["input"], {}, InputOwnerState>;

150

};

151

/** Components used for input slots */

152

slots?: InputSlots;

153

/** Input placeholder text */

154

placeholder?: string;

155

/** Input type attribute */

156

type?: string;

157

/** Input name attribute */

158

name?: string;

159

/** Input id attribute */

160

id?: string;

161

}

162

163

interface InputSlots {

164

/** Root container element */

165

root?: React.ElementType;

166

/** Input element */

167

input?: React.ElementType;

168

}

169

170

interface InputOwnerState {

171

disabled: boolean;

172

error: boolean;

173

focused: boolean;

174

required: boolean;

175

value: unknown;

176

}

177

```

178

179

**Usage Examples:**

180

181

```typescript

182

import { Input, FormControl } from "@mui/base";

183

184

// Basic input

185

<Input

186

placeholder="Enter your name"

187

onChange={(e) => setName(e.target.value)}

188

/>

189

190

// Input with form control

191

<FormControl error={hasError}>

192

<Input

193

value={email}

194

onChange={(e) => setEmail(e.target.value)}

195

type="email"

196

required

197

/>

198

</FormControl>

199

200

// Custom styled input

201

<Input

202

slotProps={{

203

root: { className: "input-wrapper" },

204

input: { className: "input-field" }

205

}}

206

/>

207

```

208

209

### Switch Component

210

211

Toggle switch component for boolean values with accessibility support.

212

213

```typescript { .api }

214

/**

215

* Toggle switch component for boolean values

216

* @param props - Switch properties including checked state and styling

217

* @returns Switch element with proper accessibility attributes

218

*/

219

function Switch<RootComponentType extends React.ElementType = "span">(

220

props: SwitchProps<RootComponentType>

221

): JSX.Element;

222

223

interface SwitchProps<RootComponentType extends React.ElementType = "span">

224

extends PolymorphicProps<SwitchTypeMap, RootComponentType> {

225

/** Whether switch is checked */

226

checked?: boolean;

227

/** Default checked state */

228

defaultChecked?: boolean;

229

/** Whether switch is disabled */

230

disabled?: boolean;

231

/** Change event handler */

232

onChange?: React.ChangeEventHandler<HTMLInputElement>;

233

/** Whether switch is read-only */

234

readOnly?: boolean;

235

/** Whether switch is required */

236

required?: boolean;

237

/** Props for customizing switch slots */

238

slotProps?: {

239

root?: SlotComponentProps<SwitchSlots["root"], {}, SwitchOwnerState>;

240

thumb?: SlotComponentProps<SwitchSlots["thumb"], {}, SwitchOwnerState>;

241

input?: SlotComponentProps<SwitchSlots["input"], {}, SwitchOwnerState>;

242

track?: SlotComponentProps<SwitchSlots["track"], {}, SwitchOwnerState>;

243

};

244

/** Components used for switch slots */

245

slots?: SwitchSlots;

246

}

247

248

interface SwitchSlots {

249

/** Root container element */

250

root?: React.ElementType;

251

/** Switch thumb element */

252

thumb?: React.ElementType;

253

/** Hidden input element */

254

input?: React.ElementType;

255

/** Switch track element */

256

track?: React.ElementType;

257

}

258

259

interface SwitchOwnerState {

260

checked: boolean;

261

disabled: boolean;

262

focusVisible: boolean;

263

readOnly: boolean;

264

}

265

```

266

267

### Slider Component

268

269

Range slider component for numeric value selection with marks and accessibility.

270

271

```typescript { .api }

272

/**

273

* Range slider component for numeric value selection

274

* @param props - Slider properties including value range and styling

275

* @returns Slider element with proper accessibility and keyboard support

276

*/

277

function Slider<RootComponentType extends React.ElementType = "span">(

278

props: SliderProps<RootComponentType>

279

): JSX.Element;

280

281

interface SliderProps<RootComponentType extends React.ElementType = "span">

282

extends PolymorphicProps<SliderTypeMap, RootComponentType> {

283

/** Current slider value or array of values */

284

value?: number | number[];

285

/** Default slider value */

286

defaultValue?: number | number[];

287

/** Minimum slider value */

288

min?: number;

289

/** Maximum slider value */

290

max?: number;

291

/** Step increment */

292

step?: number | null;

293

/** Whether slider is disabled */

294

disabled?: boolean;

295

/** Marks on the slider */

296

marks?: boolean | SliderMark[];

297

/** Change event handler */

298

onChange?: (event: Event, value: number | number[]) => void;

299

/** Change committed event handler */

300

onChangeCommitted?: (event: React.SyntheticEvent | Event, value: number | number[]) => void;

301

/** Props for customizing slider slots */

302

slotProps?: {

303

root?: SlotComponentProps<SliderSlots["root"], {}, SliderOwnerState>;

304

rail?: SlotComponentProps<SliderSlots["rail"], {}, SliderOwnerState>;

305

track?: SlotComponentProps<SliderSlots["track"], {}, SliderOwnerState>;

306

thumb?: SlotComponentProps<SliderSlots["thumb"], {}, SliderOwnerState>;

307

mark?: SlotComponentProps<SliderSlots["mark"], {}, SliderOwnerState>;

308

markLabel?: SlotComponentProps<SliderSlots["markLabel"], {}, SliderOwnerState>;

309

valueLabel?: SlotComponentProps<SliderSlots["valueLabel"], {}, SliderOwnerState>;

310

input?: SlotComponentProps<SliderSlots["input"], {}, SliderOwnerState>;

311

};

312

/** Components used for slider slots */

313

slots?: SliderSlots;

314

}

315

316

interface SliderSlots {

317

root?: React.ElementType;

318

rail?: React.ElementType;

319

track?: React.ElementType;

320

thumb?: React.ElementType;

321

mark?: React.ElementType;

322

markLabel?: React.ElementType;

323

valueLabel?: React.ElementType;

324

input?: React.ElementType;

325

}

326

327

interface SliderMark {

328

value: number;

329

label?: React.ReactNode;

330

}

331

```

332

333

### Badge Component

334

335

Badge component for status indicators and counts.

336

337

```typescript { .api }

338

/**

339

* Badge component for status indicators and counts

340

* @param props - Badge properties including content and visibility

341

* @returns Badge element positioned relative to children

342

*/

343

function Badge<RootComponentType extends React.ElementType = "span">(

344

props: BadgeProps<RootComponentType>

345

): JSX.Element;

346

347

interface BadgeProps<RootComponentType extends React.ElementType = "span">

348

extends PolymorphicProps<BadgeTypeMap, RootComponentType> {

349

/** Content rendered within the badge */

350

badgeContent?: React.ReactNode;

351

/** The badge will be added relative to this node */

352

children?: React.ReactNode;

353

/** If true, the badge is invisible */

354

invisible?: boolean;

355

/** Max count to show (default: 99) */

356

max?: number;

357

/** Controls whether badge is hidden when badgeContent is zero */

358

showZero?: boolean;

359

/** Props for customizing badge slots */

360

slotProps?: {

361

root?: SlotComponentProps<BadgeSlots["root"], {}, BadgeOwnerState>;

362

badge?: SlotComponentProps<BadgeSlots["badge"], {}, BadgeOwnerState>;

363

};

364

/** Components used for badge slots */

365

slots?: BadgeSlots;

366

}

367

368

interface BadgeSlots {

369

/** Root container element */

370

root?: React.ElementType;

371

/** Badge indicator element */

372

badge?: React.ElementType;

373

}

374

375

interface BadgeOwnerState {

376

badgeContent: React.ReactNode;

377

invisible: boolean;

378

max: number;

379

showZero: boolean;

380

}

381

```

382

383

### FormControl Component

384

385

Provides form control context to child components for coordinated state management.

386

387

```typescript { .api }

388

/**

389

* Form control context provider for coordinated form state

390

* @param props - Form control properties including value and validation state

391

* @returns Context provider for form control state

392

*/

393

function FormControl<RootComponentType extends React.ElementType = "div">(

394

props: FormControlProps<RootComponentType>

395

): JSX.Element;

396

397

interface FormControlProps<RootComponentType extends React.ElementType = "div">

398

extends PolymorphicProps<FormControlTypeMap, RootComponentType> {

399

/** Default form control value */

400

defaultValue?: unknown;

401

/** Whether form control is disabled */

402

disabled?: boolean;

403

/** Whether form control is in error state */

404

error?: boolean;

405

/** Change handler for form control */

406

onChange?: (event: React.SyntheticEvent) => void;

407

/** Whether form control is required */

408

required?: boolean;

409

/** Current form control value */

410

value?: unknown;

411

/** Form control children */

412

children?: React.ReactNode;

413

}

414

415

// Hook for accessing form control context

416

function useFormControlContext(): FormControlState | undefined;

417

418

interface FormControlState {

419

disabled: boolean;

420

error: boolean;

421

required: boolean;

422

value: unknown;

423

onChange: (event: React.SyntheticEvent) => void;

424

}

425

```

426

427

### NumberInput Component (Unstable)

428

429

Specialized number input with increment/decrement stepper controls.

430

431

```typescript { .api }

432

/**

433

* Number input component with increment/decrement controls

434

* @param props - Number input properties including min/max bounds and step

435

* @returns Number input element with stepper controls

436

*/

437

function Unstable_NumberInput<RootComponentType extends React.ElementType = "div">(

438

props: NumberInputProps<RootComponentType>

439

): JSX.Element;

440

441

interface NumberInputProps<RootComponentType extends React.ElementType = "div">

442

extends PolymorphicProps<NumberInputTypeMap, RootComponentType> {

443

/** Current number value */

444

value?: number;

445

/** Default number value */

446

defaultValue?: number;

447

/** Minimum allowed value */

448

min?: number;

449

/** Maximum allowed value */

450

max?: number;

451

/** Step increment for stepper controls */

452

step?: number;

453

/** Whether input is disabled */

454

disabled?: boolean;

455

/** Whether input has validation error */

456

error?: boolean;

457

/** Whether input is required */

458

required?: boolean;

459

/** Change event handler */

460

onChange?: (event: React.FocusEvent<HTMLInputElement> | React.PointerEvent | React.KeyboardEvent, value: number | null) => void;

461

/** Props for customizing number input slots */

462

slotProps?: {

463

root?: SlotComponentProps<NumberInputSlots["root"], {}, NumberInputOwnerState>;

464

input?: SlotComponentProps<NumberInputSlots["input"], {}, NumberInputOwnerState>;

465

incrementButton?: SlotComponentProps<NumberInputSlots["incrementButton"], {}, NumberInputOwnerState>;

466

decrementButton?: SlotComponentProps<NumberInputSlots["decrementButton"], {}, NumberInputOwnerState>;

467

};

468

/** Components used for number input slots */

469

slots?: NumberInputSlots;

470

}

471

472

interface NumberInputSlots {

473

root?: React.ElementType;

474

input?: React.ElementType;

475

incrementButton?: React.ElementType;

476

decrementButton?: React.ElementType;

477

}

478

```

479

480

## Related Hooks

481

482

```typescript { .api }

483

// Button behavior hook

484

function useButton(parameters: UseButtonParameters): UseButtonReturnValue;

485

486

// Input behavior hook

487

function useInput(parameters: UseInputParameters): UseInputReturnValue;

488

489

// Switch behavior hook

490

function useSwitch(parameters: UseSwitchParameters): UseSwitchReturnValue;

491

492

// Slider behavior hook

493

function useSlider(parameters: UseSliderParameters): UseSliderReturnValue;

494

495

// Badge display logic hook

496

function useBadge(parameters: UseBadgeParameters): UseBadgeReturnValue;

497

498

// Number input behavior hook

499

function unstable_useNumberInput(parameters: UseNumberInputParameters): UseNumberInputReturnValue;

500

```