Skip to content

Upgrade shadcn/ui to Base UI and refresh the /shadcn-ui showcase - #9

Merged
mythz merged 1 commit into
mainfrom
shadcn-upgrade
Oct 31, 2026
Merged

mythz merged 1 commit into
mainfrom
shadcn-upgrade

Conversation

@mythz

@mythz mythz commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Upgrades the template's shadcn/ui components to the current release and rebuilds the /shadcn-ui page around this template's ServiceStack integration.

Base UI instead of Radix UI

Base UI has been shadcn/ui's default component library since July 2026. It's built by the team that originally made Radix. Radix isn't deprecated, but new projects start on Base UI, so the template now does too.

  • All components are regenerated with shadcn@4.23.0 in the base-vega style. Vega is described as "the classic shadcn/ui look", the closest match to before.
  • @base-ui/react replaces Radix UI, which is removed entirely (no radix-ui or @radix-ui/* packages, including transitive ones).
  • New components: field, input, label, separator, skeleton, spinner, tooltip, empty.
  • cn now comes from shadcn's cn package (a drop-in for clsx + tailwind-merge), migrated with npx shadcn migrate cn. @/lib/utils re-exports it.
  • components.json uses base-vega, slate, Tailwind v4 CSS-only config and the correct @/lib/utils alias. Previously the alias pointed at a nonexistent @/utils.

shadcn init wasn't used for the switch. On a scratch copy it deleted the helpers in lib/utils.ts, reset the theme and changed the site font, so the equivalent changes were made by hand.

Theme

  • Current shadcn format: oklch tokens in :root / .dark, mapped with @theme inline. Chart and sidebar tokens are included.
  • The template's blue primary, 0.5rem radius and font are kept. Computed styles outside the components (body, borders, container widths, blog typography, link-dark) were measured before and after and are unchanged.
  • tw-animate-css replaces tailwindcss-animate. The old package was a Tailwind v3 plugin that was never loaded, so dialog animations never ran on main.
  • shadcn/tailwind.css provides the data-open / data-closed / ... variants the Base UI components use.
  • shadcn colors, radius and keyframes moved from tailwind.config.ts into CSS. The config keeps only the template's typography, container and link-dark settings.

Code changes for Base UI's API

  • asChild becomes render={<Button />}, including Plugin.tsx and its code sample in the 2023 JavaScript blog post.
  • DropdownMenuItem uses onClick instead of onSelect. A DropdownMenuLabel must be inside a DropdownMenuGroup; otherwise Base UI throws error #31.
  • Accordion drops type="single" / collapsible, since that's the default.
  • Links styled as buttons use buttonVariants() on a plain <a>. Base UI's Button always sets role="button", which hides the link role, and shadcn's docs warn against it.
  • TooltipProvider is added at the app root.
  • DataTable uses theme tokens instead of hard-coded gray/indigo/yellow row colors, and no longer requires callers to pass getCoreRowModel.

/shadcn-ui page

New sections showing integration with this template:

  • Live API: Hello is called as you type, with a Skeleton while loading.
  • Validation: CreateTodo's [ValidateNotEmpty] error appears in Field / FieldError, with aria-invalid styling.
  • Data table: GetWeatherForecast in DataTable, with a row DropdownMenu that opens a Sheet, plus Empty / Skeleton states.
  • Theming: token swatches that follow the header's dark-mode toggle.
  • Button sizes with tooltips, a Spinner loading button, and Dialog and Sheet demos.

Stale content fixed:

  • The Installation tab listed 6 of the 10 installed components. It's now generated from src/components/ui.
  • Copy-and-paste install steps are replaced with npx shadcn@latest add.
  • A made-up "1M+ downloads" stat is removed.
  • Hard-coded slate / gray overrides that defeated theming are removed, as is a <main> nested inside the layout's <main>.

Verification

  • npm run check (0 errors), npm run test:run, npm run build
  • In headless Chromium, light and dark: Hello API, validation error and success, table rows, row menu → Sheet, tooltip, Dialog and Sheet open and close, tabs, accordion, external links render as <a>, blog post dialog. No page errors.
  • Dialog and accordion animations run; Sheet uses CSS transitions
  • CI green on this PR

Notes

  • Bundle size: the main chunk grew from 612 to 638 kB because the root TooltipProvider includes Base UI's positioning code. The /shadcn-ui page chunk is 148 kB, mostly TanStack Table, and only loads on that route.
  • Visual changes come from the Vega style: tinted destructive buttons, lighter card-title weight, and a blurred dialog backdrop.
  • Existing dev servers need a restart after npm install. Vite serves outdated pre-bundled dependencies (HTTP 504) until it's restarted.

🤖 Generated with Claude Code

…howcase

Components
- Regenerate all components with shadcn 4.23 in the base-vega style on
  Base UI (@base-ui/react), shadcn/ui's default since July 2026. Radix UI
  is removed entirely.
- Add field, input, label, separator, skeleton, spinner, tooltip and empty
- Migrate to shadcn's `cn` package (replaces clsx + tailwind-merge) via
  `shadcn migrate cn`; lib/utils re-exports it
- components.json: base-vega style, slate base color, Tailwind v4 (no JS
  config), correct @/lib/utils alias

Theme
- Current shadcn theme format: oklch tokens in :root/.dark mapped with
  @theme inline, keeping the template's blue primary, radius and font
- tw-animate-css replaces tailwindcss-animate (never loaded, so dialog
  animations never ran) and shadcn/tailwind.css adds Base UI's data-*
  variants
- shadcn colors, radius and keyframes move out of tailwind.config.ts

Integration
- TooltipProvider at the app root
- DataTable uses theme tokens and no longer requires getCoreRowModel
- asChild -> render, onSelect -> onClick, grouped menu labels, and links
  styled with buttonVariants (Base UI's Button forces role="button")

/shadcn-ui page
- Showcases ServiceStack integration: live Hello API, CreateTodo
  validation errors in Field/FieldError, and GetWeatherForecast in
  DataTable with a row DropdownMenu that opens a Sheet
- Fixes stale content: installed components listed from the ui folder,
  CLI install steps, made-up stats removed, no hard-coded slate overrides
- Adds theming swatches, button sizes with tooltips, Dialog and Sheet

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mythz
mythz merged commit f95aafb into main Oct 31, 2026
4 checks passed
@mythz
mythz deleted the shadcn-upgrade branch October 31, 2026 16: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.

1 participant