Skip to content

feat(wireframe): navigation arrows between screens (#552) - #562

Merged
graphite-app[bot] merged 1 commit into
mainfrom
feat/wireframe-navigation
Oct 29, 2026
Merged

graphite-app[bot] merged 1 commit into
mainfrom
feat/wireframe-navigation

Conversation

@anandpant

@anandpant anandpant commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

What changes

Navigation between wireframe screens (#552), on top of the merged #561.

  • Contract: target on a button or link names the screen it opens.
    • Validation rejects a target that names no screen, or the control's own screen (unknown_wireframe_target, published as missing_edge_target), and a target on anything but a button or link.
    • Code Mode and generation also read goTo, navigatesTo, href, next and the like, and a target written as a screen's name or as #id. A target that already names a screen exactly is kept; loose spellings resolve by id, then by name, and one two screens share is left for validation to report.
  • Drawing: each such control draws an elbow arrow, bound to the control and to the target screen's frame. A link binds to an invisible box behind its words.
    • The route is the cheapest orthogonal path on a sparse grid through every obstacle's edges and the middle of every channel between them. It stays clear of every other screen, every screen's name, and everything on the control's own screen except the containers around it.
    • A route from a modal may run over what the modal's backdrop dims.
    • Each bend costs, the last 28 px into a frame run straight so the head has room, and later arrows keep off earlier ones.
    • The common case, a control beside empty space with the next screen to its right, is one straight line.
  • Sheet layout: screens now balance their rows (four desktop screens sit two by two, not three over one), which also keeps four desktop screens under the CLI's PNG area ceiling.
  • Excalidraw validation (shared helper; output is byte-identical for every family) learns two narrow exemptions, so an arrow from a button inside a card or modal validates:
    • a shape that holds the shape an arrow is bound to, which the arrow must cross on its way out;
    • a shape drawn under such a holder and covered by it, as a modal's backdrop covers the screen beneath. Only a filled shape covers: a frame or a transparent box hides nothing, wherever it sits in the scene.
    • Against main's validator, all 103 non-wireframe fixture scenes export byte-identically and validate identically, and so do 5,135 probes that shift each of their arrows 60–170 px (780 of them cross a shape).
  • Docs cost: +20 characters on the code parameter (target?: screen id on the compact line; 12,361 against 12,400), +162 on the topic. Generation rules, the Studio prompt and tool, both llms.txt files, both READMEs, docs/wireframes.md, and a changeset.

Scenario

signup-flow-wireframe: three phone screens, Create account → Verify email → Choose a plan, each Continue opening the next. Checks:

  • every screen, device, component, state and order;
  • navigation:create-account->verify-email and navigation:verify-email->choose-plan;
  • navigations-exact and controls-stated.

wireframe-drawn now also requires each stated target's arrow, from the control to its screen. Mutations (no target, the wrong screen, an unstated one) each fail exactly their check.

Verification

  • Tests that fail on main:
    • core: targets, aliases and every rejection;
    • renderer: a straight arrow to the next screen, a detour around a sibling, a route over a skipped screen, a backward link, and a screen on another row of the sheet;
    • Code Mode: name-to-id targets, exact ids that squash alike (sign-up and signup), arrows in the export, and missing_edge_target;
    • Excalidraw: an arrow through a member of a frame or transparent box drawn after it is still reported (passes on main);
    • scenarios: navigation checks and the drawn arrow.
  • Fuzz: 1,200 random wireframes at three seeds, now with random targets on buttons and links. Zero defects in exports, reloads, boxes or arrow crossings. 8 of 1,200 fall short (0.67%, under the 2% cap): a control boxed in on every side draws no arrow, or a screen widens (feat(wireframe): native UI wireframes across every surface (#552) #561 alone widens none).
  • Local: pnpm nx affected -t typecheck,test,build --base=origin/main, pnpm run check, pnpm run test:tools, pnpm nx build-storybook diagram-ui, pnpm run test:wrangler-dry-runs.
  • PNGs inspected: the signup flow, a detour around a sibling, a jump over a screen, and a route to another row.

Known limits

  • A control boxed in on every side by other components (for example between two sidebars, with a header and footer) draws no arrow; its target still stands in the spec.
  • Five or more desktop screens exceed the CLI's local PNG area ceiling. Hosted PNG and Excalidraw are unaffected.

anandpant commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator Author

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge - adds this PR to the back of the merge queue
  • fast - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@anandpant
anandpant force-pushed the feat/wireframe-navigation branch from ac8b67c to 33c9bd1 Compare October 29, 2026 16:00
@anandpant
anandpant force-pushed the feat/wireframe-navigation branch from 33c9bd1 to 598a491 Compare October 29, 2026 16:43
@anandpant
anandpant force-pushed the feat/wireframe-navigation branch from 598a491 to 4a6e7a9 Compare October 29, 2026 16:52
@anandpant
anandpant force-pushed the feat/wireframe-navigation branch 2 times, most recently from 5a3b57a to 8685c87 Compare October 29, 2026 17:38
@graphite-app
graphite-app Bot changed the base branch from feat/wireframes to graphite-base/562 October 29, 2026 17:46
@graphite-app
graphite-app Bot force-pushed the feat/wireframe-navigation branch from 8685c87 to 77084e5 Compare October 29, 2026 17:47
@graphite-app
graphite-app Bot force-pushed the graphite-base/562 branch from 3373e7f to f3b6715 Compare October 29, 2026 17:47
@cursor
cursor Bot changed the base branch from graphite-base/562 to main October 29, 2026 17:48
@graphite-app
graphite-app Bot force-pushed the feat/wireframe-navigation branch from 77084e5 to 6869312 Compare October 29, 2026 17:48
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Sketchi Icons Preview

Status: deleted

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Sketchi Web Preview

Status: deleted

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Sketchi Eval Harness Preview

Status: deleted

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Sketchi Excalidraw Workspace Preview

Status: deleted

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Sketchi Playground / Studio Preview

Status: deleted

@graphite-app

graphite-app Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Merge activity

## What changes

Navigation between wireframe screens (#552), on top of the merged #561.

- **Contract:** `target` on a button or link names the screen it opens.
  - Validation rejects a target that names no screen, or the control's own screen (`unknown_wireframe_target`, published as `missing_edge_target`), and a target on anything but a button or link.
  - Code Mode and generation also read `goTo`, `navigatesTo`, `href`, `next` and the like, and a target written as a screen's name or as `#id`. A target that already names a screen exactly is kept; loose spellings resolve by id, then by name, and one two screens share is left for validation to report.
- **Drawing:** each such control draws an elbow arrow, bound to the control and to the target screen's frame. A link binds to an invisible box behind its words.
  - The route is the cheapest orthogonal path on a sparse grid through every obstacle's edges and the middle of every channel between them. It stays clear of every other screen, every screen's name, and everything on the control's own screen except the containers around it.
  - A route from a modal may run over what the modal's backdrop dims.
  - Each bend costs, the last 28 px into a frame run straight so the head has room, and later arrows keep off earlier ones.
  - The common case, a control beside empty space with the next screen to its right, is one straight line.
- **Sheet layout:** screens now balance their rows (four desktop screens sit two by two, not three over one), which also keeps four desktop screens under the CLI's PNG area ceiling.
- **Excalidraw validation** (shared helper; output is byte-identical for every family) learns two narrow exemptions, so an arrow from a button inside a card or modal validates:
  - a shape that holds the shape an arrow is bound to, which the arrow must cross on its way out;
  - a shape drawn under such a holder and covered by it, as a modal's backdrop covers the screen beneath. Only a filled shape covers: a frame or a transparent box hides nothing, wherever it sits in the scene.
  - Against main's validator, all 103 non-wireframe fixture scenes export byte-identically and validate identically, and so do 5,135 probes that shift each of their arrows 60–170 px (780 of them cross a shape).
- **Docs cost:** +20 characters on the `code` parameter (`target?: screen id` on the compact line; 12,361 against 12,400), +162 on the topic. Generation rules, the Studio prompt and tool, both `llms.txt` files, both READMEs, `docs/wireframes.md`, and a changeset.

## Scenario

`signup-flow-wireframe`: three phone screens, Create account → Verify email → Choose a plan, each Continue opening the next. Checks:

- every screen, device, component, state and order;
- `navigation:create-account->verify-email` and `navigation:verify-email->choose-plan`;
- `navigations-exact` and `controls-stated`.

`wireframe-drawn` now also requires each stated target's arrow, from the control to its screen. Mutations (no target, the wrong screen, an unstated one) each fail exactly their check.

## Verification

- **Tests that fail on main:**
  - core: targets, aliases and every rejection;
  - renderer: a straight arrow to the next screen, a detour around a sibling, a route over a skipped screen, a backward link, and a screen on another row of the sheet;
  - Code Mode: name-to-id targets, exact ids that squash alike (`sign-up` and `signup`), arrows in the export, and `missing_edge_target`;
  - Excalidraw: an arrow through a member of a frame or transparent box drawn after it is still reported (passes on main);
  - scenarios: navigation checks and the drawn arrow.
- **Fuzz:** 1,200 random wireframes at three seeds, now with random targets on buttons and links. Zero defects in exports, reloads, boxes or arrow crossings. 8 of 1,200 fall short (0.67%, under the 2% cap): a control boxed in on every side draws no arrow, or a screen widens (#561 alone widens none).
- **Local:** `pnpm nx affected -t typecheck,test,build --base=origin/main`, `pnpm run check`, `pnpm run test:tools`, `pnpm nx build-storybook diagram-ui`, `pnpm run test:wrangler-dry-runs`.
- **PNGs inspected:** the signup flow, a detour around a sibling, a jump over a screen, and a route to another row.

## Known limits

- A control boxed in on every side by other components (for example between two sidebars, with a header and footer) draws no arrow; its target still stands in the spec.
- Five or more desktop screens exceed the CLI's local PNG area ceiling. Hosted PNG and Excalidraw are unaffected.
@graphite-app
graphite-app Bot force-pushed the feat/wireframe-navigation branch from bc5afa1 to 857329a Compare October 29, 2026 18:05
@graphite-app
graphite-app Bot merged commit 857329a into main Oct 29, 2026
14 checks passed
@graphite-app
graphite-app Bot deleted the feat/wireframe-navigation branch October 29, 2026 18:06
@graphite-app
graphite-app Bot deployed to production October 29, 2026 18:06 Active
@graphite-app
graphite-app Bot deployed to production October 29, 2026 18:06 Active
@graphite-app
graphite-app Bot deployed to production October 29, 2026 18:06 Active
@graphite-app
graphite-app Bot deployed to production October 29, 2026 18:06 Active
@graphite-app
graphite-app Bot deployed to production October 29, 2026 18:06 Active
@github-actions github-actions Bot mentioned this pull request Oct 29, 2026

This branch was successfully deployed

1 active and 1 inactive deployments
staging — 857329a9 Deployed Oct 29, 2026 by graphite-app[bot] via cleanup-preview (icons) #1058
production — 857329a9 Deployed Oct 29, 2026 by graphite-app[bot] via deploy (eval-harness) #238
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