Skip to content

fix(bulma-ui): associate the form label prop with its control via a generated id - #492

Merged
allxsmith merged 3 commits into
mainfrom
fix/368-label-htmlfor
Aug 7, 2026
Merged

allxsmith merged 3 commits into
mainfrom
fix/368-label-htmlfor

Conversation

@allxsmith

@allxsmith allxsmith commented Aug 7, 2026 •

Copy link
Copy Markdown
Owner

Closes #368.

What

The convenience label prop on the form inputs rendered a sibling <label class="label"> through Field with no htmlFor/id association: clicking the label didn't focus the control, assistive tech announced the control with no name, and getByLabelText failed. This wires it automatically for the single-control components: Input, Select, TextArea, File, Numberinput, Slider, DateInput, TimeInput, DateTimeInput.

How

One internal hook, bulma-ui/src/form/useAutoLabelId.ts (not exported, not public API), called by each convenience component. Field itself is unchanged; the hook merges htmlFor into the labelProps the component already forwards.

Rules:

  • No label → nothing changes (no id injected, zero DOM churn).
  • label set → the control gets a useId-generated id and the label gets a matching for.
  • A user-supplied id is used as the target instead of a generated one.
  • An explicit labelProps.htmlFor always wins, and suppresses id generation.
  • No wiring in modes that render no labellable control: inside an outer Field (label is dropped, as before), Numberinput plusminus bare, and the date family's inline mode.

Edge decisions:

  • File: the file input now has two labels (the Field label plus the wrapping file-label CTA); accessible name is the concatenation and clicking the Field label opens the picker. axe's best-practice rule form-field-multiple-labels may flag this as moderate; noted in the docs.
  • Slider range mode: the label targets the low thumb; each thumb keeps its own aria-label.
  • DateInput family: a user id still derives the popover id (aria-controls="<id>-popover").

Consumer-visible change

<Input label> (and the other eight) now emits id/for attributes where it previously emitted none. Consumer snapshot tests will churn (the generated value is render-order dependent and differs between React 18 :r0: and React 19 «r1»).

Out of scope (follow-up issues)

  • Autocomplete/Taginput: id currently lands on a wrapper div, needs threading to the inner input.
  • Rate/Checkboxes/Radios: group labels need role + aria-labelledby, not htmlFor.
  • <Field label> composed usage stays manual (labelProps={{ htmlFor }} + matching id), as documented.

Docs / skill

TSDoc updated on all nine (drives the generated props tables; FormFieldProps deliberately left neutral since group inputs also inherit it), hand-written Accessibility sections rewritten (input/select/textarea/field/file), skills/bestax-form caveat + checklist + signup example updated with the convenience/composed distinction kept precise, the skill-examples Storybook showcase drops the workaround, and the forms blog post note is reworded.

Testing

~30 new association tests across the nine components (association, user id, htmlFor override, no-label/no-id, inside-Field, horizontal, bare, range, inline, popover-id derivation), all React 18/19-safe (no id text asserted). pnpm all green; touched files at 100% coverage.

Summary by CodeRabbit

  • New Features

    • Form controls now automatically associate labels with inputs, selects, text areas, sliders, and date/time controls.
    • Added label support for file and number inputs.
    • Custom IDs and labelProps.htmlFor overrides remain supported.
    • Inline and composite field layouts preserve their existing association behavior.
  • Documentation

    • Updated accessibility guidance and form component references.
  • Tests

    • Added coverage for generated IDs, overrides, unlabeled controls, inline modes, and range sliders.

…enerated id

The convenience label prop rendered a sibling <label> through Field with no
htmlFor/id wiring, so clicking the label did nothing and assistive tech got
no name. Input, Select, TextArea, File, Numberinput, Slider, DateInput,
TimeInput, and DateTimeInput now generate an id with useId and wire htmlFor
when label is set: a user-supplied id is used as the target instead, an
explicit labelProps.htmlFor wins outright, and no id is injected without a
label (or in modes that render no labellable control: inside an outer Field,
plusminus bare, date-family inline).

Group and composite inputs (Checkboxes, Radios, Autocomplete, Rate, Taginput)
and Field-composed usage still need manual wiring; follow-up issues cover
those. Docs accessibility sections, the bestax-form skill, its Storybook
showcase, and the forms blog note are updated to match.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@allxsmith, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 11 minutes

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

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 07c6229a-cf70-4cd0-9df1-cdc6a9a93d53

📥 Commits

Reviewing files that changed from the base of the PR and between dc4a206 and 00385b8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (1)
  • pnpm-workspace.yaml

Walkthrough

Convenience form controls now use useAutoLabelId to generate or reuse control IDs and associate rendered labels. Tests cover the behavior. API documentation, skills, and examples describe automatic and manual association rules.

Changes

Automatic label association

Layer / File(s) Summary
Shared label-ID resolution and control integration
bulma-ui/src/form/useAutoLabelId.ts, bulma-ui/src/form/{DateInput,DateTimeInput,File,Input,Numberinput,Select,Slider,TextArea,TimeInput}.tsx, bulma-ui/src/form/Field.tsx, bulma-ui/src/form/fieldProps.ts
Controls generate or reuse IDs when they render labels. labelProps.htmlFor overrides automatic wiring. Nested fields and inline modes suppress association where specified.
Label association test coverage
bulma-ui/src/form/__tests__/*
Tests cover generated IDs, explicit IDs, overrides, omitted IDs, nested fields, inline modes, file labels, number inputs, and slider range targeting.
API guidance and examples
docs/docs/api/form/*, docs/blog/2026-08-04-forms-without-a-form-library.md, skills/bestax-form/*, bulma-ui/src/skill-examples/Form.stories.tsx
Documentation and examples describe automatic association for convenience controls and manual id/htmlFor wiring for composed fields and composite controls.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FormControl
  participant useAutoLabelId
  participant Field
  participant ControlBase
  FormControl->>useAutoLabelId: provide label, id, labelProps, and context
  useAutoLabelId-->>FormControl: return controlId and fieldLabelProps
  FormControl->>Field: pass resolved fieldLabelProps
  FormControl->>ControlBase: pass resolved controlId
Loading

Possibly related issues

  • allxsmith/bestax issue 368: The PR implements automatic id and htmlFor association for convenience form labels.
  • allxsmith/bestax issue 493: It also concerns using useAutoLabelId to associate labels with additional form controls.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: automatic association of form labels with controls using generated IDs.
Description check ✅ Passed The description explains the problem, implementation, affected components, edge cases, documentation, testing, and linked issue.
Linked Issues check ✅ Passed The changes satisfy issue #368 by automatically associating convenience labels with controls while preserving documented override and exclusion rules.
Out of Scope Changes check ✅ Passed The tests, documentation, skill updates, and Storybook changes directly support the label-association fix and its consumer-facing behavior.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/368-label-htmlfor

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Closes #368 by automatically associating convenience form labels with their controls.

Changes:

  • Adds an internal useId-based label association hook across nine controls.
  • Adds coverage for generated IDs, overrides, nested fields, and special modes.
  • Updates documentation, skill guidance, and examples.

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
skills/bestax-form/SKILL.md Updates form-label guidance and example.
skills/bestax-form/references/api.md Clarifies composed-field labeling.
docs/docs/api/form/textarea.md Documents TextArea association.
docs/docs/api/form/slider.md Documents Slider association.
docs/docs/api/form/select.md Documents Select association.
docs/docs/api/form/numberinput.md Documents Numberinput association.
docs/docs/api/form/input.md Documents Input association.
docs/docs/api/form/file.md Documents File’s dual labels.
docs/docs/api/form/field.md Clarifies manual Field wiring.
docs/docs/api/form/datetime/timeinput.md Documents TimeInput behavior.
docs/docs/api/form/datetime/datetimeinput.md Documents DateTimeInput behavior.
docs/docs/api/form/datetime/dateinput.md Documents DateInput behavior.
docs/blog/2026-08-04-forms-without-a-form-library.md Updates historical accessibility note.
bulma-ui/src/skill-examples/Form.stories.tsx Removes obsolete manual wiring.
bulma-ui/src/form/useAutoLabelId.ts Implements shared ID association.
bulma-ui/src/form/TimeInput.tsx Wires TimeInput labels.
bulma-ui/src/form/TextArea.tsx Wires TextArea labels.
bulma-ui/src/form/Slider.tsx Wires Slider labels.
bulma-ui/src/form/Select.tsx Wires Select labels.
bulma-ui/src/form/Numberinput.tsx Wires Numberinput labels.
bulma-ui/src/form/Input.tsx Wires Input labels.
bulma-ui/src/form/File.tsx Wires File labels.
bulma-ui/src/form/fieldProps.ts Documents neutral shared props.
bulma-ui/src/form/Field.tsx Clarifies Field’s manual association.
bulma-ui/src/form/DateTimeInput.tsx Wires DateTimeInput labels.
bulma-ui/src/form/DateInput.tsx Wires DateInput labels.
bulma-ui/src/form/__tests__/TimeInput.test.tsx Tests TimeInput association.
bulma-ui/src/form/__tests__/TextArea.test.tsx Tests TextArea association.
bulma-ui/src/form/__tests__/Slider.test.tsx Tests Slider association.
bulma-ui/src/form/__tests__/Select.test.tsx Tests Select association.
bulma-ui/src/form/__tests__/Numberinput.test.tsx Tests Numberinput modes.
bulma-ui/src/form/__tests__/Input.test.tsx Tests association and overrides.
bulma-ui/src/form/__tests__/File.test.tsx Tests File’s dual labels.
bulma-ui/src/form/__tests__/DateTimeInput.test.tsx Tests DateTimeInput association.
bulma-ui/src/form/__tests__/DateInput.test.tsx Tests IDs and popover derivation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +39 to +40
const controlId =
id ?? (active && !labelProps?.htmlFor ? generatedId : undefined);
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://502ae397.bestax.pages.dev

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bulma-ui/src/form/Input.tsx`:
- Around line 17-21: Update the documentation for the label and
labelProps-related props in Input to clarify that automatic label association
applies only when Input renders its own Field; when nested in an outer Field,
callers must manually associate that Field’s label because Input does not render
or forward the label props.

In `@docs/docs/api/form/datetime/dateinput.md`:
- Line 832: Update the label descriptions in
docs/docs/api/form/datetime/dateinput.md:832-832,
docs/docs/api/form/datetime/datetimeinput.md:836-836, and
docs/docs/api/form/datetime/timeinput.md:971-971 to replace “renders no input”
with wording that states inline mode has no visible input to label.

In `@docs/docs/api/form/field.md`:
- Line 492: Document the complete label-association contract across all cited
sites: in docs/docs/api/form/field.md lines 492-492 and 517-531, limit automatic
association and the label prop behavior to convenience controls rendered outside
an existing Field; in docs/docs/api/form/file.md lines 407-407 and 431-454,
qualify the two-label behavior, add matching id/htmlFor values to manual
examples, and state that explicit labelProps.htmlFor suppresses fallback ID
generation; apply matching labelProps.htmlFor/id examples and explicit-override
conditions in docs/docs/api/form/input.md lines 569-570 and 593-624,
docs/docs/api/form/numberinput.md lines 305-334, and
docs/docs/api/form/select.md lines 410-411 and 434-464; in
docs/docs/api/form/slider.md lines 344-379, document standalone rendering,
explicit overrides, and manual association when wrapped in Field.

In `@skills/bestax-form/SKILL.md`:
- Around line 122-127: Update the automatic label-association guidance in
skills/bestax-form/SKILL.md lines 122-127 to state that inline date/time picker
modes have no visible input and do not support the generated id/htmlFor
association; apply the same exception to the Field automatic-wiring note in
skills/bestax-form/references/api.md line 19. Keep the existing component and
manual-wiring guidance intact.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dc44b6f1-a813-49b1-bf71-a277a4f4e1ef

📥 Commits

Reviewing files that changed from the base of the PR and between 6d67bbf and e6686af.

📒 Files selected for processing (35)
  • bulma-ui/src/form/DateInput.tsx
  • bulma-ui/src/form/DateTimeInput.tsx
  • bulma-ui/src/form/Field.tsx
  • bulma-ui/src/form/File.tsx
  • bulma-ui/src/form/Input.tsx
  • bulma-ui/src/form/Numberinput.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__/DateInput.test.tsx
  • bulma-ui/src/form/__tests__/DateTimeInput.test.tsx
  • bulma-ui/src/form/__tests__/File.test.tsx
  • bulma-ui/src/form/__tests__/Input.test.tsx
  • bulma-ui/src/form/__tests__/Numberinput.test.tsx
  • bulma-ui/src/form/__tests__/Select.test.tsx
  • bulma-ui/src/form/__tests__/Slider.test.tsx
  • bulma-ui/src/form/__tests__/TextArea.test.tsx
  • bulma-ui/src/form/__tests__/TimeInput.test.tsx
  • bulma-ui/src/form/fieldProps.ts
  • bulma-ui/src/form/useAutoLabelId.ts
  • bulma-ui/src/skill-examples/Form.stories.tsx
  • docs/blog/2026-08-04-forms-without-a-form-library.md
  • 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/field.md
  • docs/docs/api/form/file.md
  • docs/docs/api/form/input.md
  • docs/docs/api/form/numberinput.md
  • docs/docs/api/form/select.md
  • docs/docs/api/form/slider.md
  • docs/docs/api/form/textarea.md
  • skills/bestax-form/SKILL.md
  • skills/bestax-form/references/api.md
💤 Files with no reviewable changes (1)
  • bulma-ui/src/skill-examples/Form.stories.tsx

Comment thread bulma-ui/src/form/Input.tsx Outdated
Comment on lines +17 to +21
/** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. */
label?: React.ReactNode;
/** Size for the label. */
labelSize?: FieldProps['labelSize'];
/** Props for the label element. */
/** Props for the label element. An explicit `htmlFor` here overrides the automatic association. */

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Qualify the automatic-association documentation for nested Field usage.

When Input is inside a Field, rendersLabel is false. Input does not render its own label or forward labelProps to the outer Field. Lines 17 and 21 describe association without this condition.

State that automatic association applies when Input renders its own Field. State that callers must manually associate an outer Field label.

Proposed documentation fix
-/** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. */
+/** Field label. When Input renders its own Field, it is automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. */
 ...
-/** Props for the label element. An explicit `htmlFor` here overrides the automatic association. */
+/** Props for Input's rendered label. An explicit `htmlFor` here overrides the automatic association. */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/** Field label. Automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. */
label?: React.ReactNode;
/** Size for the label. */
labelSize?: FieldProps['labelSize'];
/** Props for the label element. */
/** Props for the label element. An explicit `htmlFor` here overrides the automatic association. */
/** Field label. When Input renders its own Field, it is automatically associated with the input via `htmlFor` — uses your `id` when provided, otherwise a generated one. */
label?: React.ReactNode;
/** Size for the label. */
labelSize?: FieldProps['labelSize'];
/** Props for Input's rendered label. An explicit `htmlFor` here overrides the automatic association. */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@bulma-ui/src/form/Input.tsx` around lines 17 - 21, Update the documentation
for the label and labelProps-related props in Input to clarify that automatic
label association applies only when Input renders its own Field; when nested in
an outer Field, callers must manually associate that Field’s label because Input
does not render or forward the label props.

Comment thread docs/docs/api/form/datetime/dateinput.md Outdated
Comment thread docs/docs/api/form/field.md Outdated
Comment thread skills/bestax-form/SKILL.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated no new comments.

Suppressed comments (2)

bulma-ui/src/form/useAutoLabelId.ts:40

  • An explicit empty htmlFor does not suppress generation as documented: the truthiness check generates a control ID, while the later spread keeps the label's for="". This causes unexpected DOM churn and leaves the generated ID unassociated. Check whether htmlFor is defined rather than whether its value is truthy.
  const controlId =
    id ?? (active && !labelProps?.htmlFor ? generatedId : undefined);

skills/bestax-form/SKILL.md:219

  • The checklist recommends htmlFor plus an ID for group inputs, but a <label for> can label only one labelable control; it cannot name checkbox/radio/rating groups. This would preserve the accessibility defect for generated forms. Group containers need role="group"/role="radiogroup" and aria-labelledby, while composite controls need their inner control labeled.

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

No. Severity Area Finding Location
1 🔵 Advisory Accessibility File now emits two labels on one input (Field label-for plus the wrapping file-label); accessible name concatenates and axe flags form-field-multiple-labels (moderate). Net-positive vs. #368 and documented, on the record. bulma-ui/src/form/File.tsx:150
2 🔵 Advisory API Nine label-bearing controls now emit id/for where they emitted none, shipped as a fix (patch). Additive but churns consumer snapshots and changes the DateInput-family popover id shape (<id>-popover vs picker-<reactId>) when a label is present. bulma-ui/src/form/useAutoLabelId.ts:39

Overall: The change is sound and does exactly what #368 asks — one small, well-scoped useId-based hook that merges htmlFor into the label props each convenience component already forwards, with the control receiving a matching id. I verified empirically: getByLabelText resolves, for equals the control id, and all 572 form tests pass on the checked-out commit. The hook is called unconditionally (hooks-safe) and useId is SSR-stable on both React majors. The riskiest surface is the File double-label tradeoff and the DateInput family id-to-popover-id derivation; both are handled and covered by tests. A human should focus on confirming the patch-vs-minor call for the new id/for output (advisory 2) is acceptable given the documented consumer-snapshot churn.

Residual risk: the addressed failure class (label wired to no control) could recur three ways, each checked:

  • Dangling htmlFor (label points to a non-existent id): refuted — every path where rendersLabel is true renders a control that receives controlId (Input/Select/TextArea/File/Slider always; Numberinput only when isStepper or not-effectiveBare, matching the input-bearing branches; date family only when not-inline). When labelProps.htmlFor is user-set, generation is suppressed and the user owns the id.
  • Rest-spread clobbering controlId: refuted — the spread carries id only when the caller supplied one, in which case controlId equals the user id, so the override is value-identical; with no user id the spread has no id key and controlId stands.
  • Still-unassociated labels elsewhere: acknowledged and out of scope — Autocomplete/Taginput (id lands on a wrapper), Rate/Checkboxes/Radios (need aria-labelledby), inline date pickers (no input to target), and composed Field-label usage remain manual; all are called out in the PR body and docs, not silently dropped.

🏄 Clean little set wave, dude — one tidy hook paddles nine inputs into the a11y lineup and every test barrel rolls green. The File double-label is a mellow ripple, not a wipeout. Ship it.

Review round on #492: the auto-association docs stated the rule without its
boundary conditions. TSDoc, the Field/File docs pages, and the bestax-form
skill now say the wiring happens only when the component renders its own
Field (nested inside one, the label prop is dropped), that inline picker
modes have no visible input to label, and that an explicit labelProps.htmlFor
suppresses id generation.
Copilot AI review requested due to automatic review settings August 7, 2026 22:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 35 out of 35 changed files in this pull request and generated no new comments.

Suppressed comments (1)

bulma-ui/src/form/useAutoLabelId.ts:42

  • When labelProps contains htmlFor: undefined (for example, from a conditional value), controlId is generated because the value is falsy, but the subsequent spread overwrites the matching htmlFor with undefined. The rendered control then has an ID while its label remains unassociated. Determine whether a defined override exists and write htmlFor after spreading the remaining props.
  const controlId =
    id ?? (active && !labelProps?.htmlFor ? generatedId : undefined);
  const fieldLabelProps = active
    ? { htmlFor: controlId, ...labelProps }

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://bbe312ea.bestax.pages.dev

Three high advisories surfaced in the audit gate, none introduced by this
branch:

- nanoid <3.3.17 (GHSA-2v37-7h3g-55p8, vite>postcss chain): real patch
  available, forced via a 3.x-scoped override; 3.3.17 is past the release
  cooldown and postcss's ^3.3.16 admits it.
- image-size <=2.0.2 ICNS and JXL/HEIF infinite-loop DoS
  (GHSA-w3rx-r6r6-pgpr, GHSA-5p2g-fcmc-qvqq, Docusaurus mdx-loader): GitHub
  lists no patched release and npm's latest is still 2.0.2, so there is
  nothing to force. Ignored via auditConfig.ignoreGhsas with removal criteria
  documented in pnpm-workspace.yaml; exposure is the docs build sizing this
  repo's own images, never untrusted input.

pnpm audit --audit-level=high is clean again.
Copilot AI review requested due to automatic review settings August 7, 2026 23:01
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

Preview URL: https://9e803e61.bestax.pages.dev

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 36 out of 37 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Generated file
Suppressed comments (12)

bulma-ui/src/form/useAutoLabelId.ts:43

  • htmlFor is checked by truthiness but then spread after the generated value. Consequently, htmlFor="" does not suppress ID generation as documented, while htmlFor={undefined} can erase the generated association. Distinguish an absent value from an explicit string and apply the resolved value last.
  const controlId =
    id ?? (active && !labelProps?.htmlFor ? generatedId : undefined);
  const fieldLabelProps = active
    ? { htmlFor: controlId, ...labelProps }
    : labelProps;

bulma-ui/src/form/Input.tsx:119

  • The forwarded props are spread after controlId, so a common <Input id={optionalId} label="…" /> call where optionalId is undefined removes the generated ID while the label retains its generated htmlFor. Apply the resolved ID after the forwarded props.
    let content = <InputBase ref={ref} id={controlId} {...inputProps} />;

bulma-ui/src/form/Select.tsx:103

  • The forwarded props are spread after controlId, so an explicitly undefined optional id removes the generated ID while the label retains its generated htmlFor. Apply the resolved ID after the forwarded props.
    let content = <SelectBase ref={ref} id={controlId} {...selectProps} />;

bulma-ui/src/form/TextArea.tsx:90

  • The forwarded props are spread after controlId, so an explicitly undefined optional id removes the generated ID while the label retains its generated htmlFor. Apply the resolved ID after the forwarded props.
    let content = <TextAreaBase ref={ref} id={controlId} {...textAreaProps} />;

bulma-ui/src/form/TimeInput.tsx:115

  • Because baseProps is spread after controlId, passing an optional id whose value is undefined overwrites the generated ID and leaves the label pointing at a missing target. Spread baseProps first and apply the resolved ID last.
        id={controlId}
        {...baseProps}

bulma-ui/src/form/DateInput.tsx:119

  • Because baseProps is spread after controlId, passing an optional id whose value is undefined overwrites the generated ID and leaves the label pointing at a missing target. Spread baseProps first and apply the resolved ID last.
        id={controlId}
        {...baseProps}

bulma-ui/src/form/DateTimeInput.tsx:117

  • Because baseProps is spread after controlId, passing an optional id whose value is undefined overwrites the generated ID and leaves the label pointing at a missing target. Spread baseProps first and apply the resolved ID last.
        id={controlId}
        {...baseProps}

bulma-ui/src/form/File.tsx:159

  • The native props are spread after controlId, so an explicitly undefined optional id removes the generated ID while the Field label keeps its generated htmlFor. Apply the resolved ID after rest.
            id={controlId}
            {...rest}

bulma-ui/src/form/Numberinput.tsx:343

  • The native props are spread after controlId, so an explicitly undefined optional id removes the generated ID while the Field label keeps its generated htmlFor. Apply the resolved ID after rest.
          id={controlId}
          {...rest}

bulma-ui/src/form/Slider.tsx:680

  • The native props are spread after controlId, so an explicitly undefined optional id removes the generated ID while the Field label keeps its generated htmlFor. Apply the resolved ID after rest.
          id={controlId}
          {...rest}

bulma-ui/src/form/Slider.tsx:762

  • In range mode, rest likewise overwrites the low thumb's generated ID when the caller passes id={undefined}, leaving the Field label's htmlFor unresolved. Apply controlId after the spread.
          id={controlId}
          {...rest}

skills/bestax-form/SKILL.md:222

  • The checklist groups composite controls with labelable inputs and recommends htmlFor plus an ID, but Checkboxes, Radios, and Rate render group containers rather than labelable elements. A <label for> targeting those containers does not name the group; the PR description correctly calls for a group role plus aria-labelledby.

@allxsmith
allxsmith merged commit ef37d70 into main Aug 7, 2026
14 checks passed
@allxsmith
allxsmith deleted the fix/368-label-htmlfor branch August 7, 2026 23:16
@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 5.8.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 4.0.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@bestax-release-bot

Copy link
Copy Markdown

🎉 This PR is included in version 2.0.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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] bulma-ui: form label prop renders a Label but wires no htmlFor/id

2 participants