# glassy-liquid > Liquid Glass for the web: refraction, specular light, and the iOS 26 controls as Web Components, with React, Vue, and Svelte bindings. Docs site: https://9und30.github.io/glassy-liquid/ Every control is a custom element (``, ``, ...). The React, Vue, and Svelte components wrap those elements and are generated from one binding table, so they have the same names, props, defaults, and events. React callbacks such as `onCheckedChange` are `v-model:checked` in Vue and `bind:checked` in Svelte. Chromium refracts the live page behind the glass. Safari, every iOS browser, and Firefox show a frosted fallback unless the glass sits inside a `` that names its backdrop (an image URL in `src`, or a `glass-backdrop` child). ## Install ```sh npm install glassy-liquid ``` ## CDN The `glassy-liquid/cdn` export is `dist/glassy-liquid.min.js`. The script registers every element. `src` is any image URL. ```html Continue ``` ## Export map - `glassy-liquid`: `glass()`, `attachPress`, and the engine - `glassy-liquid/elements`: registers every custom element - `glassy-liquid/react` - `glassy-liquid/vue` - `glassy-liquid/svelte` - `glassy-liquid/svelte/actions` - `glassy-liquid/components/*`: one module per component - `glassy-liquid/scene`: the scene element on its own - `glassy-liquid/cdn`: the minified bundle - `glassy-liquid/package.json`: package metadata, not a runtime entry ## Scene image `src` on `glass-scene` accepts any image URL. The URL below is a public CC0 photograph, so the example works when pasted. The scene also paints `linear-gradient(160deg, #9bb7c9, #e7eef2)` when the image fails, and it hides the broken-image icon. https://upload.wikimedia.org/wikipedia/commons/thumb/5/58/Iceberg_reflection_in_J%C3%B6kuls%C3%A1rl%C3%B3n_%28Unsplash%29.jpg/960px-Iceberg_reflection_in_J%C3%B6kuls%C3%A1rl%C3%B3n_%28Unsplash%29.jpg ## Web Components With a bundler such as Vite. Without a build step, use the CDN script above: a bare `import "glassy-liquid/elements"` only resolves through a bundler or an import map. ```html Continue ``` ## React ```tsx "use client"; import { useState } from "react"; import { GlassScene, GlassButton, GlassSwitch } from "glassy-liquid/react"; export function Welcome() { const [on, setOn] = useState(true); return ( Continue ); } ``` ## Vue ```vue ``` ## Svelte ```svelte Continue ``` ## Next.js and server rendering The React entry (`glassy-liquid/react`) is a Client Component: the file starts with `"use client"`. In the Next.js App Router, import the components from a Client Component. The React, Vue, and Svelte bindings render `defer-hydration` on each element and remove it after hydration. While the attribute is present the element stays inert, so server markup matches the hydrated tree. Every entry point is safe to import on the server. Custom elements register only in the browser, where `customElements` exists, so importing `glassy-liquid`, `glassy-liquid/elements`, or a component module from code the server evaluates does not throw. `glass()`, `useGlass()`, and `attachPress()` touch the DOM, so call them in an effect or in `onMount`, as the playground snippets do. ## Docs - [llms-full.txt](https://9und30.github.io/glassy-liquid/llms-full.txt): this file plus the API reference, theming, and every component in every framework - [Home](https://9und30.github.io/glassy-liquid/): what the library does and the live hero - [Components](https://9und30.github.io/glassy-liquid/components.html): every component with Web Components, React, Vue, and Svelte code - [Playground](https://9und30.github.io/glassy-liquid/playground.html): tune glass options and copy the snippet - [Getting started](https://9und30.github.io/glassy-liquid/getting-started.html): install, frameworks, SSR, and your own element - [Theming](https://9und30.github.io/glassy-liquid/theming.html): CSS custom properties and shadow parts - [Accessibility](https://9und30.github.io/glassy-liquid/accessibility.html): roles, keyboard, and reduced motion or transparency - [Browser support](https://9und30.github.io/glassy-liquid/browser-support.html): which renderer runs in which browser ## Optional - [README](https://github.com/9und30/glassy-liquid#readme): the full guide, FAQ, and migration notes - [Changelog](https://github.com/9und30/glassy-liquid/blob/main/CHANGELOG.md) - [Issues](https://github.com/9und30/glassy-liquid/issues/new/choose): bug reports and feature requests. Pull requests are not accepted for now ## API reference ### Glass attributes These props are accepted on every framework component. They change the material on ``, ``, ``, ``, and ``. `` applies `material`, `blur`, and `tint` to its slab, including through `::part(glass)`. `glass()` and `useGlass()` take the same fields, plus `zoom` (default `1`), `backdrop` (default `true`), and `fill`. | Prop | Kind | Type | Default | Description | | --- | --- | --- | --- | --- | | `material` | attribute | `regular` or `clear` | `regular` | Frosted and adaptive, or transparent for media. | | `appearance` | attribute | `auto`, `light`, or `dark` | `auto` | `auto` reads `--glass-appearance`, then the page `color-scheme`. | | `radius` | attribute | number, `capsule`, or `circle` | per component | Corner radius in CSS pixels. | | `refraction` | attribute | number | scales with size | Maximum rim displacement in CSS pixels. | | `bezel` | attribute | number | `18` | Width of the refracting rim in CSS pixels. | | `blur` | attribute | number | material | Frost before refraction, in CSS pixels. | | `dispersion` | attribute | number (0 to 1) | `0.25` in WebGL, else `0` | Chromatic split at the rim. | | `tint` | attribute | CSS color | none | Color of tinted glass. | | `specular` | attribute | number (0 to 2) | `1` | Rim light strength. | | `lightAngle` | attribute | degrees | `-135` | Light direction. `-90` is the top. | | `shadow` | attribute | boolean or CSS `box-shadow` | `true` | `true` uses the material shadow. A string is used as the shadow. | | `profile` | attribute | `squircle`, `convex`, `lip`, or `flat` | `squircle` | Cross-section of the rim. | | `engine` | attribute | `auto`, `backdrop`, `scene-gl`, `scene-dom`, or `css` | `auto` | Force a renderer. Mainly for tests. | | `interactive` | attribute | boolean | per component | Press response: swell, light, and gel stretch. | Framework components also forward `class`, `style`, and other DOM attributes, and take `children` for the default slot. React refs and Vue `el` point at the custom element. Svelte uses `bind:element`. ### Components #### GlassScene Custom element: ``. Real refraction for Safari, iOS, iPadOS, and Firefox. Chromium keeps the faster page-backdrop path unless `force` is set. | Prop | Kind | Type | Default | Description | | --- | --- | --- | --- | --- | | `src` | attribute | string | none | Image URL. The scene creates a cover image in its shadow root. | | `backdrop` | attribute | string | direct child | When omitted, the direct child `[glass-backdrop]` or `[data-glass-backdrop]`. A set value is a CSS selector, queried on the scene and then on `document`. | | `force` | attribute | boolean | `false` | Use scene rendering even in Chromium. | | `mode` | attribute | `gl` or `dom` | auto | Force WebGL (`gl`) or the DOM content filter (`dom`). | Slots: default. Parts: `::part(backdrop)`. - The automatic `src` image is not a light-DOM child. Style it with `glass-scene::part(backdrop)`. - With no `src` and no `backdrop` selector, that direct child is the backdrop. An image, video, or canvas uses WebGL. Any other element uses the DOM content filter. - Glass anywhere inside the scene, including inside shadow roots, picks the scene up on its own. #### GlassSurface Custom element: ``. Generic slab for cards, widgets, and bars. The default radius is 24. No component-specific props. Slots: default. Parts: `::part(glass)`. - Accepts every glass attribute. Content goes in the default slot. #### GlassButton Custom element: ``. iOS 26 glass button. `prominent` fills with the accent, `plain` draws no glass of its own. | Prop | Kind | Type | Default | Description | | --- | --- | --- | --- | --- | | `variant` | attribute | `glass`, `prominent`, or `plain` | `glass` | Visual style. | | `size` | attribute | `small`, `medium`, or `large` | `medium` | 32, 44, or 52 CSS pixels tall. | | `shape` | attribute | `capsule`, `circle`, or `rounded` | `capsule` | `rounded` uses a 12px radius unless `radius` is set. | | `disabled` | attribute | boolean | `false` | Disables interaction and sets `aria-disabled`. | | `type` | attribute | `button`, `submit`, or `reset` | `button` | Form action when the button has no `href`. | | `href` | attribute | string | none | Renders as a link (`role="link"`) and navigates on click. | | `target` | attribute | string | none | Link target. Anything other than `_self` opens with `noopener`. | Slots: default, `icon`, `trailing`. Parts: `::part(label)`, `::part(glass)`. - Native event: `click`. Enter and Space activate the button. - Slots: `icon`, then the default slot (the label), then `trailing`. - Form-associated. Inside a form, `type="submit"` calls `requestSubmit()` and `type="reset"` resets. - Accepts every glass attribute. Default radius is `capsule`. `interactive` is on. #### GlassSwitch Custom element: ``. Toggle whose thumb lifts into a lens. Form-associated, role `switch`. | Prop | Kind | Type | Default | Description | | --- | --- | --- | --- | --- | | `disabled` | attribute | boolean | `false` | Disables the control. | | `name` | attribute | string | none | Form field name. | | `value` | attribute | string | `on` | Value submitted when the switch is on. | | `checked` | property | boolean | `false` | Controlled on state. Set the property, or the `checked` attribute for the initial value. | | `defaultChecked` | uncontrolled `checked` | boolean | `false` | Uncontrolled initial `checked` attribute. Later updates are ignored. | | `onCheckedChange` | event `change` | `(checked: boolean) => void` | none | Fires when the user toggles the switch. | | `onChange` | event `change` | `(event: Event) => void` | none | The same DOM `change` event, passed through unchanged. | Slots: none. Parts: `::part(track)`, `::part(fill)`, `::part(thumb)`, `::part(glass)`. - Also fires `input` on a user toggle. - Keyboard: Space and Enter toggle. A wrapping `