Skip to content

feat(design): the Appearance tab, with drafts, preview, review and versions - #836

Closed
mortondev wants to merge 3 commits into
feat/portal-design-v2-phase2-foundationsfrom
feat/portal-design-v2-phase2-appearance
Closed

mortondev wants to merge 3 commits into
feat/portal-design-v2-phase2-foundationsfrom
feat/portal-design-v2-phase2-appearance

Conversation

@mortondev

@mortondev mortondev commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

The fourth of the stack that builds a new design engine for the portal. This one adds the Appearance tab, where a person edits the design draft, previews it and publishes it, and a Labs switch to turn the engine on. With the switch off, nothing changes.

Labs

Settings › Labs gains a switch for the new portal design, next to Copilot on Home, with its label and description in all 13 catalogues.

Appearance

On the design engine, Settings › Portal opens on Appearance. Today's menu and welcome message sit under a Navigation tab until they move into the design. A workspace on the legacy theme keeps the page it has always had.

  • Brand: mode; the accent, background and text colours, with cards, raised surfaces, secondary text and borders behind a toggle; dark colours; heading and body fonts; heading weight; corners.
  • Sections: menu style, card style, density, filter side and page width.
  • Drawn tiles: every choice is a tile that draws what it does.
  • Saving: the draft saves on the server shortly after each change, so leaving the page loses nothing and needs no confirmation.
  • Preview: the admin resolves the draft with the code the server uses and posts the CSS, the data-qb-* attributes and the fonts into the frame, so the preview cannot drift from what visitors get. The frame applies them over the saved design and puts the saved values back when the draft ends. Light and dark follow the design's mode.
  • Draft bar: it reads "Draft · N changes, not live", counted against what visitors see now. It offers to discard the draft or review it.
  • Review and publish: lists each change with its value now and in the draft and notes the colours the solver adjusted. It refuses a design whose text cannot be read, and publishes with an optional note. A draft overtaken by another publish is refused with a message rather than overwriting it.
  • History: lists the published versions and restores one after a confirmation. A restore publishes it as the newest version and keeps any draft in progress.

The editor state now carries live, the design visitors see now, which the REST response documents too.

None of this reaches visitors: the Settings › Portal loader imports the design queries only on the design engine (a loader's imports ship in the entry chunk), and the preview frame's design channel loads only when the first draft design arrives.

Screens

Checked in a real browser against the production build on the bench database: Brand, Sections with three changes applied in the preview (pill menu, raised cards, compact density), and Review and publish listing them. No console errors.

Verification

  • Typecheck, lint, the production build and the server-function manifest check pass.
  • Unit suite: 22,293 passed. The one failure, a settings mutation test that timed out under full-suite load, passes on its own.
  • New tests:
    • the draft hook saves once after changes settle, counts changes against the live design, saves a pending change before publishing, and reports a refused publish;
    • the view shows a change in the preview and the draft bar at once, and publishes it with its note;
    • the frame applies a draft design's CSS and attributes, accepts only data-qb-* attributes, and restores the saved values;
    • the diff lists changed leaves.

@mortondev
mortondev added this pull request to stack #833 October 30, 2026 18:33
@mortondev mortondev changed the title feat/portal design v2 phase2 appearance feat(design): the Appearance tab, with drafts, preview, review and versions Oct 30, 2026
@mortondev
mortondev force-pushed the feat/portal-design-v2-phase2-appearance branch from 646818c to 6355514 Compare October 30, 2026 20:19
Settings › Labs gains a switch for the portalDesignV2 flag, next to Copilot
on Home, with its label and description in all 13 catalogues. The two
switches share one component.
On the design engine, Settings › Portal opens on Appearance, with today's
menu and welcome message under a Navigation tab until they move into the
design. The panel edits the design draft:

- Brand: mode, the accent, background and text colours with more behind a
  toggle, dark colours, heading and body fonts, heading weight and corners.
- Sections: menu style, card style, density, filter side and page width.

Every choice is a drawn tile. The draft saves shortly after each change, so
leaving the page loses nothing. The preview shows the draft: the admin
resolves it with the code the server uses and posts the CSS, the data-qb-*
attributes and the fonts into the frame, which puts the saved values back
when the draft ends.

The draft bar says how many changes are waiting, measured against what
visitors see now, and offers to discard the draft or review it. Review and
publish lists each change with its value now and in the draft, notes the
colours the solver adjusted, refuses a design whose text cannot be read, and
publishes with an optional note. History lists versions and restores one
after a confirmation.
@mortondev
mortondev force-pushed the feat/portal-design-v2-phase2-appearance branch from 6355514 to e5387c9 Compare October 30, 2026 20:40
A route's loader ships in the entry chunk, so the Settings › Portal loader's
import of the design queries (and the server functions they call) reached
every page; the help center's script budget tipped over. The loader now
imports them only for a workspace on the design engine. The preview frame's
design channel (reading a draft design and setting its attributes) moves
into a module the frame loads when the first design arrives, so visitors do
not download it either.
@mortondev

Copy link
Copy Markdown
Member Author

Condensed into #878. The stack is now five PRs, #878 to #882; this branch is kept as it was.

@mortondev mortondev closed this Nov 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant