Back to Stirling Pdf

Portal UI conventions — SUI vs Mantine

frontend/portal/UI_CONVENTIONS.md

2.13.03.1 KB
Original Source

Portal UI conventions — SUI vs Mantine

The portal has two component sources. The rule:

Simple, presentational, brand-defining UI → our SUI design system (@shared/components). Complex, stateful, or accessibility-hard widgets → Mantine. Don't reinvent what Mantine already does well; do own the look of the simple, high-frequency pieces.

Both are theme-bound: MantineProvider in App.tsx is wired to the portal's ThemeProvider (mantineTheme.ts maps the brand palette), so Mantine widgets follow the same light/dark switch and brand colours as SUI. The provider is intentional — it exists precisely so we can drop Mantine widgets in where they earn their keep.

Use SUI (@shared/components) — our own style

Layout and presentational primitives we want full brand control over and that are cheap to own:

Button · Card · StatusBadge / MethodBadge · Chip · MetricCard · MetricStrip · StatTile · ProgressBar · Avatar · Banner · Skeleton · Spinner · EmptyState · NavItem · PanelHeader · SectionDivider · Stack / Inline · Table (static/presentational) · CodeBlock · FormField (label/help/error layout) · simple Tabs.

Use Mantine — don't reinvent

Anything that needs portals, focus traps, ARIA keyboard patterns, or is just a solved hard problem:

  • Overlays: Modal, Drawer, Popover (focus trap, scroll lock, escape, focus restore)
  • Menus: Menu (roving arrow-key navigation)
  • Selects: Select / MultiSelect / Combobox / Autocomplete (keyboard + filtering)
  • Dates: @mantine/dates DatePicker / DatePickerInput (e.g. billing period range)
  • Files: @mantine/dropzone Dropzone (connect-source upload, op-runner sample drop)
  • Progress UX: Stepper (multi-step wizards), Notifications, Tooltip
  • Hooks: prefer @mantine/hooks (useDisclosure, useClickOutside, useHotkeys, …) over hand-rolling.

Why

Mantine is mature and battle-tested for accessibility. A review of the hand-rolled SUI overlays found real gaps — Dropdown has no arrow-key navigation, Modal/Drawer mishandle focus when there are no focusable children, Toast uses role="alert" for every tone — exactly the things Mantine gets right. Owning those is wasted effort and an a11y liability.

Known migrations (hand-rolled today → should be Mantine)

These shipped as SUI primitives during the initial build and should move to Mantine equivalents (fixes the a11y findings above):

Today (SUI)→ Mantine
Dropdown (menus: tier switcher, app switcher, notifications)Menu
Modal (composer, wizards, settings, create-key)Modal
Drawer (pipeline detail)Drawer
Toastnotifications
new need: billing date range@mantine/dates
new need: file upload@mantine/dropzone

Keep Tabs SUI for the simple in-page switchers; only reach for more if a true tabpanel/roving-focus contract is needed.

Migrating overlays touches visible chrome and behaviour, so do it deliberately (with eyes on the result), not as a blind sweep.