Skip to content

fix(bulma-ui): warn when a wrapper inside a Control drops its Control-level props - #928

Merged
allxsmith merged 5 commits into
mainfrom
fix/921-control-props-warning
Oct 7, 2026
Merged

allxsmith merged 5 commits into
mainfrom
fix/921-control-props-warning

Conversation

@allxsmith

@allxsmith allxsmith commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Inside a Control you wrap around it, a convenience form wrapper renders no Control of its own. The props it would have handed that Control, such as isLoading, the icon props, isExpanded, controlSize and controlClassName, then did nothing, and nothing said so. <Field><Control><Input isLoading /></Control></Field> showed no spinner and logged nothing.

Each wrapper that skips its Control inside one now decides that with rendersOwnControl, which sits beside #920's rendersOwnField in FormContext.tsx. In development it warns once per set of props, naming the ones that were dropped and saying to set them on the enclosing Control, with the Control's own name where it differs (size for controlSize, className for controlClassName). Only truthy props the caller passed count. The date and time pickers read iconLeftName before their default glyph fills it in, so that default never warns. A picker's own isLoading inside a loading Control still draws nothing, so it warns too. Rendered output is unchanged everywhere, and production stays silent.

bare-control.test.tsx records every Control the wrappers render and traces each Control-level prop to the Control prop it reaches, so a wrapper that hands its Control a new prop fails the suite until that prop joins ControlLevelProps and the wrapper passes it to the helper. The table covers every wrapper that skips its Control inside one.

Some cases stay quiet on purpose. Select's isLoading is drawn on the select itself and still works inside a Control. Slider, Rate, Checkboxes and Radios hand their Control no props at all. An inline picker renders no Control inside a Control or outside one, so its Control-level props do nothing in either place; it warns about them in both, with its own message saying to leave them out rather than pointing at the enclosing Control. File and Taginput never render a Control.

TSDoc, the API pages for the affected wrappers, the form guide and the bestax-form skill now mention the warning.

pnpm all passes locally.

Fixes #921

Summary by CodeRabbit

  • Bug Fixes

    • Form inputs now consistently handle Control-level props when nested inside an existing Control or used in inline date/time picker mode. Unsupported props have no effect and trigger a development warning, directing you to configure the enclosing Control instead.
    • Select’s isLoading behavior remains available when nested inside a Control.
  • Documentation

    • Clarified Control-prop behavior and warnings across form component guides and API references.

…-level props

Inside a caller's Control, the convenience form wrappers render no Control of their own, so the
props they would have handed it, such as isLoading, the icon props and controlSize, did nothing
without a word. rendersOwnControl now makes that decision beside rendersOwnField and, in
development, warns once per set of props, naming them and saying to set them on the enclosing
Control. Only truthy props the caller passed count, so the pickers' default left icon never
warns, and an inline picker, which renders no Control anywhere, stays quiet. Rendered output is
unchanged, and production stays silent.

The pickers take their props whole so the check reads the caller's iconLeftName before the
default fills it in. A recording Control in bare-control.test.tsx traces each Control-level prop
to the Control prop it reaches, so a wrapper that hands its Control something new fails there
until the prop joins ControlLevelProps and the wrapper passes it to the helper.

Fixes #921
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

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

Next included review available in 9 minutes.

Check out review usage here.

View limit details

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

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: allxsmith/bestax/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 98c0517f-0858-4e96-9109-c921943dffac
📥 Commits

Reviewing files that changed from the base of the PR and between f0494bd and f2afc2f.

📒 Files selected for processing (26)
  • bestax-mcp/data/components/DateInput.json
  • bestax-mcp/data/components/DateTimeInput.json
  • bestax-mcp/data/components/TimeInput.json
  • bestax-mcp/data/skills.json
  • bulma-ui/src/form/CLAUDE.md
  • bulma-ui/src/form/Checkboxes.tsx
  • bulma-ui/src/form/DateInput.tsx
  • bulma-ui/src/form/DateTimeInput.tsx
  • bulma-ui/src/form/FormContext.tsx
  • bulma-ui/src/form/Input.tsx
  • bulma-ui/src/form/Radios.tsx
  • bulma-ui/src/form/Rate.tsx
  • bulma-ui/src/form/Select.tsx
  • bulma-ui/src/form/Slider.tsx
  • bulma-ui/src/form/TextArea.tsx
  • bulma-ui/src/form/TimeInput.tsx
  • bulma-ui/src/form/__tests__/bare-control.test.tsx
  • docs/docs/api/form/datetime/dateinput.md
  • docs/docs/api/form/datetime/datetimeinput.md
  • docs/docs/api/form/datetime/timeinput.md
  • docs/docs/api/form/input.md
  • docs/docs/api/form/select.md
  • docs/docs/api/form/textarea.md
  • docs/docs/guides/library/form.md
  • skills/bestax-form/SKILL.md
  • skills/bestax-form/references/api.md

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: allxsmith/bestax/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 43d65411-d79f-4814-ac3e-13ea602e86da
📥 Commits

Reviewing files that changed from the base of the PR and between 92efac0 and f0494bd.

📒 Files selected for processing (26)
  • bestax-mcp/data/components/DateInput.json
  • bestax-mcp/data/components/DateTimeInput.json
  • bestax-mcp/data/components/TimeInput.json
  • bestax-mcp/data/skills.json
  • bulma-ui/src/form/CLAUDE.md
  • bulma-ui/src/form/Checkboxes.tsx
  • bulma-ui/src/form/DateInput.tsx
  • bulma-ui/src/form/DateTimeInput.tsx
  • bulma-ui/src/form/FormContext.tsx
  • bulma-ui/src/form/Input.tsx
  • bulma-ui/src/form/Radios.tsx
  • bulma-ui/src/form/Rate.tsx
  • bulma-ui/src/form/Select.tsx
  • bulma-ui/src/form/Slider.tsx
  • bulma-ui/src/form/TextArea.tsx
  • bulma-ui/src/form/TimeInput.tsx
  • bulma-ui/src/form/__tests__/bare-control.test.tsx
  • docs/docs/api/form/datetime/dateinput.md
  • docs/docs/api/form/datetime/datetimeinput.md
  • docs/docs/api/form/datetime/timeinput.md
  • docs/docs/api/form/input.md
  • docs/docs/api/form/select.md
  • docs/docs/api/form/textarea.md
  • docs/docs/guides/library/form.md
  • skills/bestax-form/SKILL.md
  • skills/bestax-form/references/api.md

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

Form wrappers now use a shared helper to determine whether they render a Control. In development, the helper warns when supplied Control-level props have no effect. Tests and documentation cover the updated behavior.

Changes

Form Control prop handling

Layer / File(s) Summary
Shared Control ownership check
bulma-ui/src/form/FormContext.tsx, bulma-ui/src/form/CLAUDE.md
Adds ControlLevelProps and rendersOwnControl. The helper determines Control ownership and warns when supplied Control-level props are ineffective.
Wrapper adoption
bulma-ui/src/form/*.tsx
Form wrappers use rendersOwnControl for Control rendering. Picker inputs pass inline mode and caller-supplied icon values into the decision; Select excludes isLoading.
Tests and usage guidance
bulma-ui/src/form/__tests__/bare-control.test.tsx, docs/docs/api/form/..., docs/docs/guides/library/form.md, skills/bestax-form/..., bestax-mcp/data/...
Tests cover prop forwarding, warnings, inline pickers, Select loading, and production behavior. Documentation and component reference data describe the updated prop behavior.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to f0494

No actionable issue remains in the supplied review evidence; the PR is mergeable after normal checks.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: warnings when wrappers drop Control-level props inside a Control.
Description check ✅ Passed The description explains the problem, behavior, exceptions, tests, documentation updates, and linked issue. It does not complete the template’s package, type-of-change, or checklist selections, but th…
Linked Issues check ✅ Passed Issue #921 requires development warnings for effective Control-level props that wrappers drop inside a caller’s Control. rendersOwnControl names truthy props, maps controlSize to size and `contr…
Out of Scope Changes check ✅ Passed The wrapper changes, tests, TSDoc, API pages, form guide, and bestax-form skill document or verify the behavior requested by issue #921. Inline picker warnings remain directly related: their Control-l…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

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

Comment thread bulma-ui/src/form/DateInput.tsx Outdated

@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 · 1 advisory

# Severity Area Finding Location
1 🔵 Advisory Robustness An inline picker inside a Control still drops its Control-level props silently, and the added "warns in development" clause in the pickers' isLoading TSDoc does not hold there bulma-ui/src/form/DateInput.tsx:150

Overall: The change is sound and verified end-to-end. rendersOwnControl is a faithful sibling of #920's rendersOwnField: every one of the ten wrappers that skips its own Control now routes the decision through it, and the two rewritten conditions (!insideControl → ownControl, and !insideControl && !inline → !inline && rendersOwnControl(…)) are logically identical to what they replaced, so "rendered output is unchanged" holds by construction as well as by test. The riskiest part is the hand-maintained ON_CONTROL map, and that is exactly where the test design is strongest — Required<ControlLevelProps> forces a value for every new member, Record<keyof ControlLevelProps, string> forces a mapping, and warns inside a Control for exactly the props that reach its own derives the expected mapping from the real Control prop names rather than restating it, so a drifted entry fails rather than lying. A human should focus on whether scoping inline out of the warning is the call they want; everything else is mechanical.

What I verified empirically
Check Result
jest src/form/__tests__/bare-control.test.tsx 195 passed
jest src/form 40 suites, 2368 passed
jest src/ grepped for renders no <Control> of its own 0 — the new warning fires nowhere in the existing suite, so no current usage trips it
pnpm --filter @allxsmith/bestax-bulma run test:coverage 159 suites, 6368 passed, exit 0, so the 99% gate holds
typecheck:tests clean — everyControlProp satisfies Required<ControlLevelProps> compiles
check-conformance.mjs all 20 checks pass
re-ran gen-api-docs, gen-mcp-index, gen-component-catalog, gen-eslint-meta git status clean — no stale generated artefact
Build and Test, React 18 + React 19 matrix on 5f5cbe0e success

Claim by claim against the diff: Select's isLoading is excluded from the check and still reaches SelectBase → .select.is-loading (SelectBase.tsx:96); Input's isLoading is destructured away and never reaches InputBase, so it is genuinely inert inside a Control; the pickers read props.iconLeftName before = 'calendar'/'clock'/'calendar-alt' applies, and iconLeftName="" — the documented way to hide it, DateInputBase.tsx:229 — is falsy so it correctly stays quiet; every ON_CONTROL target really exists on Control (iconLeftName/iconRightName at Control.tsx:62,66, plus size and className); Slider, Rate, Checkboxes and Radios hand their Control nothing but children. The ten wrappers that render a <Control> are exactly the ten that now call the helper — File and Taginput read insideControl but render none, and Autocomplete/Numberinput neither read it nor declare a Control-level prop.

Residual risk:

  • inline pickers — posted as finding 1. The only executable path in the diff where a Control-level prop is still dropped without a word.
  • A new Control-level prop added to a wrapper — refuted. Two independent gates: hands its Control only props that come from a Control-level prop fails on any value handed to a Control that is not one of the traced sentinels (an unlisted prop arrives as undefined, which is not in tracedProp), and warns inside a Control for exactly the props that reach its own fails when a prop reaches the Control but is not named in the warning. I traced both by hand against DateInput's derived hasIconsLeft={hasIconsLeft || !!iconLeftName}, the one non-pass-through value, and it still resolves to a traced sentinel.
  • Our own docs and stories tripping the new warning — refuted. Grepped every .stories.tsx, API page and guide for a convenience wrapper carrying a Control-level prop inside a <Control>; the only two hits are docs/docs/api/form/field.md:384 (<Control isLoading><Select isLoading>, deliberately exempt and still working) and docs/docs/api/form/datetime/timeinput.md:761 (controlSize on a standalone TimeInput, no Control in sight). The whole-suite grep above corroborates it.
  • A falsy prop warning spuriously — refuted. The filter is a plain truthiness test and Control itself keys every class off truthiness (Control.tsx:187-191), so the two agree; ignores falsy Control-level props, which a Control ignores too covers false, null and ''.
  • Production noise, or one mistake warning twice — refuted. warnOnce fails closed through isDev() (devWarnings.ts:17-23) and adds to warnedKeys only after that gate, so production neither logs nor accumulates keys; is silent in production, and renders the same asserts byte-identical markup. The Field-level and Control-level keys are namespaced apart (:Field-in-bare-Control: vs :Control-props-in-Control:), so one mistake of each kind yields one warning each.
  • Nothing in the diff is behind a flag, a network call, or a browser-only CSS rule, so there is no path I could only read rather than run. One inherited property, unchanged here: the warnOnce registry is module-global, so an SSR process logs each key once for its whole lifetime rather than once per request.

🏄 Clean little set, dude. #920 paddled out and this one just rides the same wave one reef over — zero markup change, the warning only speaks up when you have actually dropped something, and the test harness basically dares a future prop to sneak past it. Only ripple is the inline pickers quietly eating their props, and that reads more like a known sandbar than a wipeout. Good to go. 🤙

An inline date or time picker renders no Control inside a Control or outside one, so its
Control-level props do nothing in either place. The pickers skipped rendersOwnControl in inline
mode, so <Control><DateInput inline isLoading /></Control>, the shape #921 is about, stayed
silent while the isLoading TSDoc said it warns.

The pickers now pass inline to the helper, which warns in development once per set of props in
both places with its own message: the props do nothing in inline mode, so leave them out. It
does not point at the enclosing Control, whose icons would sit over the calendar. The default
left icon still never warns, and rendered output is unchanged.
@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: verify

Every open thread has a reply: fixed, with the commit, or refuted with a reason. This settles them on f0494bd.

@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://2c48d1b6.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 (verify) — 1 resolved · 0 open

# Severity Area Thread Outcome
1 🔵 Advisory Robustness An inline picker inside a Control still drops its Control-level props silently ✅ Verified fixed — resolved

Overall: This pass settled threads and reviewed no commits. The one open thread — the inline carve-out that skipped the new diagnostic, plus the isLoading TSDoc that over-claimed because of it — is genuinely fixed in f0494bdc, and fixed at the right level: rendersOwnControl now owns the inline case (FormContext.tsx:174) instead of each picker short-circuiting past it, so the helper stays the single place the Control decision and its warning live. The broadened scope (an inline picker now warns outside a Control too) is a strict superset of what the thread asked for, rendered output is unchanged on both inline paths, and the class TSDoc, the three API pages and skills/bestax-form were updated in the same commit. Nothing is left for a human to arbitrate here.

What this pass checked
  • FormContext.tsx:174 — if (!options.inline && !options.insideControl) return true; is the only early return, so an inline picker falls through to the held filter from either position. The two warnOnce keys differ (Control-props-inline vs Control-props-in-Control), so neither dedupes the other away.
  • DateInput.tsx:151-153, TimeInput.tsx:143-145, DateTimeInput.tsx:145-147 — all three pass inline: baseProps.inline, and all three still read iconLeftName: props.iconLeftName pre-default, so the component's own default glyph never counts as a prop the caller set.
  • ownControl resolves to false on both inline paths, exactly as the old !baseProps.inline && chain did, so the fix adds a warning without touching markup — pinned by the new test's withoutIds(container.innerHTML) equality assertion.
  • DateInput.tsx:64-71 — the isLoading TSDoc's "draws nothing and warns in development" is now true in inline mode too, which was the second half of the finding.
  • pnpm --filter @allxsmith/bestax-bulma exec jest src/form → 40 suites, 2371 tests, all passing.

Residual risk: none identified for the settled finding. rendersOwnControl's inline option is optional, so the non-picker wrappers that omit it keep their prior behaviour unchanged, and bare-control.test.tsx still holds ON_CONTROL to what each wrapper hands its own Control, so a new Control-level prop fails there until it is wired through both paths. A verify pass raises no new findings by design — a fresh review is what reviews the commits since.

🏄 Called the break, and the author paddled out and caught a bigger wave than the one I pointed at — inline pickers now speak up whether they're tucked into a Control or riding solo. Thread closed out clean, zero open, totally good to go.

@github-actions github-actions Bot added the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 7, 2026
@allxsmith allxsmith added the needs-human-review Loop converged (or contested): awaiting owner review + manual merge label Oct 7, 2026
@github-actions github-actions Bot removed the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

📸 Story screenshots at handoff — f0494bd

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

form-checkboxes--default · Form/Checkboxes · Default
Light Dark
form-checkboxes--default light form-checkboxes--default dark
form-checkboxes--with-colors · Form/Checkboxes · With Colors
Light Dark
form-checkboxes--with-colors light form-checkboxes--with-colors dark
form-checkboxes--disabled-group · Form/Checkboxes · Disabled Group
Light Dark
form-checkboxes--disabled-group light form-checkboxes--disabled-group dark
form-checkboxes--with-label · Form/Checkboxes · With Label
Light Dark
form-checkboxes--with-label light form-checkboxes--with-label dark
form-checkboxes--with-field-wrapper · Form/Checkboxes · With Field Wrapper
Light Dark
form-checkboxes--with-field-wrapper light form-checkboxes--with-field-wrapper dark
form-checkboxes--with-field-control-wrapper · Form/Checkboxes · With Field Control Wrapper
Light Dark
form-checkboxes--with-field-control-wrapper light form-checkboxes--with-field-control-wrapper dark
form-dateinput--default · Form/DateInput · Default
Light Dark
form-dateinput--default light form-dateinput--default dark
form-dateinput--controlled · Form/DateInput · Controlled
Light Dark
form-dateinput--controlled light form-dateinput--controlled dark
form-dateinput--sizes · Form/DateInput · Sizes
Light Dark
form-dateinput--sizes light form-dateinput--sizes dark
form-dateinput--colors · Form/DateInput · Colors
Light Dark
form-dateinput--colors light form-dateinput--colors dark
form-dateinput--inline-colors · Form/DateInput · Inline Colors
Light Dark
form-dateinput--inline-colors light form-dateinput--inline-colors dark
form-dateinput--states · Form/DateInput · States
Light Dark
form-dateinput--states light form-dateinput--states dark
form-datetimeinput--default · Form/DateTimeInput · Default
Light Dark
form-datetimeinput--default light form-datetimeinput--default dark
form-datetimeinput--controlled · Form/DateTimeInput · Controlled
Light Dark
form-datetimeinput--controlled light form-datetimeinput--controlled dark
form-datetimeinput--format-12-h · Form/DateTimeInput · Format 12 H
Light Dark
form-datetimeinput--format-12-h light form-datetimeinput--format-12-h dark
form-datetimeinput--with-seconds · Form/DateTimeInput · With Seconds
Light Dark
form-datetimeinput--with-seconds light form-datetimeinput--with-seconds dark
form-datetimeinput--format-12-h-with-seconds · Form/DateTimeInput · 12-hour with seconds
Light Dark
form-datetimeinput--format-12-h-with-seconds light form-datetimeinput--format-12-h-with-seconds dark
form-datetimeinput--formats · Form/DateTimeInput · Formats (compare)
Light Dark
form-datetimeinput--formats light form-datetimeinput--formats dark
form-input--default · Form/Input · Default
Light Dark
form-input--default light form-input--default dark
form-input--colors · Form/Input · Colors
Light Dark
form-input--colors light form-input--colors dark
form-input--sizes · Form/Input · Sizes
Light Dark
form-input--sizes light form-input--sizes dark
form-input--rounded · Form/Input · Rounded
Light Dark
form-input--rounded light form-input--rounded dark
form-input--states · Form/Input · States
Light Dark
form-input--states light form-input--states dark
form-input--loading-sizes · Form/Input · Loading Sizes
Light Dark
form-input--loading-sizes light form-input--loading-sizes dark
> ✂ 213 more matched stories skipped by the cap: `form-checkboxes--with-name`, `form-checkboxes--with-name-through-wrappers`, `form-checkboxes--controlled-group`, `form-checkboxes--uncontrolled-group`, `form-checkboxes--compound-usage`, `form-dateinput--inline`, `form-dateinput--min-max`, `form-dateinput--disabled-dates`, `form-dateinput--first-day-of-week`, `form-dateinput--locale`, … — full set in the artifact.

github-actions Bot added a commit that referenced this pull request Oct 7, 2026
@github-actions github-actions Bot added the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 7, 2026
@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: fresh

Main is merged in after #926 and #927 landed, with only the generated skills index conflicting, so this reviews the merged head. It reviews f2afc2f.

@github-actions github-actions Bot removed the review-converged Deep review converged: no blocking findings, all review threads resolved, checks green label Oct 7, 2026
@allxsmith
allxsmith merged commit 9edcc29 into main Oct 7, 2026
19 checks passed
@allxsmith
allxsmith deleted the fix/921-control-props-warning branch October 7, 2026 07:34
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://28c8ee95.bestax.pages.dev

Comment thread bulma-ui/src/form/DateInput.tsx

@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 · 1 advisory

# Severity Area Finding Location
1 🔵 Advisory Robustness A picker's iconLeftSize/hasIconsLeft warning says "set it on that Control", but the deliberately-excluded default iconLeftName means doing so renders nothing bulma-ui/src/form/DateInput.tsx:156

Overall: The change is sound. rendersOwnControl reduces to exactly the old predicate (!inline && !insideControl) on every path, so rendered output is provably unchanged, and bare-control.test.tsx is a real guard rather than a restatement — I traced both failure directions by hand (a wrapper that hands its Control a new prop lands an untraced undefined in handedToControl, and a mismatch between the props passed to the helper and the props that reach the Control breaks named/toSet), and both fail the suite. 198 tests in that file and 2388 across src/form pass locally, FormContext.tsx is at 100% on all four metrics, both tsc programs are clean, and "Build and Test" is green on f2afc2f4. The riskiest part is that ON_CONTROL, the per-wrapper argument lists, and Select's deliberate isLoading omission are three hand-maintained lists that must agree; the test holds all three together, so the human's attention is better spent on whether the inline picker's "leave it out" message is the guidance you want for controlSize/isExpanded/controlClassName inside a Control, where the icon-collision reason behind it does not apply.

Residual risk:

  • A wrapper missed entirely. Refuted: useInsideControl has exactly ten callers that skip a Control (Input, Select, TextArea, the three pickers, Slider, Rate, Checkboxes, Radios) and all ten now route through rendersOwnControl. File and Taginput read it only for rendersOwnField and render no Control (File's iconLeft/iconRight sit inside its own .file-label); Autocomplete has loading, not isLoading, and Numberinput renders its own .control with is-loading unconditionally (Numberinput.tsx:286-288), so neither drops anything.
  • A prop accepted but never handed to any Control (dropped everywhere, so never warned). Refuted: the suite asserts all 12 ControlLevelProps reach Input's and each picker's own Control; Select hands 7 and routes isLoading to SelectBase; TextArea hands its 3; Slider/Rate/Checkboxes/Radios declare none.
  • A false positive — warning for a prop that still works. Refuted: Input.isLoading is destructured away from InputBase (whose .input.is-loading draws nothing by Bulma's rules, per its own TSDoc), and the pickers' triggerIcon reads useControlLoading() rather than their isLoading prop, so renders the same inside a Control with or without those props passing for every wrapper is the real evidence.
  • A future default silently warning. Refuted: renders no Field in a bare Control and never warns for $name's own default icon both assert zero warnings for a props-free render inside a Control, so any new wrapper-supplied default fails the suite.
  • New console noise in our own examples. Refuted: swept every story and docs/docs live block — all Control-level props sit on the Control itself, no inline picker is given one, and the <Control isLoading><Select isLoading> example in field.md:382 is the case the implementation deliberately excludes.
  • Open: the inline picker's message does not point at the enclosing Control for controlSize, controlClassName, isExpanded or isLoading, which have no icon collision with the panel. Left open rather than raised — it is the reason the earlier inline thread was resolved on, and narrowing it would re-litigate that.
  • Open (prior design, out of scope): a Field-level prop inside an outer Field is still dropped in silence (rendersOwnField returns early on insideField with no warning, and bare-control.test.tsx:289-302 asserts that), and the pickers' prop-level isLoading TSDoc is the only one updated — Input/Select/TextArea carry the disclosure in the interface-level block comment, which reaches neither the generated prop tables nor the MCP index.

🏄 Clean little swell, this one — no new waves, just a lifeguard finally blowing the whistle when your isLoading wipes out inside someone else's Control. The test harness is the real board here: it'll catch the next wrapper that tries to paddle out with an undeclared prop. Good to go.

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.26.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

@allxsmith

Copy link
Copy Markdown
Owner Author

deep-review: verify

Every open thread has a reply: fixed, with the commit, or refuted with a reason. This settles them on 2b09e88.

@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 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.25.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.14.1 🎉

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

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.

Form wrappers drop their Control-level props inside a Control without a warning

1 participant