Clawscale

Drawer

A Drawer slides in from an edge of the screen, above the page. Use it for inspectors and detail panels that keep the page in view.

Usage#

import { Classes, Drawer, DrawerSize } from "@clawscale/react";

Drawer is controlled with isOpen and calls onClose like a Dialog. Put the content in a Classes.DRAWER_BODY element so it scrolls, and actions in Classes.DRAWER_FOOTER.

Examples#

Inspector#

A small drawer on the right shows the details of one item.

import { Button, Classes, Drawer, DrawerSize, PropertyList, PropertyListItem, Tag } from "@clawscale/react";
import { useState } from "react";

export default function DrawerBasic() {
  const [isOpen, setIsOpen] = useState(false);
  const close = () => setIsOpen(false);
  return (
    <>
      <Button icon="panel-stats" text="Inspect deployment" onClick={() => setIsOpen(true)} />
      <Drawer icon="cloud-upload" isOpen={isOpen} onClose={close} size={DrawerSize.SMALL} title="api-gateway v2.14.0">
        <div className={Classes.DRAWER_BODY}>
          <PropertyList compact style={{ margin: 16 }}>
            <PropertyListItem label="Status">
              <Tag intent="success" minimal>
                Healthy
              </Tag>
            </PropertyListItem>
            <PropertyListItem label="Regions">us-east-1, eu-west-1</PropertyListItem>
            <PropertyListItem label="Replicas">24 of 24 ready</PropertyListItem>
            <PropertyListItem label="Commit" monospace>
              8f3c2a1
            </PropertyListItem>
            <PropertyListItem label="Deployed">27 Sep, 09:42 UTC</PropertyListItem>
          </PropertyList>
        </div>
        <div className={Classes.DRAWER_FOOTER} style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
          <Button text="View logs" onClick={close} />
          <Button intent="danger" text="Roll back" onClick={close} />
        </div>
      </Drawer>
    </>
  );
}

Size#

size sets the width of a left or right drawer and the height of a top or bottom one. It takes any CSS length. DrawerSize has three presets: SMALL (360px), STANDARD (50%, the default) and LARGE (90%).

import { Button, Classes, Drawer, DrawerSize } from "@clawscale/react";
import { useState } from "react";

const sizes = [
  { label: "Small", size: DrawerSize.SMALL },
  { label: "Standard", size: DrawerSize.STANDARD },
  { label: "Large", size: DrawerSize.LARGE },
];

export default function DrawerSizes() {
  const [isOpen, setIsOpen] = useState(false);
  const [size, setSize] = useState<string>(DrawerSize.SMALL);
  return (
    <>
      {sizes.map((option) => (
        <Button
          key={option.label}
          text={`${option.label} (${option.size})`}
          onClick={() => {
            setSize(option.size);
            setIsOpen(true);
          }}
        />
      ))}
      <Drawer icon="history" isOpen={isOpen} onClose={() => setIsOpen(false)} size={size} title="Run history">
        <div className={Classes.DRAWER_BODY}>
          <p style={{ margin: 16 }}>This drawer is {size} wide.</p>
        </div>
      </Drawer>
    </>
  );
}

Position#

position accepts top, right (the default), bottom and left.

import { Button, Classes, Drawer, DrawerSize } from "@clawscale/react";
import { useState } from "react";

const positions = ["top", "right", "bottom", "left"] as const;

export default function DrawerPosition() {
  const [isOpen, setIsOpen] = useState(false);
  const [position, setPosition] = useState<(typeof positions)[number]>("right");
  return (
    <>
      {positions.map((value) => (
        <Button
          key={value}
          text={`From ${value}`}
          onClick={() => {
            setPosition(value);
            setIsOpen(true);
          }}
        />
      ))}
      <Drawer
        icon="notifications"
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        position={position}
        size={DrawerSize.SMALL}
        title="Alerts"
      >
        <div className={Classes.DRAWER_BODY}>
          <p style={{ margin: 16 }}>3 open alerts in eu-west-1. The oldest fired 42 min ago.</p>
        </div>
      </Drawer>
    </>
  );
}

Interactive playground#

Props
Open dropdown
View source on GitHub

Props interface#

interface DrawerProps extends OverlayableProps, BackdropProps, Props@clawscale/react
PropsDescription
autoFocus
boolean = true
Whether the overlay should acquire application focus when it first opens.
Inherited from OverlayableProps
backdropClassName
string
CSS class names to apply to backdrop element.
Inherited from BackdropProps
backdropProps
React.HTMLProps<HTMLDivElement>
HTML props for the backdrop element.
Inherited from BackdropProps
canEscapeKeyClose
boolean = true
Whether pressing the esc key should invoke onClose.
Inherited from OverlayableProps
canOutsideClickClose
boolean = true
Whether clicking outside the overlay element (either on backdrop when present or on document) should invoke onClose.
Inherited from BackdropProps
children
React.ReactNode
Drawer contents.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
enforceFocus
boolean = true
Whether the overlay should prevent focus from leaving itself. That is, if the user attempts to focus an element outside the overlay and this prop is enabled, then the overlay will immediately bring focus back to itself. If you are nesting overlay components, either disable this prop on the "outermost" overlays or mark the nested ones usePortal={false}.
Inherited from OverlayableProps
hasBackdrop
boolean = true
Whether a container-spanning backdrop element should be rendered behind the contents. When false, users will be able to scroll through and interact with overlaid content.
Inherited from BackdropProps
icon
IconName | MaybeElement
Name of a Blueprint UI icon (or an icon element) to render in the drawer's header. Note that the header will only be rendered if title is provided.
isCloseButtonShown
boolean = true
Whether to show the close button in the dialog's header. Note that the header will only be rendered if title is provided.
isOpenrequired
boolean
Toggles the visibility of the overlay and its children. This prop is required because the component is controlled.
lazy
boolean = true
If true and usePortal={true}, the Portal containing the children is created and attached to the DOM when the overlay is opened for the first time; otherwise this happens when the component mounts. Lazy mounting provides noticeable performance improvements if you have lots of overlays at once, such as on each row of a table.
Inherited from OverlayableProps
onClose
(event: React.SyntheticEvent<HTMLElement>) => void
A callback that is invoked when user interaction causes the overlay to close, such as clicking on the overlay or pressing the esc key (if enabled).
Inherited from OverlayableProps
onClosed
(node: HTMLElement) => void
Lifecycle method invoked just after the CSS _close_ transition ends but before the child has been removed from the DOM. Receives the DOM element of the child being closed.
Inherited from OverlayLifecycleProps
onClosing
(node: HTMLElement) => void
Lifecycle method invoked just before the CSS _close_ transition begins on a child. Receives the DOM element of the child being closed.
Inherited from OverlayLifecycleProps
onOpened
(node: HTMLElement) => void
Lifecycle method invoked just after the CSS _open_ transition ends. Receives the DOM element of the child being opened.
Inherited from OverlayLifecycleProps
onOpening
(node: HTMLElement) => void
Lifecycle method invoked just after mounting the child in the DOM but just before the CSS _open_ transition begins. Receives the DOM element of the child being opened.
Inherited from OverlayLifecycleProps
portalClassName
string
Space-delimited string of class names applied to the Portal element if usePortal={true}.
Inherited from OverlayableProps
portalContainer
HTMLElement = document.body
The container element into which the overlay renders its contents, when usePortal is true. This prop is ignored if usePortal is false.
Inherited from OverlayableProps
portalStopPropagationEventsdeprecated
Array<keyof HTMLElementEventMap>
A list of DOM events which should be stopped from propagating through the Portal. This prop is ignored if usePortal is false.
this prop's implementation no longer works in React v17+
Inherited from OverlayableProps
position
Position = "right"
Position of a drawer. All angled positions will be casted into pure positions (top, bottom, left, or right).
shouldReturnFocusOnClose
boolean = true
Whether the application should return focus to the last active element in the document after this overlay closes.
Inherited from OverlayableProps
size
number | string = DrawerSize.STANDARD = "50%"
CSS size of the drawer. This sets width if horizontal position (default) and height otherwise.
style
React.CSSProperties = {}
CSS styles to apply to the dialog.
title
React.ReactNode
Title of the dialog. If provided, an element with Classes.DIALOG_HEADER will be rendered inside the dialog before any children elements.
transitionDuration
number = 300
Indicates how long (in milliseconds) the overlay's enter/leave transition takes. This is used by React CSSTransition to know when a transition completes and must match the duration of the animation in CSS. Only set this prop if you override Blueprint's default transitions with new transitions of a different length.
Inherited from OverlayableProps
transitionName
string
Name of the transition for internal CSSTransition. Providing your own name here will require defining new CSS transition properties.
usePortal
boolean = true
Whether the overlay should be wrapped in a Portal, which renders its contents in a new element attached to portalContainer prop.
Inherited from OverlayableProps