Skip to content

UX spec: long-tail screens (Space Works UX across all of SpaceWorks)

Status: research only, no app code. Companion to ux-spec.md, which covers the core screens and defines the closed set of page layouts. This document covers every other screen, so that after the revamp nothing is left in the old Panel-and-stacked-forms style.

Branch feature/design-revamp. Visual identity (colour, type, logo) comes from the brand spec and PLAN.md §3. This doc covers layout, information architecture, interaction, states and copy structure only.


0.1 Layouts are the closed set from ux-spec.md

Section titled “0.1 Layouts are the closed set from ux-spec.md”

Every screen below is written as “Layout X, slots filled by …”. No screen gets its own page structure. The layouts are:

AppShell (staff/member chrome) · DashboardLayout · ListLayout · DetailLayout · SettingsLayout · FlowLayout (wizard) · AuthLayout · CenteredCardLayout · PublicLayout · PublicDetailLayout · KioskLayout.

The slot names below are what this doc assumes each layout exposes. Where ux-spec.md names a slot differently, its names win. The mapping is one-to-one, so a rename does not change any screen spec.

Layout Slots assumed here
DashboardLayout greeting (muted date/line), title, actions (1 primary pill + 1 outline), callouts[], stats[], main (sections), rail (activity / at-a-glance)
ListLayout title, subtitle, actions, callouts[], stats[], tabs (underline, with count badges), toolbar (search, filters, saved views, bulk bar), list (card rows or DataTable), pagination, rail?
DetailLayout back (“← All x”), identity (date/identity chip), title, status (pill), meta line, actions, tabs, body, rail? (at-a-glance, callout card)
SettingsLayout title, subtitle, subnav? (in-page section list), sections[] of SettingsRow (label + helper left, field right, hairlines), footer (Discard / Save), dangerZone?
FlowLayout back, title, stepper (“Step 2 of 4 · Map columns”), step body, aside? (live preview / summary), footer (Back · Next/Finish), presentation page or dialog (see §11 gaps)
AuthLayout form (left), brand panel (right)
CenteredCardLayout logo (top-left), icon tile, eyebrow, title, body, primary (full-width pill), secondary link, footnote (“Signed in as … · Switch account”)
PublicLayout PublicShell header (space brand, nav, Sign in), hero (eyebrow, title, intro), toolbar?, content, footer
PublicDetailLayout PublicShell header, hero, main, aside (sticky action card), footer
KioskLayout station bar (space avatar, station name, counter, online pill, “Lock station”), stage (scanner / PIN pad / result), side (result panel / recent list), no app chrome

0.2 Conventions used by every screen here (so they are not repeated per screen)

Section titled “0.2 Conventions used by every screen here (so they are not repeated per screen)”

Current rule (v2.0.1, 2026-11-13): This is research, including every later wireframe’s “pill” action and light-colour shorthand: use 10 px product controls, 16 px cards, current theme tokens and CR-SIDEBAR-01 geometry. Pills describe status/metadata shape, not a fully round button default. Apply the shared voice guide for current content patterns. (1A-N26) — supersedes the line above; see docs/current-rules.md#cr-scope-01.

  • One primary action per page. Actions are ranked as primary (dark/teal pill), secondary (outline pill, at most one or two) and the rest in a More menu ([More v], an outline icon button; it opens a menu of labelled items). Exports (CSV/XLSX) always go in More as “Export CSV” / “Export Excel”.
  • Row actions: one inline text action at the right of the row (reference “Send invites”, “Undo”). Every other row action goes in a row overflow [...] menu. Destructive items sit last in red and always confirm.
  • Inline Undo (reference mgr2/att11) is used for reversible one-click state changes that the API already supports reversing. Where the API has no reverse, use a confirm dialog and do not fake an Undo.
  • Contextual callout (warm yellow, icon, bold lead sentence, action link on the right) replaces today’s bg-warn boxes, read-only notices and disclosure paragraphs. There is at most two per page. Long legal or disclosure text goes behind “Read the details” (a disclosure that expands in place).
  • Danger zone (red-outlined card, last on the page) collects every irreversible control on a settings-style page. Red buttons do not appear mid-page.
  • Stat cards show label + big number (+ optional progress bar). Each one is tagged in this doc [loaded] (the number is already in the response the page fetches) or [+query] (needs one extra request to an existing endpoint, usually a filtered list count). No stat needs a backend change. If [+query] cost is a concern, drop that card. The layout copes with 2–4 cards.
  • Tabs are underline tabs. A count badge appears only when the number is [loaded]. Tab state lives in the URL query (?view= / ?section=), using the same mechanism ListViewControls/useListState already use. StaffWorkspace canonicalisation keeps location.search (<Navigate to={activeTabPath + location.search} />), so no staffTabs.ts change is needed. Only machines may carry a path segment, and that stays true.
  • States voice (brand: clear, warm, specific, says the next step):
    • Empty: “No {things} yet. {Do the next thing}.” The primary action is repeated as a button inside the empty card (dashed border, reference org4/org6).
    • Filtered empty: “Nothing matches these filters.” + “Clear filters” link.
    • Loading: skeleton rows or skeleton stat cards that match the final layout. No “Loading…” text except in aria-live status.

Current rule (v2.0.1, 2026-11-13): The canonical unknown-duration loading indicator is the full or inline box loader with a polite meaningful status label (SW-322/364, 2026-11-11/2026-11-13). A retained skeleton may reserve layout only where explicitly specified; reduced motion uses a still mark. (1A-N29) — supersedes the line above; see docs/current-rules.md#cr-motion-01.

  • Error (load): “Couldn’t load {things}. Check your connection and try again.” + “Try again” button. The raw server message goes in a muted second line when it is useful.
  • Error (action): an inline message under the control that failed: “Couldn’t {verb}. {reason}.” Never a stack of <p className="text-danger"> lines at the top of a panel. Today’s multi-error pile-ups (e.g. Transfers renders 5 separate error lines) collapse into one message per failed control.
  • Success: a toast “{Thing} {done}.” with Undo where reversible.

Current rule (v2.0.1, 2026-11-13): Use confirmed success only after the operation completes. Queued/offline work and partial failures need their own messages. Never offer generic Undo for evidence, handovers, payments or audited records; follow Voice and content and the actual reversal contract. (1A-N28) — supersedes the line above; see docs/current-rules.md#cr-content-01.

  • Status pills are a soft tint plus a word, always (brand: never colour alone).

Current rule (v2.0.1, 2026-11-13): Success/warn/info small status marks use solid fills and on-* labels in both themes. Only large dark callouts use the soft-surface recipe; accent, danger and neutral retain their named exceptions. A word remains mandatory. (1A-N27) — supersedes the line above; see docs/current-rules.md#cr-status-01.

  • Copy rules: sentence case; “Space Works” in prose; no raw enum values on screen (paid_offline → “Paid in person”, in_progress → “Printing”); no #123 IDs as primary labels; no feature-flag keys or app labels in user-facing text except on superadmin/deployment screens.
  • Accessibility carried forward: keep existing accessible names that tests may pin (they live in the gitignored test trees in the main checkout). Examples: aria-label="Personal notifications", the “QR payload” label, “Search and commands”, “Sign out”, “Station PIN”. If a name must change, the matching test changes in the same commit.
ID Reference board / screen Pattern it contributes
org1 Organiser workspace · Home greeting + date, “Your organisations” cards, dashed “+ New” card, “Coming up” date-chip rows, Recent activity rail
org2 Organiser workspace · Events title + 1 primary + 1 outline, yellow callout with link, 4 stat cards, underline tabs with counts, date-chip card rows, inline row action, dashed draft row, activity rail + “See all →”
org3 Organiser workspace · New organisation form left, live public-page preview right, primary + text “Cancel”
org4 Organiser workspace · Members “Invite someone” card (link field + status pill, Copy / New link / Revoke), person table with avatar, dashed empty “It’s just you so far…”
org5 Organiser workspace · Settings settings sub-nav under the active item, label + helper left / field right, hairlines, Discard / Save, red danger-zone card
org6 Organiser workspace · API access “New API client” card with scope check-cards, dashed empty list, yellow “Keep keys in a secret manager” strip, dark code block with Copy, accordion reference
mgr1 Managing an event · Overview “← All events”, date chip + title + status pill + meta, outline + primary pill, underline tabs, stat cards, “Latest …” list + “All guests →”, “At a glance” key-value card, yellow callout card
mgr2 Managing an event · Check-in progress stat card, yellow callout with dark action, camera block + “Start scanning”, “Find a guest” search, toggle rows, “Recent check-ins” with Undo, door-station card (Copy link / Show PIN / New PIN / red “Turn off station”)
mgr3 Managing an event · Page & programme segmented control, column cards, dashed “+ Add session”
mgr4 Managing an event · Series upcoming-date cards (first highlighted), details form, agenda list, danger zone
auth2 Sign in, invites & account · Set new password small centred card, icon tile, strength meter + rule check, “Back to sign in”
auth3 Confirm email centred card, icon tile, bold address in body, full-width primary, “Not you? Use another account”
auth4 Join organisation invite overlapping avatar tiles, “You’ve been invited to join”, role pill, one-time-link note, “Accept invite”, “Signed in as … · Switch account”
auth5 Co-organiser invite coloured header band, scoped-permission note box, “Accept & open event”
auth6 Account · Profile title + subtitle, underline tabs Profile / Security, settings rows, “Member since …” + Save
auth7 Account · Security yellow “Two-step sign-in is off” callout with dark action, password rows, “Sign out everywhere” red-outline
att9 Attending · You’re in ticket card with QR, “Add to calendar” + “Save ticket”, cancel link
att10 Attending · Station PIN big title, 8 PIN boxes, numeric pad, disabled “Open check-in” until complete
att11 Attending · Door scanner station bar (counter, Online pill, Lock station), scanner frame, big green result panel with “Next guest” + “Undo”, recent list, search + Find

Screens are grouped by layout so each batch composes the same primitives.

Batch Layout Screens
A Operational lists ListLayout Payments, Ledger, Transfers, Stocktake, To buy, To-be-fixed, Notifications, Delivery logs, Accountability, Warranties, Organized events, Member cards, Devices, Data export, Categories, Containers, Job handover, Email templates (index)
B Detail / editor DetailLayout Email template editor, Stocktake session, Container detail (drawer), Device detail (drawer), Machine service / printer queue (tab body inside the core machine-type page)
C Configuration SettingsLayout API access, Modules, Platform settings, Backup & restore, Organizations (org workspace), Member account (/member/account), Staff MFA (/mfa)
D Read-only analytics DashboardLayout Platform dashboard, Usage & limits, Organization analytics, Makerspace picker (superadmin)
E Flows FlowLayout Bulk import, QR tools (print batch), Create makerspace, Tenant migration, Password recovery
F Gates and system cards CenteredCardLayout Change-password gate, MFA challenge, Access denied, Recovery quarantine, Reset password (legacy link), Org invitation redeem, 404, route/session loading, “No makerspace”
G Public pages PublicLayout / PublicDetailLayout Landing directory, About, Public machines, Public bookings, Public events list (only if the core spec leaves it out), Print request, Public stats, Public organization, Event feedback, Self-checkout, Archived payments, FamilyHome fallbacks
H Member tab bodies AppShell (member) + ListLayout / SettingsLayout Loans, Bookings, Events (+ partner events), Payments, Inbox, Account portal (profile, card, directory, referrals, certifications)
I Stations KioskLayout Event check-in station, Public desk kiosk, Scanner page, PWA offline page
J Overlays (no layout) dialog / popover Command palette, Job tray, Setup checklist, payment dialogs, device enrollment, column mapping, panel error boundary