110k
New

Changelog

RSS

Latest updates and announcements.

January 2026 - Inline Start and End Styles

We've updated the styles for Base UI components to support inline-start and inline-end side values. The following components now support these values:

  • Tooltip
  • Popover
  • Combobox
  • Context Menu
  • Dropdown Menu
  • Hover Card
  • Menubar
  • Select

What Changed

We added new Tailwind classes to handle the logical side values:

<PopoverPrimitive.Popup
  className={cn(
    "... data-[side=bottom]:slide-in-from-top-2
    data-[side=left]:slide-in-from-right-2
    data-[side=right]:slide-in-from-left-2
    data-[side=top]:slide-in-from-bottom-2
+   data-[side=inline-start]:slide-in-from-right-2
+   data-[side=inline-end]:slide-in-from-left-2 ...",
    className
  )}
/>

Usage

<Popover>
  <PopoverTrigger>Open</PopoverTrigger>
  <PopoverContent side="inline-start">
    {/* Opens on the left in LTR, right in RTL */}
  </PopoverContent>
</Popover>

LLM Prompt

Ask your LLM to update your components by running the following prompt:

Add inline-start and inline-end support to my shadcn/ui components. Add the following Tailwind classes to each component:
 
| File | Component | Add Classes |
|------|-----------|-------------|
| tooltip.tsx | TooltipContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| tooltip.tsx | TooltipArrow | `data-[side=inline-start]:top-1/2! data-[side=inline-start]:-right-1 data-[side=inline-start]:-translate-y-1/2
data-[side=inline-end]:top-1/2! data-[side=inline-end]:-left-1 data-[side=inline-end]:-translate-y-1/2` |
| popover.tsx | PopoverContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| hover-card.tsx | HoverCardContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| select.tsx | SelectContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2
data-[align-trigger=true]:animate-none` and add `data-align-trigger={alignItemWithTrigger}` attribute |
| combobox.tsx | ComboboxContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| dropdown-menu.tsx | DropdownMenuContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| context-menu.tsx | ContextMenuContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
| menubar.tsx | MenubarContent | `data-[side=inline-start]:slide-in-from-right-2 data-[side=inline-end]:slide-in-from-left-2` |
 
Add these classes next to the existing `data-[side=top]`, `data-[side=bottom]`, `data-[side=left]`, `data-[side=right]` classes.

January 2026 - Base UI Documentation

We've shipped full documentation for Base UI components.

When we launched npx createui create in December, we introduced the ability to choose between Radix and Base UI as your component library. Today, we're following up with complete documentation for all Base UI components.

What's New

  • Full Base UI docs - Every component now has dedicated documentation for Base UI, covering usage, props, and examples.
  • Rebuilt examples - All component examples have been rebuilt for both Radix and Base UI. Switch between them to see the implementation differences.
  • Side-by-side comparison - The docs make it easy to compare how components work across both libraries.

Same Abstraction, Different Primitives

The goal remains the same: give you a consistent API regardless of which primitive library you choose. The components look and behave the same way. Only the underlying implementation changes.

// Works the same whether you're using Radix or Base UI.
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"

If you're starting a new project, run npx createui create and pick your preferred library. The CLI handles the rest.

Try createui/create

December 2025 - npx createui create

From the very first commit, the goal of shadcn/ui was to make it customizable.

The idea is to give you solid defaults, spacing, color tokens, animations, accessibility, and then let you take it from there. Tweak the code. Add new components. Change the colors. Build your own version.

But somewhere along the way, all apps started looking the same. I guess the defaults were a little too good. My bad.

Today, we're changing that: npx createui create.

Customize Everything. Pick your component library, icons, base color, theme, fonts and create your own version of shadcn/ui.

We're starting with 5 new visual styles, designed to help your UI actually feel like your UI.

  • Vega – The classic shadcn/ui look.
  • Nova – Reduced padding and margins for compact layouts.
  • Maia – Soft and rounded, with generous spacing.
  • Lyra – Boxy and sharp. Pairs well with mono fonts.
  • Mira – Compact. Made for dense interfaces.

This goes beyond theming.

Your config doesn't just change colors, it rewrites the component code to match your setup. Fonts, spacing, structure, even the libraries you use, everything adapts to your preferences.

The new CLI takes care of it all.

Start with a component library. Choose between Radix or Base UI.

We rebuilt every component for Base UI, keeping the same abstraction. They are fully compatible with your existing components, even those pulled from remote registries.

When you pull down components, we auto-detect your library and apply the right transformations.

It's time to build something that doesn't look like everything else.

Now available for Next.js, Vite, TanStack Start and v0.

Get Started

October 2025 - Registry Directory

We just published the Registry Directory: a list of code registries you can browse and pull code and components from.

https://ui.shadcn.com/docs/directory

Built into the CLI. No config required.

October 2025 - New Components

For this round of components, I looked at what we build every day, the boring stuff we rebuild over and over, and made reusable abstractions you can actually use.

These components work with every component library, Radix, Base UI, React Aria, you name it. Copy and paste to your projects.

  • Spinner: An indicator to show a loading state.
  • Kbd: Display a keyboard key or group of keys.
  • Button Group: A group of buttons for actions and split buttons.
  • Input Group: Input with icons, buttons, labels and more.
  • Field: One component. All your forms.
  • Item: Display lists of items, cards, and more.
  • Empty: Use this one for empty states.

Spinner

Okay let's start with the easiest ones: Spinner and Kbd. Pretty basic. We all know what they do.

Here's how you render a spinner:

import { Spinner } from "@/components/ui/spinner"
<Spinner />

Here's what it looks like:

Component spinner-basic not found in registry.

Here's what it looks like in a button:

Component spinner-button not found in registry.

You can edit the code and replace it with your own spinner.

Component spinner-custom not found in registry.

Kbd

Kbd is a component that renders a keyboard key.

import { Kbd, KbdGroup } from "@/components/ui/kbd"
<Kbd>Ctrl</Kbd>

Use KbdGroup to group keyboard keys together.

<KbdGroup>
  <Kbd>Ctrl</Kbd>
  <Kbd>B</Kbd>
</KbdGroup>

Component kbd-demo not found in registry.

You can add it to buttons, tooltips, input groups, and more.

Button Group

I got a lot of requests for this one: Button Group. It's a container that groups related buttons together with consistent styling. Great for action groups, split buttons, and more.

Component button-group-demo not found in registry.

Here's the code:

import { ButtonGroup } from "@/components/ui/button-group"
<ButtonGroup>
  <Button>Button 1</Button>
  <Button>Button 2</Button>
</ButtonGroup>

You can nest button groups to create more complex layouts with spacing.

<ButtonGroup>
  <ButtonGroup>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
  </ButtonGroup>
  <ButtonGroup>
    <Button>Button 3</Button>
    <Button>Button 4</Button>
  </ButtonGroup>
</ButtonGroup>

Use ButtonGroupSeparator to create split buttons. Classic dropdown pattern.

Component button-group-dropdown not found in registry.

You can also use it to add prefix or suffix buttons and text to inputs.

Component button-group-select not found in registry.

<ButtonGroup>
  <ButtonGroupText>Prefix</ButtonGroupText>
  <Input placeholder="Type something here..." />
  <Button>Button</Button>
</ButtonGroup>

Input Group

Input Group lets you add icons, buttons, and more to your inputs. You know, all those little bits you always need around your inputs.

import {
  InputGroup,
  InputGroupAddon,
  InputGroupInput,
} from "@/components/ui/input-group"
<InputGroup>
  <InputGroupInput placeholder="Search..." />
  <InputGroupAddon>
    <SearchIcon />
  </InputGroupAddon>
</InputGroup>

Here's a preview with icons:

Component input-group-icon not found in registry.

You can also add buttons to the input group.

Component input-group-button not found in registry.

Or text, labels, tooltips,...

Component input-group-text not found in registry.

It also works with textareas so you can build really complex components with lots of knobs and dials or yet another prompt form.

Component input-group-textarea not found in registry.

Oh here are some cool ones with spinners:

Component input-group-spinner not found in registry.

Field

Introducing Field, a component for building really complex forms. The abstraction here is beautiful.

It took me a long time to get it right but I made it work with all your form libraries: Server Actions, React Hook Form, TanStack Form, Bring Your Own Form.

import {
  Field,
  FieldDescription,
  FieldError,
  FieldLabel,
} from "@/components/ui/field"

Here's a basic field with an input:

<Field>
  <FieldLabel htmlFor="username">Username</FieldLabel>
  <Input id="username" placeholder="Max Leiter" />
  <FieldDescription>
    Choose a unique username for your account.
  </FieldDescription>
</Field>

Component field-input not found in registry.

It works with all form controls. Inputs, textareas, selects, checkboxes, radios, switches, sliders, you name it. Here's a full example:

Component field-demo not found in registry.

Here are some checkbox fields:

Component field-checkbox not found in registry.

You can group fields together using FieldGroup and FieldSet. Perfect for multi-section forms.

<FieldSet>
  <FieldLegend />
  <FieldGroup>
    <Field />
    <Field />
  </FieldGroup>
</FieldSet>

Component field-fieldset not found in registry.

Making it responsive is easy. Use orientation="responsive" and it switches between vertical and horizontal layouts based on container width. Done.

Component field-responsive not found in registry.

Wait here's more. Wrap your fields in FieldLabel to create a selectable field group. Really easy. And it looks great.

Component field-choice-card not found in registry.

Item

This one is a straightforward flex container that can house nearly any type of content.

I've built this so many times that I decided to create a component for it. Now I use it all the time. I use it to display lists of items, cards, and more.

import {
  Item,
  ItemContent,
  ItemDescription,
  ItemMedia,
  ItemTitle,
} from "@/components/ui/item"

Here's a basic item:

<Item>
  <ItemMedia variant="icon">
    <HomeIcon />
  </ItemMedia>
  <ItemContent>
    <ItemTitle>Dashboard</ItemTitle>
    <ItemDescription>Overview of your account and activity.</ItemDescription>
  </ItemContent>
</Item>

Component item-demo not found in registry.

You can add icons, avatars, or images to the item.

Component item-icon not found in registry.

Component item-avatar not found in registry.

And here's what a list of items looks like with ItemGroup:

Component item-group not found in registry.

Need it as a link? Use the asChild prop:

<Item asChild>
  <a href="/dashboard">
    <ItemMedia variant="icon">
      <HomeIcon />
    </ItemMedia>
    <ItemContent>
      <ItemTitle>Dashboard</ItemTitle>
      <ItemDescription>Overview of your account and activity.</ItemDescription>
    </ItemContent>
  </a>
</Item>

Component item-link not found in registry.

Empty

Okay last one: Empty. Use this to display empty states in your app.

import {
  Empty,
  EmptyContent,
  EmptyDescription,
  EmptyMedia,
  EmptyTitle,
} from "@/components/ui/empty"

Here's how you use it:

<Empty>
  <EmptyMedia variant="icon">
    <InboxIcon />
  </EmptyMedia>
  <EmptyTitle>No messages</EmptyTitle>
  <EmptyDescription>You don't have any messages yet.</EmptyDescription>
  <EmptyContent>
    <Button>Send a message</Button>
  </EmptyContent>
</Empty>

Component empty-demo not found in registry.

You can use it with avatars:

Component empty-avatar not found in registry.

Or with input groups for things like search results or email subscriptions:

Component empty-input-group not found in registry.

That's it. Seven new components. Works with all your libraries. Ready for your projects.