Skip to content

fix(builder): drop the platform-wrong keystroke hint and hold the roving stop at focus - #1029

Merged
mobeenabdullah merged 2 commits into
mainfrom
fix/builder-toolbar-hint-and-roving-stop
Aug 18, 2026
Merged

mobeenabdullah merged 2 commits into
mainfrom
fix/builder-toolbar-hint-and-roving-stop

Conversation

@mobeenabdullah

Copy link
Copy Markdown
Collaborator

Two defects in #1025, found by reviewing my own diff after both review bots hit their usage limits and never ran on it.

These fixes existed before #1025 merged but did not make it in. #1025 was merged at 09:04:44Z on head 17c181a32; I pushed the fixes at 10:03 on ce4a06158, after the merge, so they were stranded on a branch nobody would look at again. That sequencing was my error — I kept working on a PR without re-checking whether it was still open. This recovers them by cherry-pick onto current main.

1. The tooltip taught a keystroke that does nothing on macOS

It showed Ctrl+D. The binding is spelled mod, and key-spec.ts resolves mod to Command on Apple platforms, Control elsewhere. So on a Mac the tooltip named a keystroke that does nothing, for the one action an author is most likely to try to learn.

The original justification — that resolving per platform would be "a second place that decides what the key is" — conflated two different jobs: which key the BINDING is (the shortcut manager's), and how to SPELL it for a human (a display concern). Getting the second wrong is not excused by owning the first.

The right rule already exists: detectApplePlatform in packages/ui/src/lib/shortcuts/key-spec.ts. It is not on @nextlyhq/ui's public entry, so packages/builder cannot reach it, and spelling the platform a second time here would let a tooltip disagree with the binding it describes. So the hint is removed rather than guessed, with a comment recording what would bring it back. The tooltip keeps the action name and, when unavailable, the reason — which is the load-bearing content.

For context, not fixed here: the admin hardcodes ⌘ in RequestBar.tsx, which is wrong on Windows and Linux for the same underlying reason.

2. The roving tab stop fought the caret

The stop reset to the first button whenever the selection moved. But Duplicate and Select parent both move the selection while the author's focus is still on the button they pressed — so the roving index and the caret ended up on different buttons, and the next arrow press jumped backwards from where the author was looking.

Now the reset is skipped while the bar contains focus, where onFocus has already put the index in the right place.

Verified

Both fixes stub-verified in both directions, each caught by exactly the test whose name claims it:

  • reset unconditionally again → "keeps the roving stop where FOCUS is when the selection moves" fails.
  • never reset → "DOES reset the stop when focus is outside the bar" fails.

The second test is the control for the first: without it, the fix would pass against a bar that had simply stopped resetting the stop at all, stranding it on a button belonging to a block the author has moved on from.

packages/builder: 683 tests, types and lint clean. Built to completion first, then gated as separate commands — check-types depends on ^check-types and lint on nothing, so neither builds what it reads.

…ing stop at focus

The tooltip named Ctrl+D while the binding is spelled `mod`, which the
shortcut manager resolves to Command on Apple platforms. A Mac author was
being taught a keystroke that does nothing. The one rule that answers this
is the manager's own detectApplePlatform, which is not on @nextlyhq/ui's
public entry, and spelling the platform a second time here would let a
tooltip disagree with the binding it describes.

The roving tab stop reset to the first button whenever the selection moved.
Duplicate and Select parent both move it while the author's focus is still
on the button they pressed, so the stop and the caret ended up on different
buttons and the next arrow press jumped backwards.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@mobeenabdullah, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 seconds

Limit details: You’ve used all 1 included review currently available under your plan.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b65be340-0520-4c52-b89d-f52e7770f55f

📥 Commits

Reviewing files that changed from the base of the PR and between 896d1c0 and 744a791.

⛔ Files ignored due to path filters (1)
  • .changeset/builder-toolbar-hint-and-roving-stop.md is excluded by !.changeset/**
📒 Files selected for processing (5)
  • packages/builder/src/block-toolbar.test.tsx
  • packages/builder/src/block-toolbar.tsx
  • packages/builder/src/index.ts
  • packages/builder/src/toolbar-actions.test.ts
  • packages/builder/src/toolbar-actions.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@mobeenabdullah
mobeenabdullah merged commit 11ccece into main Aug 18, 2026
12 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Fallow audit report

Found 40 findings.

Details
Severity Rule Location Description
major fallow/unused-dependency apps/playground/package.json:24 Package '@nextlyhq/adapter-drizzle' is in dependencies but never imported; imported in other workspaces: packages/adapter-mysql, packages/adapter-postgres, packages/adapter-sqlite, packages/nextly
major fallow/unused-dependency apps/playground/package.json:25 Package '@nextlyhq/adapter-mysql' is in dependencies but never imported; imported in other workspaces: packages/nextly
major fallow/unused-dependency apps/playground/package.json:26 Package '@nextlyhq/adapter-postgres' is in dependencies but never imported; imported in other workspaces: packages/nextly
major fallow/unused-dependency apps/playground/package.json:27 Package '@nextlyhq/adapter-sqlite' is in dependencies but never imported; imported in other workspaces: packages/nextly
major fallow/unused-dependency apps/playground/package.json:42 Package 'sharp' is in dependencies but never imported; imported in other workspaces: packages/nextly
minor fallow/unused-dev-dependency apps/playground/package.json:45 Package '@eslint/eslintrc' is in devDependencies but never imported
minor fallow/unused-dev-dependency apps/playground/package.json:54 Package 'better-sqlite3' is in devDependencies but never imported; imported in other workspaces: packages/adapter-sqlite, packages/nextly
minor fallow/unused-dev-dependency apps/playground/package.json:55 Package 'culori' is in devDependencies but never imported; imported in other workspaces: packages/ui
minor fallow/unused-dev-dependency e2e/package.json:17 Package '@nextlyhq/adapter-drizzle' is in devDependencies but never imported; imported in other workspaces: packages/adapter-mysql, packages/adapter-postgres, packages/adapter-sqlite, packages/nextly
minor fallow/unused-dev-dependency e2e/package.json:18 Package '@nextlyhq/adapter-sqlite' is in devDependencies but never imported; imported in other workspaces: packages/nextly
minor fallow/unused-dev-dependency e2e/package.json:22 Package '@nextlyhq/plugin-form-builder' is in devDependencies but never imported; imported in other workspaces: apps/playground
minor fallow/unused-dev-dependency e2e/package.json:23 Package '@nextlyhq/plugin-page-builder' is in devDependencies but never imported; imported in other workspaces: apps/playground
minor fallow/dev-dependency-in-production package.json:92 devDependency '@manypkg/get-packages' is imported by production code at runtime (consider moving to dependencies)
minor fallow/dev-dependency-in-production package.json:104 devDependency 'micromatch' is imported by production code at runtime (consider moving to dependencies)
minor fallow/unused-dev-dependency package.json:106 Package 'publint' is in devDependencies but never imported
major fallow/unused-dependency packages/admin/package.json:110 Package '@lexical/history' is in dependencies but never imported
major fallow/unused-dependency packages/admin/package.json:119 Package '@radix-ui/react-accordion' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:120 Package '@radix-ui/react-alert-dialog' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:121 Package '@radix-ui/react-avatar' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:122 Package '@radix-ui/react-checkbox' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:123 Package '@radix-ui/react-collapsible' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:124 Package '@radix-ui/react-dialog' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:125 Package '@radix-ui/react-dropdown-menu' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:127 Package '@radix-ui/react-popover' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:128 Package '@radix-ui/react-radio-group' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:129 Package '@radix-ui/react-select' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:130 Package '@radix-ui/react-separator' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:132 Package '@radix-ui/react-switch' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:133 Package '@radix-ui/react-tabs' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:134 Package '@radix-ui/react-tooltip' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:140 Package 'cmdk' is in dependencies but never imported; imported in other workspaces: packages/ui
major fallow/unused-dependency packages/admin/package.json:149 Package 'tailwind-variants' is in dependencies but never imported
major fallow/unused-dependency packages/admin/package.json:150 Package 'tailwindcss-animate' is in dependencies but never imported
minor fallow/unused-dev-dependency packages/builder/package.json:68 Package '@nextlyhq/plugin-sdk' is in devDependencies but never imported; imported in other workspaces: apps/playground, packages/plugin-form-builder, packages/plugin-page-builder, packages/plugin-sdk, packages/plugin-seo
major fallow/unused-dependency packages/plugin-page-builder/package.json:51 Package '@dnd-kit/dom' is in dependencies but never imported
major fallow/unused-dependency packages/plugin-page-builder/package.json:52 Package '@dnd-kit/react' is in dependencies but never imported
major fallow/unused-dependency packages/plugin-page-builder/package.json:56 Package 'isomorphic-dompurify' is in dependencies but never imported; imported in other workspaces: packages/nextly
minor fallow/unused-dev-dependency packages/plugin-page-builder/package.json:63 Package '@tanstack/react-query' is in devDependencies but never imported; imported in other workspaces: packages/admin, packages/plugin-form-builder
minor fallow/unused-dev-dependency packages/plugin-page-builder/package.json:72 Package '@dnd-kit/abstract' is in devDependencies but never imported
major fallow/unused-dependency packages/telemetry/package.json:32 Package 'env-paths' is in dependencies but never imported

Generated by fallow.

@github-actions github-actions Bot added the type: docs Documentation only label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: docs Documentation only

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant