Skip to content

fix: address migration feedback from shadcn/Radix to Kumo#42

Open
geoquant wants to merge 15 commits intocloudflare:mainfrom
geoquant:geoquant/kumo-fixes-for-matt
Open

fix: address migration feedback from shadcn/Radix to Kumo#42
geoquant wants to merge 15 commits intocloudflare:mainfrom
geoquant:geoquant/kumo-fixes-for-matt

Conversation

@geoquant
Copy link

@geoquant geoquant commented Feb 7, 2026

Summary

Addresses issues surfaced during a ~70-component migration from shadcn/ui + Radix to Kumo.

Changes

Bugs

  • CLI doc/docs/ls broken — fixed registry path from catalog/ to ai/, replaced internal error message with consumer-facing text
  • Tailwind 4 @source missing from docs — fixed inconsistent Usage Example on installation page, added @source docs to package README

Type safety

  • Dialog DTS leaks @base-ui/react — wrapped sub-components (Root, Trigger, Title, Description, Close) in thin functions using ComponentPropsWithoutRef, matching Popover's pattern
  • Button aria-label on icon-only — discriminated union requires aria-label when shape="square" or shape="circle"

Accessibility

  • Label rendered <span> — changed to <label> with htmlFor support

Discoverability

  • Textarea alias for InputArea
  • ToastProvider alias for Toasty

Documentation

  • Added confirmation dialog recipe showing disablePointerDismissal
  • Updated Select basic example to use items prop
  • Documented icon-only button pattern with aria-label

Not addressed

  • Dialog.Close render prop verbosity — intentional Base UI design decision, not a Kumo concern

@geoquant geoquant force-pushed the geoquant/kumo-fixes-for-matt branch 2 times, most recently from cff2086 to b73546c Compare February 7, 2026 22:57
</p>
<CodeBlock
code={`@import "tailwindcss";
code={`@source "../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}";

Choose a reason for hiding this comment

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

The @source "../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}" example assumes a specific project structure.

It might be worth adding a short disclaimer noting that this path is relative to the user’s config file and may need adjustment. For example, if the app lives under /src, the relative path would differ (e.g. ../../node_modules/...), and copying the snippet verbatim could fail.

see issue #33

```js
// Explicit import (recommended)
import "@cloudflare/kumo/styles/tailwind";
**Important:** Tailwind CSS v4 does not scan `node_modules/` by default. You must add a `@source` directive so Tailwind can discover the utility classes used by Kumo components. Without this, components may render with missing styles (e.g. Dialogs not centered).

Choose a reason for hiding this comment

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

Would it also make sense to add this on the docs installation page?

Copy link

@ascorbic ascorbic left a comment

Choose a reason for hiding this comment

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

Great stuff, thanks

Copy link

Choose a reason for hiding this comment

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

Did this mean to remove all the props?

<Heading level={3}>Confirmation Dialog (Alert)</Heading>
<p class="mb-3 text-sm text-kumo-strong">
For confirmation dialogs that should not be dismissed by clicking outside (similar to an AlertDialog),
use <code class="rounded bg-kumo-control px-1 py-0.5 text-xs">disablePointerDismissal</code> on <code class="rounded bg-kumo-control px-1 py-0.5 text-xs">Dialog.Root</code>.
Copy link

Choose a reason for hiding this comment

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

Does disablePointerDismissal also disable escape key dismissal?

Choose a reason for hiding this comment

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

@ascorbic From my testing... no, disablePointerDismissal does not disable Escape key dismissal.

That actually seems like the correct behavior if we want to align with alertdialog patterns. Pressing Esc should be equivalent to activating the Cancel / Discard action and should return focus to the trigger, per the ARIA Authoring Practices:
https://www.w3.org/WAI/ARIA/apg/patterns/alertdialog/examples/alertdialog/

Also, the prop name explicitly refers to pointer dismissal, so it makes sense that it only blocks outside pointer interactions, not keyboard dismissal via Esc.

Comment on lines 239 to 241
code={`@source "../node_modules/@cloudflare/kumo/dist/**/*.{js,jsx,ts,tsx}";
@import "tailwindcss";
@import "@cloudflare/kumo/styles/tailwind";`}
Copy link

Choose a reason for hiding this comment

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

…mples

The Usage Example section on the installation page was missing the
@source directive, causing consumers following that example to get
silently broken styles (e.g. Dialogs rendering in top-left corner).

Also adds @source documentation to the package README, which previously
had no mention of this requirement. Fixes stale 'catalog/' path
reference in README.
The CLI was looking for the component registry at 'catalog/' but the
file is at 'ai/component-registry.json'. This caused all three
documentation commands to fail with a misleading error referencing
an internal build script (pnpm build:ai-metadata) that doesn't exist.

Fixed path from 'catalog' to 'ai' and replaced the internal error
message with a consumer-facing one.
…ences

Dialog was the only compound component that directly assigned Base UI
sub-components without wrapping them, causing generated .d.ts files to
emit 'typeof DialogBase.Root' references that leak @base-ui/react
into downstream consumers' type resolution.

Now wraps Root, Trigger, Title, Description, and Close in thin wrapper
functions (matching the pattern used by Popover) so the emitted types
use ComponentPropsWithoutRef instead of direct typeof references.
Also exports the new sub-component prop types for library consumers.
…ssal

Adds a 'Confirmation Dialog (Alert)' example to the Dialog docs page
that demonstrates using disablePointerDismissal on Dialog.Root to
prevent overlay dismissal — the Kumo equivalent of AlertDialog.

This addresses the discoverability gap where users migrating from
Radix/shadcn don't know how to create non-dismissible confirmation
dialogs.
The Label component rendered a <span> which doesn't create an
accessible association with its form control. Changed the standalone
rendering to use a <label> element and added the htmlFor prop so
consumers can associate the label with a specific form control.

The asContent mode still renders a <span> since it's used inside
another element (like Field) that handles accessibility.
Exports InputArea as Textarea from both the component path and the
main barrel export for discoverability. Consumers searching for
'textarea' in autocomplete or docs will now find the component.
Exports Toasty as ToastProvider for discoverability. Consumers
searching for 'toast provider' or 'ToastProvider' (the standard
name in other UI libraries) will now find the component.
The basic Select example showed value and label being identical
(value='Apple', children='Apple') which masked the fact that without
the items prop, the trigger displays the raw value string. Updated
to use lowercase values with items prop so the correct pattern is
shown first, with an explanation of what items controls.
The icon-only button example didn't include aria-label, teaching an
inaccessible pattern. Added explanation text about the accessibility
requirement and updated both the code example and demo to include
aria-label on shape='square' and shape='circle' buttons.
…ed union

When shape is 'square' or 'circle', TypeScript now requires aria-label
at the type level. This catches silent accessibility bugs where
icon-only buttons have no screen reader label. Regular buttons with
shape='base' (the default) are unaffected.
Adds a Vite plugin that rewires @cloudflare/kumo imports to raw source
files during astro dev, enabling instant HMR without rebuilding the
kumo package. Production builds still use dist/ exports to validate
the real consumer experience.
Address review feedback:
- Add warning callout about Tailwind v4 requiring @source directive
- Add note that @source path is relative to CSS file location
- Apply to both installation docs page and README
The codegen script only handled intersection types (allOf) and plain
properties, causing discriminated unions like ButtonProps to produce
empty props. Now merges properties from all union members, marking
props as optional when they don't appear in every member.

Regenerated registry with --no-cache to restore Button's 14 props.
Kumo's @theme tokens must be registered before Tailwind processes them,
so @import "@cloudflare/kumo/styles" must come before @import "tailwindcss".
Fixed all code snippets in the installation page and README to match
the working order used in the docs site's own global.css.
@geoquant geoquant force-pushed the geoquant/kumo-fixes-for-matt branch from b10af05 to 93cc97a Compare February 9, 2026 20:03
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.

5 participants