Skip to content

Generate toolbar: balanced rows at tablet and desktop widths - #231

Merged
Programcode merged 2 commits into
design/debateowl-restylefrom
design/generate-toolbar-even-rows
Oct 24, 2026
Merged

Programcode merged 2 commits into
design/debateowl-restylefrom
design/generate-toolbar-even-rows

Conversation

@Programcode

@Programcode Programcode commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

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:

  • A row that fits on one line stays one natural, left-aligned line, as before.
  • A row that has to wrap is split into lines whose button counts differ by at most one (3+2, not 4+1). Each line's buttons then stretch, in proportion to their labels, until the line is full. The Export tag keeps its own width at the start of its line.

Phones (below 640px) keep the even pairs from #229 unchanged.

useBalancedRow in ExportToolbar.tsx measures 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 evenRows prop, 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 asserted pointer: coarse.

Row shapes below are top row | export row. "1 line" means the row fits on one line.

  • Phones 375x812, 390x844, 430x932. Unchanged from before: pairs, with the Export tag on its own line, and "Megnyitás a Keresztkérdezésben" taking a full line. 0 findings.
  • iPad 768x1024. EN: 1 line | 1 line. HU and ES: 3+2 (was 4+1) | 1 line. 0 findings.
  • iPad 820x1180. EN and ES: 1 line | 1 line. HU: 3+2 (was 4+1) | 1 line. 0 findings.
  • iPad 1024x768 and 1024x1366. Every language and state: 3+2 | 3+2. Before, EN was 4+1 | 4+1 and HU was 3+2 | 4+1. 0 findings.
  • iPad 1180x820 and 1366x1024. EN one-off: 1 line | 1 line. EN saved, HU and ES: 3+2 (was 4+1) | 1 line. HU saved already split 3+2 and still does. 0 findings.
  • Desktop 1280x800, 1440x900, 1920x1080. Same as 1366. 0 findings.
  • Shared case page. Only the export row, which fits on one line from 640px up in EN and HU. Phones show the tag line and two pairs, as before. 0 findings.

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-restyle at aa92de4b, and after is this branch. Click an image for full size. The files replace the Generate images in docs/screenshots/menu-layout/, and the new saved and shared states are added.

one-off case (Save button), EN, light

Before

before gen-filled-en-light

After

after gen-filled-en-light

one-off case, EN, dark

Before

before gen-filled-en-dark

After

after gen-filled-en-dark

one-off case, HU, light

Before

before gen-filled-hu-light

After

after gen-filled-hu-light

one-off case, HU, dark

Before

before gen-filled-hu-dark

After

after gen-filled-hu-dark

filed in a debate (Saved to History), HU, light

Before

before gen-saved-hu-light

After

after gen-saved-hu-light

filed in a debate, HU, dark

Before

before gen-saved-hu-dark

After

after gen-saved-hu-dark

filed in a debate, EN, light

Before

before gen-saved-en-light

After

after gen-saved-en-light

filed in a debate, EN, dark

Before

before gen-saved-en-dark

After

after gen-saved-en-dark

one-off case, ES, light

Before

before gen-filled-es-light

After

after gen-filled-es-light

regenerating a section (Undo disabled), EN, light

Before

before gen-regenerating-en-light

After

after gen-regenerating-en-light

shared case page /share/:code, EN, light

Before

before share-en-light

After

after share-en-light

shared case page, HU, dark

Before

before share-hu-dark

After

after share-hu-dark

Test results

All local, from this worktree. GitHub Actions is billing-blocked, so CI shows red without having run.

  • npm run verify passed 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 @smoke browser tests.
  • On the local verify stack with the fake provider, these passed on both desktop-chromium and mobile-chromium: recipes/ai-tools (8 and 8), recipes/case-generation (9 and 9), e2e/full-stack/ai-tools (5 and 5) and e2e/full-stack/public (1 and 1, the share link).
  • The Ask and Generate browser specs (authed-pages, results-overflow, hungarian-parity, localization, animation-polish, first-run) passed on desktop and mobile Chromium: 114 passed, none failed or skipped.
  • Not run: the rest of 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

  • Desktop now stretches wrapped rows too. At 1280 to 1920, Hungarian, Spanish and the English saved state used to wrap 4+1 left-aligned. They're now 3+2 and full width. That follows "every width where they wrap", but it overrides the 2026-05-27 left-aligned rule wherever a row wraps. A row that fits stays left-aligned.
  • Stretched buttons differ in width. Buttons grow in proportion to their labels, so the long label stays the widest, and the lines are full width but the buttons aren't equal. Equal-width buttons would squeeze "Megnyitás a Keresztkérdezésben" or make the short ones very wide.
  • "Saved to History" is a status, not a button. When it stretches, its text stays left-aligned inside a wider space (see the saved HU images at 1024).
  • The saved flag doesn't survive a reload. Reopening Generate in a debate shows the case with Save again. That's existing behaviour, not something this PR changed, but I noticed it while capturing.
  • If the results column ever gets narrower. In a test page, a column under about 510px can't fit the HU or ES saved row on two lines. Any three-line split of five buttons leaves one alone, so "Megnyitás a Keresztkérdezésben" takes a full line, the same rule phones use. The real app never gets that narrow from 640px up today. The narrowest case is 1024px, with the form beside the results, and that still splits 3+2.
  • Repo size. The 24 montages add about 7 MB. The capture spec and montage script stay in the gitignored .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

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>
@coderabbitai

coderabbitai Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.

Comment @coderabbitai help to get the list of available commands.

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>
@Programcode
Programcode marked this pull request as ready for review October 24, 2026 19:57
Copilot AI balanced review requested due to automatic review settings October 24, 2026 19:57
@Programcode
Programcode merged commit 894e6d1 into design/debateowl-restyle Oct 24, 2026
3 of 10 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

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.

2 participants