Skip to content

feat(ProgressGroup): new component - #443

Merged
IgorShevchik merged 1 commit into
mainfrom
sync/nuxt-14ac243
Aug 19, 2026
Merged

feat(ProgressGroup): new component#443
IgorShevchik merged 1 commit into
mainfrom
sync/nuxt-14ac243

Conversation

@IgorShevchik

Copy link
Copy Markdown
Collaborator

Port of nuxt/ui@14ac2438 (nuxt/ui#6860). Last of six in the queue, after #442.

Two things at once: a new component, and a fix to the existing Progress that stands on its own.

Half one — the Progress fix

statusStyle wrote the size inline:

{ [orientation === 'vertical' ? 'height' : 'width']: `${percent}%` }

An inline style beats any class, so b24ui.status could not change the size — the override was accepted and silently ignored. It moves to a CSS variable the theme reads: w-(--percent) horizontally, h-(--percent) vertically, with transition-[width]/transition-[height] moved out of the base slot to match.

This fork's statusStyle was not upstream's. Ours falls back to fit-content when there is no percent; upstream has no fallback. It survives the move because w-(--percent) emits width: var(--percent) whatever the value is — but nothing tested it, so ['with status at zero', …] is new. Mutation-verified: replacing the fallback with ${percent ?? 0}% fails that case and only that case.

The commit's progress.md changes come too — the note pointing at ProgressGroup, and the tip about :b24ui="{ status: 'w-full' }", which is exactly what this change makes possible.

Half two — the component

Adopted by decision, as with Splitter.

The colour mechanism is an adaptation, not a translation

Upstream colours the indicator directly: indicator: bg-${color}. Here a colour is a style-* class that defines --b24ui-background, which the indicator reads — Progress puts that class on root.

A group needs a colour per segment, so the class moves down one level: onto segment, and onto the legend's itemLeadingDot and itemLeadingIcon, each reading the variable it defines.

Checked in the rendered output rather than the source:

data-slot="segment"         class="… style-filled-alert"
data-slot="indicator"       class="size-full bg-(--b24ui-background)"
data-slot="itemLeadingDot"  class="… style-filled-warning bg-(--b24ui-background) size-2"

Arbitrary CSS colours: deliberately not taken

Upstream widens color to (string & {}) and applies an off-palette value inline. Removed here along with the themeColors/customColors computeds it needs, its tip in progress.md, and ProgressGroupCustomColorExample.

Two reasons, both recorded when the decision was taken: the mechanism keys off bg-${color} on the indicator, which is not how this fork colours anything; and (string & {}) for a colour would be the library's first — the pattern exists here only for target, rel and slot names.

One difference a reader will notice

The leading icon renders data-slot="icon", not data-slot="itemLeadingIcon". That is not this component: b24icons set data-slot="icon" on their own root and shadow whatever is passed. Uniform across the fork — 6672 occurrences in the snapshots and zero component-specific icon slots, Accordion included. The class still arrives, which is what carries the colour.

Not ported

  • docs/public/components/{light,dark}/progress-group.png — a preview grid this fork does not have.
  • ComponentProps.vue / ComponentPropsSchema.vue — upstream's docs plumbing for the (string & {}) colour type, which is not here.

Verify (CI=true)

dev:prepare (all four apps) · lint · typecheck · test · build · docs:generate — all green. Tests 6790 passed | 6 skipped across 298 files.

52 snapshots written for ProgressGroup, 8 moved for Progress. docs:generate prerenders 1255 routes, up from 1248 — the page and its two examples build and render.

Ledger

2beb2345 and a630c943 reconciled with #442 and squash b6252d89. cursor14ac2438, entry and log added, .sync/dep-parity.json refreshed.

This closes the queue: cursor reaches nuxt/ui@v4 HEAD as of this run. A bookkeeping PR follows to fill in this entry's own pr/b24ui_sha.


Generated by Claude Code

Port of nuxt/ui@14ac2438 (#6860). Two things at once: a new component, and
a fix to the existing `Progress` that stands on its own.

## The Progress fix

`statusStyle` wrote the size inline, and an inline style beats any class —
so `b24ui.status` could not change it. The override was accepted and
silently ignored. It moves to a CSS variable the theme reads:
`w-(--percent)` horizontally, `h-(--percent)` vertically, with the
transitions moved out of the base slot to match.

This fork's `statusStyle` was not upstream's: ours falls back to
`fit-content` when there is no percent, and upstream has no fallback. It
survives the move because `w-(--percent)` emits `width: var(--percent)`
whatever the value is — but nothing tested it, so that case is new, and
mutation-verified: replacing the fallback with `${percent ?? 0}%` fails it
and only it.

## The component

Adopted by decision, as with Splitter.

The colour mechanism is a real adaptation rather than a translation.
Upstream colours the indicator directly with `bg-${color}`. Here a colour
is a `style-*` class that defines `--b24ui-background`, which the indicator
reads, and `Progress` puts that class on `root`. A group needs a colour per
*segment*, so the class moves down one level: onto `segment`, and onto the
legend's dot and icon, each reading the variable it defines.

Checked in the rendered output rather than the source — the segment carries
`style-filled-alert`, the indicator `bg-(--b24ui-background)`, the dot
both.

Arbitrary CSS colours are deliberately not taken. Upstream widens `color`
to `(string & {})` and applies an off-palette value inline; that is removed
here along with the computeds it needs, its tip in `progress.md` and its
example. The mechanism keys off `bg-${color}` on the indicator, which is
not how this fork colours anything, and `(string & {})` for a colour would
be the library's first — the pattern exists only for `target`, `rel` and
slot names.

`UIcon` becomes `<Component :is="item.icon">` and `IconProps['name']`
becomes `IconComponent`.

One difference worth knowing: the leading icon renders `data-slot="icon"`,
not `data-slot="itemLeadingIcon"`. b24icons set that on their own root and
shadow whatever is passed — uniformly, 6672 occurrences across the
snapshots and no component-specific icon slot anywhere, `Accordion`
included. The class still arrives, which is what carries the colour.

Not ported: the preview PNGs, for a grid this fork does not have, and
`ComponentProps.vue` / `ComponentPropsSchema.vue`, which carry upstream's
docs plumbing for the `(string & {})` colour type.

Verify (CI=true): dev:prepare across all four apps · lint · typecheck ·
test (6790 passed, 6 skipped, 298 files) · build · docs:generate — all
green. 52 snapshots for ProgressGroup, 8 moved for Progress, and
docs:generate prerenders 1255 routes against 1248, so the page and its two
examples build.
@IgorShevchik
IgorShevchik merged commit 367cbf5 into main Aug 19, 2026
1 check passed
@IgorShevchik
IgorShevchik deleted the sync/nuxt-14ac243 branch August 19, 2026 15:47
IgorShevchik added a commit that referenced this pull request Aug 19, 2026
Bookkeeping only, per PORTING.md §6 step 4: the last entry of a run cannot
name its own merge, so it lands as `pending-merge` and a follow-up fills it
in. Merged in #443, squash `367cbf5e`.

No `pending-merge` remains. 261 entries, and `cursor` is `14ac2438` — the
`nuxt/ui@v4` HEAD this run started from, so the queue is empty.

`.sync/dep-parity.json` already sits at this cursor; #443 refreshed it.

Two JSON fields. Verified with lint and the `test/utils` suite, which is
where both specs that read `.sync/` live — `icon-map.spec.ts` and
`dep-parity.spec.ts`, the latter comparing this file's `cursor` against the
snapshot's.

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