create-bestax 4.2.7 → 4.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-bestax",
3
- "version": "4.2.7",
3
+ "version": "4.2.9",
4
4
  "description": "Create a new bestax-bulma project",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,7 +39,7 @@
39
39
  "figures": "^6.1.0",
40
40
  "fs-extra": "^11.4.0",
41
41
  "prompts": "^2.4.2",
42
- "@allxsmith/bestax-bulma": "^5.15.0"
42
+ "@allxsmith/bestax-bulma": "^5.16.4"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@jest/globals": "^30.0.0",
@@ -72,7 +72,9 @@ Storybook `argTypes`/tests:
72
72
  `validAlignments`, `validTextTransforms`, `validTextWeights`, `validFontFamilies`,
73
73
  `validDisplays`, `validVisibilities`, `validFlexDirections`, `validFlexWraps`,
74
74
  `validJustifyContents`, `validAlignContents`, `validAlignItems`, `validAlignSelfs`,
75
- `validFlexGrowShrink`, `validViewports`.
75
+ `validFlexGrowShrink`, `validViewports`, `validFloats`, `validOverflows`,
76
+ `validInteractions`, `validCursors`, `validRadii`, `validShadows`,
77
+ `validResponsives`.
76
78
 
77
79
  ```ts
78
80
  export type MyColor = (typeof validColors)[number];
@@ -97,6 +97,46 @@ Rules that keep components consistent:
97
97
  - **Spread `rest`, not `props`**, onto the DOM node — `useBulmaClasses` has already stripped the
98
98
  helper props out of `rest`, so they don't leak to the DOM as invalid attributes.
99
99
  - **Set `displayName`** on `forwardRef` components (needed for tests and Storybook autodocs).
100
+ - **A polymorphic `as` means the props follow it, and usually the ref too.** If `as` accepts any
101
+ `React.ElementType`, do not pin the props to one element — split them into a
102
+ `FooOwnProps` interface and intersect it with `ComponentPropsWithoutRef<T>`, then cast
103
+ the `forwardRef` result to `PolymorphicComponent<FooOwnProps, 'default-tag'>`
104
+ (`src/helpers/polymorphic.ts`). `Button.tsx` is the reference.
105
+ **Write that intersection out in the alias; do not build it from
106
+ `PolymorphicProps<T, FooOwnProps>`.** The API-docs extractor walks heritage
107
+ syntactically, and it cannot see through a generic alias or a distributive
108
+ conditional — routing the alias through the helper drops most of the props
109
+ table without failing (#667). `PolymorphicProps` is for consumer and wrapper
110
+ types; `PolymorphicComponent<FooOwnProps, 'default-tag'>` is the cast target,
111
+ and `PolymorphicComponentWithoutRef` the one for a component that forwards no
112
+ ref. Add type-level checks in `src/__typetests__/` both ways — that the
113
+ default `as` accepts its element's props and a different `as` rejects them.
114
+ Tests and stories are type-checked too (`typecheck:tests`), but `__typetests__/`
115
+ is the home for these: `pnpm typecheck` reads it, so a consumer running that
116
+ script gets them as well. Pinning the props instead
117
+ rejects correct code and accepts incorrect code at the same time, which is what #641 fixed
118
+ across eight components. A literal union (`Title.tsx`) escapes the generic only when its
119
+ members genuinely **share** a prop and ref surface — `h1`–`h6` and `p` all carry plain
120
+ `HTMLAttributes`, so one interface describes them all. It is not a general exemption:
121
+ `Dropdown.Item`'s `'a' | 'div' | 'button'` differ in `href`, `disabled`, `type` and their ref
122
+ element, and pinning them to one interface reproduces exactly this defect (#663). When the
123
+ members differ, constrain `T` to the union rather than dropping the generic —
124
+ `ConstrainedPolymorphicComponentWithoutRef` in `helpers/polymorphic.ts` is that
125
+ shape, and `Dropdown.Item` is the worked example. Two consequences to pin while
126
+ you are there. **Default the alias's `T` to the whole union, not to the rendered
127
+ element** — narrowing it would break `const p: SomeProps = { as: 'div' }`, which
128
+ compiles for every consumer today; the cost is that the bare alias then carries
129
+ only the keys all members share, so no `href` (#667, `next-major`). The
130
+ component keeps full precision at each call site regardless. And a wrapping HOC
131
+ (`React.memo`) infers through the derivation overload, so it collapses onto the
132
+ component's default element — stricter than the component, not looser, whatever
133
+ a reader expects.
134
+ Forward the ref unless the component owns the node it needs: `Reveal` observes
135
+ an element for scroll intersection and wraps a custom `as` in its own `div`,
136
+ so the element `as` names is not the one it holds — it uses
137
+ `PolymorphicComponentWithoutRef` and forwards none. That is the exception, not
138
+ a licence to skip refs; everything a consumer might focus or measure should
139
+ forward one.
100
140
  - **Element sizing uses an inline `'small' | 'medium' | 'large'` union**, mapped to `is-small` /
101
141
  `is-medium` / `is-large` (see `Tabs.tsx`, `Control.tsx`). Do **not** reach for the `validSizes`
102
142
  constant — that one is `'0'…'6' | 'auto'` and exists for **spacing** helpers, not element size.
@@ -58,11 +58,11 @@ Every component also accepts the shared Bulma helper props (`m`/`p` spacing, `te
58
58
 
59
59
  `<Hero>` is a full-width banner. Subcomponents: `Hero.Head`, `Hero.Body`, `Hero.Foot`.
60
60
 
61
- | Prop | Type |
62
- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
- | `color` | `primary \| link \| info \| success \| warning \| danger \| black \| white \| light \| dark` (CSS-backed). Also accepted but deprecated, no CSS, dev-warn: `black-bis`, `black-ter`, the greys, `inherit`, `current` |
64
- | `size` | `'small' \| 'medium' \| 'large' \| 'fullheight' \| 'fullheight-with-navbar'` |
65
- | `fullheightWithNavbar` | `boolean` |
61
+ | Prop | Type |
62
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63
+ | `color` | `primary \| link \| info \| success \| warning \| danger \| black \| white \| light \| dark` (CSS-backed). Also accepted but deprecated, no CSS, dev-warn: every other `validColors` member, plus `inherit` and `current` |
64
+ | `size` | `'small' \| 'medium' \| 'large' \| 'fullheight' \| 'fullheight-with-navbar'` |
65
+ | `fullheightWithNavbar` | `boolean` |
66
66
 
67
67
  ```tsx
68
68
  <Hero color="primary" size="medium">
@@ -243,7 +243,8 @@ a navbar that mounts conditionally.
243
243
 
244
244
  **Routing:** in a routed app, don't use `href="#"` — render items as the router's link
245
245
  component. `Menu.Item as={Link} to="/x"` and `Navbar.Item as={Link} to="/x"` both compile
246
- without casts (their props allow extra keys). Drive `active` from `useLocation().pathname`.
246
+ without casts (their props follow `as`, so `to` is checked against the router's own link
247
+ type). Drive `active` from `useLocation().pathname`.
247
248
  Full patterns (including Buttons that navigate and Next.js `href`): the docs guide at
248
249
  https://bestax.io/docs/guides/features/routing.
249
250
 
@@ -14,20 +14,20 @@ component.
14
14
 
15
15
  bloomer's `withHelpersModifiers` mixed these into every component.
16
16
 
17
- | bloomer | bestax-bulma | note |
18
- | --------------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19
- | `hasTextAlign="centered"` | `textAlign="centered"` | `left` / `right` / `centered` — same union |
20
- | `hasTextColor="grey-light"` | `textColor="grey-light"`, or `className="has-text-grey-light"` | `textColor` is declared per component, not by the helper hook, so it carries over on the ~48 targets that have it and becomes the Bulma class on the rest (`Tag`, `Table`, `Hero`, `Menu`, `Breadcrumb`, `Panel`, `Icon`, `Progress`, the form controls); every Bulma 0.6 colour and shade works but `white-ter`/`white-bis` |
21
- | `isPulled="right"` | `float="right"` | |
22
- | `isClearfix` | `clearfix` | |
23
- | `isOverlay` | `overlay` | |
24
- | `isUnselectable` | `interaction="unselectable"` | |
25
- | `isMarginless` | `m="0"` | bestax expresses the `is-*less` helpers as spacing |
26
- | `isPaddingless` | `p="0"` | |
27
- | `isFullWidth` | `isFullWidth` | on Button, Select, Table, Tabs; a TODO elsewhere |
28
- | `isDisplay`, `isHidden` | `display*`, `visibility*` | flattened — see below |
29
- | `tag` | `as` | where bestax declares one — see below |
30
- | `render` | — | always a TODO |
17
+ | bloomer | bestax-bulma | note |
18
+ | --------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
19
+ | `hasTextAlign="centered"` | `textAlign="centered"` | `left` / `right` / `centered` — same union |
20
+ | `hasTextColor="grey-light"` | `textColor="grey-light"`, or `className="has-text-grey-light"` | `textColor` is declared per component, not by the helper hook, so it carries over on the ~48 targets that have it and becomes the Bulma class on the rest (`Tag`, `Table`, `Hero`, `Menu`, `Breadcrumb`, `Panel`, `Icon`, `Progress`, the form controls); every Bulma 0.6 colour and shade works |
21
+ | `isPulled="right"` | `float="right"` | |
22
+ | `isClearfix` | `clearfix` | |
23
+ | `isOverlay` | `overlay` | |
24
+ | `isUnselectable` | `interaction="unselectable"` | |
25
+ | `isMarginless` | `m="0"` | bestax expresses the `is-*less` helpers as spacing |
26
+ | `isPaddingless` | `p="0"` | |
27
+ | `isFullWidth` | `isFullWidth` | on Button, Select, Table, Tabs; a TODO elsewhere |
28
+ | `isDisplay`, `isHidden` | `display*`, `visibility*` | flattened — see below |
29
+ | `tag` | `as` | where bestax declares one — see below |
30
+ | `render` | — | always a TODO |
31
31
 
32
32
  ## `isDisplay` and `isHidden`
33
33
 
@@ -101,18 +101,49 @@ Everywhere else `tag` is left in place with a TODO. On the components that becom
101
101
  (`Help`, `Label`, `Heading`, `BreadcrumbItem`, `PanelTab`, `TabLink`, `Page`, `HeroVideo`) a
102
102
  literal `tag` is honoured — `<Help tag="span">` becomes `<span className="help">`.
103
103
 
104
+ A literal `tag` outside the union its bestax target narrows `as` to — `<Media tag="section">`,
105
+ `<Control tag="span">` — is dropped with a `prop:as` TODO naming the tags that component does
106
+ render. bloomer rendered the tag you asked for; bestax does not offer it there, and writing it
107
+ through produced output the project could not compile.
108
+
109
+ ## `href` picks the element
110
+
111
+ bestax gives an element the attributes of the tag `as` names, so `href` exists only where that
112
+ tag is an `<a>`. bloomer had no such rule, and the two libraries part company in two ways.
113
+
104
114
  bloomer's `Button` and `Image` never took `tag` at all. Seven bloomer components — `Button`,
105
115
  `Delete`, `LevelItem`, `DropdownItem`, `NavbarItem`, `PanelBlock`, `CardFooterItem` — rendered
106
116
  an `<a>` whenever `href` was set, whatever `tag` said, and a `<div>` (or their default tag)
107
- otherwise; the rest (`MenuLink`, `PageControl`, `Dropdown`, …) rendered their `tag` regardless.
108
- The codemod keeps that: `Button` and `LevelItem` gain `as="a"` beside a literal `href`; a `tag`
109
- next to a literal `href` is dropped on the switching targets that already render an anchor
110
- (`Navbar.Item`, `Dropdown.Item`, `Panel.Block`); a `NavbarItem` or `DropdownItem` with neither
111
- `href` nor `tag` gains `as="div"`, because bestax's `Navbar.Item` and `Dropdown.Item` default
112
- to an `<a>`. A dynamic `href={expr}` was a runtime decision bloomer made and bestax cannot, so it
113
- is flagged (`prop:href`) rather than guessed. bestax's `Panel.Block` is always an `<a>`, so only
114
- a `PanelBlock` with `href` becomes one — the rest stay the plain `<div class="panel-block">` (or
115
- the `tag` you gave) that bloomer rendered.
117
+ otherwise; the rest (`MenuLink`, `NavbarLink`, `PageControl`, `Dropdown`, …) rendered their
118
+ `tag` regardless.
119
+
120
+ **On the switching components the `href` wins the element**, because that is what bloomer
121
+ rendered. `Button` and `LevelItem` gain `as="a"`; on the targets that already render an anchor
122
+ (`Navbar.Item`, `Dropdown.Item`, `Panel.Block`) the `tag` is simply dropped and the `href`
123
+ stays — each of those takes the anchor's props under its default `as`. A `NavbarItem` or
124
+ `DropdownItem` with neither `href` nor `tag` gains `as="div"`, because bestax's `Navbar.Item`
125
+ and `Dropdown.Item` default to an `<a>`. An empty or false `href` selected nothing in bloomer
126
+ and is dropped. bestax's `Panel.Block` is always an `<a>`, so only a `PanelBlock` with `href`
127
+ becomes one — the rest stay the plain `<div class="panel-block">` (or the `tag` you gave) that
128
+ bloomer rendered.
129
+
130
+ A dynamic `href={expr}` was a runtime decision bloomer made and bestax's `as` is one element or
131
+ the other. It resolves to the anchor, which is the branch the `href` is there for, and the
132
+ `prop:href` TODO names the element to render by hand for the empty case:
133
+
134
+ ```jsx
135
+ <Button href={p.url} tag="span">x</Button>
136
+ // TODO(bestax-migrate): bloomer chose the element at runtime … render <span> by hand where
137
+ // the `href` is empty
138
+ <Button href={p.url} as="a">x</Button>
139
+ ```
140
+
141
+ **Everywhere else the element wins.** `MenuLink` and `NavbarLink` rendered their `tag` whatever
142
+ `href` said, so `<MenuLink href="/x" tag="span">` really was a `<span href="/x">` — which
143
+ navigates nowhere in any browser. The element stays and the attribute that did nothing goes,
144
+ with a `prop:href` TODO. The same happens to a component that becomes plain markup: a
145
+ `<TabLink href="#one" tag="span">` becomes a `<span>`, and its `href` is named rather than
146
+ written. Where the link was the intent, drop the `tag`.
116
147
 
117
148
  ## Helper props on parts that take none
118
149
 
@@ -87,12 +87,14 @@ bestax's `Dropdown` takes a `label` and renders its own trigger and menu, so blo
87
87
  </Dropdown>
88
88
 
89
89
  <Dropdown label="Open" active right>
90
- <Dropdown.Item onClick={() => navigate('/a')}>A</Dropdown.Item>
90
+ <Dropdown.Item href="/a">A</Dropdown.Item>
91
91
  </Dropdown>
92
92
  ```
93
93
 
94
- bestax's `Dropdown.Item` declares no `href` (`prop:href` on a `DropdownItem`): navigate in
95
- `onClick`, or put an `<a>` inside the item.
94
+ bestax's `Dropdown.Item` renders an `<a>` by default and takes that anchor's props, so the
95
+ `href` carries over. It keeps one only where the element it renders is the anchor: on
96
+ `as="div"` or `as="button"` the attribute is dropped (`prop:href`), and the item is a link
97
+ again if you drop the `as`.
96
98
  `isHoverable` → `hoverable`, `isActive` → `active` carry over on the `Dropdown` itself.
97
99
 
98
100
  ## `prop:tag` — polymorphism
@@ -108,6 +110,56 @@ Elsewhere, render the element you wanted directly, or move the bestax component
108
110
  A dynamic `tag` on a component that becomes plain markup is flagged the same way — the plain
109
111
  element takes bloomer's default tag.
110
112
 
113
+ ## `prop:as` — a tag the component does not render
114
+
115
+ Several bestax components accept `as` but narrow it to the tags Bulma's markup allows there, so
116
+ a literal `tag` outside that union (`<Media tag="section">`, `<Control tag="span">`) becomes a
117
+ `prop:as` TODO listing the tags that component does render. Wrap the component in the element
118
+ you wanted, or restructure.
119
+
120
+ ## `prop:href` — a link needs the anchor
121
+
122
+ bestax gives an element the attributes of the tag `as` names, so an `href` belongs on an `<a>`
123
+ or on a custom component you pass to `as`, never on another intrinsic tag. bloomer's `MenuLink`, `NavbarLink` and the components that become plain
124
+ markup rendered their `tag` whatever `href` said, so `<MenuLink href="/x" tag="span">` really
125
+ was a `<span href="/x">` — an attribute no browser acts on. The element stays, the dead
126
+ attribute goes:
127
+
128
+ ```jsx
129
+ <MenuLink href="/x" tag="span">Home</MenuLink>
130
+ <Menu.Item as="span">Home</Menu.Item>
131
+ ```
132
+
133
+ Drop the `tag` where the link was the point. On the components that switched to an `<a>` on
134
+ `href` the codemod does that for you — see [prop-map.md](prop-map.md).
135
+
136
+ Most targets take no `href` at all. It lives on `Menu.Item`, `Navbar.Item`, `Navbar.Link`,
137
+ `Panel.Block`, `Dropdown.Item` and the three `Pagination` controls, which render an `<a>` unless
138
+ told otherwise,
139
+ and on `Button` and `Level.Item` once `as="a"` names one — those two render a `<button>` and a
140
+ `<div>` by default, and drop the attribute. Everywhere else the codemod removes it.
141
+
142
+ `Dropdown.Item` is the one to read twice: it accepts `as="a" | "div" | "button"` and takes the
143
+ props of whichever you name, so the default `<a>` keeps an `href` and the other two do not.
144
+ Drop the `as` to make it a link again; inside the `<button>` form an `<a>` would nest
145
+ interactive content, so navigate in `onClick` there.
146
+
147
+ ## `prop:target`, `prop:download`, `prop:hrefLang`, `prop:ping`, `prop:referrerPolicy`, `prop:media`
148
+
149
+ `target`, `download`, `hrefLang`, `ping`, `referrerPolicy` and `media` follow the element the same way
150
+ `href` does, and they are invalid on the wrong one whether or not an `href` is beside them —
151
+ `<Navbar.Link as="span" target="_blank">` does not compile on its own. Each is judged against
152
+ the element that actually renders, not as a group, so a `referrerPolicy` on an `<img>` or a
153
+ `target` on a `<form>` stays where it is legal. Where one is removed the TODO quotes it. Put it
154
+ on an `<a>` inside, or make the element one that takes it.
155
+
156
+ `rel` is never touched: React declares it on `HTMLAttributes`, so it is valid on every element.
157
+
158
+ A component can be narrower than its element. One that takes no `href` at any `as` takes none of
159
+ these either. `Level.Item` is not narrower: it declares the anchor's whole attribute surface at
160
+ every `as` and forwards it only on the `<a>`, so all of these survive at `as="a"` and none of
161
+ them reaches a `<p>` or a `<div>`.
162
+
111
163
  ## `prop:render` — the render prop
112
164
 
113
165
  bloomer's `render` handed the computed props (`className` included) to your own renderer:
@@ -159,7 +211,9 @@ value, or a dynamic `className` the class cannot be spliced into, is flagged wit
159
211
 
160
212
  ## Props with no counterpart
161
213
 
162
- Each of these is left in place with a TODO:
214
+ Each of these raises a TODO. Most are left on the element for you to resolve; the `href` rows
215
+ are the exception — bestax types no `href` onto the element these ended up on, so the codemod
216
+ removes the attribute and the TODO quotes what it was:
163
217
 
164
218
  | prop | on | what to do |
165
219
  | ------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
@@ -167,8 +221,9 @@ Each of these is left in place with a TODO:
167
221
  | `hasAddons="fullwidth"` | `Field` | `hasAddons` plus `className="has-addons-fullwidth"` |
168
222
  | `isAlign` | `TabList` | set `align` on the `<Tabs>` — Bulma aligns the container |
169
223
  | `isGrid` | `Columns` | Bulma removed `columns.is-grid` in 0.5; use `isMultiline` with sized columns, or `Grid` |
170
- | `href` | `CardFooterItem`, `CardHeaderIcon`, `Delete`, `DropdownItem` | put an `<a>` inside, or handle it in `onClick` |
171
- | `href={expr}` (dynamic) | `Button`, `LevelItem` and the other components that switched to an `<a>` on `href` | bloomer decided the element at runtime; set `as` conditionally by hand |
224
+ | `href` | `CardFooterItem`, `CardHeaderIcon`, `Delete` | put an `<a>` inside, or handle it in `onClick` |
225
+ | `href` beside a `tag` | `MenuLink`, `NavbarLink`, and anything that becomes plain markup | the tag bloomer rendered was no anchor, so the `href` did nothing; drop the `tag` |
226
+ | `href={expr}` (dynamic) | `Button`, `LevelItem` and the other components that switched to an `<a>` on `href` | resolved to the anchor; render the other element by hand where the `href` is empty |
172
227
  | `href` | `NavbarItem hasDropdown` | bestax's `Navbar.Dropdown` is the container; put the `href` on the `Navbar.Link` inside |
173
228
  | `isRatio` beside `isSize` | `Image` | bestax's one `size` took the fixed size; restore the ratio if that was the point |
174
229
 
@@ -202,11 +257,6 @@ prop conditionally:
202
257
  counterpart in bestax (only `isNarrowTouch`) — Bulma keeps the `is-*-touch` classes, so use
203
258
  `className`.
204
259
 
205
- ## `prop:hasTextColor="white-ter"` / `"white-bis"`
206
-
207
- Two Bulma 0.6 shades bestax has no colour for. Use `white`, or a custom class. Every other colour
208
- and shade of that era exists in bestax verbatim.
209
-
210
260
  ## `value-reference` — a component used as a value
211
261
 
212
262
  `const Wrapped = Box` and `{ Subtitle }` are rewritten to the bestax binding (`Hero.Foot`,
@@ -98,7 +98,7 @@ test holds to rbx's own export surface in both directions.
98
98
  | `Navbar.Divider` | `Navbar.Divider` | mapped |
99
99
  | `Navbar.Menu` | `Navbar.Menu` | mapped |
100
100
  | `Navbar.Link` | `Navbar.Link` | mapped |
101
- | `Navbar.Item` | _structural_ | mapped |
101
+ | `Navbar.Item` | `Navbar.Item` | mapped |
102
102
  | `Navbar.Item.Container` | _structural_ | mapped |
103
103
  | `Navbar.Dropdown` | _structural_ | mapped |
104
104
  | `Navbar.Segment` | _structural_ | mapped |
@@ -28,8 +28,7 @@ rbx mixes these into every component via `HelpersProps`.
28
28
  | `shadowless` | `shadow="shadowless"` | |
29
29
  | `unselectable` | `interaction="unselectable"` | |
30
30
 
31
- Two rbx colour names have no bestax equivalent: **`white-ter`** and **`white-bis`**. Everything
32
- else in rbx's `colors` and `shades` unions exists in bestax verbatim.
31
+ Every name in rbx's `colors` and `shades` unions exists in bestax verbatim.
33
32
 
34
33
  ## Bare boolean modifiers → `is*`
35
34
 
@@ -86,7 +85,7 @@ rbx has three shapes; all three flatten to bestax's per-viewport props.
86
85
 
87
86
  rbx's `forwardRefAs` puts `as` on **every** component. bestax declares it on a smaller set, and
88
87
  several of those narrow it to specific tags (`Footer` is `'footer' | 'div'`, `Control` is
89
- `'div'`). The codemod passes `as` through only where bestax really accepts it, and TODOs it
88
+ `'div' | 'p'`). The codemod passes `as` through only where bestax really accepts it, and TODOs it
90
89
  everywhere else:
91
90
 
92
91
  | bestax component | `as` accepts |
@@ -98,7 +97,7 @@ everywhere else:
98
97
  | `Media` | `'article' \| 'div'` |
99
98
  | `Media.Left` | `'figure' \| 'div'` |
100
99
  | `Level.Item` | `'div' \| 'p' \| 'a'` |
101
- | `Control` | `'div'` |
100
+ | `Control` | `'div' \| 'p'` |
102
101
  | `Menu.Item` | any element type |
103
102
  | `Dropdown.Item` | `'a' \| 'div' \| 'button'` |
104
103
  | `Navbar.Item`, `Navbar.Link` | any element type |
@@ -113,7 +112,28 @@ wrong:
113
112
  other two.
114
113
  - Several of the accepted props are **narrow literal unions**, so `as={SomeComponent}` still
115
114
  fails to typecheck even where `as` is allowed — which is deliberate: a visible type error
116
- beats a silent rewrite.
115
+ beats a silent rewrite. A **literal** outside the union is a different case: the codemod can
116
+ read it, so `<Control as="span">` drops the `as` with a `prop:as` TODO naming the tags that
117
+ component does render. Writing it through produced output the project could not compile.
118
+ Note that this one does change the rendered element: rbx's `forwardRefAs` rendered the tag you
119
+ gave it, so that really was a `<span>`, and the TODO exists to tell you the element moved.
120
+
121
+ ## `href` follows `as`
122
+
123
+ bestax gives an element the attributes of the tag `as` names, so `href` exists only where that
124
+ tag is an `<a>`. rbx is looser: `<Button as="span" href="/x">` type-checks there and renders
125
+ `<span href="/x">`, which navigates nowhere in any browser.
126
+
127
+ So the codemod keeps the element and drops the attribute, with a `prop:href` TODO:
128
+
129
+ ```jsx
130
+ <Button as="span" href="/x">x</Button>
131
+ <Button as="span">x</Button> // + TODO(bestax-migrate): `href` on `as="span"` …
132
+ ```
133
+
134
+ `<Button href="/x">` with no `as` goes the same way — bestax's `Button` renders a `<button>`,
135
+ so there is no anchor for the attribute to sit on. Where the link was the intent, set `as="a"`;
136
+ that is what keeps the `href`. Dropping the `as` does not, on this component.
117
137
 
118
138
  ## Refs
119
139
 
@@ -51,6 +51,50 @@ bestax's `<File>` renders the whole Bulma structure itself, so `File.Label`, `Fi
51
51
  rbx puts `as` on everything; bestax does not. Either render the tag directly, or restructure.
52
52
  See the `as` section of [prop-map.md](prop-map.md) for the components that do accept it.
53
53
 
54
+ The same rule fires a second way: several bestax components accept `as` but narrow it to the
55
+ tags Bulma's markup allows there, so a literal outside that union (`<Control as="span">`,
56
+ `<Media as="section">`) is dropped and named. The TODO lists the tags that component renders.
57
+
58
+ ## `prop:href` — a link needs the anchor
59
+
60
+ bestax gives an element the attributes of the tag `as` names, so an `href` belongs on an `<a>`
61
+ or on a custom component you pass to `as`, never on another intrinsic tag. rbx let the two disagree, and the browser ignored the result:
62
+ `<Menu.List.Item as="span" href="/x">` rendered a `<span>` that navigated nowhere.
63
+
64
+ The codemod keeps the element you asked for and drops the attribute that did nothing:
65
+
66
+ ```jsx
67
+ <Menu.List.Item as="span" href="/x">Home</Menu.List.Item>
68
+ <Menu.Item as="span">Home</Menu.Item>
69
+ ```
70
+
71
+ Most targets take no `href` at all. It lives on `Menu.Item`, `Navbar.Item`, `Navbar.Link`,
72
+ `Panel.Block`, `Dropdown.Item` and the three `Pagination` controls, which render an `<a>` unless
73
+ told otherwise,
74
+ and on `Button` and `Level.Item` once `as="a"` names one — those two render a `<button>` and a
75
+ `<div>` by default, and drop the attribute. Everywhere else the codemod removes it.
76
+
77
+ `Dropdown.Item` is the one to read twice: it accepts `as="a" | "div" | "button"` and takes the
78
+ props of whichever you name, so the default `<a>` keeps an `href` and the other two do not.
79
+ Drop the `as` to make it a link again; inside the `<button>` form an `<a>` would nest
80
+ interactive content, so navigate in `onClick` there.
81
+
82
+ ## `prop:target`, `prop:download`, `prop:hrefLang`, `prop:ping`, `prop:referrerPolicy`, `prop:media`
83
+
84
+ `target`, `download`, `hrefLang`, `ping`, `referrerPolicy` and `media` follow the element the same way
85
+ `href` does, and they are invalid on the wrong one whether or not an `href` is beside them —
86
+ `<Navbar.Link as="span" target="_blank">` does not compile on its own. Each is judged against
87
+ the element that actually renders, not as a group, so a `referrerPolicy` on an `<img>` or a
88
+ `target` on a `<form>` stays where it is legal. Where one is removed the TODO quotes it. Put it
89
+ on an `<a>` inside, or make the element one that takes it.
90
+
91
+ `rel` is never touched: React declares it on `HTMLAttributes`, so it is valid on every element.
92
+
93
+ A component can be narrower than its element. One that takes no `href` at any `as` takes none of
94
+ these either. `Level.Item` is not narrower: it declares the anchor's whole attribute surface at
95
+ every `as` and forwards it only on the `<a>`, so all of these survive at `as="a"` and none of
96
+ them reaches a `<p>` or a `<div>`.
97
+
54
98
  ## `component:Generic` — rbx's base element
55
99
 
56
100
  `Generic` is rbx's untyped passthrough. Render the underlying tag, and move its helper props to
@@ -155,10 +199,6 @@ children — where it renders its own background and close button, both wired to
155
199
  form instead, which renders only what you wrote; there, wire your own `Modal.Background`'s
156
200
  `onClick` to the same `onClose`.
157
201
 
158
- ## `prop:textColor="white-ter"` / `"white-bis"`
159
-
160
- The only two rbx colour names bestax does not carry. Use `white`, or a custom class.
161
-
162
202
  ## `value-reference` — a component used as a value
163
203
 
164
204
  `const X = Card.Header;` and similar. The codemod rewrites what it can prove safe and flags the
@@ -29,6 +29,23 @@ this automatically for literal values; dynamic values get TODOs.
29
29
  | flexbox props | same names/values (`flexDirection`, `justifyContent`, …) |
30
30
  | `clearfix`, `overlay` | same |
31
31
 
32
+ ## `renderAs` → `as`, and the props that follow it
33
+
34
+ bestax gives an element the attributes of the tag `as` names, and several components narrow
35
+ `as` to the tags Bulma's markup allows there (`Footer` is `'footer' | 'div'`, `Control` is
36
+ `'div' | 'p'`, `Level.Item` is `'div' | 'p' | 'a'`). RBC's `renderAs` took any tag, so two
37
+ shapes cannot carry across:
38
+
39
+ - a `renderAs` outside that union — `<Media renderAs="section">` — drops the `as` with a
40
+ `prop:as` TODO naming the tags the component does render;
41
+ - an `href` beside a `renderAs` that is not an `<a>` (`<Menu.List.Item renderAs="span"
42
+ href="/x">`) keeps the element and drops the `href`, with a `prop:href` TODO. RBC rendered
43
+ a `<span href="/x">` there, which navigates nowhere in any browser, so nothing working is
44
+ lost. Drop the `renderAs` where the link was the point.
45
+
46
+ `<Button href="/x">` with no `renderAs` goes the same way: bestax's `Button` renders a
47
+ `<button>`. Set `as="a"` to make it a link.
48
+
32
49
  ## Boolean modifier convention
33
50
 
34
51
  RBC uses bare booleans (`loading`, `outlined`, `rounded`, `fullwidth`); bestax prefixes
@@ -17,7 +17,7 @@ Reported from package.json, not a code TODO. bestax-bulma's peers: **React ^18 |
17
17
  **@fortawesome/fontawesome-free ^6.7 || ^7** (FA 5 apps: upgrade, or
18
18
  `npm install --legacy-peer-deps` and keep FA 5 for your own `<i>` tags).
19
19
 
20
- ## `Element` — no generic element
20
+ ## `component:Element` — no generic element
21
21
 
22
22
  bestax has no `Element`. Pick the semantic component (`Block`, `Box`, `Content`, …) that
23
23
  matches the usage, or plain JSX with classes:
@@ -29,7 +29,7 @@ matches the usage, or plain JSX with classes:
29
29
  <Span textColor="grey" m="2">…</Span> // bestax exports Span/Paragraph/Strong/etc.
30
30
  ```
31
31
 
32
- ## `Tile` — Bulma v1 replaced tiles with Grid
32
+ ## `component:Tile` — Bulma v1 replaced tiles with Grid
33
33
 
34
34
  Convert ancestor/parent/child tile trees to `Grid`/`Cell` (docs:
35
35
  https://bestax.io/docs/api/grid):
@@ -87,7 +87,7 @@ RBC modal has) selects the **compound** form, and that renders only the children
87
87
  So `closeOnBlur` and `showClose={true}` mean "add those two children"; passing either as `false`
88
88
  means "drop the prop", since the compound form gives you neither unless you ask.
89
89
 
90
- ## `touch` / `untilWidescreen` / `untilFullhd` / `{ only: true }` breakpoints
90
+ ## `responsive` — `touch` / `untilWidescreen` / `untilFullhd` / `{ only: true }` breakpoints
91
91
 
92
92
  No bestax helper-prop variants exist. Use Bulma classes directly:
93
93
  `className="is-hidden-touch"`, `is-flex-tablet-only`, etc. (all still exist in Bulma v1).
@@ -113,7 +113,7 @@ The codemod only rewrites literals. Convert the expression at its source, e.g.:
113
113
  <Block textSize={String(n) as '1' | '2' | '3' | '4' | '5' | '6' | '7'}>
114
114
  ```
115
115
 
116
- ## Button shade colors (`black-bis`, `grey-light`, …) and `isSelected`
116
+ ## `prop:color` — Button shade colors (`black-bis`, `grey-light`, …) and `isSelected`
117
117
 
118
118
  bestax `Button` colors are the semantic set + `text`/`ghost`. For shades use
119
119
  `bgColor`/`textColor` (they accept the full palette incl. shades), and replace
@@ -146,6 +146,53 @@ to `<Delete>`, a plain function component that forwards no ref — even though `
146
146
  does. The codemod detects that case and replaces the general advice with a TODO naming
147
147
  `Delete`, so the message on the line is the one to trust.
148
148
 
149
+ ## `prop:as` — a tag the component does not render
150
+
151
+ Several bestax components accept `as` but narrow it to the tags Bulma's markup allows there, so
152
+ a literal `renderAs` outside that union (`<Media renderAs="section">`, `<Footer
153
+ renderAs="section">`) becomes a `prop:as` TODO listing the tags that component does render. Wrap
154
+ the component in the element you wanted, or restructure. See the `as` section of
155
+ [prop-map.md](prop-map.md) for which components accept it at all.
156
+
157
+ ## `prop:href` — a link needs the anchor
158
+
159
+ bestax gives an element the attributes of the tag `as` names, so an `href` belongs on an `<a>`
160
+ or on a custom component you pass to `as`, never on another intrinsic tag. RBC let the two
161
+ disagree, and the browser ignored the result: `<Menu.List.Item renderAs="span" href="/x">`
162
+ rendered a `<span>` that navigated nowhere. The element stays, the dead attribute goes:
163
+
164
+ ```jsx
165
+ <Menu.List.Item renderAs="span" href="/x">Home</Menu.List.Item>
166
+ <Menu.Item as="span">Home</Menu.Item>
167
+ ```
168
+
169
+ Most targets take no `href` at all. It lives on `Menu.Item`, `Navbar.Item`, `Navbar.Link`,
170
+ `Panel.Block`, `Dropdown.Item` and the three `Pagination` controls, which render an `<a>` unless
171
+ told otherwise,
172
+ and on `Button` and `Level.Item` once `as="a"` names one — those two render a `<button>` and a
173
+ `<div>` by default, and drop the attribute. Everywhere else the codemod removes it.
174
+
175
+ `Dropdown.Item` is the one to read twice: it accepts `as="a" | "div" | "button"` and takes the
176
+ props of whichever you name, so the default `<a>` keeps an `href` and the other two do not.
177
+ Drop the `as` to make it a link again; inside the `<button>` form an `<a>` would nest
178
+ interactive content, so navigate in `onClick` there.
179
+
180
+ ## `prop:target`, `prop:download`, `prop:hrefLang`, `prop:ping`, `prop:referrerPolicy`, `prop:media`
181
+
182
+ `target`, `download`, `hrefLang`, `ping`, `referrerPolicy` and `media` follow the element the same way
183
+ `href` does, and they are invalid on the wrong one whether or not an `href` is beside them —
184
+ `<Navbar.Link as="span" target="_blank">` does not compile on its own. Each is judged against
185
+ the element that actually renders, not as a group, so a `referrerPolicy` on an `<img>` or a
186
+ `target` on a `<form>` stays where it is legal. Where one is removed the TODO quotes it. Put it
187
+ on an `<a>` inside, or make the element one that takes it.
188
+
189
+ `rel` is never touched: React declares it on `HTMLAttributes`, so it is valid on every element.
190
+
191
+ A component can be narrower than its element. One that takes no `href` at any `as` takes none of
192
+ these either. `Level.Item` is not narrower: it declares the anchor's whole attribute surface at
193
+ every `as` and forwards it only on the `<a>`, so all of these survive at `as="a"` and none of
194
+ them reaches a `<p>` or a `<div>`.
195
+
149
196
  ## Helper props dropped from plain-element replacements
150
197
 
151
198
  Where the codemod produced a plain element (`Form.Label` → `<label>`, `Breadcrumb.Item` →
@@ -13,7 +13,7 @@ This is the self-contained inventory of the color/size/variant props that matter
13
13
  members still typecheck on `Progress`/`Notification`/`Hero` but style nothing. They are
14
14
  **deprecated**: passing one logs a console warning in development, and they will be removed
15
15
  from those unions in the next major (the `has-text-*`/`has-background-*` **helpers** do cover
16
- all 17). On the `Hero` root, `inherit` and `current` are equally CSS-less and deprecated
16
+ every one of them). On the `Hero` root, `inherit` and `current` are equally CSS-less and deprecated
17
17
  (its `Head`/`Body`/`Foot` sub-components keep them, as text helpers). `Pagination` and
18
18
  `Tabs` ship no color CSS for **any** value — their entire `color`
19
19
  prop is deprecated. Before relying on an unusual value, grep the shipped CSS:
@@ -39,50 +39,50 @@ This is the self-contained inventory of the color/size/variant props that matter
39
39
  ```
40
40
  primary, link, info, success, warning, danger,
41
41
  black, black-bis, black-ter, grey-darker, grey-dark, grey, grey-light, grey-lighter,
42
- white, light, dark
42
+ white, white-bis, white-ter, light, dark
43
43
  ```
44
44
 
45
45
  Shades (`colorShade` / `backgroundColorShade`): `00, 05, 10, … 95, invert, light, dark, soft, bold, on-scheme`.
46
46
 
47
47
  ## Component `color` / `size` props (verbatim unions)
48
48
 
49
- | Component | `color` accepts | `size` accepts | Notes |
50
- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
51
- | `Button` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black \| text \| ghost` | `small \| normal \| medium \| large` | adds `text`, `ghost`; also `isLight`, `isOutlined`, `isInverted`, `isRounded` |
52
- | `Notification` | the 17 `validColors` (`black-bis`, `black-ter`, and greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | — | also `isLight` |
53
- | `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isLight`, `isRounded`, `isDelete`, `isHoverable` |
54
- | `Box` | `primary \| link \| info \| success \| warning \| danger` | — | `color` renders `has-text-<color>`, same as `textColor` (which wins when both are set; no `.box.is-*` ships — tint via `bgColor`); also `hasShadow` |
55
- | `Message` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only |
56
- | `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
57
- | `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `16x16 \| 24x24 \| 32x32 \| 48x48 \| 64x64 \| 96x96 \| 128x128 \| number` | initials/icon background (auto-derived from `name` when unset); also `shape` |
58
- | `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
59
- | `Title` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | also `isSpaced` |
60
- | `SubTitle` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | — |
61
- | `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
62
- | `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
63
- | `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
64
- | `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
65
- | `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isBoxed`, `isFullwidth` |
66
- | `Hero` | the 17 `validColors` + `inherit`/`current` (`black-bis`, `black-ter`, greys, `inherit`, `current` deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large \| fullheight \| fullheight-with-navbar` | section background |
67
- | `LinkButton` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black` | — | button-styled link; emits `link-button-<color>` — **no `isLight`/`isOutlined`/`isInverted`** |
68
- | `Loading` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | spinner color; default light grey |
69
- | `Navbar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
70
- | `Numberinput` | `primary \| link \| info \| success \| warning \| danger \| light \| dark` | `small \| medium \| large` | also `inputColor` (the 6) for the inner input |
71
- | `Pagination` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
72
- | `Panel` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
73
- | `Progress` | the 17 `validColors` (`black-bis`, `black-ter`, and greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large` | — |
74
- | `Radio` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
75
- | `Rate` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
76
- | `Select` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded` |
77
- | `Slider` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded`, `isCircle` |
78
- | `Steps` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
79
- | `Switch` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | also `isRounded`, `isThin`, `isOutlined` |
80
- | `Tabs` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
81
- | `Taginput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `tagColor` (the 6 + `dark \| light`) for the tags |
82
- | `TextArea` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
83
- | `TimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | — |
84
- | `Tooltip` | `primary \| link \| info \| success \| warning \| danger \| dark \| light` | `small \| medium \| large` | — |
85
- | `Tr` / `Td` / `Th` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | cell background; cells take `textAlign`/`textWeight`/`textSize` directly |
49
+ | Component | `color` accepts | `size` accepts | Notes |
50
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
51
+ | `Button` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black \| text \| ghost` | `small \| normal \| medium \| large` | adds `text`, `ghost`; also `isLight`, `isOutlined`, `isInverted`, `isRounded` |
52
+ | `Notification` | every `validColors` member (the `-bis`/`-ter` shades and the greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | — | also `isLight` |
53
+ | `Tag` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `normal \| medium \| large` | also `isLight`, `isRounded`, `isDelete`, `isHoverable` |
54
+ | `Box` | `primary \| link \| info \| success \| warning \| danger` | — | `color` renders `has-text-<color>`, same as `textColor` (which wins when both are set; no `.box.is-*` ships — tint via `bgColor`); also `hasShadow` |
55
+ | `Message` | `primary \| link \| info \| success \| warning \| danger` | — | the 6 only |
56
+ | `Input` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
57
+ | `Avatar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `16x16 \| 24x24 \| 32x32 \| 48x48 \| 64x64 \| 96x96 \| 128x128 \| number` | initials/icon background (auto-derived from `name` when unset); also `shape` |
58
+ | `Badge` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | pill background; default `danger` |
59
+ | `Title` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | also `isSpaced` |
60
+ | `SubTitle` | — (no `color`; use `textColor`) | `1`–`6` (string or number) | — |
61
+ | `Autocomplete` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
62
+ | `Checkbox` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
63
+ | `DateInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
64
+ | `DateTimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded` |
65
+ | `File` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isBoxed`, `isFullwidth` |
66
+ | `Hero` | every `validColors` member + `inherit`/`current` (the `-bis`/`-ter` shades, the greys, `inherit` and `current` deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large \| fullheight \| fullheight-with-navbar` | section background |
67
+ | `LinkButton` | `primary \| link \| info \| success \| warning \| danger \| white \| light \| dark \| black` | — | button-styled link; emits `link-button-<color>` — **no `isLight`/`isOutlined`/`isInverted`** |
68
+ | `Loading` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | spinner color; default light grey |
69
+ | `Navbar` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
70
+ | `Numberinput` | `primary \| link \| info \| success \| warning \| danger \| light \| dark` | `small \| medium \| large` | also `inputColor` (the 6) for the inner input |
71
+ | `Pagination` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
72
+ | `Panel` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | — |
73
+ | `Progress` | every `validColors` member (the `-bis`/`-ter` shades and the greys deprecated: no CSS, dev-warn, removed next major — see ⚠️) | `small \| medium \| large` | — |
74
+ | `Radio` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | the 6 only |
75
+ | `Rate` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
76
+ | `Select` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded` |
77
+ | `Slider` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `isRounded`, `isCircle` |
78
+ | `Steps` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | the 6 only |
79
+ | `Switch` | `primary \| link \| info \| success \| warning \| danger` | `small \| normal \| medium \| large` | also `isRounded`, `isThin`, `isOutlined` |
80
+ | `Tabs` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | **entire `color` prop deprecated** (no CSS ships; dev-warn; removal next major) |
81
+ | `Taginput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | also `tagColor` (the 6 + `dark \| light`) for the tags |
82
+ | `TextArea` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | `small \| medium \| large` | also `isRounded`, `isStatic` |
83
+ | `TimeInput` | `primary \| link \| info \| success \| warning \| danger` | `small \| medium \| large` | — |
84
+ | `Tooltip` | `primary \| link \| info \| success \| warning \| danger \| dark \| light` | `small \| medium \| large` | — |
85
+ | `Tr` / `Td` / `Th` | `primary \| link \| info \| success \| warning \| danger \| black \| dark \| light \| white` | — | cell background; cells take `textAlign`/`textWeight`/`textSize` directly |
86
86
 
87
87
  The 6 brand colors (`primary, link, info, success, warning, danger`) are the ones a custom theme
88
88
  recolors via the HSL trios (see `css-variables.md`). The greyscale and `white`/`light`/`dark`