Liquid Glass for the web: the rim refraction, light and motion of iOS 27 glass on any rounded element. React bindings and pill tabs. MIT.
| 1 | # @colineapp/liquid-glass |
| 2 | |
| 3 | > Liquid Glass for the web: the rim refraction, light and motion of iOS 27's glass on any rounded element, with React bindings, menus that pour out of their button, and segmented tabs whose thumb clears into a lens. MIT. |
| 4 | |
| 5 | Version 0.2.0. Install: `npm install @colineapp/liquid-glass` |
| 6 |
| 7 | ## A menu that pours out of its button |
| 8 |
| 9 | The button becomes the menu, and the menu draws back into it. A pill slides under the row you point at. |
| 10 |
| 11 | ```tsx |
| 12 | import { useLayoutEffect, useRef, type RefObject } from "react"; |
| 13 | import { LiquidGlass, useLiquidGlassHighlight, type LiquidGlassHandle } from "@colineapp/liquid-glass/react"; |
| 14 |
| 15 | // Render it once open, placed below its button. To close it: |
| 16 | // if (await glass.current?.drawBack()) setOpen(false); |
| 17 | export function Menu({ button, glass, items }: { |
| 18 | button: RefObject<HTMLButtonElement | null>; |
| 19 | glass: RefObject<LiquidGlassHandle | null>; |
| 20 | items: string[]; |
| 21 | }) { |
| 22 | const menu = useRef<HTMLDivElement>(null); |
| 23 | useLiquidGlassHighlight(menu); |
| 24 | useLayoutEffect(() => { |
| 25 | if (button.current) void glass.current?.pourFrom(button.current, { cover: true }); |
| 26 | }, [button, glass]); |
| 27 | return ( |
| 28 | <div ref={menu} role="menu" className="absolute left-0 top-12 w-56 rounded-3xl p-1.5"> |
| 29 | <LiquidGlass glassRef={glass} appearance="class" floating /> |
| 30 | {items.map((item) => ( |
| 31 | <button key={item} role="menuitem" className="w-full rounded-2xl px-3 py-2 text-left"> |
| 32 | {item} |
| 33 | </button> |
| 34 | ))} |
| 35 | </div> |
| 36 | ); |
| 37 | } |
| 38 | ``` |
| 39 |