Skip to content

UI: Make dialogs consistent and fix their dark mode background - #71806

Merged
bbovenzi merged 1 commit into
apache:mainfrom
astronomer:modal
Aug 19, 2026
Merged

UI: Make dialogs consistent and fix their dark mode background#71806
bbovenzi merged 1 commit into
apache:mainfrom
astronomer:modal

Conversation

@ryanahamilton

@ryanahamilton ryanahamilton commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

The UI hand-assembled the same Chakra Dialog scaffolding in around fifty places, and it had drifted: close triggers, lazyMount/unmountOnExit flags, heading sizes and the placement of action buttons all varied, so a dialog's chrome depended on which screen opened it. Only 7 of ~50 dialogs used Dialog.Footer; the rest hand-rolled a right-aligned <Flex> of buttons inside the body.

This adds a shared Modal component that takes the structure as props, migrates the call sites onto it, and moves dialog theming into the Chakra slot recipe so it applies everywhere at once.

Notable user-facing changes

  • Dark mode background fixed. Chakra defaults dialog content to bg.panel, which resolves to gray.950 in dark mode — far darker than the page, so dialogs looked detached. Both resolve to white in light mode, which is why this went unnoticed. Content now uses bg.
  • Action buttons moved into a real footer on ~21 dialogs, separated by a top border.
  • Dialog headers now carry the Nav sidebar's brand.muted tint, and the close button is styled like the nav buttons.
  • A Cancel action is now supplied automatically alongside footerActions (opt out with hideCancelAction).
  • Narrow viewports get a 4-unit gutter instead of the dialog sitting flush against the browser edges.
Before - Dark Mode After - Dark Mode
file-a38871eae2723babf03744427b56a8e0 file-2f3352939d4df79a9dfe28d60eae2952
Before - Light Mode After - Light Mode
file-fa7306474e0d81b89cc0d3542e908616 file-49fa7db8c85d7ba17ea6713923f665b5

Points worth a reviewer's attention

  • Footer button order is deliberately reversed in source. footerActions takes the primary action first so it leads the tab order, while flexDirection: row-reverse still renders it rightmost. Migrated call sites had their Cancel/Save order flipped to suit; passing them in the old order silently swaps the buttons on screen.
  • lazyMount and unmountOnExit now default to true. 27 dialogs previously lacked unmountOnExit, so their state now resets on close. This is usually what you want, but it is a behaviour change for those.
  • Dialog.Title replaces a plain Heading, which wires up aria-labelledby — the dialog is now announced by its title, which it was not before.
  • The close button moved inside the flex header. This fixes a pre-existing overlap where it sat on top of right-aligned header content (DagImportErrorsModal / PluginImportErrorsModal search bars). One consequence: a modal with no title and no custom header renders no header, and therefore no close button.

Deliberately not migrated

Four dialogs keep raw Dialog because they do not fit the Header/Body/Footer slot order:

  • ClearTaskInstanceConfirmationDialog — has no Dialog.Body at all and branches to null; the only user of Dialog.Description.
  • MarkdownModal / DisplayMarkdownButton — a ResizableWrapper sits between Dialog.Content and the Header/Body pair.
  • SearchDagsButton — a five-line command-palette dialog with none of the boilerplate Modal exists to remove.

The Edge3 provider has 12 more hand-rolled dialogs, but it is a separate distribution that cannot import airflow-core UI internals.

Testing

  • 1012/1012 UI tests pass; Modal has 12 new tests covering slot overrides, footer ordering and DOM/tab order, the cancel action, and hideCancelAction
  • pnpm lint (ESLint + tsc) and prek run --stage pre-commit clean
  • Theming verified in a real browser in both colour modes, including size="full" and size="cover", since Chakra recipe styles are not present in the happy-dom test environment
Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Claude Code (Opus 5)

Dialog scaffolding was hand-assembled in around fifty places and had
drifted apart: close triggers, mount flags, heading sizes and the
placement of action buttons all varied, so a dialog's chrome depended on
which screen happened to open it. Keeping any of that consistent relied
on each author copying the surrounding code correctly, and several
dialogs had already diverged.

In dark mode Chakra's default panel background resolves much darker than
the page background, leaving dialogs looking detached from the app behind
them. Light mode resolves both to white, so the discrepancy was easy to
miss and had gone unnoticed.

Giving the scaffolding a single definition means the chrome is consistent
by construction rather than by convention, and puts theming in one place
that applies to every dialog at once.
@bbovenzi
bbovenzi merged commit d59ac4d into apache:main Aug 19, 2026
142 of 147 checks passed
@bbovenzi
bbovenzi deleted the modal branch August 19, 2026 14:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:UI Related to UI/UX. For Frontend Developers.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants