Repository navigation
feat(web): group questions into screens in the builder - #206
Merged
Merged
Conversation
…ne page The slides description, in the create-form dialog and in Design, now says what slides do with screens: "One screen at a time. Group questions to show several on one screen." A form with screens switched to One page gets a note under the layout picker: screens only apply to Slides, and they are kept, so switching back restores them. EN and ES, with a changeset for @quill/shared. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
What every builder surface needs to agree on, in one pure module (screen-util.ts) with its spec: - whether the boundary above a question can be joined, and why not: no question shown above it, a calendar, reveal or file upload, a hidden question, or a full screen of 10; - the screens in author order, which the chips and the progress count; - where a dragged question lands: it stays within its own screen, joins a screen when dropped between two of its questions, and leaves it anywhere else; one that cannot join lands right after the screen instead of cutting it in two, and a hidden one stays put, since it cuts nothing; - a question shown again rejoining the screen around it; - where the partial point, and a "reveal after" card, go around a screen, and the partial point staying with its screen when its anchor is dragged out; - where a jump lands: inside its own screen (ignored) or mid-screen (the whole screen opens); - `withScreens`, the canonical pass the editor runs on open and after every edit; it returns the very same config for every frozen legacy fixture and template, on both layouts, so opening one is not an edit. Plus the notes those surfaces show and all their copy, EN and ES. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
The preview's stepper counts screens: a screen of several questions is one stop, and "Step N of M" reads screens. The frame is still asked to start on a step index, the first of the screen, so the preview protocol does not change. A form without screens has one step per screen, so its numbers are the ones it always had. The math is a pure `previewNav` with its spec, cover, clamping and an empty form included. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
`CanvasScreen` renders a screen the way the respondent sees it: every question on it editable in place, the one the settings panel describes marked, one button labelled like the public screen (the last question's own text, else Next or Submit; a leading message does not lend its "Continue") and the progress counted in screens. `CanvasQuestion` takes an optional progress position for forms with screens; its chrome, progress and button are shared with the new card, unchanged. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
On slides, the Logic canvas draws a dashed frame behind the questions of
each screen, labelled like the spine ("Screen 2 · 3 questions"), redrawn
around a question being dragged, and counted in the canvas size. When the
box would also take in a question that is not on the screen (parallel rows
can put one there), each of its questions gets its own frame instead. The
list view names each screen on its first question. Nothing is drawn on one
page, and nodes and edges stay exactly where they were.
Refs #200
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Josue Hernandez <josue@daptatech.com>
…s panel The builder side of screens, on slides only (one page shows none of it and keeps the ids, so switching back restores the screens): - Spine: a chain on the boundary above each question joins it to the screen above or starts a new screen there, in the grip column. It shows on hover and focus (faintly without hover), always while joined, and where it cannot join it stays reachable, dimmed, with the reason. The rows of a screen close into one block under its name; numbering stays per question. The lead-capture nudge knows an email on the last screen. - Settings: the same boundary as an always visible switch after the Logic card, the only way to group below lg where the spine is hidden; hints on the type and hidden controls say what they do to a screen; "reveal after" on a question of a screen says "after this screen" and inserts the card after its last question; the Logic card notes a jump that runs on leaving the screen, a target mid-screen or inside its own screen, and a question that shows or hides live on its own screen. - Jumps: the Logic and Branching dialogs, the rule rows and the scheduler's after-booking picker offer screen starts only and never the question's own screen; a target a rule already holds stays listed, with a note on what it does. - Canvas and state: a question of a screen draws the whole screen, keyed by the screen so moving between its questions keeps the card, and a form with screens counts progress in screens. Every edit runs `withScreens`, so ids stay canonical and, on slides, the partial point never sits inside a screen; drags follow the join and leave rules on both layouts. `layout` is required wherever it changes what is offered. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
v19-screens gains the builder: the spine and the settings switch join and split the same boundary, the canvas shows the whole screen and the draft saves the ids; jump targets are screen starts, with the note in the Logic card and the dialog, and the preview walks screens; one page hides every control, keeps the screens, and Design says so. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
…, with its reason Below lg the settings switch is the only way to group questions, and a boundary that cannot be joined used a natively disabled switch: out of the Tab order, with the reason printed under it but not linked to it. It now stays focusable, is announced as unavailable (`aria-disabled`), is described by its reason (`aria-describedby`), and a click or a key press does nothing, as the spine's chain already did. `Switch` and `InlineField` learn to pass both through; every other caller renders exactly as before. The reasons live in one place (`screenBlockReason`) for the spine and the switch. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
A jump that already points inside a screen (or inside its own) stays listed in its picker, so the author sees what it holds. Every picker kept every rule's target, though: one stale target showed up in the other rules and in "Always go to", and a new rule started on it when it came first. Each select now keeps only its own current value, and a new rule starts on the first target the form actually offers. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
…in it A hidden file upload is transparent inside a screen, so it can sit between two of its questions; shown again, it could not rejoin and the canonical pass cut the screen in two. It now lands right after the screen, as a drag would put it, with the partial point and the selection following it. A restored crash backup also goes through the canonical pass now, like every other change. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
The reason a question type cannot share a screen said "Calendars" and "calendarios", but the type gallery calls it "Scheduler" and "Agendador", the names an author looks for. It now reads "Schedulers, reveal screens and file uploads always get a screen of their own." and "Los agendadores, las pantallas de revelación y las subidas de archivo siempre van en su propia pantalla." wherever it shows: the spine's chain, the settings switch and the type picker's hint. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
… screen Showing a hidden question again put it back on the screen around it even when that screen already showed ten, past the builder's cap. It now leaves the screen and lands right after it, as a drop onto a full screen does; one short of the cap, it goes back in as before. The hint shown before hiding still says that hiding takes the question off its screen. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
Nothing can be joined above the first question shown, yet the spine drew a greyed chain on its top edge, and during a drag on whichever row happened to be first. The chain is now not drawn at all on a row with no question shown above it (hidden ones are transparent), and every chain steps aside while a row is dragged: each boundary is about to change, and they rode along on rows that moved. The disabled chains with a reason stay everywhere else, and the settings switch is unchanged. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
The selected row was three accent shapes that did not line up: its border, an inner rail pill and the title button's square focus outline; inside a screen the border also sat on the screen's own edge, past the block. A row's state is now ONE outline drawn inside its border, in the row's shape: rounded on a question of its own, the screen's corners on a screen's first and last row, square between, so it never covers the screen's edge. Hover is a finer version of the same outline, and keyboard focus on the title shows as it too. The chains get a halo in the card's colour, so the seam and an outline stop short of them instead of running underneath. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
…he screen name put Rows of different heights stretched and squashed mid-drag, text included: dnd-kit's full transform carries a scale for that case. Sortable rows now move by translation only. The dragged spine row lifts as a rounded card with a shadow, at full opacity, and the "Screen N" label is no longer part of its screen's first row, so it stays in place instead of riding along. The keyboard reorder is unchanged. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
The name stays out of the draggable rows so it never rides along, but mid-drag the rows slide under it while it holds still, so it sat over rows of another screen. It now fades out until the drop, like the chains, and keeps its space so nothing below jumps. Refs #200 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Josue Hernandez <josue@daptatech.com>
josue-commits
changed the base branch from
feat/screen-groups-engine-renderer
to
develop
September 26, 2026 15:46
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #200 (2 of 2).
Stacked on the engine PR (#205). This PR targets
feat/screen-groups-engine-renderer. Merge it after that PR, then retarget it todevelop.This is the builder side of screens. Authors join a question to the screen above it, and the screen then shows as one unit everywhere the builder shows the form.
What it adds
lgthe spine is hidden, so this switch is the only way to group there.Notes for review
Testing
pnpm typecheck,pnpm lintandpnpm testpass; web has 1122 tests.v19-screenscovers the builder: the spine toggle, the Settings switch, the screen canvas, the preview by screens and the jump target list.v18andv17in the same run: 24 passed.v19builder cases were run again in Chromium: 3/3.🤖 Generated with Claude Code