Blocks
Copy for LLM
NowPlaying
A media now-playing card: album art, title + artist, a scrub bar, and elapsed / remaining times. A status display for playback your app tracks. Audio support in the Display webview is undocumented; verify on-device.
Installation
npx @glasskit-ui/cli add now-playingInstall the SDK (it provides GlassViewport, useDpad and the stylesheet), then copy these files into your project:
npm install @glasskit-ui/react// components/lib/utils.tsimport { clsx, type ClassValue } from "clsx";import { twMerge } from "tailwind-merge";export type { ClassValue };/** * Merge class names the shadcn way: clsx joins conditionals, tailwind-merge * de-dupes conflicting Tailwind utilities so a consumer's `className` override * wins (e.g. passing `px-2` beats the component's `px-6`). Lens components are * Tailwind utilities + `--gk-*` tokens, so this de-dupe matters. */export function cn(...inputs: ClassValue[]): string { return twMerge(clsx(inputs));}/** * Accessible name from a free-form `label` prop: the label itself when it's a * plain string, otherwise undefined (a ReactNode can't become an aria-label). */export function stringLabel(label: unknown): string | undefined { return typeof label === "string" ? label : undefined;}// components/glasskit/now-playing.tsximport type { ReactNode } from "react";import { cn } from "../lib/utils";/** * <NowPlaying> — a media "now playing" card: album art, title + artist, a * scrub bar, and elapsed / remaining times. The art is a node you pass (an * <img>, or a gradient tile for podcasts/radio). `progress` is 0–100. Pure * display; wire transport controls with <Button>s in `controls`. RTL-safe. * * Platform note (2026-06): Meta has not documented `<audio>` / Web Audio * support for Display web apps, and the glasses' own media player owns the * speakers. Treat this as a status display for playback your app tracks * (e.g. a server-side or phone session) — verify on-device before shipping * an app that plays audio in the webview. */export function NowPlaying({ art, title, artist, progress = 0, elapsed, remaining, controls, className,}: { /** Album art — an <img> or a gradient tile. */ art?: ReactNode; title: ReactNode; artist?: ReactNode; /** 0–100. */ progress?: number; elapsed?: ReactNode; remaining?: ReactNode; /** Optional transport row. */ controls?: ReactNode; className?: string;}) { const pct = Math.max(0, Math.min(progress, 100)); return ( <div className={cn("flex w-full flex-col gap-4", className)}> <div className="flex items-center gap-4"> {art != null ? ( <span className="block size-[92px] shrink-0 overflow-hidden rounded-lens [box-shadow:inset_0_1px_0_rgba(255,255,255,0.25),0_10px_24px_-10px_rgba(0,0,0,0.7)] [&>span]:block [&>span]:size-full [&>span]:object-cover [&_img]:block [&_img]:size-full [&_img]:object-cover"> {art} </span> ) : null} <div className="flex min-w-0 flex-col gap-1 text-start"> <span className="t-readout font-bold text-foreground">{title}</span> {artist != null ? ( <span className="t-body text-muted-foreground">{artist}</span> ) : null} </div> </div> <progress className="gk-progress__el" value={pct} max={100} aria-label="Playback position" /> {elapsed != null || remaining != null ? ( <div className="t-caption flex justify-between text-foreground-faint [font-variant-numeric:tabular-nums]"> <span>{elapsed}</span> <span>{remaining}</span> </div> ) : null} {controls != null ? ( <div className="flex justify-center gap-3.5">{controls}</div> ) : null} </div> );}Usage
<NowPlaying art={<img src={cover} alt="" />} title="Midnight City" artist="M83" progress={42} elapsed="1:48" remaining="-2:31"/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
art | ReactNode | — | Album art: an <img> or a gradient tile. |
title / artist | ReactNode | — | Track + artist. |
progress | number | 0 | 0–100 scrub position. |
elapsed / remaining | ReactNode | — | Time labels. |
controls | ReactNode | — | Optional transport row. |
MediaThumb
A photo / reel tile (Photos, Instagram): a rounded media tile with optional duration pill and caption overlay. Compose in a grid for a gallery.
AssistantOrb
The Meta-AI presence: a glowing gradient orb that animates per state: idle breathe, listening pulse, thinking swirl, speaking. Pair with a transcript line.