# liquidcn > Liquid Glass components for shadcn/ui: spring-driven glass on top of the shadcn components you already use, installed from a registry. Early stage: APIs may still change, so add liquidcn to existing projects with care. Each liquid component extends the shadcn/ui component of the same name and keeps its API: the same props, refs, and events. Install one with the shadcn CLI, then import it from `@/components/ui/liquid/` instead of `@/components/ui/`. It needs React 19, Tailwind CSS v4, and a shadcn `components.json`. ## Button Glass button that swells under the finger, stretches on drag, and morphs its width and content. Includes a prominent tinted variant. - Docs: https://liquidcn.snmandela.com/docs/components/button - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-button.json` ### Usage ```tsx import { Button } from "@/components/ui/liquid/button" ``` ### API #### Button Every prop of the shadcn Button is forwarded, including refs and `asChild`. - `variant` (`"default" | "prominent" | "secondary" | "outline" | "ghost" | "destructive" | "link"`, default `"default"`): `prominent` is tinted with `--liquid-accent`, like iOS `.glassProminent`. - `size` (`"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"`, default `"default"`): Text sizes keep a 44 px minimum height; icon sizes are 44 px circles. - `asChild` (`boolean`, default `false`): Render the child element, such as a link, with the button's glass. ### Accessibility - Renders a native `button` (or your element with `asChild`), so focus, Enter, and Space work as usual. - Icon-only buttons need an `aria-label`. When content morphs, update the label with it. - Under reduced motion the swell, stretch, and morph are removed; the button still changes instantly. ## Dropdown Menu Glass menus that grow out of their trigger as a droplet and fold back into it through a teardrop neck, keeping the focus management of the shadcn dropdown menu. - Docs: https://liquidcn.snmandela.com/docs/components/dropdown-menu - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-dropdown-menu.json` ### Usage ```tsx import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/liquid/dropdown-menu" Save to collection ``` ### API #### DropdownMenuContent Every prop of the shadcn DropdownMenuContent is forwarded. The other parts are re-exported unchanged, so imports stay the same. - `overlap` (`boolean`, default `true`): Open over the trigger and grow out of it, as iOS does. - `side` (`"top" | "right" | "bottom" | "left"`, default `"bottom"`): Which way the panel extends from the trigger. - `--liquid-morph-duration` (`CSS time`, default `520ms`): Length of the unfold, set on any ancestor or the root. ### Accessibility - The base menu's semantics and focus management: opening from the keyboard focuses the first item, Escape returns focus to the trigger. - The press that opens the menu cannot select the item that appears under the finger. Press, drag, and release still selects, as on iOS. - Under reduced motion the panel appears and disappears without the droplet. ## Tab Bar Floating glass tab bar with a search button: search collapses the tabs into a circle and stretches the button into a field, and the two glass surfaces fuse when pressed. - Docs: https://liquidcn.snmandela.com/docs/components/tab-bar - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-tab-bar.json` ### Usage ```tsx import { TabBar, TabBarItems, TabBarSearch } from "@/components/ui/liquid/tab-bar" import { Tabs, TabsList, TabsTrigger } from "@/components/ui/liquid/tabs" } label="Back to Calls"> Calls Contacts ``` ### API #### TabBar Lays out the tabs and the search button, and owns the search state. - `searching` (`boolean`): Whether search is open. Leave it undefined to let the tab bar manage it. - `defaultSearching` (`boolean`, default `false`): Initial state when uncontrolled. - `onSearchingChange` (`(searching: boolean) => void`): Called when search opens or closes. #### TabBarItems The glass around a liquid `TabsList` (or a list of links with a lens). While searching, the tabs are `inert` and a circle stands in for them. - `icon` (`ReactNode`): Shown in the circle, usually the selected tab's icon. - `label` (`string`, default `"Show tabs"`): Accessible name of the circle, which closes search. #### TabBarSearch The search button that becomes the field. Props, ref, and events go to the ``; `className` styles the glass. - `closeLabel` (`string`, default `"Close search"`): Accessible name of the close button in the field. - `--liquid-tab-bar-width` (`CSS length`, default `the bar's resting width`): Width of the whole bar while searching, set on `TabBar`. ### Accessibility - The search button has an accessible name, and opening search moves focus to the field. - Escape, the close button, or the circle closes search and returns focus to the search button. - While searching, the tabs are `inert` and hidden from assistive technology, so focus cannot reach what is folded away. - The neck and the refraction are decorative: `aria-hidden`, off under reduced motion, reduced transparency, increased contrast, and forced colors. ## Tabs Glass tabs with a lifting, magnifying lens you can drag across tabs, keeping the keyboard navigation of shadcn Tabs. - Docs: https://liquidcn.snmandela.com/docs/components/tabs - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-tabs.json` ### Usage ```tsx import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/liquid/tabs" Photos Albums Your photos Your albums ``` ### API #### TabsList Adds the lens. Every prop of the shadcn TabsList is forwarded; `Tabs`, `TabsTrigger`, and `TabsContent` are the shadcn parts with liquid styles. - `className` (`string`): Add `liquid-tabbar` for an iOS tab bar with icons over labels. - `--liquid-lens-ink` (`CSS color`, default `var(--liquid-accent)`): Color of the labels under the lens. ### Accessibility - Tabs semantics from the base component: `tablist`, `tab`, and `tabpanel` roles, with arrow keys, Home, and End. - The lens shows an `inert`, `aria-hidden` copy of the list. Screen readers only meet the real tabs. - A drag selects the tab where it is released and moves focus with it, so the roving tab stop stays in sync. ## Toast Top-center glass notifications with pill formation, soft stacking, and Sonner accessibility. - Docs: https://liquidcn.snmandela.com/docs/components/sonner - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-sonner.json` ### Usage ```tsx import { Toaster, toast } from "@/components/ui/liquid/sonner" // Once, near the root of your app. toast.success("Saved to your collection", { description: "A little moment, kept forever.", }) ``` ### API #### Toaster Sonner's Toaster with liquid defaults. Every Sonner prop is forwarded, and `toast` is Sonner's own. - `position` (`Position`, default `"top-center"`): Where the pills form. iOS places them at the top. - `visibleToasts` (`number`, default `3`): How many stay visible before older ones tuck behind. - `closeButton` (`boolean`, default `true`): A round close button inside each pill. ### Accessibility - Sonner announces each toast in a polite live region, and Alt+T moves focus to the notifications. - Timers pause while the pointer is over a toast or pressing it, and while the page is hidden. - Every toast has a close button and can also be swiped away. - Under reduced motion toasts appear at full size with no formation. ## Toolbar Floating glass toolbar: groups of swelling buttons on one capsule with a lifting selection lens, and round buttons beside them that fuse with it when pressed. - Docs: https://liquidcn.snmandela.com/docs/components/toolbar - Install: `npx shadcn@latest add https://liquidcn.snmandela.com/r/liquid-toolbar.json` ### Usage ```tsx import { Toolbar, ToolbarButton, ToolbarGroup, ToolbarSeparator, } from "@/components/ui/liquid/toolbar" ``` ### API #### Toolbar A `div` with the toolbar role that lays out groups and round buttons. Other props go to the `div`. - `orientation` (`"horizontal" | "vertical"`, default `"horizontal"`): Lays the toolbar out in a row or a column; arrow keys follow. #### ToolbarGroup A capsule of glass around related buttons, with the selection lens. Props go to the `div`. #### ToolbarButton A liquid `Button`, so it takes the shadcn Button props. In a group it sits on the group's glass; directly in the toolbar it is a round glass button of its own. - `aria-pressed` (`boolean`): The lens lands on the button in a group where this is true. - `variant` (`LiquidButtonVariant`, default `"ghost" in a group, "default" outside`): Any liquid Button variant, e.g. `prominent` for a tinted round button. #### ToolbarSeparator A line between buttons, across the toolbar's direction. ### Accessibility - One tab stop for the whole toolbar. Arrow keys along its direction move between buttons and wrap, mirrored in right-to-left layouts; Home and End jump to the ends. Disabled buttons are skipped. - Icon buttons need an `aria-label`. Toggles use `aria-pressed` with a label that stays the same. - The lens and the glass neck are decorative and hidden from assistive technology.