# 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 |
| A magnifying lens | `variant="lens" geometry={LENS_GEOMETRY} samples={4}`, then `magnify()` |
## 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 magnifying lens
The tab lens on its own: the lens variant, its geometry, four samples and magnify().
```tsx
import { useRef } from "react";
import { LENS_GEOMETRY } from "@colineapp/liquid-glass";
import { LiquidGlass, type LiquidGlassHandle } from "@colineapp/liquid-glass/react";
export function Lens() {
const lens = useRef(null);
return (