or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-types.mdcore-components.mdindex.mdinteractive-components.md

configuration-types.mddocs/

0

# Configuration & Types

1

2

Type definitions and interfaces for configuring drawer behavior. This section covers all the available options for customizing drawer behavior, animations, and interactions.

3

4

## Capabilities

5

6

### DialogProps Interface

7

8

Main configuration interface for the Root component that controls all aspects of drawer behavior.

9

10

```typescript { .api }

11

/**

12

* Main props interface for Root component

13

* Union of WithFadeFromProps or WithoutFadeFromProps

14

*/

15

type DialogProps = (WithFadeFromProps | WithoutFadeFromProps) & BaseDialogProps;

16

17

interface BaseDialogProps {

18

/** Controlled open state */

19

open?: boolean;

20

/** Callback fired when open state changes */

21

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

22

/** Default open state for uncontrolled usage */

23

defaultOpen?: boolean;

24

/** Child components */

25

children?: React.ReactNode;

26

/** Controlled active snap point */

27

activeSnapPoint?: number | string | null;

28

/** Callback to set active snap point */

29

setActiveSnapPoint?: (snapPoint: number | string | null) => void;

30

/** Threshold for closing (default: 0.25) */

31

closeThreshold?: number;

32

/** Prevent body style changes */

33

noBodyStyles?: boolean;

34

/** Enable background scaling effect */

35

shouldScaleBackground?: boolean;

36

/** Change background color when scaling */

37

setBackgroundColorOnScale?: boolean;

38

/** Duration for scroll lock in ms (default: 100) */

39

scrollLockTimeout?: number;

40

/** Fixed positioning behavior */

41

fixed?: boolean;

42

/** Restrict dragging to handle only */

43

handleOnly?: boolean;

44

/** Allow dismissal via gestures (default: true) */

45

dismissible?: boolean;

46

/** Drag event handler */

47

onDrag?: (event: React.PointerEvent<HTMLDivElement>, percentageDragged: number) => void;

48

/** Release event handler */

49

onRelease?: (event: React.PointerEvent<HTMLDivElement>, open: boolean) => void;

50

/** Modal behavior (default: true) */

51

modal?: boolean;

52

/** Nested drawer support */

53

nested?: boolean;

54

/** Close callback */

55

onClose?: () => void;

56

/** Drawer direction (default: 'bottom') */

57

direction?: DrawerDirection;

58

/** Disable scroll prevention (default: true) */

59

disablePreventScroll?: boolean;

60

/** Reposition inputs on keyboard */

61

repositionInputs?: boolean;

62

/** Disable velocity-based snapping */

63

snapToSequentialPoint?: boolean;

64

/** Portal container */

65

container?: HTMLElement | null;

66

/** Animation end callback */

67

onAnimationEnd?: (open: boolean) => void;

68

/** Prevent scroll restoration */

69

preventScrollRestoration?: boolean;

70

/** Auto focus behavior */

71

autoFocus?: boolean;

72

}

73

```

74

75

### Snap Points Configuration

76

77

Snap points allow drawers to "snap" to specific positions, creating multi-height drawer experiences.

78

79

```typescript { .api }

80

/**

81

* Props for drawers with fade configuration

82

*/

83

interface WithFadeFromProps {

84

/** Array of snap points - numbers 0-100 for % or px values like "300px" */

85

snapPoints: (number | string)[];

86

/** Index from which overlay fade should be applied */

87

fadeFromIndex: number;

88

}

89

90

/**

91

* Props for drawers without fade configuration

92

*/

93

interface WithoutFadeFromProps {

94

/** Optional array of snap points */

95

snapPoints?: (number | string)[];

96

/** Not allowed when snapPoints are optional */

97

fadeFromIndex?: never;

98

}

99

```

100

101

**Usage Examples:**

102

103

```typescript

104

// Drawer with snap points and fade

105

<Drawer.Root

106

snapPoints={[0.2, 0.5, 0.8]}

107

fadeFromIndex={1} // Fade starts from 50% height

108

>

109

{/* drawer content */}

110

</Drawer.Root>

111

112

// Drawer with pixel-based snap points

113

<Drawer.Root

114

snapPoints={["100px", "300px", "500px"]}

115

fadeFromIndex={0}

116

>

117

{/* drawer content */}

118

</Drawer.Root>

119

120

// Drawer without snap points

121

<Drawer.Root>

122

{/* drawer content */}

123

</Drawer.Root>

124

```

125

126

### Direction and Positioning

127

128

Control drawer direction and positioning behavior.

129

130

```typescript { .api }

131

/**

132

* Valid drawer directions

133

*/

134

type DrawerDirection = 'top' | 'bottom' | 'left' | 'right';

135

136

/**

137

* Snap point configuration interface

138

*/

139

interface SnapPoint {

140

/** Fraction of screen height/width (0-1) */

141

fraction: number;

142

/** Absolute height/width in pixels */

143

height: number;

144

}

145

```

146

147

**Usage Examples:**

148

149

```typescript

150

// Bottom drawer (default)

151

<Drawer.Root direction="bottom">

152

{/* content */}

153

</Drawer.Root>

154

155

// Side drawer

156

<Drawer.Root direction="right">

157

{/* content */}

158

</Drawer.Root>

159

160

// Top drawer

161

<Drawer.Root direction="top">

162

{/* content */}

163

</Drawer.Root>

164

```

165

166

### Event Handlers

167

168

Event handling configuration for custom behavior during drawer interactions.

169

170

```typescript { .api }

171

/**

172

* Drag event handler type

173

*/

174

type DragHandler = (event: React.PointerEvent<HTMLDivElement>, percentageDragged: number) => void;

175

176

/**

177

* Release event handler type

178

*/

179

type ReleaseHandler = (event: React.PointerEvent<HTMLDivElement>, open: boolean) => void;

180

181

/**

182

* Animation end handler type

183

*/

184

type AnimationEndHandler = (open: boolean) => void;

185

```

186

187

**Usage Examples:**

188

189

```typescript

190

function CustomDrawer() {

191

const handleDrag = (event: React.PointerEvent<HTMLDivElement>, percentage: number) => {

192

console.log(`Dragged to ${percentage}%`);

193

// Custom drag behavior

194

};

195

196

const handleRelease = (event: React.PointerEvent<HTMLDivElement>, open: boolean) => {

197

console.log(`Released, drawer is ${open ? 'open' : 'closed'}`);

198

// Custom release behavior

199

};

200

201

const handleAnimationEnd = (open: boolean) => {

202

console.log(`Animation ended, drawer is ${open ? 'open' : 'closed'}`);

203

// Post-animation logic

204

};

205

206

return (

207

<Drawer.Root

208

onDrag={handleDrag}

209

onRelease={handleRelease}

210

onAnimationEnd={handleAnimationEnd}

211

>

212

{/* drawer content */}

213

</Drawer.Root>

214

);

215

}

216

```

217

218

### Individual Type Exports

219

220

These types are exported individually for direct use in TypeScript projects.

221

222

```typescript { .api }

223

/**

224

* Props interface for drawers with fade configuration

225

*/

226

interface WithFadeFromProps {

227

/** Array of snap points - numbers 0-100 for % or px values like "300px" */

228

snapPoints: (number | string)[];

229

/** Index from which overlay fade should be applied */

230

fadeFromIndex: number;

231

}

232

233

/**

234

* Props interface for drawers without fade configuration

235

*/

236

interface WithoutFadeFromProps {

237

/** Optional array of snap points */

238

snapPoints?: (number | string)[];

239

/** Not allowed when snapPoints are optional */

240

fadeFromIndex?: never;

241

}

242

243

/**

244

* Props type for Content component - exported individually

245

*/

246

type ContentProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>;

247

248

/**

249

* Props type for Handle component - exported individually

250

*/

251

interface HandleProps extends React.ComponentPropsWithoutRef<'div'> {

252

/** Prevent snap point cycling when dragging the handle */

253

preventCycle?: boolean;

254

}

255

```

256

257

### Component-Specific Types

258

259

Additional type definitions for individual components.

260

261

```typescript { .api }

262

/**

263

* Props type for Portal component (internal)

264

*/

265

type PortalProps = React.ComponentPropsWithoutRef<typeof DialogPrimitive.Portal> & {

266

/** Override container for portal rendering */

267

container?: HTMLElement;

268

}

269

```

270

271

### Advanced Configuration

272

273

Advanced configuration options for fine-tuning drawer behavior.

274

275

```typescript { .api }

276

/**

277

* Advanced configuration options

278

*/

279

interface AdvancedConfig {

280

/** Threshold for closing drawer (0-1, default: 0.25) */

281

closeThreshold?: number;

282

/** Timeout for scroll lock in milliseconds (default: 100) */

283

scrollLockTimeout?: number;

284

/** Prevent default body style changes */

285

noBodyStyles?: boolean;

286

/** Scale background content when drawer opens */

287

shouldScaleBackground?: boolean;

288

/** Change background color during scaling */

289

setBackgroundColorOnScale?: boolean;

290

/** Use fixed positioning */

291

fixed?: boolean;

292

/** Only allow dragging via handle */

293

handleOnly?: boolean;

294

/** Disable gesture-based dismissal */

295

dismissible?: boolean;

296

/** Disable scroll prevention (default: true) */

297

disablePreventScroll?: boolean;

298

/** Reposition inputs when keyboard appears */

299

repositionInputs?: boolean;

300

/** Disable velocity-based snap point selection */

301

snapToSequentialPoint?: boolean;

302

/** Prevent scroll position restoration */

303

preventScrollRestoration?: boolean;

304

/** Control auto-focus behavior */

305

autoFocus?: boolean;

306

}

307

```

308

309

**Usage Examples:**

310

311

```typescript

312

// Fine-tuned drawer configuration

313

<Drawer.Root

314

closeThreshold={0.4} // Require 40% drag to close

315

scrollLockTimeout={1000} // 1 second scroll lock

316

shouldScaleBackground={true}

317

setBackgroundColorOnScale={true}

318

handleOnly={true} // Only draggable via handle

319

repositionInputs={true} // Handle mobile keyboards

320

snapToSequentialPoint={true} // Disable velocity snapping

321

>

322

{/* drawer content */}

323

</Drawer.Root>

324

325

// Mobile-optimized drawer

326

<Drawer.Root

327

fixed={true}

328

repositionInputs={true}

329

disablePreventScroll={false}

330

direction="bottom"

331

>

332

{/* mobile-friendly content */}

333

</Drawer.Root>

334

```

335

336

### Context and Hooks

337

338

Advanced context and hook types for custom drawer implementations.

339

340

```typescript { .api }

341

/**

342

* Hook to access drawer context from within drawer components

343

* @returns DrawerContextValue object with drawer state and methods

344

* @throws Error if used outside of Drawer.Root

345

*/

346

function useDrawerContext(): DrawerContextValue;

347

348

/**

349

* Context value interface containing all drawer state and methods

350

*/

351

interface DrawerContextValue {

352

/** Ref to the drawer content element */

353

drawerRef: React.RefObject<HTMLDivElement>;

354

/** Ref to the overlay element */

355

overlayRef: React.RefObject<HTMLDivElement>;

356

/** Pointer press handler */

357

onPress: (event: React.PointerEvent<HTMLDivElement>) => void;

358

/** Pointer release handler */

359

onRelease: (event: React.PointerEvent<HTMLDivElement> | null) => void;

360

/** Drag handler */

361

onDrag: (event: React.PointerEvent<HTMLDivElement>) => void;

362

/** Nested drawer drag handler */

363

onNestedDrag: (event: React.PointerEvent<HTMLDivElement>, percentageDragged: number) => void;

364

/** Nested drawer open change handler */

365

onNestedOpenChange: (open: boolean) => void;

366

/** Nested drawer release handler */

367

onNestedRelease: (event: React.PointerEvent<HTMLDivElement>, open: boolean) => void;

368

/** Whether drawer can be dismissed */

369

dismissible: boolean;

370

/** Current open state */

371

isOpen: boolean;

372

/** Current dragging state */

373

isDragging: boolean;

374

/** Keyboard visibility ref */

375

keyboardIsOpen: React.MutableRefObject<boolean>;

376

/** Computed snap point offsets */

377

snapPointsOffset: number[] | null;

378

/** Configured snap points */

379

snapPoints?: (number | string)[] | null;

380

/** Current active snap point index */

381

activeSnapPointIndex?: number | null;

382

/** Modal behavior setting */

383

modal: boolean;

384

/** Whether overlay should fade */

385

shouldFade: boolean;

386

/** Current active snap point */

387

activeSnapPoint?: number | string | null;

388

/** Function to set active snap point */

389

setActiveSnapPoint: (snapPoint: number | string | null) => void;

390

/** Function to close drawer */

391

closeDrawer: () => void;

392

/** Open prop from parent */

393

openProp?: boolean;

394

/** Open change callback from parent */

395

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

396

/** Drawer direction */

397

direction: DrawerDirection;

398

/** Whether to scale background */

399

shouldScaleBackground: boolean;

400

/** Whether to change background color on scale */

401

setBackgroundColorOnScale: boolean;

402

/** Whether to apply body styles */

403

noBodyStyles: boolean;

404

/** Whether only handle can drag */

405

handleOnly?: boolean;

406

/** Portal container */

407

container?: HTMLElement | null;

408

/** Auto focus setting */

409

autoFocus?: boolean;

410

/** Animation state ref */

411

shouldAnimate?: React.MutableRefObject<boolean>;

412

}

413

```

414

415

**Usage Examples:**

416

417

```typescript

418

import { useDrawerContext } from "vaul";

419

420

// Custom component that uses drawer context

421

function CustomDrawerComponent() {

422

const { isOpen, closeDrawer, isDragging } = useDrawerContext();

423

424

return (

425

<div>

426

<p>Drawer is {isOpen ? 'open' : 'closed'}</p>

427

<p>Currently {isDragging ? 'dragging' : 'not dragging'}</p>

428

<button onClick={closeDrawer}>Close Drawer</button>

429

</div>

430

);

431

}

432

433

// Use within drawer content

434

<Drawer.Root>

435

<Drawer.Trigger>Open</Drawer.Trigger>

436

<Drawer.Portal>

437

<Drawer.Content>

438

<CustomDrawerComponent />

439

</Drawer.Content>

440

</Drawer.Portal>

441

</Drawer.Root>

442

```

443

444

### State Management Types

445

446

Types for controlled and uncontrolled state management.

447

448

```typescript { .api }

449

/**

450

* Controlled state configuration

451

*/

452

interface ControlledState {

453

/** Current open state */

454

open: boolean;

455

/** State change handler */

456

onOpenChange: (open: boolean) => void;

457

/** Current active snap point */

458

activeSnapPoint?: number | string | null;

459

/** Active snap point change handler */

460

setActiveSnapPoint?: (snapPoint: number | string | null) => void;

461

}

462

463

/**

464

* Uncontrolled state configuration

465

*/

466

interface UncontrolledState {

467

/** Default open state */

468

defaultOpen?: boolean;

469

/** Close callback for uncontrolled usage */

470

onClose?: () => void;

471

}

472

```

473

474

**Usage Examples:**

475

476

```typescript

477

// Controlled drawer

478

function ControlledDrawer() {

479

const [open, setOpen] = useState(false);

480

const [activeSnap, setActiveSnap] = useState<number | null>(null);

481

482

return (

483

<Drawer.Root

484

open={open}

485

onOpenChange={setOpen}

486

activeSnapPoint={activeSnap}

487

setActiveSnapPoint={setActiveSnap}

488

snapPoints={[0.3, 0.6, 0.9]}

489

>

490

{/* drawer content */}

491

</Drawer.Root>

492

);

493

}

494

495

// Uncontrolled drawer

496

function UncontrolledDrawer() {

497

return (

498

<Drawer.Root

499

defaultOpen={false}

500

onClose={() => console.log('Drawer closed')}

501

>

502

{/* drawer content */}

503

</Drawer.Root>

504

);

505

}

506

```

507

508

### Utility Types

509

510

Additional utility types used internally but may be useful for advanced usage.

511

512

```typescript { .api }

513

/**

514

* Utility type for any function

515

*/

516

type AnyFunction = (...args: any) => any;

517

518

/**

519

* Snap point configuration interface

520

*/

521

interface SnapPoint {

522

/** Fraction of screen height/width (0-1) */

523

fraction: number;

524

/** Absolute height/width in pixels */

525

height: number;

526

}

527

```