Migrating from shadcn/ui

Most of what you know from shadcn/ui carries over: Radix underneath, Tailwind, the source in your repo. Here is every shadcn component's Koala counterpart, and every name that changes.

At a glance#

Where the two meet and where they part. The sections below go through each difference.

Feature
shadcn/ui
Koala UI
Foundations
Source in your repoIncludedIncluded
Radix primitivesIncludedIncluded
Tailwind CSS v4IncludedIncluded
Variant recipescvatv, with slots
IconsLucidePhosphor
Theming
Themes24
Accent colors18
Densities12
Components
Data table, date picker, comboboxNot includedIncluded
Rich text editor, file upload, AI chatNot includedIncluded
Charts, carousel, drawer, calendarThird-partyBuilt in
Beyond components
SectionsApp blocks190
Page examplesNot included34
TemplatesNot included7
Updates that keep your editsNot includedIncluded
License
PriceFreeFree and Pro

What carries over#

  • The source lives in your repo under components/ui/, and the import paths stay the same: @/components/ui/button.
  • Radix primitives for behavior and accessibility, asChild through Radix Slot, className merged last with cn, and a data-slot on every part.
  • Named exports composed as parts: <Card><CardHeader><CardTitle>.
  • Tailwind CSS v4, with theming through CSS variables.

What changes#

  • tv instead of cva. Variant recipes are tailwind-variants, with slots for multi-part components, and VariantProps comes from @/lib/tv. Nothing in Koala uses class-variance-authority.
  • More tokens. The color roles you know (background, foreground, primary, muted, border) are joined by brand (the accent), body for reading copy, canvas, link and status roles with a -strong text step. Four themes (light, cream, dark, moonlight) and eight accents replace one light and one dark palette. See Colors.
  • The brand leads. variant="primary" is the brand color, where shadcn’s default button is near black. neutral is the black one.
  • Fields have two parts. InputRoot is the frame and InputField the input, so prefixes, suffixes and buttons sit inside one border. The same goes for TextareaRoot and TextareaField.
  • Components, not recipes. Data table, date picker, combobox (SelectSearch) and pagination ship as components you configure, not snippets you assemble.
  • Fewer dependencies. Charts, the carousel, the drawer and the calendar are Koala’s own: no Recharts, Embla, Vaul or react-day-picker. Icons are Phosphor, not Lucide.
  • Density and control size. size is sm 32, md 36 and lg 40px on every control, and a DensityProvider tightens a whole app shell at once. See Density.
  • Its own CLI. koalaui-cli records installs in koala.json instead of components.json, and diff and update bring upstream changes in without overwriting the files you edited. See Installation.

Component map#

Every shadcn/ui component and where it lands. A Koala name links to its docs page, where the full API and examples live.

shadcn/uiKoala UIWhat changes
AccordionAccordionSame parts. Adds a variant axis for flush, contained and grid layouts.
AlertAlertThe glyph goes in AlertIcon and the text in AlertContent; AlertActions holds buttons. Variants: default, success, warning, info, destructive.
Alert DialogDialogAlertDialog, AlertDialogContent, AlertDialogAction → Dialog, DialogContent, DialogFooter
There is no separate alert dialog: a Dialog whose footer carries the destructive Button.
Aspect RatioNone yet, see Aspect RatioTailwind's aspect-* utilities on the frame, no component.
AvatarAvatarSame three parts, plus AvatarStatus, AvatarBadge, a size scale and a shape.
BadgeBadgeSee the variant map below. Adds status and category tones, dot, pill and size.
BreadcrumbBreadcrumbSame parts.
ButtonButtonSee the variant and size map below. iconOnly replaces size="icon"; loading is built in.
Button GroupButton GroupButton inside the group → ButtonGroupItem
The group sets variant and size for its items.
CalendarDate PickerCalendar → Calendar
Koala's own calendar: no react-day-picker, no date library.
CardCardSame parts, plus CardMedia for an inset picture.
CarouselCarouselCarouselItem → CarouselSlide
No Embla dependency. Adds CarouselIndicators.
ChartChartChartContainer → Chart
ChartTooltip + ChartTooltipContent → ChartTooltip
ChartLegend + ChartLegendContent → ChartLegend
Recharts Line, Area, Bar → ChartLine, ChartArea, ChartBar
Its own SVG charts, no Recharts: Chart takes data, index and config, and the series are parts.
CheckboxCheckboxSame.
CollapsibleCollapsibleSame parts, plus CollapsibleIcon, a mark that turns with its trigger. The height tween is built in; className on CollapsibleContent styles the body.
ComboboxSelectPopover + Command recipe → SelectSearch, SelectSearchTrigger, SelectSearchContent, SelectSearchItem
A component, not a recipe. For several values, MultiSelect.
CommandCommandSame parts, CommandDialog included.
Context MenuContext MenuSame parts.
Data TableData TableTanStack Table recipe → DataTable
A component, not a recipe: columns and data in, with sorting, filters, selection, pagination, grouping and row reorder.
Date PickerDate PickerPopover + Calendar recipe → DatePicker, DateRangePicker
Components, with presets.
DialogDialogSame parts, plus DialogBody, DialogIcon and DialogStepper. The overlay is inside DialogContent.
DrawerDrawerNo Vaul dependency: a bottom sheet is DrawerContent side="bottom". Adds DrawerBody and stacked views.
Dropdown MenuDropdown MenuSame parts. Rows can carry a description (DropdownMenuItemText); a delete row is variant="destructive".
EmptyEmpty StateEmpty → EmptyState
EmptyMedia → EmptyStateMedia
EmptyTitle → EmptyStateTitle
EmptyDescription → EmptyStateDescription
EmptyContent → EmptyStateActions
FieldFieldFieldDescription, FieldError → FieldHint
FieldSet + FieldLegend → FieldGroup, FieldGroupLabel
An error is hasError on Field: it turns the hint into the message and sets aria-invalid.
FormFormNot a react-hook-form wrapper: Form is a plain <form> that sets the rhythm and the control size, and Field wires the label and hint. Bring your own validation.
Hover CardHover CardSame parts, plus HoverCardTitle and HoverCardDescription. The card is Popover's surface, with showArrow and density.
InputInputInput → InputRoot, InputField
Two parts: InputRoot is the frame, InputField the <input>. Prefixes, suffixes, PasswordInput, NumberInput and PhoneInput included.
Input GroupInput GroupInputGroup joins ordinary Koala controls (an input, a select, a button) into one frame; InputGroupAddon holds text or icons.
Input OTPOTP InputInputOTP, InputOTPGroup, InputOTPSlot → OTPInput
One component; the slots come from length.
ItemListItemGroup → List
Item → ListItem
ItemMedia → ListItemMedia
ItemContent → ListItemContent
ItemTitle → ListItemTitle
ItemDescription → ListItemDescription
ItemActions → ListItemMeta
KbdKbdSame.
LabelLabelSame, plus Hint for the line under a control.
MenubarMenubarSame parts. The menus are Dropdown Menu's panels: a delete row is variant="destructive", and a checkbox row can be variant="switch".
Native SelectNative SelectSame parts. size (sm, md, lg) matches the Select trigger, and inside a Field it wires its own id, hint and error state.
Navigation MenuNavbarNavbar is the whole site bar: brand, links with dropdowns, actions and the mobile menu.
PaginationPaginationA ready component (page, pageCount, onPageChange); PaginationRoot and its parts for a custom layout.
PopoverPopoverSame parts, plus PopoverTitle, PopoverDescription and PopoverCloseButton.
ProgressProgressSame, plus ProgressLabel and ProgressValue.
Radio GroupRadio GroupSame parts, plus RadioCard for option cards.
ResizableResizableSame parts.
Scroll AreaScroll AreaScrollBar is not a part: orientation (vertical, horizontal, both) draws the bars. Adds fade for the edges and viewportRef.
SelectSelectSame parts.
SeparatorDividerSeparator → Divider
Adds a label and dashed, dotted and gradient strokes.
SheetDrawerSheet → Drawer
SheetTrigger → DrawerTrigger
SheetContent → DrawerContent
SheetHeader → DrawerHeader
SheetTitle → DrawerTitle
SheetDescription → DrawerDescription
SheetFooter → DrawerFooter
SheetClose → DrawerClose
side goes on DrawerContent.
SidebarSidebarSidebarMenuItem + SidebarMenuButton → SidebarItem
The shell (SidebarProvider, SidebarInset, SidebarTrigger) is the Layout component: Layout, LayoutSidebar, LayoutContent, LayoutSidebarTrigger.
SkeletonSkeletonSame.
SliderSliderSame, plus SliderInput: a track beside a value box you can scrub.
Sonner (and Toast)Toasttoast and <Toaster /> from sonner → toast, Toaster
The same call shape: toast(), toast.success(), toast.error(), toast.promise(). Mount <Toaster /> once.
SpinnerSpinnerSame.
SwitchSwitchSame.
TableData TableTable, TableHeader, TableBody, TableRow, TableHead, TableCell → Table, TableHeader, TableBody, TableRow, TableHead, TableCell
The same parts, exported from @/components/ui/data-table.
TabsTabsSame parts. Adds a variant (pill, folder, line, chip) and TabsPanels.
TextareaTextareaTextarea → TextareaRoot, TextareaField
Two parts like Input, plus TextareaCount for a live character count.
ToggleToggleVariants outline (the default) and ghost; size is sm or md, and iconOnly replaces the square size. Adds ToggleIcon for a pressed glyph.
Toggle GroupToggle GroupSame parts.
TooltipTooltipTooltip + TooltipTrigger + TooltipContent → Tooltip
TooltipProvider → TooltipGroup
One element: <Tooltip content="Save"> wraps the trigger, placement sets the side.
TypographyProseProse styles rendered long-form HTML (a blog post, docs) in one wrapper.

Variants and sizes#

The values that are named differently. Anything not listed keeps its shadcn name.

Button variant

shadcn/uiKoala UINotes
defaultprimaryThe brand color. For shadcn's black button, neutral.
secondarysecondary
outlineoutline
ghostghost
destructivedestructiveA soft red tint; destructiveGhost for a quiet delete.
linklink

Button size

shadcn/uiKoala UINotes
smsm32px
defaultmd36px, the default
lglg40px
iconiconOnlyA boolean, combined with any size
Nonexl44px, for marketing calls to action

Badge variant

shadcn/uiKoala UINotes
defaultprimaryKoala's default is a muted gray chip.
secondarysecondary
outlineoutline
destructivedestructiveA soft tint, like the other status tones.

Alert variant

shadcn/uiKoala UINotes
defaultdefault
destructivedestructive
Nonesuccess, warning, info

Moving a project over#

  1. Clear shadcn’s colors. Delete the :root and .dark blocks shadcn added to your global stylesheet (app/globals.css, or src/index.css in Vite), and its @custom-variant dark line: they redefine --background, the other roles and --radius, and would override Koala’s themes. init warns you about each one still there.
  2. Run init. It writes the tokens to koala.css (app/ in Next.js, src/styles/ in Vite), the helpers to lib/ and the theme provider. shadcn’s lib/utils.ts is replaced: Koala’s cn has the same signature, with tailwind-merge taught Koala’s tokens. If you edited yours, init keeps it and tells you what to merge.
  3. Swap one component at a time. Delete shadcn’s file and add Koala’s. The import path does not change, so only the parts and props in the map above do. add refuses while a flat components/ui/<name>.tsx is still there, for the component you asked for and for every Koala component it pulls in: the import would resolve to that file instead of Koala’s folder.
  4. Let the type checker find the rest. Koala’s props are typed, so a leftover shadcn prop or value fails to compile.
  5. Clean up once nothing imports them: components.json, class-variance-authority, lucide-react and the packages Koala replaced.
# 1. Tokens, the lib helpers and the theme provider (after removing shadcn's color blocks)npx koalaui-cli@latest init# 2. One component at a time: delete shadcn's file, add Koala'srm components/ui/button.tsxnpx koalaui-cli@latest add button

Why Koala#

  • More of the product, already built. 123 components, free, including the ones you would otherwise assemble: a data table, date and range pickers, charts, a command palette, a rich text editor, file upload, and AI chat and prompt input.
  • Sections, pages and templates. 190 sections for marketing, app and store pages, in families (hero, feature, pricing, FAQ, checkout and more), 34 page examples and 7 templates. One sample of every family is free; the rest is Koala UI Pro.
  • Theming with range. Four themes, eight accents and a radius knob from one layer of tokens: a re-skin is a class, not a fork.
  • Two densities. The same components set a spacious marketing page and a dense dashboard.
  • Finish. Every component goes through the same polish pass: 40px hit areas, concentric radii, tabular numbers, reduced-motion fallbacks and AA contrast in every theme.
  • Updates that keep your edits. diff and update compare against what was installed, replace the files you did not touch and list the ones you did.

FAQ#

Yes, one component at a time. Both live in components/ui with the same import paths, so each component is either shadcn's file or Koala's folder: delete the file before you add the folder (the CLI refuses otherwise, and names the files in the way). The core color roles share their names, so the shadcn components you have not moved yet mostly pick up Koala's colors.