Skip to content

fix(field): don't render an empty label element - #898

Merged
mattrothenberg merged 3 commits into
mainfrom
mrothenberg/fix-tag-input-empty-label
Oct 28, 2026
Merged

mattrothenberg merged 3 commits into
mainfrom
mrothenberg/fix-tag-input-empty-label

Conversation

@mattrothenberg

@mattrothenberg mattrothenberg commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Field always rendered its <label>, even with no label content. Input, InputArea and TagInput wrap themselves in Field whenever they have a description or error, so without a label they rendered an empty <label>. That caused two problems:

  • An empty row above the control. TagInput hits this as soon as an entry fails validateValue.
  • No accessible name. Base UI points the control's aria-labelledby at the empty label, which overrides aria-label. <Input aria-label="Name" description="…" /> was announced with no name.
field-empty-label-before-after

Fix

Field skips the <label> only when it would render nothing: label and labelTooltip are each a value React renders as nothing (undefined, null, a boolean or ""), and there is no "(optional)" indicator. Every other case renders exactly as before, including label={0}, tooltip-only and optional-only labels, and hideLabel. TagInput no longer passes label ?? "".

Regression check

  • Only Input, InputArea and TagInput ever give Field an empty label. The other wrappers (Select, Combobox, Autocomplete, InputGroup, SensitiveInput, Switch) only use Field with a label.

  • No docs demo renders those three with a description or error but no label, so no docs screenshots change.

  • Unit suite: 1312 passed. That's the baseline of 1298 plus 14 new tests; no existing test changed.

  • The 10 new bug tests fail on main. The new "keeps the label" tests pass on both main and this branch.

  • Browser suite: same results as main. Its failures (Select truncating trigger visual, Flow connectors) also fail on main, and a clipboard-dependent TagInput paste test is flaky under parallel runs. That test renders no Field, and it passes 5/5 in isolation.

  • tsc, lint and format are clean.

  • Reviews

  • bonk has reviewed the change

  • automated review not possible because: small change to one condition; regression coverage added and existing suites compared against main

  • Tests

  • Tests included/updated

  • Automated tests not possible - manual testing has been completed as follows:

  • Additional testing not necessary because:

@ask-bonk

ask-bonk Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

LGTM!

Review notes
  • Confirmed the review target is pull request #898. I am inspecting its existing review state, the TagInput implementation and tests, and applicable package guidance before evaluating the three changed files.
  • The checked-out head matches PR #898, and there are no existing reviews or review comments to duplicate. The change preserves the Field wrapper for feedback and adds a regression test; I am now checking Field label semantics and the exact PR patch to validate edge cases.
  • Field explicitly supports hideLabel while retaining descriptions and errors, so the modified props produce the intended structure and keep Base UI field wiring intact. The API patch confirms only these three files changed; no conflicting prior feedback exists. I will run the focused TagInput test suite and inspect the field test coverage for wrapper behavior.
  • Inspected Field tests and TagInput documentation usage. The focused TagInput test command could not run because pnpm is not installed in this environment.

github run

@clanky-the-clanker

clanky-the-clanker Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

✅ Approved — The fix is small and correct, and regression tests cover it. The changeset wording now matches the code, and nothing is left open.

The decision is advisory: this comment never approves, blocks or requests changes on the pull request.


✅ All checks passed

🔒 Security: ✅ LGTM

This is a UI and accessibility fix and has no security impact.


📖 AGENTS.md: ✅ LGTM

The pull request includes the changeset that packages/kumo requires and the required description checklist.


📋 Code Quality: ✅ LGTM

The hasLabelContent check skips the <label> only when label and labelTooltip each render nothing (undefined, null, a boolean or "") and there is no "(optional)" indicator. This also covers the label={true} and labelTooltip="" cases noted in the earlier review. The tests cover each empty value and the cases that must keep the label (0, tooltip-only, optional-only, hideLabel). Removing label ?? "" in TagInput goes with the new check.


⚡ Performance: ✅ LGTM

No performance concerns.


📝 Documentation: ✅ LGTM

.changeset/field-empty-label.md:5 names the exact values treated as empty (undefined, null, a boolean or ""), which matches rendersNothing in field.tsx:124-126. The earlier note about overstated wording is resolved.


Reviewed commit: 8fb72d95 — same changes as 3efdb9f4, so this is that commit's review (no new review was run; line numbers are as of 3efdb9f4)

@pkg-pr-new

pkg-pr-new Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
npm i https://pkg.pr.new/@cloudflare/kumo@898

commit: 8fb72d9

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://mrothenberg-fix-tag-input-empty-label-kumo-docs.design-engineering.workers.dev (commit 8fb72d9)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://f21056a7-kumo-docs.design-engineering.workers.dev 8fb72d9 2026-10-28T15:04:10.358Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://38b39142-kumo-docs.design-engineering.workers.dev 3efdb9f 2026-10-28T12:39:39.614Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://fe243366-kumo-docs.design-engineering.workers.dev c1e6d05 2026-10-28T02:21:17.595Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://6e05ac76-kumo-docs.design-engineering.workers.dev 4ebdd2c 2026-10-28T02:10:44.257Z Visit the dashboard ↗

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Visual contracts

Linux Chromium references exercised by the PR's visual-contracts job.

1 curated contract

truncating text trigger

truncating text trigger

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

📐 Bundle Size

Consumer fixtures bundled against packages/kumo/dist (peers external, minified ESM).

Fixture Raw Gzip Brotli
Button (root) 166.6 KB 50.9 KB 44.3 KB
Button (components/button) 166.5 KB 50.9 KB 44.2 KB
Button + Dialog + Select (root) 293.5 KB 87.5 KB 73.7 KB
Button + Dialog + Select (component subpaths) 293.6 KB 87.7 KB 73.7 KB
Chart (root) 238.5 KB 71.9 KB 61.9 KB
Chart (components/chart) 238.5 KB 71.9 KB 61.9 KB
Badge (components/badge) 36.5 KB 12.7 KB 11.1 KB
Flow (components/flow) 200.7 KB 59.2 KB 51.8 KB
Button (primitives/button) 12.4 KB 4.5 KB 4.0 KB
Primitives barrel 718.4 KB 198.5 KB 154.5 KB
Code highlighting (code) 2.07 MB 469.2 KB 350.6 KB

npm tarball: 565 files, 1.56 MB packed, 7.30 MB unpacked.

⚠️ 25 flagged files in tarball (tests / raw scripts)
  • dist/blocks-source/delete-resource/delete-resource.test.tsx
  • dist/blocks-source/resource-list/resource-list.test.tsx
  • scripts/component-registry/cache.ts
  • scripts/component-registry/discovery.ts
  • scripts/component-registry/example-cleanup.ts
  • scripts/component-registry/index.test.ts
  • scripts/component-registry/index.ts
  • scripts/component-registry/markdown-generator.ts
  • scripts/component-registry/metadata.ts
  • scripts/component-registry/props-filter.ts
  • scripts/component-registry/schema-generator.ts
  • scripts/component-registry/sub-components.ts
  • scripts/component-registry/types.ts
  • scripts/component-registry/utils.ts
  • scripts/component-registry/variant-parser.ts
  • scripts/css-build.ts
  • scripts/format-generated.ts
  • scripts/generate-globe-land-mask.mjs
  • scripts/generate-primitives.ts
  • scripts/theme-generator/config.ts
  • scripts/theme-generator/generate-css.test.ts
  • scripts/theme-generator/generate-css.ts
  • scripts/theme-generator/index.ts
  • scripts/theme-generator/migrate.ts
  • scripts/theme-generator/types.ts

Report-only: no size thresholds are enforced yet.

Commit: 8fb72d95

@mattrothenberg
mattrothenberg force-pushed the mrothenberg/fix-tag-input-empty-label branch from 4ebdd2c to c1e6d05 Compare October 28, 2026 02:18
@mattrothenberg mattrothenberg changed the title fix(tag-input): don't render an empty label without a label prop fix(field): don't render an empty label element Oct 28, 2026
@mattrothenberg
mattrothenberg merged commit 06726b0 into main Oct 28, 2026
19 checks passed
@mattrothenberg
mattrothenberg deleted the mrothenberg/fix-tag-input-empty-label branch October 28, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants