or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# RC-Drawer

1

2

## Overview

3

4

RC-Drawer is a comprehensive React component for creating slide-out navigation panels and sidebar interfaces. It provides smooth animations, flexible positioning, keyboard support, focus management, and accessibility features. The component supports four placement positions, nested drawer management with push/pull behavior, and extensive customization options for modern React applications.

5

6

## Package Information

7

8

- **Package Name**: rc-drawer

9

- **Package Type**: npm

10

- **Language**: TypeScript

11

- **Installation**: `npm install rc-drawer`

12

13

## Core Imports

14

15

```typescript

16

import Drawer from "rc-drawer";

17

import type { DrawerProps } from "rc-drawer";

18

```

19

20

For CommonJS:

21

22

```javascript

23

const Drawer = require("rc-drawer");

24

```

25

26

## Basic Usage

27

28

```typescript

29

import React, { useState } from "react";

30

import Drawer from "rc-drawer";

31

32

function App() {

33

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

34

35

return (

36

<div>

37

<button onClick={() => setOpen(true)}>Open Drawer</button>

38

<Drawer

39

open={open}

40

onClose={() => setOpen(false)}

41

placement="right"

42

width={300}

43

>

44

<h2>Drawer Content</h2>

45

<p>This is the drawer content</p>

46

</Drawer>

47

</div>

48

);

49

}

50

```

51

52

## Architecture

53

54

RC-Drawer is built with several key architectural components:

55

56

- **Portal Integration**: Uses `@rc-component/portal` for rendering outside the React component tree

57

- **Motion System**: Leverages `rc-motion` for smooth slide animations and transitions

58

- **Context System**: Provides context for nested drawer management and ref sharing

59

- **Focus Management**: Automatic focus handling with focus trapping and restoration

60

- **Accessibility**: Full ARIA support with proper dialog semantics and keyboard navigation

61

62

## Capabilities

63

64

### Main Drawer Component

65

66

The primary React component for creating drawer interfaces with comprehensive configuration options.

67

68

```typescript { .api }

69

/**

70

* Main drawer component that renders a slide-out panel with backdrop

71

*/

72

declare const Drawer: React.FC<DrawerProps>;

73

74

interface DrawerProps extends

75

Omit<DrawerPopupProps, 'prefixCls' | 'inline'>,

76

DrawerPanelEvents,

77

DrawerPanelAccessibility {

78

/** CSS class prefix (default: 'rc-drawer') */

79

prefixCls?: string;

80

/** Controls drawer visibility */

81

open?: boolean;

82

/** Close event handler */

83

onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;

84

/** Whether to destroy drawer content when closed */

85

destroyOnClose?: boolean;

86

/** Portal container selector/element */

87

getContainer?: PortalProps['getContainer'];

88

/** Reference to drawer panel element */

89

panelRef?: React.Ref<HTMLDivElement>;

90

/** Custom class names for different parts */

91

classNames?: DrawerClassNames;

92

/** Custom styles for different parts */

93

styles?: DrawerStyles;

94

}

95

```

96

97

### Placement and Positioning

98

99

Control where the drawer appears and how it animates into view.

100

101

```typescript { .api }

102

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

103

104

interface DrawerPopupProps {

105

/** Drawer placement position (default: 'right') */

106

placement?: Placement;

107

/** Drawer width for left/right placement or height for top/bottom */

108

width?: number | string;

109

/** Drawer height for top/bottom placement */

110

height?: number | string;

111

/** Custom motion configuration or function returning motion config */

112

motion?: CSSMotionProps | ((placement: Placement) => CSSMotionProps);

113

/** z-index for drawer stacking */

114

zIndex?: number;

115

}

116

```

117

118

**Usage Example:**

119

120

```typescript

121

// Left sidebar drawer

122

<Drawer placement="left" width={250} open={leftOpen}>

123

<Navigation />

124

</Drawer>

125

126

// Top notification drawer

127

<Drawer placement="top" height={100} open={notificationOpen}>

128

<Notifications />

129

</Drawer>

130

131

// Custom animation

132

<Drawer

133

placement="right"

134

motion={(placement) => ({

135

motionName: `slide-${placement}`,

136

duration: 300

137

})}

138

open={customOpen}

139

>

140

<Content />

141

</Drawer>

142

```

143

144

### Mask and Backdrop Control

145

146

Configure the backdrop overlay and its behavior.

147

148

```typescript { .api }

149

interface DrawerPopupProps {

150

/** Whether to show backdrop mask (default: true) */

151

mask?: boolean;

152

/** Whether clicking mask closes drawer (default: true) */

153

maskClosable?: boolean;

154

/** Custom mask CSS class name */

155

maskClassName?: string;

156

/** Custom mask inline styles */

157

maskStyle?: React.CSSProperties;

158

/** Custom mask animation configuration */

159

maskMotion?: CSSMotionProps;

160

}

161

```

162

163

**Usage Example:**

164

165

```typescript

166

// Drawer without backdrop

167

<Drawer mask={false} open={open}>

168

<Content />

169

</Drawer>

170

171

// Drawer with custom mask styling

172

<Drawer

173

maskStyle={{ backgroundColor: 'rgba(0, 0, 0, 0.8)' }}

174

maskClassName="custom-mask"

175

open={open}

176

>

177

<Content />

178

</Drawer>

179

```

180

181

### Nested Drawer Management

182

183

Support for multiple drawers with push/pull behavior.

184

185

```typescript { .api }

186

interface PushConfig {

187

/** Push distance for nested drawers */

188

distance?: number | string;

189

}

190

191

interface DrawerPopupProps {

192

/** Push configuration for nested drawers (default: true with 180px distance) */

193

push?: boolean | PushConfig;

194

}

195

196

interface DrawerContextProps {

197

/** Current push distance */

198

pushDistance?: number | string;

199

/** Function to push parent content */

200

push: VoidFunction;

201

/** Function to pull parent content back */

202

pull: VoidFunction;

203

}

204

```

205

206

**Usage Example:**

207

208

```typescript

209

// Nested drawers with custom push distance

210

<Drawer open={level1Open} push={{ distance: 200 }}>

211

<div>

212

<h2>Level 1 Drawer</h2>

213

<button onClick={() => setLevel2Open(true)}>Open Level 2</button>

214

<Drawer open={level2Open} push={{ distance: 150 }}>

215

<h3>Level 2 Drawer</h3>

216

</Drawer>

217

</div>

218

</Drawer>

219

220

// Disable push behavior

221

<Drawer push={false} open={open}>

222

<Content />

223

</Drawer>

224

```

225

226

### Event Handling

227

228

Comprehensive event handling for user interactions.

229

230

```typescript { .api }

231

interface DrawerPanelEvents {

232

/** Mouse enter event on drawer panel */

233

onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;

234

/** Mouse over event on drawer panel */

235

onMouseOver?: React.MouseEventHandler<HTMLDivElement>;

236

/** Mouse leave event on drawer panel */

237

onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;

238

/** Click event on drawer panel */

239

onClick?: React.MouseEventHandler<HTMLDivElement>;

240

/** Key down event on drawer panel */

241

onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;

242

/** Key up event on drawer panel */

243

onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;

244

}

245

246

interface DrawerProps {

247

/** Called after drawer open/close animation completes */

248

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

249

/** Called when drawer should be closed (ESC key, mask click, etc.) */

250

onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;

251

}

252

```

253

254

### Focus and Keyboard Management

255

256

Built-in accessibility features for keyboard navigation and focus management.

257

258

```typescript { .api }

259

interface DrawerPopupProps {

260

/** Whether to auto-focus drawer when opened (default: true) */

261

autoFocus?: boolean;

262

/** Whether to enable keyboard support like ESC to close (default: true) */

263

keyboard?: boolean;

264

}

265

```

266

267

**Usage Example:**

268

269

```typescript

270

// Drawer with custom keyboard handling

271

<Drawer

272

keyboard={false} // Disable built-in ESC handling

273

autoFocus={false} // Don't auto-focus

274

onKeyDown={(e) => {

275

if (e.key === 'Escape' && customCondition) {

276

handleCustomClose();

277

}

278

}}

279

open={open}

280

>

281

<Content />

282

</Drawer>

283

```

284

285

### Accessibility Support

286

287

Full ARIA attributes support for screen readers and assistive technologies.

288

289

```typescript { .api }

290

type DrawerPanelAccessibility = Pick<

291

React.DialogHTMLAttributes<HTMLDivElement>,

292

keyof React.AriaAttributes

293

>;

294

295

interface DrawerProps extends DrawerPanelAccessibility {

296

// All ARIA attributes are supported

297

'aria-labelledby'?: string;

298

'aria-describedby'?: string;

299

'aria-label'?: string;

300

// ... all other ARIA attributes

301

}

302

```

303

304

**Usage Example:**

305

306

```typescript

307

<Drawer

308

open={open}

309

aria-labelledby="drawer-title"

310

aria-describedby="drawer-description"

311

>

312

<h2 id="drawer-title">Settings</h2>

313

<p id="drawer-description">Configure your application settings</p>

314

<SettingsForm />

315

</Drawer>

316

```

317

318

### Advanced Styling

319

320

Comprehensive styling customization with CSS classes and inline styles.

321

322

```typescript { .api }

323

interface DrawerClassNames {

324

/** Class name for mask overlay */

325

mask?: string;

326

/** Class name for content wrapper */

327

wrapper?: string;

328

/** Class name for content section */

329

section?: string;

330

}

331

332

interface DrawerStyles {

333

/** Styles for mask overlay */

334

mask?: React.CSSProperties;

335

/** Styles for content wrapper */

336

wrapper?: React.CSSProperties;

337

/** Styles for content section */

338

section?: React.CSSProperties;

339

}

340

341

interface DrawerPopupProps {

342

/** Root container CSS class */

343

rootClassName?: string;

344

/** Root container inline styles */

345

rootStyle?: React.CSSProperties;

346

/** Drawer content CSS class */

347

className?: string;

348

/** Drawer content inline styles */

349

style?: React.CSSProperties;

350

/** Element ID for the drawer */

351

id?: string;

352

/** Custom render function for drawer content */

353

drawerRender?: (node: React.ReactNode) => React.ReactNode;

354

}

355

```

356

357

**Usage Example:**

358

359

```typescript

360

<Drawer

361

classNames={{

362

mask: 'custom-mask-class',

363

wrapper: 'custom-wrapper-class',

364

section: 'custom-section-class'

365

}}

366

styles={{

367

mask: { backgroundColor: 'rgba(0, 0, 0, 0.5)' },

368

wrapper: { boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)' },

369

section: { padding: '24px' }

370

}}

371

rootClassName="drawer-container"

372

className="drawer-content"

373

drawerRender={(content) => (

374

<div className="custom-drawer-wrapper">

375

{content}

376

</div>

377

)}

378

open={open}

379

>

380

<Content />

381

</Drawer>

382

```

383

384

### Rendering Control

385

386

Control when and how the drawer is rendered in the DOM.

387

388

```typescript { .api }

389

interface DrawerPopupProps {

390

/** Force render drawer even when closed */

391

forceRender?: boolean;

392

/** Whether drawer is rendered inline (no portal) */

393

inline?: boolean;

394

}

395

396

interface DrawerProps {

397

/** Whether to destroy drawer content when closed */

398

destroyOnClose?: boolean;

399

/** Portal container for drawer rendering */

400

getContainer?: PortalProps['getContainer'];

401

}

402

```

403

404

**Usage Example:**

405

406

```typescript

407

// Always keep drawer in DOM

408

<Drawer forceRender open={open}>

409

<ExpensiveComponent />

410

</Drawer>

411

412

// Render inline (no portal)

413

<div className="drawer-container">

414

<Drawer getContainer={false} open={open}>

415

<Content />

416

</Drawer>

417

</div>

418

419

// Custom container

420

<Drawer getContainer={() => document.getElementById('drawer-root')}>

421

<Content />

422

</Drawer>

423

```

424

425

## Default Values

426

427

The Drawer component comes with sensible defaults:

428

429

- `prefixCls`: `'rc-drawer'`

430

- `placement`: `'right'`

431

- `autoFocus`: `true`

432

- `keyboard`: `true`

433

- `width`: `378`

434

- `mask`: `true`

435

- `maskClosable`: `true`

436

- `pushDistance`: `180` (for nested drawers)

437

438

## Error Handling

439

440

The component includes built-in validation and warnings:

441

442

- Warns about deprecated props in development mode

443

- Validates proper SSR usage (drawer should not be open during SSR)

444

- Validates width/height value types

445

446

## TypeScript Support

447

448

RC-Drawer is built with TypeScript and provides complete type definitions:

449

450

```typescript { .api }

451

// Main component export

452

export default Drawer;

453

454

// Type exports

455

export type { DrawerProps };

456

```

457

458

**Note**: Internal types like `Placement`, `DrawerClassNames`, `DrawerStyles`, and `PushConfig` are part of the `DrawerProps` interface but not directly exported as standalone types. Access them through the main `DrawerProps` type or define them inline in your TypeScript code when needed.