Skip to content

feat(checkbox)!: align onCheckedChange with Base UI, remove deprecated props#416

Open
mattrothenberg wants to merge 5 commits intomainfrom
refactor/checkbox-onCheckedChange-eventDetails
Open

feat(checkbox)!: align onCheckedChange with Base UI, remove deprecated props#416
mattrothenberg wants to merge 5 commits intomainfrom
refactor/checkbox-onCheckedChange-eventDetails

Conversation

@mattrothenberg
Copy link
Copy Markdown
Collaborator

@mattrothenberg mattrothenberg commented Apr 15, 2026

Summary

This PR aligns Checkbox's onCheckedChange callback with Base UI's native signature and removes deprecated props that have been superseded.

Background

Base UI's Checkbox provides onCheckedChange with two arguments:

onCheckedChange?: (checked: boolean, eventDetails: CheckboxRootChangeEventDetails) => void

Kumo was wrapping this and only exposing the first argument (checked: boolean), while maintaining three deprecated alternative props (onChange, onValueChange, onClick) for backwards compatibility. This added complexity and prevented consumers from accessing the underlying event when needed.

Changes

onCheckedChange now exposes event details

The callback signature now matches Base UI:

// Before
onCheckedChange={(checked) => console.log(checked)}

// After - eventDetails available as optional second argument
onCheckedChange={(checked, eventDetails) => {
  console.log(checked);
  console.log(eventDetails.event); // native event if needed
}}

Existing code that only uses the first argument continues to work unchanged.

Removed deprecated props

Removed Prop Replacement
onChange onCheckedChange
onValueChange onCheckedChange
onClick Standard React event handling via spread props

Simplified internals

  • Removed handleCheckedChange wrapper functions in both CheckboxBase and CheckboxItem
  • Now passes onCheckedChange directly to Base UI
  • Type is derived directly from Base UI: BaseCheckbox.Root.Props["onCheckedChange"]

New export

Added CheckboxChangeEventDetails type export for consumers who need to type the event details:

import { Checkbox, type CheckboxChangeEventDetails } from '@cloudflare/kumo';

const handleChange = (checked: boolean, details: CheckboxChangeEventDetails) => {
  // ...
};

What's NOT changing

  • Checkbox.Group's onValueChange prop - This is a different API that returns string[] (the array of selected values), not a boolean. It remains unchanged.
  • Table.CheckCell and Table.CheckHead - These have their own onValueChange prop that wraps Checkbox internally. They continue to provide a simpler (checked: boolean) => void API, which makes sense for table selection use cases.

Migration

// Before (deprecated)
<Checkbox onChange={(e) => console.log(e.target.checked)} />
<Checkbox onValueChange={(checked) => setChecked(checked)} />

// After
<Checkbox onCheckedChange={(checked) => setChecked(checked)} />

// If you need the event
<Checkbox onCheckedChange={(checked, { event }) => {
  console.log(event);
}} />

Breaking Change Justification

  1. The deprecated props have been marked deprecated - consumers have had time to migrate
  2. Simpler API surface - one callback instead of three overlapping ones
  3. Better Base UI alignment - reduces maintenance burden and gives consumers access to the full API
  4. Type safety - the onChange prop was using as never cast internally, which was a code smell

  • Reviews
  • bonk has reviewed the change
  • automated review not possible because: this is a breaking API change requiring human judgment
  • Tests
  • Tests included/updated
  • Additional testing not necessary because: existing checkbox demos use onCheckedChange and continue to work; API table auto-generates from types

…cated props

BREAKING CHANGE: onCheckedChange signature now includes eventDetails as second argument.
Removed deprecated props: onChange, onValueChange, onClick
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 15, 2026

npm i https://pkg.pr.new/@cloudflare/kumo@416

commit: b3dedb1

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

Docs Preview

View docs preview

Commit: 969ffbf

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 15, 2026

Visual Regression Report — 24 changed, 13 unchanged

24 screenshot(s) with visual changes:

Button / Basic

198 px (0.2%) changed

Before After Diff
Before After Diff

Button / Variant: Destructive

1,112 px (1.1%) changed

Before After Diff
Before After Diff

Button / Variant: Secondary Destructive

383 px (0.38%) changed

Before After Diff
Before After Diff

Button / Sizes

860 px (0.85%) changed

Before After Diff
Before After Diff

Button / Icon Only

92 px (0.09%) changed

Before After Diff
Before After Diff

Button / Loading State

606 px (0.6%) changed

Before After Diff
Before After Diff

Button / Disabled State

117 px (0.12%) changed

Before After Diff
Before After Diff

Dialog / Dialog With Actions

138 px (0.14%) changed

Before After Diff
Before After Diff

Dialog / Dialog Basic

114 px (0.11%) changed

Before After Diff
Before After Diff

Dialog / Dialog Alert

354 px (0.35%) changed

Before After Diff
Before After Diff

Dialog / Dialog Confirmation

1,097 px (1.08%) changed

Before After Diff
Before After Diff

Dialog / Dialog With Select

225 px (0.22%) changed

Before After Diff
Before After Diff

Dialog / Dialog With Combobox

130 px (0.13%) changed

Before After Diff
Before After Diff

Dialog (Open)

0 px (0%) changed

Before After Diff
Before After Diff

Select / Select Basic

300 px (0.3%) changed

Before After Diff
Before After Diff

Select / Select Without Label

161 px (0.16%) changed

Before After Diff
Before After Diff

Select / Select With Field

1,170 px (0.99%) changed

Before After Diff
Before After Diff

Select / Select Placeholder

418 px (0.41%) changed

Before After Diff
Before After Diff

Select / Select With Tooltip

500 px (0.49%) changed

Before After Diff
Before After Diff

Select / Select Loading

1,369 px (0.64%) changed

Before After Diff
Before After Diff

Select / Select Multiple

556 px (0.55%) changed

Before After Diff
Before After Diff

Select / Select Disabled Options

508 px (0.5%) changed

Before After Diff
Before After Diff

Select / Select Long List

898 px (0.76%) changed

Before After Diff
Before After Diff

Select (Open)

181 px (0%) changed

Before After Diff
Before After Diff
13 screenshot(s) unchanged
  • Button / Variant: Primary
  • Button / Variant: Secondary
  • Button / Variant: Ghost
  • Button / Variant: Outline
  • Button / With Icon
  • Button / Title
  • Dialog / Dialog With Dropdown
  • Select / Select Sizes
  • Select / Select Custom Rendering
  • Select / Select Complex
  • Select / Select Disabled Items
  • Select / Select Grouped
  • Select / Select Grouped With Disabled

Generated by Kumo Visual Regression

@mattrothenberg
Copy link
Copy Markdown
Collaborator Author

/bigbonk

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk bot left a comment

Choose a reason for hiding this comment

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

Review

Clean PR — the intent is sound and the implementation is minimal. Removing the deprecated wrapper and passing onCheckedChange straight through to Base UI is the right call. Two issues to flag:

1. CheckboxChangeEventDetails is not reachable from the public API

The PR description advertises this import:

import { type CheckboxChangeEventDetails } from '@cloudflare/kumo';

But the type is only exported from checkbox.tsx. It's missing from both barrel files:

  • packages/kumo/src/components/checkbox/index.ts — needs type CheckboxChangeEventDetails added to the export list
  • packages/kumo/src/index.ts (line 46) — needs it added to the re-export

Without this, consumers can't actually import the type.

2. Stale registry metadata injects a ghost onValueChange prop

packages/kumo/scripts/component-registry/metadata.ts lines 257-262 still defines:

Checkbox: {
  onValueChange: {
    type: "(checked: boolean) => void",
    description: "Callback when checkbox value changes",
  },
},

This is in ADDITIONAL_COMPONENT_PROPS, which means the generated component-registry.json will advertise onValueChange as a valid prop on Checkbox even though the type no longer accepts it. This will confuse both AI consumers of the registry and the no-deprecated-props lint rule (which reads from the registry). This entry should be removed.

Minor notes

  • The visual regression diffs (0.17%–1% pixel changes) look like sub-pixel rendering noise, not functional changes — expected given this is a props-only change with no styling modifications.
  • The Checkbox.Group.onValueChange prop is correctly left alone.
  • The HomeGrid.tsx update from onValueChange to onCheckedChange is correct.
  • The whitespace-only reformatting of the hover:ring-kumo-hairline line is harmless but worth noting — it's unrelated to the feature change.

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Apr 15, 2026

Review posted on PR #416. Here's a summary of the findings:

Two issues flagged:

  1. CheckboxChangeEventDetails is dead code — The PR introduces this type and the description says consumers can import { type CheckboxChangeEventDetails } from '@cloudflare/kumo', but it's missing from both barrel files (checkbox/index.ts and src/index.ts). The import won't work.

  2. Stale registry metadatascripts/component-registry/metadata.ts still injects onValueChange as an ADDITIONAL_COMPONENT_PROPS entry for Checkbox. After this PR, that prop no longer exists on the type, so the generated registry will advertise a ghost prop that doesn't work. This feeds into both AI tooling and the no-deprecated-props lint rule.

Everything else looks good — the core change (removing the wrapper and passing onCheckedChange directly to Base UI) is clean and correct. The visual regression diffs are sub-pixel noise as expected for a props-only change.

github run

@mattrothenberg
Copy link
Copy Markdown
Collaborator Author

/bigbonk updated. can you re-review and approve now?

Copy link
Copy Markdown
Contributor

@ask-bonk ask-bonk bot left a comment

Choose a reason for hiding this comment

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

Review

Clean change overall. The core simplification (dropping the wrapper, passing onCheckedChange straight through to Base UI) is correct and the changeset is well-written.

Bonk findings triage

Finding #1 (partially valid): CheckboxChangeEventDetails is exported from checkbox/index.ts (line 5), but it's missing from the main barrel at src/index.ts:46:

export { Checkbox, type CheckboxProps } from "./components/checkbox";
//                  ^ needs type CheckboxChangeEventDetails here

The PR description and changeset both advertise import { type CheckboxChangeEventDetails } from '@cloudflare/kumo' — that import will fail at the package level. Needs a one-line fix.

Finding #2 (already addressed): The stale Checkbox.onValueChange entry in ADDITIONAL_COMPONENT_PROPS was already removed in this PR (visible in the diff). Bonk may have been looking at a stale version. No action needed.

Remaining issue

Add CheckboxChangeEventDetails to the main barrel export:

- export { Checkbox, type CheckboxProps } from "./components/checkbox";
+ export { Checkbox, type CheckboxProps, type CheckboxChangeEventDetails } from "./components/checkbox";

Co-authored-by: mattrothenberg <mattrothenberg@users.noreply.github.com>
@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Apr 15, 2026

That's a pre-existing error (the ai/schemas module is auto-generated and doesn't exist in the source tree, as documented in AGENTS.md). Not related to this PR.

The fix is straightforward. Here's a summary:

What I did:

  • Reviewed the PR and triaged bonk's two findings
  • Bonk finding update readme #1 (partially valid): CheckboxChangeEventDetails was correctly exported from checkbox/index.ts but missing from the main barrel src/index.ts. Fixed by adding it to the re-export at packages/kumo/src/index.ts:49.
  • Bonk finding Updating components #2 (already addressed): The stale Checkbox.onValueChange in ADDITIONAL_COMPONENT_PROPS was already removed in this PR's diff. No action needed.
  • Posted a review comment explaining both findings and the fix

github run

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant