All component snippets
Button
Button, html
<glass-button shape="circle" aria-label="Back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg></glass-button>
<glass-button>Edit</glass-button>
<glass-button variant="prominent">Done</glass-button>
Button, react
import { GlassButton } from "glassy-liquid/react";
export function Buttons() {
return (
<>
<GlassButton shape="circle" aria-label="Back">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" strokeWidth="2.4" aria-hidden="true">
<path d="M15 18l-6-6 6-6" />
</svg>
</GlassButton>
<GlassButton onClick={() => {}}>Edit</GlassButton>
<GlassButton variant="prominent" onClick={() => {}}>Done</GlassButton>
</>
);
}
Button, vue
<script setup lang="ts">
import { GlassButton } from "glassy-liquid/vue";
</script>
<template>
<GlassButton shape="circle" aria-label="Back">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true">
<path d="M15 18l-6-6 6-6" />
</svg>
</GlassButton>
<GlassButton @click="() => {}">Edit</GlassButton>
<GlassButton variant="prominent" @click="() => {}">Done</GlassButton>
</template>
Button, svelte
<script>
import { GlassButton } from "glassy-liquid/svelte";
</script>
<GlassButton shape="circle" aria-label="Back">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.4" aria-hidden="true">
<path d="M15 18l-6-6 6-6" />
</svg>
</GlassButton>
<GlassButton onclick={() => {}}>Edit</GlassButton>
<GlassButton variant="prominent" onclick={() => {}}>Done</GlassButton>
Button events
click Native click, also from Enter and Space.
Surface
Surface, html
<glass-surface radius="34" style="width:170px;height:170px;padding:16px">
<small>Mountain lake</small>
<b>14°</b>
</glass-surface>
<glass-surface material="clear" radius="40" style="width:170px;height:170px"></glass-surface>
Surface, react
import { GlassSurface } from "glassy-liquid/react";
export function LakeCard() {
return (
<GlassSurface radius={34} style={{ width: 170, height: 170, padding: 16 }}>
<small>Mountain lake</small>
<b>14°</b>
</GlassSurface>
);
}
Surface, vue
<script setup lang="ts">
import { GlassSurface } from "glassy-liquid/vue";
</script>
<template>
<GlassSurface :radius="34" style="width:170px;height:170px;padding:16px">
<small>Mountain lake</small>
<b>14°</b>
</GlassSurface>
</template>
Surface, svelte
<script>
import { GlassSurface } from "glassy-liquid/svelte";
</script>
<GlassSurface radius={34} style="width:170px;height:170px;padding:16px">
<small>Mountain lake</small>
<b>14°</b>
</GlassSurface>
Switch
Switch, html
<glass-surface radius="28" style="width:min(320px,100%);padding:6px 18px;display:flex;flex-direction:column">
<label class="controls__row"><span class="controls__label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2.5 9a14 14 0 0 1 19 0M5.5 12.4a9.5 9.5 0 0 1 13 0M8.6 15.8a5 5 0 0 1 6.8 0"/><circle cx="12" cy="19" r="1" fill="currentColor"/></svg>Wi-Fi</span><glass-switch checked name="wifi"></glass-switch></label>
<label class="controls__row"><span class="controls__label"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.5 20.5l1.5-1 1.5 1v-4l7.5 2.5v-2.2L13.5 11V5a1.5 1.5 0 0 0-3 0v6L3 16.8V19l7.5-2.5z"/></svg>Airplane Mode</span><glass-switch name="air"></glass-switch></label>
</glass-surface>
Switch, react
import { useState } from "react";
import { GlassSwitch } from "glassy-liquid/react";
export function WifiSwitch() {
const [wifi, setWifi] = useState(true);
return <GlassSwitch checked={wifi} onCheckedChange={setWifi} aria-label="Wi-Fi" />;
}
Switch, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassSwitch } from "glassy-liquid/vue";
const wifi = ref(true);
</script>
<template>
<GlassSwitch v-model:checked="wifi" aria-label="Wi-Fi" />
</template>
Switch, svelte
<script>
import { GlassSwitch } from "glassy-liquid/svelte";
let wifi = $state(true);
</script>
<GlassSwitch bind:checked={wifi} aria-label="Wi-Fi" />
Switch events
input On every change made by the user.change Same moment. Read event.target.checked.
Slider
Slider, html
<glass-surface radius="28" style="width:min(320px,100%);padding:18px;display:flex;flex-direction:column;gap:22px">
<glass-slider value="62" aria-label="Brightness"></glass-slider>
<glass-slider value="50" step="25" ticks aria-label="Speed"></glass-slider>
</glass-surface>
Slider, react
import { useState } from "react";
import { GlassSlider } from "glassy-liquid/react";
export function Volume() {
const [volume, setVolume] = useState(62);
const [speed, setSpeed] = useState(50);
return (
<>
<GlassSlider value={volume} onValueChange={(value) => setVolume(Math.round(value))} aria-label="Volume" />
<p>{Math.round(volume)}</p>
<GlassSlider value={speed} step={25} ticks onValueCommit={(value) => setSpeed(Math.round(value))} aria-label="Speed" />
</>
);
}
Slider, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassSlider } from "glassy-liquid/vue";
const volume = ref(62);
const speed = ref(50);
function commit(value: number) {
speed.value = Math.round(value);
}
</script>
<template>
<GlassSlider v-model:value="volume" aria-label="Volume" />
<p>{{ Math.round(volume) }}</p>
<GlassSlider v-model:value="speed" :step="25" ticks aria-label="Speed" @value-commit="commit" />
</template>
Slider, svelte
<script>
import { GlassSlider } from "glassy-liquid/svelte";
let volume = $state(62);
let speed = $state(50);
function commit(value) {
speed = Math.round(value);
}
</script>
<GlassSlider bind:value={volume} aria-label="Volume" />
<p>{Math.round(volume)}</p>
<GlassSlider bind:value={speed} step={25} ticks aria-label="Speed" onValueCommit={commit} />
Slider events
input While dragging. React onValueChange. Vue @value-change or :onValueChange. Svelte onValueChange.change On release, or when a key commits. React onValueCommit. Vue @value-commit. Svelte onValueCommit.
Tab bar
Tab bar, html
<glass-tab-bar value="home" aria-label="Main" style="width:min(360px,100%)">
<glass-tab value="home"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M12 3.2l9 8.1h-2.6V20a1 1 0 0 1-1 1h-3.6v-6.2h-3.6V21H6.6a1 1 0 0 1-1-1v-8.7H3z"/></svg>Home</glass-tab>
<glass-tab value="library"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3.5" y="7" width="17" height="13" rx="3"/><path d="M6.5 4h11"/></svg>Library</glass-tab>
<glass-tab value="recent"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="8.6"/><path d="M12 7.5V12l3 2"/></svg>Recent</glass-tab>
<glass-tab value="profile"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="8" r="3.8"/><path d="M4.5 20.5c.9-3.7 3.9-5.8 7.5-5.8s6.6 2.1 7.5 5.8"/></svg>Profile</glass-tab>
</glass-tab-bar>
Tab bar, react
import { useState } from "react";
import { GlassTabBar, GlassTab } from "glassy-liquid/react";
export function MainTabs() {
const [tab, setTab] = useState("home");
return (
<GlassTabBar value={tab} onValueChange={setTab} aria-label="Main">
<GlassTab value="home">Home</GlassTab>
<GlassTab value="library">Library</GlassTab>
</GlassTabBar>
);
}
Tab bar, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassTabBar, GlassTab } from "glassy-liquid/vue";
const tab = ref("home");
</script>
<template>
<GlassTabBar v-model:value="tab" aria-label="Main">
<GlassTab value="home">Home</GlassTab>
<GlassTab value="library">Library</GlassTab>
</GlassTabBar>
</template>
Tab bar, svelte
<script>
import { GlassTabBar, GlassTab } from "glassy-liquid/svelte";
let tab = $state("home");
</script>
<GlassTabBar bind:value={tab} aria-label="Main">
<GlassTab value="home">Home</GlassTab>
<GlassTab value="library">Library</GlassTab>
</GlassTabBar>
Tab bar events
change detail: { value, index }
Segmented
Segmented, html
<glass-segmented value="week" aria-label="Range">
<glass-segment value="day">Day</glass-segment>
<glass-segment value="week">Week</glass-segment>
<glass-segment value="month">Month</glass-segment>
<glass-segment value="year">Year</glass-segment>
</glass-segmented>
Segmented, react
import { useState } from "react";
import { GlassSegmented, GlassSegment } from "glassy-liquid/react";
export function Range() {
const [range, setRange] = useState("week");
return (
<GlassSegmented value={range} onValueChange={setRange} aria-label="Range">
<GlassSegment value="day">Day</GlassSegment>
<GlassSegment value="week">Week</GlassSegment>
</GlassSegmented>
);
}
Segmented, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassSegmented, GlassSegment } from "glassy-liquid/vue";
const range = ref("week");
</script>
<template>
<GlassSegmented v-model:value="range" aria-label="Range">
<GlassSegment value="day">Day</GlassSegment>
<GlassSegment value="week">Week</GlassSegment>
</GlassSegmented>
</template>
Segmented, svelte
<script>
import { GlassSegmented, GlassSegment } from "glassy-liquid/svelte";
let range = $state("week");
</script>
<GlassSegmented bind:value={range} aria-label="Range">
<GlassSegment value="day">Day</GlassSegment>
<GlassSegment value="week">Week</GlassSegment>
</GlassSegmented>
Segmented events
change detail: { value, index }
Toolbar
Toolbar, html
<glass-toolbar style="width:min(360px,100%)">
<glass-button shape="circle" aria-label="Back"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg></glass-button>
<glass-spacer></glass-spacer>
<glass-group>
<glass-button variant="plain" shape="circle" aria-label="Share"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v12M8 7l4-4 4 4M5 12v7a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-7"/></svg></glass-button>
<glass-button variant="plain" shape="circle" aria-label="Favorite"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20.5s-7.5-4.6-9.6-9.2A5.3 5.3 0 0 1 12 6.2a5.3 5.3 0 0 1 9.6 5.1C19.5 15.9 12 20.5 12 20.5z"/></svg></glass-button>
</glass-group>
<glass-button shape="circle" aria-label="More"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="5" cy="12" r="2"/><circle cx="12" cy="12" r="2"/><circle cx="19" cy="12" r="2"/></svg></glass-button>
</glass-toolbar>
Toolbar, react
import { GlassToolbar, GlassGroup, GlassSpacer, GlassButton } from "glassy-liquid/react";
export function EditorBar() {
return (
<GlassToolbar>
<GlassButton shape="circle" aria-label="Back">Back</GlassButton>
<GlassSpacer />
<GlassGroup>
<GlassButton variant="plain" shape="circle" aria-label="Share">Share</GlassButton>
</GlassGroup>
</GlassToolbar>
);
}
Toolbar, vue
<script setup lang="ts">
import { GlassToolbar, GlassGroup, GlassSpacer, GlassButton } from "glassy-liquid/vue";
</script>
<template>
<GlassToolbar>
<GlassButton shape="circle" aria-label="Back">Back</GlassButton>
<GlassSpacer />
<GlassGroup>
<GlassButton variant="plain" shape="circle" aria-label="Share">Share</GlassButton>
</GlassGroup>
</GlassToolbar>
</template>
Toolbar, svelte
<script>
import { GlassToolbar, GlassGroup, GlassSpacer, GlassButton } from "glassy-liquid/svelte";
</script>
<GlassToolbar>
<GlassButton shape="circle" aria-label="Back">Back</GlassButton>
<GlassSpacer />
<GlassGroup>
<GlassButton variant="plain" shape="circle" aria-label="Share">Share</GlassButton>
</GlassGroup>
</GlassToolbar>
Search
Search, html
<div class="row" style="width:min(360px,100%)">
<glass-search placeholder="Search fruit" aria-label="Search fruit" style="flex:1"></glass-search>
<glass-button shape="circle" aria-label="Dictate"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3"/></svg></glass-button>
</div>
Search, react
import { useState } from "react";
import { GlassSearch } from "glassy-liquid/react";
export function FruitSearch() {
const [query, setQuery] = useState("");
return (
<GlassSearch
value={query}
onValueChange={setQuery}
onSearch={() => {}}
placeholder="Search fruit"
aria-label="Search fruit"
/>
);
}
Search, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassSearch } from "glassy-liquid/vue";
const query = ref("");
function submit(_value: string) {}
</script>
<template>
<GlassSearch v-model:value="query" placeholder="Search fruit" aria-label="Search fruit" @search="submit" />
</template>
Search, svelte
<script>
import { GlassSearch } from "glassy-liquid/svelte";
let query = $state("");
function submit(_value) {}
</script>
<GlassSearch bind:value={query} placeholder="Search fruit" aria-label="Search fruit" onSearch={submit} />
Search events
input, change As a native input.search detail: { value }, fired on Enter.
Sheet
Sheet, html
<glass-button variant="prominent" id="open-demo-sheet">Show sheet</glass-button>
<glass-sheet id="demo-sheet" detents="medium large" aria-label="Trip details">
<h3>Mountain lake</h3>
<p>Drag the grabber to resize. Flick down to close.</p>
</glass-sheet>
<script>
document.getElementById("open-demo-sheet").addEventListener("click", () => {
document.getElementById("demo-sheet").open = true;
});
</script>
Sheet, react
import { useState } from "react";
import { GlassSheet, GlassButton } from "glassy-liquid/react";
export function TripSheet() {
const [open, setOpen] = useState(false);
return (
<>
<GlassButton variant="prominent" onClick={() => setOpen(true)}>Show sheet</GlassButton>
<GlassSheet open={open} onOpenChange={setOpen} detents="medium large" aria-label="Trip details">
<h3>Mountain lake</h3>
</GlassSheet>
</>
);
}
Sheet, vue
<script setup lang="ts">
import { ref } from "vue";
import { GlassSheet, GlassButton } from "glassy-liquid/vue";
const open = ref(false);
</script>
<template>
<GlassButton variant="prominent" @click="open = true">Show sheet</GlassButton>
<GlassSheet v-model:open="open" detents="medium large" aria-label="Trip details">
<h3>Mountain lake</h3>
</GlassSheet>
</template>
Sheet, svelte
<script>
import { GlassSheet, GlassButton } from "glassy-liquid/svelte";
let open = $state(false);
</script>
<GlassButton variant="prominent" onclick={() => (open = true)}>Show sheet</GlassButton>
<GlassSheet bind:open={open} detents="medium large" aria-label="Trip details">
<h3>Mountain lake</h3>
</GlassSheet>
Sheet events
toggle detail: { open }detent detail: { index, height }
Scroll edge
Scroll edge, html
<div style="position:relative;width:min(340px,100%);height:280px;border-radius:26px;overflow:hidden">
<div style="height:100%;overflow:auto;padding:76px 14px 14px;display:grid;gap:10px">
<glass-surface radius="18" style="padding:14px 16px">Clear, 14°</glass-surface>
<glass-surface radius="18" style="padding:14px 16px">Bright, 12°</glass-surface>
<glass-surface radius="18" style="padding:14px 16px">High cloud, 9°</glass-surface>
<glass-surface radius="18" style="padding:14px 16px">Still, 11°</glass-surface>
<glass-surface radius="18" style="padding:14px 16px">Cold, 8°</glass-surface>
</div>
<glass-progressive-blur edge="top" size="92"></glass-progressive-blur>
<glass-toolbar style="position:absolute;top:12px;left:12px;right:12px">
<glass-button size="small">Today</glass-button>
<glass-spacer></glass-spacer>
<glass-button size="small" shape="circle" aria-label="Add"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></glass-button>
</glass-toolbar>
</div>
Scroll edge, react
import { GlassProgressiveBlur, GlassToolbar, GlassButton, GlassSurface } from "glassy-liquid/react";
export function ScrollEdge() {
return (
<div style={{ position: "relative", width: 340, height: 280, borderRadius: 26, overflow: "hidden" }}>
<div style={{ height: "100%", overflow: "auto", padding: "76px 14px 14px", display: "grid", gap: 10 }}>
<GlassSurface radius={18} style={{ padding: "14px 16px" }}>Clear, 14°</GlassSurface>
<GlassSurface radius={18} style={{ padding: "14px 16px" }}>Bright, 12°</GlassSurface>
<GlassSurface radius={18} style={{ padding: "14px 16px" }}>Still, 11°</GlassSurface>
</div>
<GlassProgressiveBlur edge="top" size={92} />
<GlassToolbar style={{ position: "absolute", top: 12, left: 12, right: 12 }}>
<GlassButton size="small">Today</GlassButton>
</GlassToolbar>
</div>
);
}
Scroll edge, vue
<script setup lang="ts">
import { GlassProgressiveBlur, GlassToolbar, GlassButton, GlassSurface } from "glassy-liquid/vue";
</script>
<template>
<div style="position: relative; width: 340px; height: 280px; border-radius: 26px; overflow: hidden">
<div style="height: 100%; overflow: auto; padding: 76px 14px 14px; display: grid; gap: 10px">
<GlassSurface :radius="18" style="padding: 14px 16px">Clear, 14°</GlassSurface>
<GlassSurface :radius="18" style="padding: 14px 16px">Bright, 12°</GlassSurface>
<GlassSurface :radius="18" style="padding: 14px 16px">Still, 11°</GlassSurface>
</div>
<GlassProgressiveBlur edge="top" :size="92" />
<GlassToolbar style="position: absolute; top: 12px; left: 12px; right: 12px">
<GlassButton size="small">Today</GlassButton>
</GlassToolbar>
</div>
</template>
Scroll edge, svelte
<script>
import { GlassProgressiveBlur, GlassToolbar, GlassButton, GlassSurface } from "glassy-liquid/svelte";
</script>
<div style="position: relative; width: 340px; height: 280px; border-radius: 26px; overflow: hidden">
<div style="height: 100%; overflow: auto; padding: 76px 14px 14px; display: grid; gap: 10px">
<GlassSurface radius={18} style="padding: 14px 16px">Clear, 14°</GlassSurface>
<GlassSurface radius={18} style="padding: 14px 16px">Bright, 12°</GlassSurface>
<GlassSurface radius={18} style="padding: 14px 16px">Still, 11°</GlassSurface>
</div>
<GlassProgressiveBlur edge="top" size={92} />
<GlassToolbar style="position: absolute; top: 12px; left: 12px; right: 12px">
<GlassButton size="small">Today</GlassButton>
</GlassToolbar>
</div>