Skip to content

feat(Card): add size prop for compact and roomy padding - #475

Merged
IgorShevchik merged 5 commits into
mainfrom
revive/card-size
Sep 14, 2026
Merged

IgorShevchik merged 5 commits into
mainfrom
revive/card-size

Conversation

@IgorShevchik

@IgorShevchik IgorShevchik commented Aug 24, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

B24Card gains a size prop — xs / sm / md / lg — controlling the padding of header, body and footer.

<B24Card size="xs" title="Compact" />
<B24Card title="Default" />
<B24Card size="lg" title="Roomy" />

The padding is lifted out of those three slot bases into a size variant, with defaultVariants pinning md.

The scale

Every step is a package token, not a literal. src/runtime/air-design-tokens/tw-style/spacing.css registers the scale in @theme as --spacing-*, so Tailwind generates first-class utilities from it and no arbitrary-value syntax is needed:

size classes px (base / sm:px / sm:py)
xs p-sm sm:px-xs2 sm:py-xs 12 / 10 / 8
sm p-md sm:px-sm2 sm:py-xs2 16 / 14 / 10
md p-xl sm:px-lg2 sm:py-md 24 / 22 / 16
lg p-3xl sm:px-2xl sm:py-lg 32 / 28 / 20

Verified by compiling the candidates through the installed engine: p-xl emits padding: var(--spacing-xl). Referencing --ui-space-inline-* directly would have compiled too but resolved to nothing at runtime — those live in 001_b24_global.css, outside @theme, and Tailwind emits only the @theme variables a generated utility references.

card.ts is the first theme to use these utilities; the rest of src/theme/ still writes raw p-[Npx], so the porting note says not to read their form as the convention here.

Behavioural change — one pixel

The May draft wrote the steps as literal pixels. Ten of the twelve values already sat exactly on the package scale; two did not, and both are corrected here:

  • lg's sm:px: 30px → 28px (--spacing-2xl). New value, nothing shipped with it.
  • md's sm:py: 15px → 16px (--spacing-md). This one predates the branch, so every existing card gains one pixel of vertical padding at the sm breakpoint. Agreed with the maintainer. It is the only behavioural change in this PR, and the reason the Card snapshots now differ in substance rather than only in class order.

Everything else renders as before: md is the default, and its other two values are unchanged.

Tests

test/components/Card.spec.ts gains sizes.map cases. They carry title, description, body and footer together, because the three padded slots only render with content — a bare { props: { size } } case shows no padding class at all and would collide with every other bare case (#454).

The gap this closes was real and measured: before, breaking xs, sm or lg left the entire suite green. Only md was protected, and only by accident — eight unrelated cases render header and footer under the default size. Now breaking xs reddens its own case, and test/utils/indistinguishable-snapshots.spec.ts reports no new collision.

Docs

The ### Size section was a bespoke ::component-example where 42 of 44 component pages use ::component-code. Rewritten to match the neighbouring ### Variant section in the same file, so the reader gets a live size selector; CardSizeExample.vue is removed.

Upstream

Upstream's Card has only variant and keeps the padding in the slot bases as literals (/tmp/nuxtui/src/theme/card.ts at cursor 2b29c33). A §2 invariant in .sync/PORTING.md records the divergence and the tell for a port that reverts it: fourteen snapshot entries, seven in each of Card.spec.ts.snap and its -vue counterpart.

Verification

  • pnpm lint clean, pnpm typecheck 0 errors, pnpm test 351 files / 7987 passed / 6 skipped.
  • Snapshot changes inspected mechanically, not by eye.
  • Compile behaviour of the utilities checked against the installed Tailwind, not assumed.

Review

/review plus the five-reviewer panel, per the repo rules for a public API change. Security reported nothing and said so. QA independently found the coverage gap; Engineering and the CTO both flagged the unanchored scale. All of it is addressed in the final commit — including a correction to my own earlier claim: the numbers were not invented, they were on the package scale and merely unattributed. I established that only after the maintainer pushed back on how I had "verified" the Button scale, which I had not.

Not done

  • The docs site was not opened in a browser; the section is verified by matching the shape of the neighbouring section and by the suite, not by looking at the rendered page.
  • The remaining themes still write raw p-[Npx]. Converting them is a separate change and is not attempted here.

🤖 Generated with Claude Code

https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc

claude added 3 commits August 24, 2026 04:22
Introduce a 'xs' | 'sm' | 'md' | 'lg' size variant that drives the
padding of the header, body and footer slots — useful for popovers and
densely packed dashboards where the default md spacing is too generous.
md is the default and matches the previous slot defaults.

https://claude.ai/code/session_013gYN6XWQ18LRJdDsatDpf7
The `size` variant lifts the padding out of the `header`/`body`/`footer` slot
bases, so for the default `md` it now lands after the variant classes instead of
before them. Fourteen snapshot lines move; every one differs only in the order of
classes inside `class="…"` — set-equal, and nothing else on the line changes.
Rendering at the default size is unchanged.
@IgorShevchik
IgorShevchik marked this pull request as ready for review September 13, 2026 06:13
Upstream's `Card` has only `variant`, and keeps the header/body/footer padding
in the slot bases. b24ui lifts it into a `size` variant with `md` reproducing
the previous values exactly, so a port that rewrites `src/theme/card.ts` would
silently push the padding back and drop the variant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
The May draft wrote the four size steps as literal pixels. Measured against
`src/runtime/air-design-tokens/tw-style/spacing.css`, ten of those twelve values
already sat exactly on the package's own spacing scale — they were disciplined,
just not traceable from the theme. Two did not: `lg`'s `sm:px` at 30px, and
`md`'s `sm:py` at 15px, which predates this branch.

The scale is registered in `@theme` as `--spacing-*`, so Tailwind generates
first-class utilities from it and no arbitrary-value syntax is needed at all:

    xs  p-sm  sm:px-xs2 sm:py-xs    12 / 10 / 8
    sm  p-md  sm:px-sm2 sm:py-xs2   16 / 14 / 10
    md  p-xl  sm:px-lg2 sm:py-md    24 / 22 / 16
    lg  p-3xl sm:px-2xl sm:py-lg    32 / 28 / 20

Verified by compiling the candidates through the installed engine: `p-xl` emits
`padding: var(--spacing-xl)`. Referencing `--ui-space-inline-*` directly would
have compiled too but resolved to nothing — those live in `001_b24_global.css`,
outside `@theme`, and Tailwind emits only the `@theme` variables a generated
utility references.

Two deliberate value changes, both agreed with the maintainer: `lg`'s `sm:px`
30px → 28px, and `md`'s `sm:py` 15px → 16px. The second alters what existing
cards render at the `sm` breakpoint by one pixel — the only behavioural change
in this branch, and the reason the Card snapshots now differ in substance rather
than only in class order.

`card.ts` is the first theme to use these utilities; the rest still write raw
`p-[Npx]`, so the porting note says not to read their form as the convention.

Review findings addressed alongside:
- `test/components/Card.spec.ts` had no case for the new prop, and `xs`, `sm`
  and `lg` were caught by nothing — breaking `xs` left the suite green. Added
  `sizes.map` cases carrying title, description, body and footer, because the
  three padded slots only render with content and a bare case would collide with
  every other bare case. Breaking `xs` now reddens its own case, and
  `indistinguishable-snapshots` reports no new collision.
- The docs `### Size` section used a bespoke `::component-example` where 42 of
  44 component pages use `::component-code`. Rewritten to match the neighbouring
  `### Variant` section; `CardSizeExample.vue` is removed.
- The porting note now says fourteen snapshot *entries*, seven in each of the
  two Card snapshot files, rather than an ambiguous "fourteen lines".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012MsMuj8Fic9tjWVjyEyrxc
@IgorShevchik
IgorShevchik merged commit b821eef into main Sep 14, 2026
3 checks passed
@IgorShevchik
IgorShevchik deleted the revive/card-size branch September 14, 2026 05:08
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