Skip to content

fix(bulma-ui): avoid empty class attribute on several components - #793

Merged
allxsmith merged 2 commits into
mainfrom
claude/issue-767-20260927-1344
Sep 27, 2026
Merged

allxsmith merged 2 commits into
mainfrom
claude/issue-767-20260927-1344

Conversation

@bestaxbot

Copy link
Copy Markdown
Collaborator

Summary

Several components passed the result of classNames(...) straight to className, so when every entry was falsy the result ('') rendered as class="" instead of omitting the attribute. Fixed by falling back to undefined, the same pattern SelectBase already uses for its inner <select> (className={innerSelectClass || undefined}).

Fixed sites:

  • Image's <img>
  • Menu.Item's inner link (unless active)
  • Tabs' Tab, TabItem, and TabList
  • Table.Thead, Table.Tbody, Table.Tfoot, Table.Tr, Table.Th, and Table.Td

Test plan

  • Added a failing-first regression test for each affected component asserting class is completely absent (not merely empty) when nothing would set it; confirmed all 11 failed against the pre-fix code with class="".
  • Applied the || undefined fix at each site; confirmed the same tests pass.
  • pnpm --filter @allxsmith/bestax-bulma run lint
  • pnpm --filter @allxsmith/bestax-bulma run typecheck and typecheck:tests
  • pnpm --filter @allxsmith/bestax-bulma run test:coverage (4247 passed, 99.6% overall coverage)
  • pnpm run format:check
  • pnpm run gen:catalog:check (no diff — no components added/renamed)
  • pnpm run check:conformance (only pre-existing version-regression failure, caused by this sandbox's shallow clone, unrelated to this change)
  • pnpm --filter @allxsmith/bestax-bulma run build
  • pnpm --filter @allxsmith/bestax-bulma run build-storybook

Fixes #767

Generated with Claude Code

Image's <img>, Menu.Item's inner link, Tabs' Tab/TabItem/TabList, and
the Table.Thead/Tbody/Tfoot/Tr/Th/Td family passed classNames(...)
straight to className, so an all-falsy result rendered class="" instead
of omitting the attribute. Fall back to undefined the way SelectBase's
inner <select> already does.

Fixes #767

Co-authored-by: Alex Smith <allxsmith@users.noreply.github.com>
@bestaxbot bestaxbot added the ai-loop AI-authored PR in the autonomous review/fix loop label Sep 27, 2026
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 13 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

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

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: allxsmith/bestax/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: cacb89fa-d61e-4ba0-8014-8d05bbc45450

📥 Commits

Reviewing files that changed from the base of the PR and between f40a19c and 7324a93.

📒 Files selected for processing (13)
  • bulma-ui/src/components/Menu.tsx
  • bulma-ui/src/components/Tabs.tsx
  • bulma-ui/src/components/__tests__/Menu.test.tsx
  • bulma-ui/src/components/__tests__/Tabs.test.tsx
  • bulma-ui/src/elements/Image.tsx
  • bulma-ui/src/elements/Tbody.tsx
  • bulma-ui/src/elements/Td.tsx
  • bulma-ui/src/elements/Tfoot.tsx
  • bulma-ui/src/elements/Th.tsx
  • bulma-ui/src/elements/Thead.tsx
  • bulma-ui/src/elements/Tr.tsx
  • bulma-ui/src/elements/__tests__/Image.test.tsx
  • bulma-ui/src/elements/__tests__/Table.test.tsx

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.

@github-actions

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://6fbaae4a.bestax.pages.dev

Comment thread bulma-ui/src/components/Menu.tsx
@github-actions

Copy link
Copy Markdown
Contributor

AI loop status: iteration 1/4 — fix-reviews at 0b7cca3 (2026-09-27T14:29:04Z).
Managed by claude-pr-loop.yml. To resume after a pause: set iteration back to 0 on the first line, re-add ai-loop, remove ai-loop-paused, then re-run via workflow_dispatch.

A nested MenuList gates the menu-list class off, so with no className and no
helper props its classNames() result is '' and React renders class="" — the
same shape as the other sites fixed here.

Co-Authored-By: Claude <noreply@anthropic.com>
@bestaxbot

Copy link
Copy Markdown
Collaborator Author

Fix pass recap (iteration 1)

One open AI review thread, and it was a real one.

Finding Thread Outcome
Nested Menu.List still rendered class="" (Menu.tsx:131) claude deep review Fixed in 7324a93

Nothing refuted this round.

What I changed

MenuList only applies menu-list when level === 0, so a nested list with no className and no helper props reduced ulClass to '' and React wrote class="" — the identical defect this PR set out to remove, in the one family the issue names. I applied the same || undefined guard used at the other eleven sites and added a regression test beside the existing applies menu-list class only to top-level MenuList case. As with the original eleven, I verified it failing-first: against the unguarded line it reports class="", and it passes with the guard.

Gates run

Gate Result
lint (bulma-ui) pass — 0 errors, 7 pre-existing warnings
typecheck + typecheck:tests pass
test:coverage (bulma-ui) pass — 129 suites, 4248 tests, thresholds met
format:check pass
check:conformance pass — all 20 checks, including version-regression (the shallow-clone failure noted in the PR body is gone now that the clone is complete)
gen:catalog:check / gen:mcp:check pass — no diff
build pass
build-storybook pass

@github-actions

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://7558a640.bestax.pages.dev

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deep review — 0 blocking · 3 advisory

N Severity Area Finding Location
1 🔵 Advisory API The wrapping <li> in MenuItem is the one element left in a touched file that can still emit class="": it takes className raw, so <Menu.Item className=""> renders <li class=""> while <Table.Td className=""> now omits the attribute. Caller-supplied, so outside the shape 767 describes, but the inconsistency now sits inside a file this PR touches. bulma-ui/src/components/Menu.tsx:260
2 🔵 Advisory Robustness The inner element of MenuItem moves from an empty-string className to undefined. With as set to a custom component, a consumer that interpolates className into a template string now renders base undefined where it used to render base with a trailing space. The same trade-off SelectBase already made — recorded, not contested. bulma-ui/src/components/Menu.tsx:268
3 🔵 Advisory Correctness PR body is stale against HEAD, and is maintainer-facing because neither this review nor the fix agent can edit it: the Fixed sites list omits the MenuList <ul> and the count of 11 is 12 as of 7324a93. The version-regression conformance failure it notes does not reproduce here either — pnpm check:conformance passes all 22 checks on this SHA. PR description

Overall: The change is sound and narrowly scoped — classNames(...) || undefined at each of the 12 sites, matching the SelectBase precedent and the 27 places in the library that already do exactly this. I verified it empirically rather than by reading the diff: the full suite is green (4248 passed, 129 suites, coverage gate exit 0), pnpm check:conformance passes all 22 checks, format:check is clean, and lint reports 0 errors (7 pre-existing warnings in Slider/Taginput, untouched). Branch coverage is the strongest evidence the new tests are real rather than decorative: Menu.tsx, Tabs.tsx, Image.tsx, Tbody, Tfoot and Thead report 100% branches, and for Th/Td/Tr the uncovered-branch lines are 53-54 plus 68-69, 59, and 45 — the pre-existing isAligned/color/width ternaries, never the new || lines — so both sides of every added || are exercised, which means each new test genuinely reaches the empty-string case that used to render class="". The riskiest part of this PR is what is not in it, so start with the residual-risk list below rather than with the twelve one-line edits.

Residual risk:

  • Other components in the same failure class — refuted for the touched files, and as far as static analysis reaches for the rest. I walked every className= site in bulma-ui/src (about 388) and checked the expression behind each: every remaining one carries an unconditional base from a string literal (usePrefixedClassNames("column"), "field-label", "level-item", "breadcrumb", "image", "tabs", "tabs-content", "menu", "menu-label", "table", "table-container", and so on), so none can collapse to the empty string.
  • All-conditional expressions that only look unsafe — refuted one at a time. Reveal builds itemAnimationClasses from an object alone (Reveal.tsx:196), but revealed = !isAnimated || isRevealed keeps one key truthy in every state. Icon prefers containerClassName over its default (Icon.tsx:307), and an empty containerClassName is falsy, so it falls back to icon. The inner <ul> of Breadcrumb (Breadcrumb.tsx:83) takes no className at all.
  • Custom class prefix — refuted. The process helper inside createPrefixedClassNames early-returns on the empty string before prefixing (bulma-ui/src/helpers/classNames.ts:110-116), so a ConfigProvider classPrefix cannot turn an all-falsy set into a bare-prefix class, and every fix here holds identically under one.
  • Caller-supplied empty strings — open. <Menu.Item className=""> (row 1) and <Panel.InputBlock iconClassName="">, which renders <i class=""> (bulma-ui/src/components/Panel.tsx:264, default fas fa-search), are the two paths that still reach class="". Both sit outside the shape the issue describes — nothing puts a class on it — so they are named here rather than posted inline.
  • Reintroduction — open. Nothing mechanical stops the next component from handing an all-conditional classNames(...) result straight to className: there is no lint rule and no check:conformance rule for it (I grepped scripts/ and eslint-plugin/src), and coverage cannot see it. The 12 new assertions pin only the sites that exist today.
  • Downstream staleness — refuted. The absorbs refusal in bestax-migrate that says a bestax target renders the inner element with no class attribute (bestax-migrate/src/sources/bulma-classes/plan.ts:635) fires for two entries only, Select (inner <select>, already guarded) and Breadcrumb (inner <ul>, classless), so widening the set of classless elements invalidates no codemod message. The Image and Menu.Item mappings this unblocks are explicitly deferred to their own PR.
  • Prior review — the nested MenuList finding from the earlier pass is genuinely fixed by 7324a93 (Menu.tsx:131), with its own test and 100% branch coverage on the file. That thread is resolved and is not reopened here.

🏄 Twelve tiny || undefined tweaks, zero drama — the markup comes out clean as a glassy dawn set, the whole suite paddles out green, and the only thing still bobbing in the lineup is an empty className somebody hands you on purpose. Good to go, brah.

@bestaxbot

Copy link
Copy Markdown
Collaborator Author

🏂 Rode it summit to base without catching a single edge. 1 iteration(s) deep, CI all-green top to base, and every AI review thread resolved and stomped flat.

You fleshbags kept the merge button for yourselves — so @allxsmith, wiggle those opposable thumbs and squash-merge when you're stoked. Loop never merges; apparently 'ship it' needs a pulse. 🤙

@github-actions github-actions Bot added needs-human-review Loop converged (or contested): awaiting owner review + manual merge and removed ai-loop AI-authored PR in the autonomous review/fix loop labels Sep 27, 2026
@github-actions
github-actions Bot requested a review from allxsmith September 27, 2026 17:06
@github-actions

Copy link
Copy Markdown
Contributor

📸 Story screenshots at handoff — 7324a93

15 stories (light + dark) from this PR's changed files under bulma-ui/src/ (workflow run · artifact story-screenshots-pr-793, 30-day retention).

elements-image--default · Elements/Image · Default
Light Dark
elements-image--default light elements-image--default dark
elements-image--rounded · Elements/Image · Rounded
Light Dark
elements-image--rounded light elements-image--rounded dark
elements-image--retina · Elements/Image · Retina
Light Dark
elements-image--retina light elements-image--retina dark
elements-image--aspect-ratio-16-by-9 · Elements/Image · Aspect Ratio 16 By 9
Light Dark
elements-image--aspect-ratio-16-by-9 light elements-image--aspect-ratio-16-by-9 dark
elements-image--aspect-ratio-4-by-3 · Elements/Image · Aspect Ratio 4 By 3
Light Dark
elements-image--aspect-ratio-4-by-3 light elements-image--aspect-ratio-4-by-3 dark
elements-image--with-margin · Elements/Image · With Margin
Light Dark
elements-image--with-margin light elements-image--with-margin dark
components-menu--basic · Components/Menu · Basic
Light Dark
components-menu--basic light components-menu--basic dark
components-menu--compound-usage · Components/Menu · Compound Usage
Light Dark
components-menu--compound-usage light components-menu--compound-usage dark
components-menu--forwarded-ref · Components/Menu · Forwarded ref (inner element, not the `<li>`)
Light Dark
components-menu--forwarded-ref light components-menu--forwarded-ref dark
components-tabs--default · Components/Tabs · Default
Light Dark
components-tabs--default light components-tabs--default dark
components-tabs--controlled · Components/Tabs · Controlled
Light Dark
components-tabs--controlled light components-tabs--controlled dark
components-tabs--external-navigation · Components/Tabs · External Navigation
Light Dark
components-tabs--external-navigation light components-tabs--external-navigation dark
components-tabs--alignment-centered · Components/Tabs · Alignment Centered
Light Dark
components-tabs--alignment-centered light components-tabs--alignment-centered dark
components-tabs--alignment-right · Components/Tabs · Alignment Right
Light Dark
components-tabs--alignment-right light components-tabs--alignment-right dark
components-tabs--small-tabs · Components/Tabs · Small Tabs
Light Dark
components-tabs--small-tabs light components-tabs--small-tabs dark
> ✂ 17 more matched stories skipped by the cap: `elements-image--with-iframe`, `elements-image--with-custom-child`, `elements-image--with-text-color-and-background`, `components-tabs--medium-tabs`, `components-tabs--large-tabs`, `components-tabs--boxed-tabs`, `components-tabs--toggle-tabs`, `components-tabs--toggle-rounded-tabs`, `components-tabs--fullwidth-tabs`, `components-tabs--with-icons`, … — full set in the artifact.

github-actions Bot added a commit that referenced this pull request Sep 27, 2026
@allxsmith
allxsmith merged commit 7c5c316 into main Sep 27, 2026
52 of 54 checks passed
@allxsmith
allxsmith deleted the claude/issue-767-20260927-1344 branch September 27, 2026 17:12
bestax-release-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
## [5.16.11](https://github.com/allxsmith/bestax/compare/@allxsmith/bestax-bulma@5.16.10...@allxsmith/bestax-bulma@5.16.11) (2026-09-27)

### Bug Fixes

* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.16.11 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
# [2.13.0](https://github.com/allxsmith/bestax/compare/bestax-migrate@2.12.0...bestax-migrate@2.13.0) (2026-09-27)

### Bug Fixes

* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))

### Features

* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bulma-ui:** let Card.Header.Title and Card.FooterItem render Bulma's own tags ([#794](#794)) ([47ecdb6](47ecdb6))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.13.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
# [2.14.0](https://github.com/allxsmith/bestax/compare/bestax-migrate@2.13.0...bestax-migrate@2.14.0) (2026-09-27)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
bestax-release-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
# [1.7.0](https://github.com/allxsmith/bestax/compare/bestax-mcp@1.6.0...bestax-mcp@1.7.0) (2026-09-27)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** keep menuitemcheckbox and menuitemradio items in Dropdown's arrow-key order ([#786](#786)) ([064155a](064155a))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))
* **bulma-ui:** render the four burger spans Bulma v1 positions ([#785](#785)) ([8e4e1e6](8e4e1e6))
* **bulma-ui:** stop shipping test-only exports, and document notification() ([#781](#781)) ([5f95398](5f95398))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
* **bestax-migrate:** convert conditional classes in clsx and classnames calls ([8948cce](8948cce))
* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bulma-ui:** let Card.Header.Title and Card.FooterItem render Bulma's own tags ([#794](#794)) ([47ecdb6](47ecdb6))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.7.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

bestax-release-bot Bot pushed a commit that referenced this pull request Sep 27, 2026
## [1.1.4](https://github.com/allxsmith/bestax/compare/@allxsmith/eslint-plugin-bestax@1.1.3...@allxsmith/eslint-plugin-bestax@1.1.4) (2026-09-27)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** keep menuitemcheckbox and menuitemradio items in Dropdown's arrow-key order ([#786](#786)) ([064155a](064155a))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))
* **bulma-ui:** render the four burger spans Bulma v1 positions ([#785](#785)) ([8e4e1e6](8e4e1e6))
* **bulma-ui:** stop shipping test-only exports, and document notification() ([#781](#781)) ([5f95398](5f95398))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
* **bestax-migrate:** convert conditional classes in clsx and classnames calls ([8948cce](8948cce))
* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bulma-ui:** let Card.Header.Title and Card.FooterItem render Bulma's own tags ([#794](#794)) ([47ecdb6](47ecdb6))
bestax-release-bot Bot pushed a commit that referenced this pull request Sep 29, 2026
# [5.18.0](https://github.com/allxsmith/bestax/compare/@allxsmith/bestax-bulma@5.17.0...@allxsmith/bestax-bulma@5.18.0) (2026-09-29)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-mcp:** say an .image converts around elements written out, not an expression ([49bb27b](49bb27b))
* **bestax-migrate:** convert an .image around its children only when they're elements ([ff99907](ff99907))
* **bestax-migrate:** flag react-bulma-components Pagination's delta={0} rather than renaming it ([e339ff1](e339ff1))
* **bestax-migrate:** keep a .menu-list around a bestax Menu.List as markup ([2119c3f](2119c3f))
* **bestax-migrate:** keep a Modal part as markup inside an existing bestax Modal ([cfd5f15](cfd5f15))
* **bestax-migrate:** keep a named anchor as markup instead of saying its name does nothing ([74dc360](74dc360)), closes [#fragment](https://github.com/allxsmith/bestax/issues/fragment)
* **bestax-migrate:** know a bestax part imported under its flat export ([7a325ee](7a325ee))
* **bestax-migrate:** leave a wrapper tag alone when none of its classes would become a prop ([2397b9d](2397b9d))
* **bestax-migrate:** leave a wrapper tag with no helper class alone, TODOs and all ([1167a29](1167a29))
* **bestax-migrate:** map react-bulma-components Pagination onto the props it now renders from ([6cd4b51](6cd4b51))
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **bestax-migrate:** write a tabIndex string as a number on every root ([546bf8a](546bf8a)), closes [#814](#814)
* **bulma-ui:** name Pagination's page links, and read a count that's no number as its default ([0a1cf06](0a1cf06))
* **bulma-ui:** prefix the is-current and is-disabled classes on Pagination's parts ([c9a5fae](c9a5fae))
* **bulma-ui:** read a Pagination current page that's no number as the first ([68e963b](68e963b))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))
* **eslint-plugin:** report .menu, .menu-label and .menu-list with the converts message ([8ffaccc](8ffaccc))
* **eslint-plugin:** report Modal's parts with the message for a class the codemod converts ([87f3c08](87f3c08))
* **eslint-plugin:** report Pagination's converting parts with the converts message ([6b94f14](6b94f14))

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-mcp:** look up .menu and its label and list as Menu's parts ([f9fe7cd](f9fe7cd))
* **bestax-mcp:** look up Card's title and footer items on the tags their as takes ([ba8193e](ba8193e))
* **bestax-mcp:** look up Modal's parts as components ([b71583a](b71583a))
* **bestax-mcp:** look up Pagination, its list and its previous and next links as components ([f1298df](f1298df))
* **bestax-mcp:** say an .image converts around anything but a bare <img> ([60e9219](60e9219))
* **bestax-mcp:** say Menu.List renders .menu-list only at the top level ([dcce74f](dcce74f))
* **bestax-migrate:** convert .menu, its labels and its top-level lists ([02f4db6](02f4db6))
* **bestax-migrate:** convert .tabs and .icon around their children ([#815](#815)) ([3967a80](3967a80))
* **bestax-migrate:** convert a menu list's items to Menu.Item ([#816](#816)) ([b385687](b385687))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
* **bestax-migrate:** convert an .image around anything but a bare <img> ([0a31c5b](0a31c5b)), closes [#801](#801)
* **bestax-migrate:** convert Card's title and footer items on the tags their as takes ([20bc0c6](20bc0c6)), closes [#794](#794)
* **bestax-migrate:** convert Modal's parts element by element ([4d41ad2](4d41ad2)), closes [#805](#805)
* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bestax-migrate:** convert Pagination, its list and its previous and next links ([d75bc70](d75bc70)), closes [#807](#807)
* **bestax-migrate:** convert Panel and its heading, tabs and blocks ([#811](#811)) ([0694e54](0694e54))
* **bulma-ui:** render Pagination from total, current and onPageChange ([f7ddf04](f7ddf04)), closes [#813](#813)
bestax-release-bot Bot pushed a commit that referenced this pull request Oct 8, 2026
## [4.2.13](https://github.com/allxsmith/bestax/compare/create-bestax@4.2.12...create-bestax@4.2.13) (2026-10-08)

### Bug Fixes

* **bestax-mcp:** give .image's ratios their reason in the lookup ([3ea4d0c](3ea4d0c))
* **bestax-mcp:** say an .image converts around elements written out, not an expression ([49bb27b](49bb27b))
* **bestax-migrate:** convert an .image around its children only when they're elements ([ff99907](ff99907))
* **bestax-migrate:** flag react-bulma-components Pagination's delta={0} rather than renaming it ([e339ff1](e339ff1))
* **bestax-migrate:** keep a .menu-list around a bestax Menu.List as markup ([2119c3f](2119c3f))
* **bestax-migrate:** keep a Modal part as markup inside an existing bestax Modal ([cfd5f15](cfd5f15))
* **bestax-migrate:** keep a named anchor as markup instead of saying its name does nothing ([74dc360](74dc360)), closes [#fragment](https://github.com/allxsmith/bestax/issues/fragment)
* **bestax-migrate:** keep a page link as markup when its li is a component's only child ([0e72683](0e72683))
* **bestax-migrate:** know a bestax part imported under its flat export ([7a325ee](7a325ee))
* **bestax-migrate:** leave a wrapper tag alone when none of its classes would become a prop ([2397b9d](2397b9d))
* **bestax-migrate:** leave a wrapper tag with no helper class alone, TODOs and all ([1167a29](1167a29))
* **bestax-migrate:** map react-bulma-components Pagination onto the props it now renders from ([6cd4b51](6cd4b51))
* **bestax-migrate:** rename rbx innerRef to ref on a plain Navbar.Item too ([bb6ace0](bb6ace0)), closes [#734](#734)
* **bestax-migrate:** say why .image's ratios stay classes ([2fbfbd5](2fbfbd5))
* **bestax-migrate:** write a File text with a backslash as a string ([212831e](212831e))
* **bestax-migrate:** write a tabIndex string as a number on every root ([546bf8a](546bf8a)), closes [#814](#814)
* **bestax-migrate:** write isFullwidth from react-bulma-components too ([01da047](01da047))
* **bestax-migrate:** write isFullwidth rather than its deprecated alias from bloomer ([c2a1d22](c2a1d22)), closes [#680](#680)
* **bulma-ui:** announce polite notifications through a status region kept from mount ([#835](#835)) ([c93478d](c93478d))
* **bulma-ui:** answer the granularity review on native input and blur ([7a17486](7a17486))
* **bulma-ui:** apply textColor helper class on Navbar Menu, Start, End, and Burger ([#792](#792)) ([feb83c8](feb83c8))
* **bulma-ui:** attach useFocusTrap to a container that mounts after it turns on ([17a944d](17a944d))
* **bulma-ui:** avoid empty class attribute on several components ([#793](#793)) ([7c5c316](7c5c316))
* **bulma-ui:** bring File and Taginput under the bare-Control Field rule ([cdaa6c2](cdaa6c2))
* **bulma-ui:** clear a picker's unused seed whenever its popover closes ([cbe86c5](cbe86c5))
* **bulma-ui:** close a picker's popover on Alt+ArrowUp from inside it ([b6da4ef](b6da4ef))
* **bulma-ui:** color the calendar from the color prop and read TimeInput's wheel variables ([2251e67](2251e67)), closes [#832](#832)
* **bulma-ui:** color TimeInput's wheels from the color prop ([#832](#832)) ([ad370c9](ad370c9))
* **bulma-ui:** commit nothing when a picker popover is dismissed ([0a46209](0a46209))
* **bulma-ui:** commit nothing when Enter confirms untouched picker text ([773e146](773e146))
* **bulma-ui:** commit nothing when focus leaves a picker untouched ([30b4849](30b4849))
* **bulma-ui:** document the checkbox, radio and switch color and size tuples ([bd39ff3](bd39ff3))
* **bulma-ui:** draw the time wheel focus ring where the wheel's mask shows it ([e1d8c9f](e1d8c9f)), closes [#832](#832)
* **bulma-ui:** drop the openOnFocus TSDoc reason that only holds for segments ([efde0d9](efde0d9))
* **bulma-ui:** Dropdown items withhold attributes by tag and answer Enter and Space ([#827](#827)) ([f6aeb2d](f6aeb2d))
* **bulma-ui:** fall back when useFocusTrap's initialFocusRef can't take focus ([c191931](c191931))
* **bulma-ui:** fire the pickers' onOpen and onClose once under StrictMode ([#896](#896)) ([20b51ed](20b51ed))
* **bulma-ui:** give the calendar's day grid rows of a week ([971a196](971a196)), closes [#774](#774)
* **bulma-ui:** give the selected calendar cell a ring that shows on its fill ([b3eecc6](b3eecc6))
* **bulma-ui:** hide a picker's launcher for a loading Control it sits in ([9a3888e](9a3888e))
* **bulma-ui:** hide a picker's launcher only for the spinner it draws ([7a28a0e](7a28a0e))
* **bulma-ui:** hold Portal to looking a selector up on each render ([8fe02ce](8fe02ce))
* **bulma-ui:** hold the year-1 floor under a max before it ([4f6eb18](4f6eb18))
* **bulma-ui:** judge image map areas by their image in useFocusTrap ([af7bc59](af7bc59))
* **bulma-ui:** keep a range's end while the start's digits are coming ([8d1f862](8d1f862))
* **bulma-ui:** keep a read-only date or time picker closed on ArrowDown ([ba74bf7](ba74bf7))
* **bulma-ui:** keep a tab stop in the year list when the year falls outside it ([fe028c1](fe028c1))
* **bulma-ui:** keep an empty picker's seed while a portaled popover is open ([1e66528](1e66528))
* **bulma-ui:** keep an inline date picker's calendar on its released id ([c26da07](c26da07)), closes [#897](#897) [#897](#897)
* **bulma-ui:** keep button defaults through a spread, and type the buttons that had none ([#853](#853)) ([0810482](0810482))
* **bulma-ui:** keep button types and Avatar's accessible name through a spread ([#826](#826)) ([dc798d4](dc798d4))
* **bulma-ui:** keep menuitemcheckbox and menuitemradio items in Dropdown's arrow-key order ([#786](#786)) ([064155a](064155a))
* **bulma-ui:** keep Numberinput's buttons in a row inside Field > Control ([4dff84c](4dff84c))
* **bulma-ui:** keep Numberinput's Field examples in a row and labelled ([c937c88](c937c88))
* **bulma-ui:** keep radiusless zeroing the radius inside a Theme ([07db6a3](07db6a3)), closes [#829](#829) [#694](#694)
* **bulma-ui:** keep the calendar behind DateTimeInput's time wheels out of reach ([c7f674c](c7f674c))
* **bulma-ui:** keep the clock's seconds out of a picked date and time ([0af2e71](0af2e71))
* **bulma-ui:** keep the Field for horizontal and fieldClassName in a bare Control ([e4dc513](e4dc513))
* **bulma-ui:** keep the picker focus rings visible in every color ([612aa09](612aa09))
* **bulma-ui:** keep the range band under the pointer in the calendar ([c1f2008](c1f2008))
* **bulma-ui:** key the Avatar link warning on the element and attributes ([e628eba](e628eba)), closes [#733](#733) [#733](#733)
* **bulma-ui:** key the Control-level warning by its advice ([24cda3d](24cda3d))
* **bulma-ui:** leave keys on a control inside a tab to that control ([4a9f7b6](4a9f7b6))
* **bulma-ui:** leave rel out of the Avatar link attribute warning ([b059476](b059476)), closes [#733](#733) [#733](#733)
* **bulma-ui:** let Autocomplete's clear button give way to a loading spinner ([5c11fb2](5c11fb2))
* **bulma-ui:** let Escape in a popover's year dropdown go back to the grid ([a8b1dbf](a8b1dbf)), closes [#901](#901)
* **bulma-ui:** let File's picked-files count be reworded, and document its name in the label ([e86545c](e86545c))
* **bulma-ui:** let focus follow the keys in an inline calendar, and skip disabled days for the tab stop ([#885](#885)) ([f55af27](f55af27))
* **bulma-ui:** let several isRoot Themes share the :root style element ([04f399f](04f399f)), closes [#736](#736)
* **bulma-ui:** let the arrow keys move through the calendar's year dropdown ([6abc329](6abc329)), closes [#901](#901)
* **bulma-ui:** let the picker bases give way to a loading Control too ([66e803a](66e803a))
* **bulma-ui:** let useFocusTrap go of a container that leaves while it is on ([8c56d7a](8c56d7a))
* **bulma-ui:** let warnOnce decide when the Avatar link warning fires ([1a5965c](1a5965c)), closes [#733](#733)
* **bulma-ui:** make ArrowUp raise a time wheel's value ([c27c310](c27c310))
* **bulma-ui:** make auto leave room for an in-place picker panel's themed offset ([8c534bd](8c534bd)), closes [#904](#904)
* **bulma-ui:** make Tabs keyboard operable with the WAI-ARIA tabs pattern ([fe0e7ef](fe0e7ef))
* **bulma-ui:** make Theme colorMode switch the scheme under the prefixed builds ([#894](#894)) ([2bd6ec2](2bd6ec2))
* **bulma-ui:** make Theme's radius the helper it is typed as ([36c73d3](36c73d3)), closes [#694](#694)
* **bulma-ui:** make useFocusTrap follow radio groups and initialFocusRef past the trap ([d6219d4](d6219d4))
* **bulma-ui:** match a picker's opening focus only inside its calendar ([e3c22ed](e3c22ed))
* **bulma-ui:** merge className into Navbar.Divider instead of overwriting it ([#791](#791)) ([fcc0d51](fcc0d51))
* **bulma-ui:** move focus into DateTimeInput's time wheels as they open ([adfa9db](adfa9db))
* **bulma-ui:** move the year dropdown's tab stop with the arrow keys ([f56daf5](f56daf5))
* **bulma-ui:** name a picker's default icon when its icon size or column moves ([6f6de39](6f6de39))
* **bulma-ui:** name custom elements among the targets that get Avatar's target and rel ([a962259](a962259)), closes [#733](#733)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([15cbbb8](15cbbb8)), closes [#952](#952)
* **bulma-ui:** name DateRangeInput's default icon in its Control-level warning ([9cbe7ca](9cbe7ca)), closes [#952](#952)
* **bulma-ui:** name Pagination's page links, and read a count that's no number as its default ([0a1cf06](0a1cf06))
* **bulma-ui:** open DateRangeInput's popover on Alt+ArrowDown, as the other pickers ([c0e22ec](c0e22ec))
* **bulma-ui:** open the date and time popovers on Alt+ArrowDown ([6db22cc](6db22cc))
* **bulma-ui:** order the Tabs fallback stop by index and style disabled tabs ([eefd283](eefd283))
* **bulma-ui:** pick a DateInput day at midnight by key as by click ([92c27ca](92c27ca))
* **bulma-ui:** place a portaled picker panel by its coordinates alone ([#886](#886)) ([040299b](040299b))
* **bulma-ui:** place toasts and notifications at the position they were shown with ([#834](#834)) ([62feab9](62feab9))
* **bulma-ui:** prefix the is-current and is-disabled classes on Pagination's parts ([c9a5fae](c9a5fae))
* **bulma-ui:** reach Taginput's delete buttons and Autocomplete's clear button ([21a064b](21a064b))
* **bulma-ui:** read a Pagination current page that's no number as the first ([68e963b](68e963b))
* **bulma-ui:** read clicks and focus inside a shadow root ([474f2cc](474f2cc))
* **bulma-ui:** read picker bounds and months in years 0 to 99 as written ([#890](#890)) ([02fb619](02fb619))
* **bulma-ui:** render the four burger spans Bulma v1 positions ([#785](#785)) ([8e4e1e6](8e4e1e6))
* **bulma-ui:** restore a portaled Modal's focus to an opener in a shadow root ([c564bd3](c564bd3))
* **bulma-ui:** return focus to the input when a date picker closes ([b741264](b741264))
* **bulma-ui:** say a picked DateTimeInput day keeps milliseconds and meets the bounds ([3536467](3536467))
* **bulma-ui:** say Tab reaches DateRangeInput's end input only when typing ([d2d3d1a](d2d3d1a))
* **bulma-ui:** say where Numberinput goes bare and test bare={false} in a Field ([0461631](0461631))
* **bulma-ui:** send a press on DateRangeInput's field to the nearer input ([f06b2b0](f06b2b0))
* **bulma-ui:** settle Popover's deep review findings ([feadaf4](feadaf4))
* **bulma-ui:** show the picked file with File's hasName and add a keyboard focus ring ([7881db4](7881db4))
* **bulma-ui:** show toasts, notifications and dialogs raised before their container mounts ([#828](#828)) ([2ab4493](2ab4493))
* **bulma-ui:** skip the Avatar target warning on elements with their own target ([27b58f4](27b58f4)), closes [#733](#733)
* **bulma-ui:** start a date picker's focus on the focused cell ([#897](#897)) ([6a55714](6a55714))
* **bulma-ui:** stop Bulma's spinners under reduced motion in every stylesheet ([b234712](b234712)), closes [#770](#770)
* **bulma-ui:** stop form wrappers nesting a Field in a bare Control ([2c6d295](2c6d295))
* **bulma-ui:** stop shipping test-only exports, and document notification() ([#781](#781)) ([5f95398](5f95398))
* **bulma-ui:** stop the date pickers at year 1 ([853142a](853142a))
* **bulma-ui:** stop the indeterminate progress bar and skeleton pulse under reduced motion ([bcf5407](bcf5407))
* **bulma-ui:** stop the Rate pop and DateTimeInput scrim under reduced motion ([3a59129](3a59129))
* **bulma-ui:** stop TimeInput reopening on the focus its popover hands back ([1c87c15](1c87c15))
* **bulma-ui:** strip the Avatar link warning from production builds ([a243fa5](a243fa5)), closes [#733](#733)
* **bulma-ui:** warn about a dropped Avatar href only for an as the caller wrote ([c93b27c](c93b27c)), closes [#733](#733)
* **bulma-ui:** warn in development when Avatar drops an href on a non-link as ([c76e632](c76e632)), closes [#733](#733)
* **bulma-ui:** warn when a root Theme drops its className and helpers ([05c10e0](05c10e0))
* **bulma-ui:** warn when a wrapper inside a Control drops its Control-level props ([cbf434b](cbf434b)), closes [#921](#921)
* **bulma-ui:** warn when an inline picker drops its Control-level props ([f0494bd](f0494bd)), closes [#921](#921)
* **bulma-ui:** warn when Avatar drops a target or rel on a non-link as ([50c385e](50c385e)), closes [#733](#733) [#733](#733)
* **create-bestax:** check the react ranges fit the library's peers, not equal them ([8ae5a0c](8ae5a0c)), closes [#950](#950)
* **create-bestax:** import the icon CSS for every Bulma flavor, not only complete ([a712b91](a712b91)), closes [#946](#946)
* **create-bestax:** install react and react-dom so Yarn 1 reports no unmet peers ([9c9814c](9c9814c)), closes [#644](#644) [#950](#950)
* **create-bestax:** name the files the overwrite prompt removes, and stop on a file path ([39b6232](39b6232)), closes [#945](#945)
* **create-bestax:** never empty a non-empty folder under -y, and validate flags first ([917f195](917f195)), closes [#950](#950) [#945](#945) [#950](#950)
* **create-bestax:** warn when the icon CSS import has nowhere to go ([f7f0b64](f7f0b64)), closes [#946](#946) [#946](#946)
* **eslint-plugin:** judge Columns' gap by its own steps, and lengths as lengths ([4786c8d](4786c8d))
* **eslint-plugin:** report .file as a class the codemod converts ([72a32c9](72a32c9))
* **eslint-plugin:** report .image with the message for a class the codemod converts ([d27c19b](d27c19b))
* **eslint-plugin:** report .menu, .menu-label and .menu-list with the converts message ([8ffaccc](8ffaccc))
* **eslint-plugin:** report .select and .breadcrumb as converted ([a9d8082](a9d8082))
* **eslint-plugin:** report Bulma form markup as classes the codemod converts ([128e832](128e832))
* **eslint-plugin:** report Bulma skeletons as converted ([04ca4ee](04ca4ee))
* **eslint-plugin:** report Modal's parts with the message for a class the codemod converts ([87f3c08](87f3c08))
* **eslint-plugin:** report Pagination's converting parts with the converts message ([6b94f14](6b94f14))
* **eslint-plugin:** report the pagination links and ellipsis as classes the codemod converts ([54ba0b3](54ba0b3))
* **eslint-plugin:** report Theme's deprecated radius route accurately ([5605816](5605816)), closes [#694](#694)
* **eslint-plugin:** suggest radiusless for a near miss on Theme ([21aa9a7](21aa9a7)), closes [#694](#694)

### Features

* **bestax-mcp:** look up .image as Image, with the props it takes from its <img> ([3e63230](3e63230))
* **bestax-mcp:** look up .menu and its label and list as Menu's parts ([f9fe7cd](f9fe7cd))
* **bestax-mcp:** look up Card's title and footer items on the tags their as takes ([ba8193e](ba8193e))
* **bestax-mcp:** look up Modal's parts as components ([b71583a](b71583a))
* **bestax-mcp:** look up Pagination, its list and its previous and next links as components ([f1298df](f1298df))
* **bestax-mcp:** look up the bestax component and props for a Bulma class string ([4a4b246](4a4b246)), closes [#744](#744)
* **bestax-mcp:** publish to the official MCP Registry ([74efc7f](74efc7f))
* **bestax-mcp:** say a Bulma field wraps its children only when horizontal ([929bc82](929bc82))
* **bestax-mcp:** say an .image converts around anything but a bare <img> ([60e9219](60e9219))
* **bestax-mcp:** say Menu.List renders .menu-list only at the top level ([dcce74f](dcce74f))
* **bestax-mcp:** say when a component renders the children from a count ([b60c295](b60c295))
* **bestax-mcp:** say when a component renders the element inside it ([4ced25c](4ced25c))
* **bestax-mcp:** say when a component renders the li around its element, or its own text ([8fd3faf](8fd3faf))
* **bestax-mcp:** say when a component renders the whole .file tree from props ([976d8a3](976d8a3))
* **bestax-migrate:** convert .file inside a Field, building its tree from props ([724dff5](724dff5)), closes [#809](#809)
* **bestax-migrate:** convert .icon-text, building its icons from props ([#823](#823)) ([933868f](933868f))
* **bestax-migrate:** convert .menu, its labels and its top-level lists ([02f4db6](02f4db6))
* **bestax-migrate:** convert .select and .breadcrumb with the element inside them ([d76c569](d76c569))
* **bestax-migrate:** convert .tabs and .icon around their children ([#815](#815)) ([3967a80](3967a80))
* **bestax-migrate:** convert a menu list's items to Menu.Item ([#816](#816)) ([b385687](b385687))
* **bestax-migrate:** convert an .image and its <img> to Image ([d4f3673](d4f3673)), closes [#793](#793)
* **bestax-migrate:** convert an .image around anything but a bare <img> ([0a31c5b](0a31c5b)), closes [#801](#801)
* **bestax-migrate:** convert Bulma cards built from their parts ([#752](#752)) ([1b08e17](1b08e17))
* **bestax-migrate:** convert Bulma form fields, controls, inputs and textareas ([3da788d](3da788d)), closes [#743](#743)
* **bestax-migrate:** convert Bulma grids and cells ([#760](#760)) ([22adc7c](22adc7c)), closes [#743](#743)
* **bestax-migrate:** convert Bulma navbars ([#754](#754)) ([02fdd72](02fdd72))
* **bestax-migrate:** convert Bulma skeletons ([2574ace](2574ace))
* **bestax-migrate:** convert Card's title and footer items on the tags their as takes ([20bc0c6](20bc0c6)), closes [#794](#794)
* **bestax-migrate:** convert conditional classes in clsx and classnames calls ([8948cce](8948cce))
* **bestax-migrate:** convert Modal's parts element by element ([4d41ad2](4d41ad2)), closes [#805](#805)
* **bestax-migrate:** convert navbar dividers with classes, and navbar text colors ([#796](#796)) ([c97c7e9](c97c7e9))
* **bestax-migrate:** convert Pagination, its list and its previous and next links ([d75bc70](d75bc70)), closes [#807](#807)
* **bestax-migrate:** convert Pagination's page links and ellipsis in their li's place ([ae720fa](ae720fa)), closes [#809](#809)
* **bestax-migrate:** convert Panel and its heading, tabs and blocks ([#811](#811)) ([0694e54](0694e54))
* **bestax-migrate:** convert the gap, position, overflow, radius and aspect-ratio helpers ([13dcf63](13dcf63))
* **bestax-migrate:** fold .table-container and .fixed-grid into the component inside ([#761](#761)) ([72504f5](72504f5)), closes [#743](#743)
* **bulma-ui:** add Bulma's gap helper props to every component ([#877](#877)) ([1bd4abc](1bd4abc))
* **bulma-ui:** add Bulma's position, overflow, radius and aspect-ratio helper props ([#845](#845)) ([64fb91c](64fb91c))
* **bulma-ui:** add Collapses, an accordion group for Collapse ([#849](#849)) ([a12c823](a12c823))
* **bulma-ui:** add DateRangeInput ([50fcba7](50fcba7)), closes [#774](#774)
* **bulma-ui:** add Loader, Bulma's inline spinner ([c5e9eb0](c5e9eb0)), closes [#770](#770)
* **bulma-ui:** add month and year pickers to DateInput through granularity ([c4cfc2b](c4cfc2b)), closes [#773](#773)
* **bulma-ui:** add Popover ([2e17fac](2e17fac)), closes [#776](#776)
* **bulma-ui:** export ClientOnly and useIsHydrated ([2c0c1e6](2c0c1e6))
* **bulma-ui:** export Portal ([346d8c2](346d8c2))
* **bulma-ui:** export useFocusTrap, counting the stops the browser's Tab visits ([c304fef](c304fef)), closes [#772](#772)
* **bulma-ui:** let Card.Header.Title and Card.FooterItem render Bulma's own tags ([#794](#794)) ([47ecdb6](47ecdb6))
* **bulma-ui:** make columnGap the column gap helper on Theme ([eb2c611](eb2c611)), closes [#694](#694)
* **bulma-ui:** render Pagination from total, current and onPageChange ([f7ddf04](f7ddf04)), closes [#813](#813)
* **eslint-plugin:** add an opt-in rule for plain elements styled with a Bulma component class ([#750](#750)) ([0bb4d80](0bb4d80))
* **eslint-plugin:** check the gap helper props ([b53a749](b53a749))
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 4.2.13 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-assisted deep-review needs-human-review Loop converged (or contested): awaiting owner review + manual merge released

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] bulma-ui: several components render an empty class attribute

2 participants