feat(Splitter): new component - #441
Merged
Merged
Conversation
Port of nuxt/ui@ae2bd5eb (#6670). Resizable panels separated by draggable handles, wrapping reka-ui's `SplitterGroup` / `SplitterPanel` / `SplitterResizeHandle`. Adopting a whole component is not a mechanical port, so it was put to the maintainer with the alternatives rather than decided here. It duplicates nothing: `DashboardPanel` and `DashboardResizeHandle` build on reka-ui's `Primitive`, not on the splitter primitives — checked before proposing, because "we already have something like that" would have been the cheap wrong answer. The component itself is upstream's, with §1's mechanical rewrites: `ui` -> `b24ui` throughout, `#build/b24ui/splitter`, `appConfig.b24ui?.splitter`. The reka-ui imports keep their own names, so the template is unchanged. The theme is adapted rather than copied. Upstream's handle focus ring is `focus-visible:outline-primary`; ours follows `button.ts` and `checkbox.ts` — `outline-transparent focus-visible:outline-2 focus-visible:outline-offset-2` with `--ui-color-accent-soft-element-blue`, the token `table.ts` already uses for focusable rows. Docs, the four examples and the playground page were translated, not copied. `bg-elevated/50`, `border-default` and `text-muted` become the matching b24ui tokens; `color="neutral" variant="subtle"` becomes `color="air-secondary"`, since this Button has no `variant`; and the collapsible example's `i-lucide-panel-left-{open,close}` become the b24icons the dictionary maps `panelOpen`/`panelClose` to — `outline/OpenChatIcon` and `outline/CloseChatIcon`, not `main/…`, which is where a first guess put them. Registered in the three places a component needs: `src/theme/index.ts`, `src/runtime/types/index.ts`, and the outer block of `src/runtime/types/theme.ts` — that file has two, and the `prose` one closes at line 159. Not ported: `docs/public/components/{light,dark}/splitter.png`. They feed a preview grid this fork does not have — `docs/public/components/` does not exist here and nothing references it. Tests are upstream's spec with `ui` -> `b24ui` and its `bg-primary` probe replaced by a token; 24 snapshots generated against our theme, plus the axe pass. Checked in the output rather than the source that the adaptation landed: the rendered handle carries our focus ring. Verify (CI=true): dev:prepare across all four apps · lint · typecheck · test (6734 passed, 6 skipped, 296 files) · build · docs:generate — all green. docs:generate prerenders 1248 routes against 1240 before, so the component page and its four examples build and render.
This was referenced Aug 19, 2026
IgorShevchik
added a commit
that referenced
this pull request
Aug 20, 2026
…stry (#447) Splitter (#441) and ProgressGroup (#443) each shipped with `src/`, tests, a docs page and the nuxt playground, and each was missing four further registries. None of them can fail a build, which is why both passed the full gate twice. - `docs/nuxt.config.ts` → `pages`: neither route was listed. The page still prerenders, because the crawler follows the sidebar link, so nothing looked wrong — but that array is the declared list the `/raw/<page>.md` routes are generated from, and `skills/b24-ui-nuxt/references/components.md` links to exactly those URLs. `empty` and `page-card-group` had been missing longer; both are registered here too. - `playgrounds/demo`: no page for either component, so the Demo link the docs page is supposed to carry had nothing to point at. Both pages are written the way the other 79 are — `<PlaygroundPage>` with `#controls`, the theme's variants driven through `<Matrix>` — rather than copied from the nuxt playground, which is a scratch page with a different job. - `useNavigation.ts` in the demo playground: both names added in place. - The Demo link itself, on both docs pages. Also on those pages: `description:` was Nuxt UI's sentence verbatim on Splitter and near-verbatim on ProgressGroup, both rewritten; `keywords:` added; and Splitter's Reka link used `iconName: RekaIcon`, a name that has never existed in `src/runtime/dictionary/icons.ts`. `resolveIcon()` returns `undefined` for it and the template renders the link with no icon, silently — the convention on the other 34 pages is an avatar, `/b24ui/avatar/rekaui.svg`, and that is what it uses now. `test/utils/docs-component-registries.spec.ts` holds the part of this that is mechanically checkable: page ↔ `pages` entry in both directions, every `iconName:` resolvable in the dictionary, every Demo link and every demo nav entry resolving to a file that exists. It cannot demand a demo page per component (33 of 120 pages carry no Demo link by choice) or tell a rewritten description from a copied one; those stay in the checklist that `.sync/PORTING.md` §6 now spells out for the next component. Verified: four mutations against the new spec — dropping the `splitter` route, adding a route with no page behind it, restoring `iconName: RekaIcon`, renaming the demo page away — each red, and the tree green. Both demo pages loaded in a browser off `demo:generate`'s output: the splitter renders two panel groups, the progress group six segments, no console errors. Co-authored-by: Shevchik Igor <noreply@anthropic.com>
4 tasks
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.
Port of
nuxt/ui@ae2bd5eb(nuxt/ui#6670). Third of six in the queue, after #439.Resizable panels separated by draggable handles, wrapping reka-ui's
SplitterGroup/SplitterPanel/SplitterResizeHandle.Adopted by decision, not by default
A whole new component is not a mechanical port, so it went to the maintainer with the alternatives — adopt / skip / defer to an issue — rather than being decided in the sync. Answer: adopt and adapt.
It duplicates nothing here. We already have
DashboardPanelandDashboardResizeHandle, but those build on reka-ui'sPrimitive, not on the splitter primitives — checked before proposing, because "we already have something like that" would have been the cheap wrong answer.What is upstream's, and what is not
The component is upstream's, with §1's mechanical rewrites:
ui→b24uithroughout (prop, slot props, item key,appConfig.b24ui?.splitter) and#build/b24ui/splitter. The reka-ui imports keep their own names, so the template is unchanged.The theme is adapted, not copied. Upstream's handle focus ring is
focus-visible:outline-2 focus-visible:outline-primary. Ours follows the convention already inbutton.tsandcheckbox.ts:— the same token
table.tsuses for focusable rows.Docs, the four examples and the playground page were translated.
bg-elevated/50→bg-(--ui-color-bg-content-secondary),border-default→border-(--ui-color-divider-default),text-muted→text-description.color="neutral" variant="subtle"→color="air-secondary", since this fork's Button has novariant. And the collapsible example'si-lucide-panel-left-{open,close}become the b24icons the dictionary mapspanelOpen/panelCloseto —outline/OpenChatIconandoutline/CloseChatIcon, notmain/…, which is where a first guess put them.Registered in the three places a component needs:
src/theme/index.ts,src/runtime/types/index.ts, and the outer block ofsrc/runtime/types/theme.ts— that file has two, and theproseone closes at line 159, so the placement is worth stating rather than assuming.Not ported
docs/public/components/{light,dark}/splitter.png. They feed a preview grid this fork does not have:docs/public/components/does not exist here and nothing references it.Tests
Upstream's spec, with
ui→b24uiand itsbg-primaryprobe class replaced by a token. 24 snapshots generated against our theme, plus the accessibility pass.Checked in the output rather than the source that the theme adaptation actually landed:
Verify (
CI=true)dev:prepare(all four apps) ·lint·typecheck·test·build·docs:generate— all green. Tests 6734 passed | 6 skipped across 296 files.docs:generateprerenders 1248 routes, up from 1240 — the component page and its four examples build and render, which is the check that the docs half actually works rather than merely existing.Ledger
6f82268band3d2129d2reconciled with #439 and squash167cd6f3.cursor→ae2bd5eb, entry and log added,.sync/dep-parity.jsonrefreshed to the new cursor.Remaining:
2beb2345+a630c943(showcase, no-ops) and14ac2438(ProgressGroup, also adopted, plus the--percentfix for the existingProgress).Generated by Claude Code