or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-rc-drawer

React drawer component with slide-out navigation panels, animations, and flexible positioning

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/rc-drawer@8.0.x

To install, run

npx @tessl/cli install tessl/npm-rc-drawer@8.0.0

index.mddocs/

RC-Drawer

Overview

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.

Package Information

  • Package Name: rc-drawer
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install rc-drawer

Core Imports

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

For CommonJS:

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

Basic Usage

import React, { useState } from "react";
import Drawer from "rc-drawer";

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

  return (
    <div>
      <button onClick={() => setOpen(true)}>Open Drawer</button>
      <Drawer
        open={open}
        onClose={() => setOpen(false)}
        placement="right"
        width={300}
      >
        <h2>Drawer Content</h2>
        <p>This is the drawer content</p>
      </Drawer>
    </div>
  );
}

Architecture

RC-Drawer is built with several key architectural components:

  • Portal Integration: Uses @rc-component/portal for rendering outside the React component tree
  • Motion System: Leverages rc-motion for smooth slide animations and transitions
  • Context System: Provides context for nested drawer management and ref sharing
  • Focus Management: Automatic focus handling with focus trapping and restoration
  • Accessibility: Full ARIA support with proper dialog semantics and keyboard navigation

Capabilities

Main Drawer Component

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

/**
 * Main drawer component that renders a slide-out panel with backdrop
 */
declare const Drawer: React.FC<DrawerProps>;

interface DrawerProps extends 
  Omit<DrawerPopupProps, 'prefixCls' | 'inline'>,
  DrawerPanelEvents,
  DrawerPanelAccessibility {
  /** CSS class prefix (default: 'rc-drawer') */
  prefixCls?: string;
  /** Controls drawer visibility */
  open?: boolean;
  /** Close event handler */
  onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
  /** Whether to destroy drawer content when closed */
  destroyOnClose?: boolean;
  /** Portal container selector/element */
  getContainer?: PortalProps['getContainer'];
  /** Reference to drawer panel element */
  panelRef?: React.Ref<HTMLDivElement>;
  /** Custom class names for different parts */
  classNames?: DrawerClassNames;
  /** Custom styles for different parts */
  styles?: DrawerStyles;
}

Placement and Positioning

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

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

interface DrawerPopupProps {
  /** Drawer placement position (default: 'right') */
  placement?: Placement;
  /** Drawer width for left/right placement or height for top/bottom */
  width?: number | string;
  /** Drawer height for top/bottom placement */
  height?: number | string;
  /** Custom motion configuration or function returning motion config */
  motion?: CSSMotionProps | ((placement: Placement) => CSSMotionProps);
  /** z-index for drawer stacking */
  zIndex?: number;
}

Usage Example:

// Left sidebar drawer
<Drawer placement="left" width={250} open={leftOpen}>
  <Navigation />
</Drawer>

// Top notification drawer
<Drawer placement="top" height={100} open={notificationOpen}>
  <Notifications />
</Drawer>

// Custom animation
<Drawer 
  placement="right"
  motion={(placement) => ({
    motionName: `slide-${placement}`,
    duration: 300
  })}
  open={customOpen}
>
  <Content />
</Drawer>

Mask and Backdrop Control

Configure the backdrop overlay and its behavior.

interface DrawerPopupProps {
  /** Whether to show backdrop mask (default: true) */
  mask?: boolean;
  /** Whether clicking mask closes drawer (default: true) */
  maskClosable?: boolean;
  /** Custom mask CSS class name */
  maskClassName?: string;
  /** Custom mask inline styles */
  maskStyle?: React.CSSProperties;
  /** Custom mask animation configuration */
  maskMotion?: CSSMotionProps;
}

Usage Example:

// Drawer without backdrop
<Drawer mask={false} open={open}>
  <Content />
</Drawer>

// Drawer with custom mask styling
<Drawer 
  maskStyle={{ backgroundColor: 'rgba(0, 0, 0, 0.8)' }}
  maskClassName="custom-mask"
  open={open}
>
  <Content />
</Drawer>

Nested Drawer Management

Support for multiple drawers with push/pull behavior.

interface PushConfig {
  /** Push distance for nested drawers */
  distance?: number | string;
}

interface DrawerPopupProps {
  /** Push configuration for nested drawers (default: true with 180px distance) */
  push?: boolean | PushConfig;
}

interface DrawerContextProps {
  /** Current push distance */
  pushDistance?: number | string;
  /** Function to push parent content */
  push: VoidFunction;
  /** Function to pull parent content back */
  pull: VoidFunction;
}

Usage Example:

// Nested drawers with custom push distance
<Drawer open={level1Open} push={{ distance: 200 }}>
  <div>
    <h2>Level 1 Drawer</h2>
    <button onClick={() => setLevel2Open(true)}>Open Level 2</button>
    <Drawer open={level2Open} push={{ distance: 150 }}>
      <h3>Level 2 Drawer</h3>
    </Drawer>
  </div>
</Drawer>

// Disable push behavior
<Drawer push={false} open={open}>
  <Content />
</Drawer>

Event Handling

Comprehensive event handling for user interactions.

interface DrawerPanelEvents {
  /** Mouse enter event on drawer panel */
  onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
  /** Mouse over event on drawer panel */
  onMouseOver?: React.MouseEventHandler<HTMLDivElement>;
  /** Mouse leave event on drawer panel */
  onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;
  /** Click event on drawer panel */
  onClick?: React.MouseEventHandler<HTMLDivElement>;
  /** Key down event on drawer panel */
  onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;
  /** Key up event on drawer panel */
  onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;
}

interface DrawerProps {
  /** Called after drawer open/close animation completes */
  afterOpenChange?: (open: boolean) => void;
  /** Called when drawer should be closed (ESC key, mask click, etc.) */
  onClose?: (e: React.MouseEvent | React.KeyboardEvent) => void;
}

Focus and Keyboard Management

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

interface DrawerPopupProps {
  /** Whether to auto-focus drawer when opened (default: true) */
  autoFocus?: boolean;
  /** Whether to enable keyboard support like ESC to close (default: true) */
  keyboard?: boolean;
}

Usage Example:

// Drawer with custom keyboard handling
<Drawer 
  keyboard={false} // Disable built-in ESC handling
  autoFocus={false} // Don't auto-focus
  onKeyDown={(e) => {
    if (e.key === 'Escape' && customCondition) {
      handleCustomClose();
    }
  }}
  open={open}
>
  <Content />
</Drawer>

Accessibility Support

Full ARIA attributes support for screen readers and assistive technologies.

type DrawerPanelAccessibility = Pick<
  React.DialogHTMLAttributes<HTMLDivElement>,
  keyof React.AriaAttributes
>;

interface DrawerProps extends DrawerPanelAccessibility {
  // All ARIA attributes are supported
  'aria-labelledby'?: string;
  'aria-describedby'?: string;
  'aria-label'?: string;
  // ... all other ARIA attributes
}

Usage Example:

<Drawer 
  open={open}
  aria-labelledby="drawer-title"
  aria-describedby="drawer-description"
>
  <h2 id="drawer-title">Settings</h2>
  <p id="drawer-description">Configure your application settings</p>
  <SettingsForm />
</Drawer>

Advanced Styling

Comprehensive styling customization with CSS classes and inline styles.

interface DrawerClassNames {
  /** Class name for mask overlay */
  mask?: string;
  /** Class name for content wrapper */
  wrapper?: string;
  /** Class name for content section */
  section?: string;
}

interface DrawerStyles {
  /** Styles for mask overlay */
  mask?: React.CSSProperties;
  /** Styles for content wrapper */
  wrapper?: React.CSSProperties;
  /** Styles for content section */
  section?: React.CSSProperties;
}

interface DrawerPopupProps {
  /** Root container CSS class */
  rootClassName?: string;
  /** Root container inline styles */
  rootStyle?: React.CSSProperties;
  /** Drawer content CSS class */
  className?: string;
  /** Drawer content inline styles */
  style?: React.CSSProperties;
  /** Element ID for the drawer */
  id?: string;
  /** Custom render function for drawer content */
  drawerRender?: (node: React.ReactNode) => React.ReactNode;
}

Usage Example:

<Drawer
  classNames={{
    mask: 'custom-mask-class',
    wrapper: 'custom-wrapper-class',
    section: 'custom-section-class'
  }}
  styles={{
    mask: { backgroundColor: 'rgba(0, 0, 0, 0.5)' },
    wrapper: { boxShadow: '0 4px 20px rgba(0, 0, 0, 0.15)' },
    section: { padding: '24px' }
  }}
  rootClassName="drawer-container"
  className="drawer-content"
  drawerRender={(content) => (
    <div className="custom-drawer-wrapper">
      {content}
    </div>
  )}
  open={open}
>
  <Content />
</Drawer>

Rendering Control

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

interface DrawerPopupProps {
  /** Force render drawer even when closed */
  forceRender?: boolean;
  /** Whether drawer is rendered inline (no portal) */
  inline?: boolean;
}

interface DrawerProps {
  /** Whether to destroy drawer content when closed */
  destroyOnClose?: boolean;
  /** Portal container for drawer rendering */
  getContainer?: PortalProps['getContainer'];
}

Usage Example:

// Always keep drawer in DOM
<Drawer forceRender open={open}>
  <ExpensiveComponent />
</Drawer>

// Render inline (no portal)
<div className="drawer-container">
  <Drawer getContainer={false} open={open}>
    <Content />
  </Drawer>
</div>

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

Default Values

The Drawer component comes with sensible defaults:

  • prefixCls: 'rc-drawer'
  • placement: 'right'
  • autoFocus: true
  • keyboard: true
  • width: 378
  • mask: true
  • maskClosable: true
  • pushDistance: 180 (for nested drawers)

Error Handling

The component includes built-in validation and warnings:

  • Warns about deprecated props in development mode
  • Validates proper SSR usage (drawer should not be open during SSR)
  • Validates width/height value types

TypeScript Support

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

// Main component export
export default Drawer;

// Type exports
export type { DrawerProps };

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.