mobile-first-ui · git:20260819.e68485f · 2026-08-19 · sha256 043a35b916ca2fe3
mobile-first-ui git:20260819.e68485fA
Immutable. This exact content never changes and is served at /api/v1/blob/043a35b916ca2fe3.
---
description: Mobile-first UI for settings, dialogs, and lists — smaller type, stacked layouts, nested add dialogs
globs: "**/*.{tsx,jsx}"
alwaysApply: true
---
# Mobile-first UI
Design for ~320–390px first, then `sm:` / `md:`. Do not assume a desktop row will fit on a phone.
## Type and controls
- On `max-sm`, prefer `text-xs` / `text-[11px]` over `text-sm` / `text-base`. Nested dialogs, sheets, and the mobile sidebar must get the same scale (they portal outside the settings panel).
- Inputs, selects, and textareas: compact on mobile (`h-8`, `text-sm`). Do not use `text-base` on fields just to dodge iOS zoom if it makes settings look oversized.
- If a field has a leading icon, set explicit `pl-*` **and** `md:pl-*` so `md:px-*` on `Input` cannot cover the placeholder.
## Layout
- Stack before clustering. One primary action row; extra actions wrap or sit on the next line.
- Flex children that wrap text need `min-w-0`. Long URLs/IDs: `break-all` or `wrap-break-word`.
- Do not put copy and a button in one `justify-between` row on mobile if the button will collide with the text — stack (`flex-col` → `sm:flex-row`).
- Filter-heavy headers (search + multiple selects) should collapse on mobile so the list remains visible.
- Dialogs must fit `100dvh` minus the floating close control. Pin footer actions (`shrink-0`); scroll the body (`min-h-0 flex-1 overflow-y-auto`). Never use a body `max-h-[70vh]` that plus header/footer overflows the screen.
## Add operations
- **Always** open a nested dialog for add flows (providers, accounts, personas, skills). Do not inline add forms into the parent list.
```tsx
// ❌ BAD — add form in the list
{showAdd && <AddAccountForm />}
// ✅ GOOD — nested dialog, Cancel/Save in the footer
<Dialog open={showAdd} onOpenChange={setShowAdd}>
<DialogContent className="flex max-h-[calc(100dvh-5.5rem)] flex-col p-0">
…
</DialogContent>
</Dialog>
```