# Using @colineapp/liquid-glass For coding agents adding Liquid Glass to a web app. Liquid Glass for the web: the rim refraction, light and motion of iOS 27's glass on any rounded element, with React bindings and tabs whose thumb lifts into a lens. MIT. Version 0.1.0. Every option has a plain-text page under https://liquid-glass.coline.space/docs/options/; the index is https://liquid-glass.coline.space/llms.txt. ## Install ```sh npm install @colineapp/liquid-glass ``` Import the stylesheet once, at the app's root: ```ts import "@colineapp/liquid-glass/styles.css"; ``` ## Pick the entry point - React: `import { LiquidGlass, useLiquidGlass, useLiquidGlassTabs } from "@colineapp/liquid-glass/react"`. - Anything else: `import { createLiquidGlass, attachLiquidGlassTabs } from "@colineapp/liquid-glass"`. - With a class-based dark mode (Tailwind `dark:`, next-themes), pass `appearance="class"`. Otherwise the glass follows prefers-color-scheme. ## Pick the options | Surface | Options | | --- | --- | | Nav bar, toolbar, card | none, or `interactive` if it holds controls | | Search field, button you press | `interactive swell` | | Menu, popover | `floating`, and `materialize()` on open | | Dialog, sheet | `floating="dialog"`, `fit="scroll"` if it scrolls itself | | Glass over a photo or video | `variant="clear"` | | Tinted glass | `hue="#3d6bff"` | | Segmented control, tab bar | `useLiquidGlassTabs(trackRef)` on your own tabs | ## Rules that keep the glass working - Put the glass first inside a positioned (relative, absolute or fixed), rounded element. It takes the element's corner radius and follows its size. - Paint nothing over it: no background, border or box-shadow on the surface. The glass draws its own edge. - No opacity below 1, filter, mask or backdrop-filter on the surface or its ancestors while the glass shows. Each makes a backdrop root, and the glass would see only that element instead of the page. - To show or hide a surface, fade and zoom its contents, never the surface itself, and call materialize() and dematerialize() for the glass. - Controls on glass get no glass of their own: give the selected or hovered one the liquid-glass-well class. - Rim refraction renders in Chromium. Safari and Firefox get the same material, light and motion without the bend. ## Checking your work - The surface element has `data-liquid-glass="dark"` or `"light"` once the glass is attached, and its glass child has `data-ready` once the rim is built. - In Chromium the glass child also has `data-refraction`. If the glass looks flat grey or empty, an ancestor has opacity, a filter, a mask or a backdrop-filter. - Don't put a background colour on the surface to make it look glassy: the glass is the background. ## Examples ### A glass toolbar in React Render first inside a positioned, rounded element. ```tsx import { LiquidGlass } from "@colineapp/liquid-glass/react"; import "@colineapp/liquid-glass/styles.css"; export function Toolbar() { return ( ); } ``` ### Without React createLiquidGlass inserts the glass as the element's first child. ```ts import { createLiquidGlass } from "@colineapp/liquid-glass"; import "@colineapp/liquid-glass/styles.css"; const glass = createLiquidGlass(document.querySelector(".toolbar")!, { interactive: true, }); glass.update({ variant: "clear" }); glass.destroy(); ``` ### Pill tabs Your tabs, your selection; the thumb follows aria-selected. ```tsx import { useRef } from "react"; import { useLiquidGlassTabs } from "@colineapp/liquid-glass/react"; export function Period({ value, onChange }: { value: string; onChange: (value: string) => void }) { const track = useRef(null); useLiquidGlassTabs(track, { appearance: "class" }); return (
{["Day", "Week", "Month"].map((label) => ( ))}
); } ``` ### A menu that materializes Fade the contents, never the surface; the glass grows from clear. ```tsx import { useEffect, useRef, useState } from "react"; import { LiquidGlass, type LiquidGlassHandle } from "@colineapp/liquid-glass/react"; export function Menu({ open, items }: { open: boolean; items: string[] }) { const glass = useRef(null); const [active, setActive] = useState(-1); useEffect(() => { if (open) void glass.current?.materialize({ duration: 240, scale: 0.96 }); }, [open]); if (!open) return null; return (
{items.map((item, index) => ( ))}
); } ``` ### A glass dialog floating="dialog" casts the deeper shadow; the glass materializes as the contents zoom in. ```tsx import { useLayoutEffect, useRef } from "react"; import { LiquidGlass, type LiquidGlassHandle } from "@colineapp/liquid-glass/react"; export function ShareDialog({ onClose }: { onClose: () => void }) { const glass = useRef(null); useLayoutEffect(() => { void glass.current?.materialize({ duration: 280, scale: 0.95 }); }, []); const close = () => void glass.current?.dematerialize({ duration: 180, scale: 0.97 }).then(onClose); return (

Share this album

); } ``` ### A search field that swells interactive lights it under the pointer; swell springs it on press. ```tsx ``` ### A glass card Regular glass on a rounded box: the rim bends what crosses it, and the body keeps the card's text legible. ```tsx import { LiquidGlass } from "@colineapp/liquid-glass/react"; import "@colineapp/liquid-glass/styles.css"; export function Card() { return (

Now playing

Glass takes the box's radius and follows its size.

); } ```