Repository navigation
Generate toolbar: balanced rows at tablet and desktop widths - #231
Conversation
From 640px up, a Generate toolbar row that fits on one line stays one natural, left-aligned line. A row that has to wrap is cut into lines whose button counts differ by at most one (3+2, not 4+1), and each line's buttons grow in proportion to their labels until the line is full. The Export tag keeps its own width at the start of its line. Phones keep the even pairs from #229. The split is measured, because where a row breaks depends on the language and on whether Save or "Saved to History" is showing. It stays behind the opt-in evenRows prop, so Attack, Brainstorm and Factoids are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the
|
Twelve viewports per image: phones, iPad portrait and landscape including 820x1180 and 1180x820, and desktop. EN, HU and ES, light and dark, the saved state, and the shared case page. Before is aa92de4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Follow-up to #229. This is a layout-only change. Every control, label and translation is unchanged, and so is the button order: Save, Undo, Discuss, Flowcharts, Open in Crossfire, then Export, Clipboard, PDF, DOCX and Google Docs.
The problem
On tablets the Generate result toolbar wrapped raggedly. At 1024x768 and 1024x1366 in English the top row put Save, Undo, Discuss and Flowcharts on one line and left Open in Crossfire alone on the next, and the export row did the same with Google Docs. In Hungarian the top row went 4+1 at almost every width from 640px to 1920px.
What changed
From 640px up:
Phones (below 640px) keep the even pairs from #229 unchanged.
useBalancedRowinExportToolbar.tsxmeasures the buttons in the browser and picks the split. CSS alone can't, because where a row breaks depends on the language, on whether Save or "Saved to History" is showing, and on the column width. That width drops by about 200px at 1024px, where the form moves beside the results. The hook recomputes on resize, when the window crosses 640px, after web fonts load, and on every render, so switching language or saving the case re-splits the row.It stays behind the opt-in
evenRowsprop, which only Generate passes. Attack, Brainstorm and Factoids don't pass it: they get no new classes and the hook returns before measuring anything.recipes/ai-tools, which drives them, passed on desktop and mobile.Audit results per viewport
This is the audit #229 used. It checks for page overflow, overlapping controls, controls outside the toolbar, clipped button text, rows that scroll instead of wrapping, and touch targets under 44px on touch viewports. A new check fails a wrapped row that leaves a lone button not spanning the row, or whose line counts differ by more than one.
The script drove the real app on the local verify stack, with local Supabase, real Edge Functions and the fake model provider. It covered EN, HU and ES, light and dark, a one-off case, a case filed in a debate, and
/share/:code. It emulated touch on phones and tablets and assertedpointer: coarse.Row shapes below are top row | export row. "1 line" means the row fits on one line.
A width sweep on the real page then went through every width from 640 to 1279px one pixel at a time, and 1280 to 1920px in 8px steps, on a touch device, in EN and HU, one-off and saved. After this change it found no lone buttons, no unbalanced rows and no page overflow. Before, it found 3,598 problems across the same widths.
Screenshots
Each image is one state at all 12 viewports, cropped to the result header. Before is
design/debateowl-restyleataa92de4b, and after is this branch. Click an image for full size. The files replace the Generate images indocs/screenshots/menu-layout/, and the new saved and shared states are added.one-off case (Save button), EN, light
Before
After
one-off case, EN, dark
Before
After
one-off case, HU, light
Before
After
one-off case, HU, dark
Before
After
filed in a debate (Saved to History), HU, light
Before
After
filed in a debate, HU, dark
Before
After
filed in a debate, EN, light
Before
After
filed in a debate, EN, dark
Before
After
one-off case, ES, light
Before
After
regenerating a section (Undo disabled), EN, light
Before
After
shared case page /share/:code, EN, light
Before
After
shared case page, HU, dark
Before
After
Test results
All local, from this worktree. GitHub Actions is billing-blocked, so CI shows red without having run.
npm run verifypassed at 41f5cb3, the code commit. That covers the docs check, lint, typecheck, 651 unit tests, 30 collaboration tests, 470 edge tests, the build, the service worker check and 47@smokebrowser tests.desktop-chromiumandmobile-chromium:recipes/ai-tools(8 and 8),recipes/case-generation(9 and 9),e2e/full-stack/ai-tools(5 and 5) ande2e/full-stack/public(1 and 1, the share link).authed-pages,results-overflow,hungarian-parity,localization,animation-polish,first-run) passed on desktop and mobile Chromium: 114 passed, none failed or skipped.npm run test:e2e, which holds the three known failures on main (loading-performance.spec.ts:63,navigation-performance.spec.ts:344,search-quality.spec.ts:7). Also not run: the agentic suite, which spends OpenRouter credit, WebKit, and staging. No real iPad was used; the iPad widths are Chromium with touch emulated.Not sure about
.verify/, as in Ask Options join the mode row; Generate actions in purpose order #229, so the run can't be reproduced from the repo.🤖 Generated with Claude Code