Introduction
CupertinoUI is a set of shadcn/ui components that look and feel like macOS 27. Same names, same props, native-looking results.
"use client"
import * as React from "react"
import {
ChevronLeftIcon,
ChevronRightIcon,
Columns3Icon,
LayoutGridIcon,
ListIcon,
ShareIcon,
} from "lucide-react"
import { SearchField } from "@/components/ui/search-field"
import {
Toolbar,
ToolbarSpacer,
ToolbarTitle,
} from "@/components/ui/toolbar"
import {
ToolbarButton,
ToolbarButtonGroup,
ToolbarButtonGroupSeparator,
} from "@/components/ui/toolbar-button-group"
import {
Window,
WindowContent,
WindowControls,
WindowMain,
} from "@/components/ui/window"
export default function ToolbarDemo() {
const [view, setView] = React.useState("grid")
return (
<Window className="h-60 w-full max-w-2xl">
<WindowMain>
<Toolbar>
<WindowControls className="mx-3" />
<ToolbarButtonGroup>
<ToolbarButton aria-label="Back">
<ChevronLeftIcon className="size-5" />
</ToolbarButton>
<ToolbarButtonGroupSeparator />
<ToolbarButton aria-label="Forward" disabled>
<ChevronRightIcon className="size-5" />
</ToolbarButton>
</ToolbarButtonGroup>
<ToolbarTitle title="Projects" />
<ToolbarSpacer />
<ToolbarButtonGroup
type="single"
value={view}
onValueChange={setView}
aria-label="View"
className="max-sm:hidden"
>
<ToolbarButton value="grid" aria-label="Icons">
<LayoutGridIcon strokeWidth={1.6} />
</ToolbarButton>
<ToolbarButton value="list" aria-label="List">
<ListIcon strokeWidth={1.6} />
</ToolbarButton>
<ToolbarButton value="columns" aria-label="Columns">
<Columns3Icon strokeWidth={1.6} />
</ToolbarButton>
</ToolbarButtonGroup>
<ToolbarButtonGroup>
<ToolbarButton aria-label="Share">
<ShareIcon strokeWidth={1.6} />
</ToolbarButton>
</ToolbarButtonGroup>
<SearchField variant="glass" size="xl" className="w-40 max-md:hidden" aria-label="Search" />
</Toolbar>
<WindowContent className="flex items-center justify-center bg-mac-content text-mac-label-secondary">
Viewing as {view}
</WindowContent>
</WindowMain>
</Window>
)
}What is CupertinoUI?
CupertinoUI is a shadcn/ui registry. Like shadcn/ui, it is not a package you install from npm: the CLI copies the source of each component into your project, where you own it and can change anything.
The components keep shadcn’s names and APIs, so a <Button variant="secondary"> or a <DropdownMenu> works exactly as you expect. What changes is the look: controls, menus, windows, sidebars and toolbars follow macOS 27, including its Liquid Glass toolbar capsules, pill-shaped switch knobs and rounded menu highlights.
How it was made
Every value lives in one CSS file, macos.css. Colors, text styles and control sizes are what macOS 27 reports through AppKit, and window chrome, materials and shadows were measured from screenshots of macOS 27 at one pixel per point: the desktop demo rebuilds a real desktop with these components and is compared with the original. Design Sources lists the source of every value.
What’s included
- 77 components: controls such as buttons, pop-up buttons, switches and sliders; menus, alerts and popovers; and Mac-specific pieces like windows, toolbars, sidebars, grouped forms and list views.
- Blocks: complete windows ready to drop into a page. Sign In, Preferences, Save, Reminders and Feedback are free. Finder, System Settings, Mail and Notes come with CupertinoUI Pro.
- A theme with light and dark appearances and the macOS accent colors.
FAQ
Can I use CupertinoUI next to regular shadcn/ui components?
Yes. The theme maps shadcn’s tokens (--primary, --border, --radius and so on) to macOS values, so stock shadcn components blend in. The sidebar is called MacSidebar so it doesn’t collide with shadcn’s Sidebar.
Does it work outside Next.js?
The components are plain React with Tailwind CSS v4 and Base UI. Any framework the shadcn CLI supports works; adjust the path of macos.css to your project.
Is this affiliated with Apple?
No. CupertinoUI is an independent project styled after Apple’s public design resources.
Ready? Start with Installation.