Skip to content

docs(sync): record that upstream's Slider is this fork's Range - #423

Merged
IgorShevchik merged 1 commit into
mainfrom
docs/porting-component-names
Aug 18, 2026
Merged

docs(sync): record that upstream's Slider is this fork's Range#423
IgorShevchik merged 1 commit into
mainfrom
docs/porting-component-names

Conversation

@IgorShevchik

Copy link
Copy Markdown
Collaborator

Added after I answered a sync check wrongly.

What happened

The queue holds nuxt/ui@f3c2ac21, fix(Slider): bind form aria attributes on thumbs instead of root. I reported it as a no-op, on these grounds:

there is no Slider component anywhere in src/, and 249 ledger entries never mention one

Both statements are true. The conclusion was wrong: the search was by name, and the name is the one thing that changed.

src/runtime/components/Range.vue is upstream's Slider. It wraps the same SliderRoot / SliderTrack / SliderRange / SliderThumb, has the same root/track/range/thumb slots and the same color/size/orientation/disabled variants, its theme is src/theme/range.ts, its page is range.md — and its props line is upstream's verbatim:

export interface RangeProps extends Pick<SliderRootProps, 'name' | 'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'> {

The fix applies here in full. It is ported separately, in queue order.

Why there was nothing to catch it

.sync/ had no component-name map at all. icon-map.json and color-map.json cover tokens; nothing covered wrappers. So a name-based search returning nothing had no counterweight, and "the fork does not have this component" reads like a recorded decision rather than an artefact of the query.

§1 now carries:

  • the rename, as a row in the mechanical-rewrites table;
  • why grepping an upstream component name is the wrong move — only the b24ui wrapper is renamed. Every reka-ui export keeps its own name inside the file, so a diff touching SliderThumb needs no rewriting at all. Search the wrapped primitive or the props, not the wrapper;
  • the full comparison, so the next reader does not have to trust a single example.

The comparison

Both trees hold 180 components. 19 exist only upstream, 19 only here, and none of those 38 is a second rename — checked pairwise rather than assumed.

  • upstream onlyAuthForm, BlogPost, BlogPosts, Carousel, ChangelogVersion, ChangelogVersions, Icon, Marquee, PageAnchors, PageCTA, PageHero, PageLogos, PricingPlan, PricingPlans, PricingTable, Tree, content/ContentNavigation, prose/CodeTree, prose/Icon
  • b24ui onlyAdvice, Countdown, DescriptionList, ModalDialogClose, Navbar, NavbarDivider, NavbarSection, NavbarSpacer, PageCardGroup, SidebarBody, SidebarFooter, SidebarHeader, SidebarHeading, SidebarLayout, SidebarSection, SidebarSpacer, TableWrapper, prose/H5, prose/H6

The note ships the command to re-derive both lists, since a list in prose is a snapshot. I ran it against the note's own figures before committing: 180 vs 180, 40 differing names.

Deliberately untested

Worth being explicit, since this repo's habit is to guard every new rule. A test here could only assert that our side of a map exists — Range.vue does exist, so such a guard would have passed while I was drawing the wrong conclusion. It would add the appearance of coverage without the substance. The rule is documentation, and says so.

Verify

lint and test/utils (415 tests, 22 files). Markdown only; nothing executable changes.


Generated by Claude Code

Added after answering a sync check wrongly.

The queue holds nuxt/ui@f3c2ac21, `fix(Slider): bind form aria attributes
on thumbs instead of root`. I reported it as a no-op because there is no
`Slider` component anywhere in `src/`, and because 249 ledger entries never
mention one. Both statements are true. The conclusion was wrong: the search
was by name, and the name is the one thing that changed.

`Range.vue` wraps the same `SliderRoot`/`SliderTrack`/`SliderRange`/
`SliderThumb` and repeats upstream's `Pick<SliderRootProps, 'name' |
'disabled' | 'inverted' | 'min' | 'max' | 'step' | 'minStepsBetweenThumbs'>`
line verbatim, with the same four slots and the same variants. The fix
applies here in full, and is ported separately.

No component-name map existed in `.sync/` at all — `icon-map.json` and
`color-map.json` cover tokens, nothing covered wrappers — which is why
there was nothing to contradict the wrong answer. §1 now carries the
rename, why grepping for an upstream component name is the wrong move
(only the b24ui wrapper is renamed; every reka-ui export inside the file
keeps its own name, so a diff touching `SliderThumb` needs no rewriting),
and the full comparison: both trees hold 180 components, 19 exist only
upstream and 19 only here, and none of those 38 is a second rename —
checked pairwise rather than assumed.

The note carries the command to re-derive both lists, since it is a
snapshot. Ran it against the note's own figures: 180 vs 180, 40 differing
names.

Deliberately untested. A guard could only assert our side of a map exists,
which is exactly what would not have caught this, so the rule is
documentation and says so rather than implying coverage it does not have.
@IgorShevchik
IgorShevchik merged commit 844830f into main Aug 18, 2026
1 check passed
@IgorShevchik
IgorShevchik deleted the docs/porting-component-names branch August 18, 2026 03:30
IgorShevchik pushed a commit that referenced this pull request Aug 18, 2026
Port of nuxt/ui@f3c2ac21 (#6768).

`useFormField`'s `ariaAttrs` — `aria-invalid` and `aria-describedby` — were
spread onto `SliderRoot`, which renders no `role`. Assistive technology
therefore read an invalid slider as valid and never reached the error text.
The widget is the thumb, and the thumb is what carries `role="slider"`, so
the attributes move there — both sites, the tooltip-wrapped one and the
bare one.

Upstream calls this component `Slider`; here it is `Range`, recorded in
PORTING.md §1 since #423 — which exists because this very commit was first
reported as a no-op on the grounds that no `Slider` component exists. Only
the wrapper is renamed: every reka-ui export inside the file keeps its own
name, so `SliderRoot` and `SliderThumb` needed no rewriting and the diff is
upstream's line for line apart from `ui` -> `b24ui`. The defect was ours in
full.

The test is upstream's with the guard renamed. `FormField.spec.ts` keys
`describe.each` off `__name`, so the block runs only if that value is
exactly `Range` — checked in the reporter output rather than assumed, since
a guard that never matches is a test that passes without running.

Two mutations, each failing a different assertion. Reverting fully fails
the role check (`expected undefined to be 'slider'`); leaving the
attributes on the root as well as the thumbs fails the count (`length of 1
but got 2`). Both halves are load-bearing.

No snapshot moved, which here means the opposite of the usual. `Range`'s
own spec renders the component standalone, outside a `FormField`, so
`ariaAttrs` is empty and moving an empty object changes no rendered
attribute — the `role="slider"` occurrences in those snapshots come from
reka-ui and never carried `aria-invalid`. The snapshots could not have
caught this defect, which is why it is pinned by a FormField-level test.

Also refreshes `.sync/dep-parity.json` and corrects §6, which this port
caught contradicting itself. The rule said to refresh the snapshot "when a
port touches a manifest"; the guard requires the snapshot's cursor to equal
the ledger's, always. The guard is right and the prose was wrong: a
snapshot one commit behind has not been compared against current upstream,
so if a bump landed in between, this fork still matches the stale file, the
guard stays green, and the drift is real — the exact failure the mechanism
exists to catch. §6 now says to refresh on every port that advances the
cursor. Here that rewrote one line and left all 148 versions identical,
which is itself the evidence that nothing drifted.

Verify (CI=true): lint · typecheck · test (6708 passed, 6 skipped, 294
files) · build — all green. No docs:generate; the commit touches no docs/.
IgorShevchik added a commit that referenced this pull request Aug 18, 2026
Port of nuxt/ui@f3c2ac21 (#6768).

`useFormField`'s `ariaAttrs` — `aria-invalid` and `aria-describedby` — were
spread onto `SliderRoot`, which renders no `role`. Assistive technology
therefore read an invalid slider as valid and never reached the error text.
The widget is the thumb, and the thumb is what carries `role="slider"`, so
the attributes move there — both sites, the tooltip-wrapped one and the
bare one.

Upstream calls this component `Slider`; here it is `Range`, recorded in
PORTING.md §1 since #423 — which exists because this very commit was first
reported as a no-op on the grounds that no `Slider` component exists. Only
the wrapper is renamed: every reka-ui export inside the file keeps its own
name, so `SliderRoot` and `SliderThumb` needed no rewriting and the diff is
upstream's line for line apart from `ui` -> `b24ui`. The defect was ours in
full.

The test is upstream's with the guard renamed. `FormField.spec.ts` keys
`describe.each` off `__name`, so the block runs only if that value is
exactly `Range` — checked in the reporter output rather than assumed, since
a guard that never matches is a test that passes without running.

Two mutations, each failing a different assertion. Reverting fully fails
the role check (`expected undefined to be 'slider'`); leaving the
attributes on the root as well as the thumbs fails the count (`length of 1
but got 2`). Both halves are load-bearing.

No snapshot moved, which here means the opposite of the usual. `Range`'s
own spec renders the component standalone, outside a `FormField`, so
`ariaAttrs` is empty and moving an empty object changes no rendered
attribute — the `role="slider"` occurrences in those snapshots come from
reka-ui and never carried `aria-invalid`. The snapshots could not have
caught this defect, which is why it is pinned by a FormField-level test.

Also refreshes `.sync/dep-parity.json` and corrects §6, which this port
caught contradicting itself. The rule said to refresh the snapshot "when a
port touches a manifest"; the guard requires the snapshot's cursor to equal
the ledger's, always. The guard is right and the prose was wrong: a
snapshot one commit behind has not been compared against current upstream,
so if a bump landed in between, this fork still matches the stale file, the
guard stays green, and the drift is real — the exact failure the mechanism
exists to catch. §6 now says to refresh on every port that advances the
cursor. Here that rewrote one line and left all 148 versions identical,
which is itself the evidence that nothing drifted.

Verify (CI=true): lint · typecheck · test (6708 passed, 6 skipped, 294
files) · build — all green. No docs:generate; the commit touches no docs/.

Co-authored-by: Shevchik Igor <noreply@anthropic.com>
IgorShevchik added a commit that referenced this pull request Aug 20, 2026
Ports two contiguous upstream commits, batched per PORTING.md §6 step 4b.

nuxt/ui@545f9e37 `fix(Icon): render bundled icons during SSR in Vue` —
no-op. There is no `Icon` component in this fork at all: `find src -name
'Icon.vue'` returns nothing and `src/runtime/vue/components/` holds only
`color-mode`. By design rather than omission, and already recorded — the §1
component comparison from #423 lists `Icon` and `prose/Icon` among the
nineteen names that exist only upstream. Icons here are
`@bitrix24/b24icons-vue` components imported and rendered directly, so
there is no SSR path to fix.

nuxt/ui@be58f3f5 `docs(table): pin TanStack Table links to v8` — ported.
`latest` now resolves to a major whose API the documentation no longer
matches. It applies here for the same reason, checked rather than assumed:
this fork depends on `@tanstack/vue-table ^8.21.3`, so every `latest` link
documents an API our Table does not implement.

18 links across `docs/content/docs/2.components/table.md` and
`skills/b24-ui-nuxt/references/recipes/data-tables.md`, plus the two labels
upstream widened to name the version.

We inherit the mislabelled link too. Line 523, in *With column pinning*,
pointed at the **row** pinning API; it now points at column pinning. Worth
separating from the version pin: that one is a content error, and a sweep
of `latest` -> `v8` alone would have carried it forward untouched.

Not applicable: `docs/.../3.migration/2.v3.md`. Our migration directory
holds only `1.v2.md` — this fork has no v3 migration page.

Verify (CI=true): lint · test (6790 passed, 6 skipped, 298 files) ·
docs:generate (1255 routes) — all green. Documentation only. Zero
`tanstack.com/table/latest` remain; 18 `tanstack.com/table/v8`.

Co-authored-by: Shevchik Igor <noreply@anthropic.com>
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