Clawscale

Dialog

A Dialog shows a focused task above the page, such as a form or a review. It blocks the rest of the app until the user closes it. MultistepDialog splits a longer task into steps.

Usage#

import { Dialog, DialogBody, DialogFooter } from "@clawscale/react";
<Dialog isOpen={isOpen} onClose={close} title="Schedule ingest-orders">
  <DialogBody>{/* content */}</DialogBody>
  <DialogFooter actions={<Button intent="primary" text="Save" onClick={close} />} />
</Dialog>

Dialog is controlled with isOpen. It calls onClose when the user presses escape, clicks the backdrop or clicks the close button. The header renders only when title is set.

Examples#

Basic#

DialogBody pads the content. DialogFooter puts actions on the right and its children on the left.

import { Button, Dialog, DialogBody, DialogFooter, FormGroup, HTMLSelect, InputGroup } from "@clawscale/react";
import { useState } from "react";

export default function DialogBasic() {
  const [isOpen, setIsOpen] = useState(false);
  const close = () => setIsOpen(false);
  return (
    <>
      <Button icon="time" text="Edit schedule" onClick={() => setIsOpen(true)} />
      <Dialog icon="time" isOpen={isOpen} onClose={close} title="Schedule ingest-orders">
        <DialogBody>
          <FormGroup helperText="Every day at 02:15." label="Cron expression" labelFor="schedule-cron">
            <InputGroup defaultValue="15 2 * * *" id="schedule-cron" />
          </FormGroup>
          <FormGroup label="Time zone" labelFor="schedule-zone">
            <HTMLSelect fill id="schedule-zone" options={["UTC", "Europe/Berlin", "America/New_York"]} />
          </FormGroup>
        </DialogBody>
        <DialogFooter
          actions={
            <>
              <Button text="Cancel" onClick={close} />
              <Button intent="primary" text="Save schedule" onClick={close} />
            </>
          }
        >
          Next run: 28 Sep, 02:15 UTC
        </DialogFooter>
      </Dialog>
    </>
  );
}

Scrollable body#

DialogBody scrolls once its content is taller than 70% of the viewport. The header and footer stay in place. Set useOverflowScrollContainer={false} to turn this off.

import { Button, Dialog, DialogBody, DialogFooter, HTMLTable } from "@clawscale/react";
import { useState } from "react";

const partitions = Array.from({ length: 90 }, (_, index) => ({
  day: new Date(Date.UTC(2026, 5, 30 + index)).toISOString().slice(0, 10),
  rows: (41_200 + index * 137).toLocaleString("en-US"),
}));

export default function DialogScrollable() {
  const [isOpen, setIsOpen] = useState(false);
  const close = () => setIsOpen(false);
  return (
    <>
      <Button icon="history" text="Review backfill" onClick={() => setIsOpen(true)} />
      <Dialog icon="history" isOpen={isOpen} onClose={close} title="Backfill orders_daily">
        <DialogBody>
          <HTMLTable compact striped style={{ width: "100%" }}>
            <thead>
              <tr>
                <th>Partition</th>
                <th>Rows</th>
              </tr>
            </thead>
            <tbody>
              {partitions.map((partition) => (
                <tr key={partition.day}>
                  <td>dt={partition.day}</td>
                  <td>{partition.rows}</td>
                </tr>
              ))}
            </tbody>
          </HTMLTable>
        </DialogBody>
        <DialogFooter actions={<Button intent="primary" text="Start backfill" onClick={close} />}>
          90 partitions, us-east-1
        </DialogFooter>
      </Dialog>
    </>
  );
}

Multistep dialog#

MultistepDialog takes DialogStep children. Each step has a title for the navigation and a panel, usually a DialogBody. It renders the back and next buttons. finalButtonProps sets the button on the last step.

import { Button, DialogBody, DialogStep, FormGroup, HTMLSelect, InputGroup, MultistepDialog } from "@clawscale/react";
import { useState } from "react";

export default function DialogMultistep() {
  const [isOpen, setIsOpen] = useState(false);
  const close = () => setIsOpen(false);
  const source = (
    <DialogBody>
      <FormGroup label="Source table" labelFor="pipeline-source">
        <HTMLSelect fill id="pipeline-source" options={["raw.orders", "raw.events", "raw.customers"]} />
      </FormGroup>
    </DialogBody>
  );
  const schedule = (
    <DialogBody>
      <FormGroup helperText="Every day at 02:15 UTC." label="Cron expression" labelFor="pipeline-cron">
        <InputGroup defaultValue="15 2 * * *" id="pipeline-cron" />
      </FormGroup>
    </DialogBody>
  );
  const review = (
    <DialogBody>
      <p>raw.orders loads into analytics.orders_daily every day at 02:15 UTC in us-east-1.</p>
    </DialogBody>
  );
  return (
    <>
      <Button icon="add" intent="primary" text="Create pipeline" onClick={() => setIsOpen(true)} />
      <MultistepDialog
        finalButtonProps={{ intent: "primary", text: "Create pipeline", onClick: close }}
        icon="data-lineage"
        isOpen={isOpen}
        onClose={close}
        title="New pipeline"
      >
        <DialogStep id="source" panel={source} title="Source" />
        <DialogStep id="schedule" panel={schedule} title="Schedule" />
        <DialogStep id="review" panel={review} title="Review" />
      </MultistepDialog>
    </>
  );
}

Props interface#

interface DialogProps extends OverlayableProps, BackdropProps, Props@clawscale/react
PropsDescription
aria-describedby
string
ID of an element that contains description text inside this dialog.
aria-labelledby
string
ID of the element that contains title or label text for this dialog.
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
Dialog contents.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
containerRef
React.Ref<HTMLDivElement>
Ref attached to the Classes.DIALOG_CONTAINER element.
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
never = true
Dialog always has a backdrop so this prop cannot be overriden.
icon
IconName | MaybeElement
Name of a Blueprint UI icon (or an icon element) to render in the dialog's header. Note that the header will only be rendered if title is not null or undefined.
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 not null or undefined.
isOpen
boolean = false
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
role
Extract<React.AriaRole, "dialog" | "alertdialog"> = "dialog"
shouldReturnFocusOnClose
boolean = true
Whether the application should return focus to the last active element in the document after this overlay closes.
Inherited from OverlayableProps
style
React.CSSProperties = {}
CSS styles to apply to the dialog.
title
React.ReactNode
Title of the dialog. If not null or undefined, an element with Classes.DIALOG_HEADER will be rendered inside the dialog before any children elements. An empty string "" will render the header without a visible title (useful for showing the close button without a title).
titleTagName
React.ElementType<React.HTMLAttributes<HTMLElement>> = H2
HTML heading component to use for the dialog title.
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
interface DialogBodyProps extends Props, HTMLDivProps@clawscale/react
PropsDescription
children
React.ReactNode
Dialog body contents.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
useOverflowScrollContainer
boolean = true
Enable scrolling for the container
interface DialogFooterProps extends Props, HTMLDivProps@clawscale/react
PropsDescription
actions
React.ReactNode
Dialog actions (typically buttons) are rendered on the right side of the footer.
children
React.ReactNode
Child contents are rendered on the left side of the footer.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
minimal
boolean = false;
Use a "minimal" appearance for the footer, simply applying an HTML role and some visual padding. This is useful for small dialogs, and should not be used with <DialogBody useOverflowScrollContainer>.
interface MultistepDialogProps extends DialogProps@clawscale/react
PropsDescription
aria-describedby
string
ID of an element that contains description text inside this dialog.
Inherited from DialogProps
aria-labelledby
string
ID of the element that contains title or label text for this dialog.
Inherited from DialogProps
autoFocus
boolean = true
Whether the overlay should acquire application focus when it first opens.
Inherited from OverlayableProps
backButtonProps
DialogStepButtonProps
Props for the back button.
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
Dialog steps.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
closeButtonProps
DialogStepButtonProps
Props for the close button that appears in the footer.
containerRef
React.Ref<HTMLDivElement>
Ref attached to the Classes.DIALOG_CONTAINER element.
Inherited from DialogProps
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
finalButtonProps
DialogStepButtonProps
Props for the button to display on the final step.
hasBackdrop
never = true
Dialog always has a backdrop so this prop cannot be overriden.
Inherited from DialogProps
icon
IconName | MaybeElement
Name of a Blueprint UI icon (or an icon element) to render in the dialog's header. Note that the header will only be rendered if title is not null or undefined.
Inherited from DialogProps
initialStepIndex
number
A 0 indexed initial step to start off on, to start in the middle of the dialog, for example. If the provided index exceeds the number of steps, it defaults to the last step. If a negative index is provided, it defaults to the first step.
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 not null or undefined.
Inherited from DialogProps
isOpen
boolean = false
Toggles the visibility of the overlay and its children. This prop is required because the component is controlled.
Inherited from DialogProps
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
navigationPosition
MultistepDialogNavPosition = "left"
Position of the step navigation within the dialog.
nextButtonProps
DialogStepButtonProps
Props for the next button.
onChange
(newDialogStepId: DialogStepId, prevDialogStepId: DialogStepId | undefined, event: MouseEvent<HTMLElement, MouseEvent>): void
A callback that is invoked when the user selects a different step by clicking on back, next, or a step itself.
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
resetOnClose
boolean = true
Whether to reset the dialog state to its initial state on close. By default, closing the dialog will reset its state.
role
Extract<React.AriaRole, "dialog" | "alertdialog"> = "dialog"
Inherited from DialogProps
shouldReturnFocusOnClose
boolean = true
Whether the application should return focus to the last active element in the document after this overlay closes.
Inherited from OverlayableProps
showCloseButtonInFooter
boolean = false
Whether the footer close button is shown. When this value is true, the button will appear regardless of the value of isCloseButtonShown.
style
React.CSSProperties = {}
CSS styles to apply to the dialog.
Inherited from DialogProps
title
React.ReactNode
Title of the dialog. If not null or undefined, an element with Classes.DIALOG_HEADER will be rendered inside the dialog before any children elements. An empty string "" will render the header without a visible title (useful for showing the close button without a title).
Inherited from DialogProps
titleTagName
React.ElementType<React.HTMLAttributes<HTMLElement>> = H2
HTML heading component to use for the dialog title.
Inherited from DialogProps
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.
Inherited from DialogProps
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
interface DialogStepProps extends Props, Omit<HTMLDivProps, "id" | "title" | "onClick">@clawscale/react
PropsDescription
backButtonProps
DialogStepButtonProps
Props for the back button.
className
string
A space-delimited list of class names to pass along to a child element.
Inherited from Props
idrequired
DialogStepId
Unique identifier used to identify which step is selected.
nextButtonProps
DialogStepButtonProps
Props for the next button.
panelrequired
React.JSX.Element
Panel content, rendered by the parent MultistepDialog when this step is active.
panelClassName
string
Space-delimited string of class names applied to multistep dialog panel container.
title
React.ReactNode
Content of step title element, rendered in a list left of the active panel.