Skip to main content

Overview

Dialogs are high-level components used to render modal popups such as preferences, repository settings, and error messages. They’re built on the HTML5 <dialog> element and are shown as modals, constraining tab navigation within the dialog itself.

Basic Structure

A typical dialog follows this structure:

Dialog Component

The main Dialog component accepts several important props:

Example Implementation

From app/src/ui/dialog/dialog.tsx:252:

OkCancelButtonGroup

The OkCancelButtonGroup component handles platform-specific button ordering automatically:
  • Windows/Linux: Ok, Cancel
  • macOS: Cancel, Ok
This follows platform conventions as outlined in Nielsen Norman Group’s research on button order.

Basic Usage

Customization Options

From app/src/ui/dialog/ok-cancel-button-group.tsx:5:

Destructive Dialogs

For destructive actions (hard to recover from), set destructive={true} to make the Cancel button the default.
The destructive prop:
  • Makes the Cancel button the submit button (default action)
  • Prevents accidental destructive actions
  • Does not change which button triggers onSubmit vs onDismissed

Error Handling

Inline Errors

Dialogs should render errors inline using the DialogError component rather than opening new error dialogs. From app/src/ui/dialog/error.tsx:16:

Usage Example

The DialogError component must be the first child of the Dialog element.

Error Content Guidelines

1

Use text-based content

Keep error content primarily text-based and concise.
2

Omit 'Error' prefix

Don’t include the word “Error” - the styling makes it evident.
3

Be specific

Provide actionable information about what went wrong.

Best Practices

Content Structure

DO: Let child components render DialogContent
DON’T: Wrap children inside DialogContent

Layout Components

DO: Use Row components for layout The Row component receives bottom margin when used as an immediate child of DialogContent, making it excellent for structuring content. For primary text content, use <p> elements instead of Row.

Accessibility

Focus Management

Dialogs automatically manage focus based on this priority order:
1

Preferred focus element

Element with DialogPreferredFocusClassName class
2

Lowest positive tabIndex

Element with the lowest explicit tab index
3

First tabbable element

First input, textarea, or tabIndex=0 element
4

First submit button

Default action button
5

Any button

Remaining focusable buttons
6

Close button

Dialog dismiss button

ARIA Attributes

For alert dialogs that interrupt user workflow:

Dialog Lifecycle

Dismissal Grace Period

Dialogs implement a 250ms grace period after mounting before acknowledging dismissal:
This prevents users from accidentally dismissing important dialogs that appear while they’re clicking elsewhere.

Form Submission

All dialogs contain a top-level form element:
  • Submit: Triggers onSubmit event (affirmative action)
  • Reset: Triggers onDismissed event (cancel action)
  • Keyboard shortcuts: Ctrl/Cmd+W or Escape dismisses the dialog

Common Patterns

Simple Confirmation Dialog

Loading State

Non-dismissable Dialog