Skip to content

Glass control center

A smart-home control center in the frosted-glass style of modern operating systems. The colored blobs behind the cards are a shader graph (shaders/blobs.pzshad), so the blur you see through each card moves with them.

Glass control center

Windows, macOS and Linux
uv run --with pyzed-ui python examples/showcase/glass_dashboard.py

glass blurs what is behind the card, not a fake gradient.

GLASS = {"tint": "#ffffff", "strength": 0.10, "blur": 28}
card.style(glass=GLASS, radius=22, padding=20)

The album cover spins while music plays; lit bulbs bloom.

cover.animate("spin", duration=12000)

Sliders and switches update the state like in any Pyzed app.

pz.slider(0, 100, self.volume, on_change=self.set_volume)
  • Change the tint and strength in GLASS and see how much of the background shows through.
  • Turn every light on and watch the bloom.
  • Swap the blobs for another graph from Shaders and effects, such as nebula.pzshad.
examples/showcase/glass_dashboard.py
"""A frosted-glass control center: music, lights, climate and a schedule over moving color.
python examples/showcase/glass_dashboard.py
- The background is a shader graph of soft color blobs that drift with time
(``shaders/blobs.pzshad``, made of nodes in Pyzed Design).
- Every card is ``glass``: a tinted panel that blurs what moves behind it (``backdrop_blur``).
- Switches, sliders and the play button update the cards; values move with ``transition``.
"""
from pathlib import Path
import pyzed as pz
SHADER = Path(__file__).parent / "shaders" / "blobs.pzshad"
from pyzed import ui
GLASS = {"tint": "#ffffff", "strength": 0.10, "blur": 28}
WHITE = "#ffffff"
MUTED = "#ffffffaa"
class Dashboard(pz.App):
title = "Control center"
size = (1180, 700)
theme = pz.themes.ONE_DARK
def __init__(self):
self.playing = True
self.volume = 64.0
self.lights = {"Living room": True, "Kitchen": False, "Studio": True}
self.brightness = 72.0
self.temperature = 21.5
def toggle_play(self):
self.playing = not self.playing
def set_volume(self, value):
self.volume = value
def toggle_light(self, name):
self.lights[name] = not self.lights[name]
def set_brightness(self, value):
self.brightness = value
def warmer(self):
self.temperature = min(28.0, self.temperature + 0.5)
def cooler(self):
self.temperature = max(16.0, self.temperature - 0.5)
def card(self, title, icon, body, width):
head = pz.row([pz.icon(icon, size=16, color=WHITE), pz.text(title, size=13, weight="semibold", color=WHITE)],
spacing=8, align="center")
return pz.column([head, body], spacing=14).style(glass=GLASS, radius=22, padding=20, width=width)
def music(self):
cover = pz.container(pz.icon("disc-3", size=44, color="#ffffffdd"), width=112, height=112,
align_x="center", align_y="center").style(
background=pz.Gradient(["#f472b6", "#8b5cf6", "#22d3ee"], angle=135), radius=18,
rotate=0, bloom=("#c084fc", 0.4))
if self.playing:
cover = cover.animate("spin", duration=12000)
controls = pz.row([
pz.icon("skip-back", size=20, color=WHITE),
pz.mouse_area(pz.container(pz.icon("pause" if self.playing else "play", size=22, color="#111827"),
width=48, height=48, align_x="center", align_y="center").style(
background=WHITE, radius=24, glow=("#ffffff88", 14)), on_press=self.toggle_play).animate(
"shrink", on="press"),
pz.icon("skip-forward", size=20, color=WHITE),
], spacing=22, align="center")
info = pz.column([
pz.text("Midnight City", size=20, weight="bold", color=WHITE),
pz.text("Neon Avenue · Afterglow", size=13, color=MUTED),
pz.container(pz.container(None, height=4).style(background=WHITE, radius=2).transition(
width=230 * (0.42 if self.playing else 0.41), duration=400), width=230).style(
background="#ffffff33", radius=2),
pz.row([pz.text("1:48", size=11, color=MUTED), pz.space(width="fill"),
pz.text("4:16", size=11, color=MUTED)], width=230),
controls,
], spacing=8)
volume = pz.row([
pz.icon("volume-1", size=16, color=MUTED),
pz.slider(0, 100, self.volume, on_change=self.set_volume, width="fill", accent=WHITE,
bg="#ffffff33"),
pz.icon("volume-2", size=16, color=MUTED),
], spacing=10, align="center")
return self.card("Now playing", "music", pz.column([pz.row([cover, info], spacing=20, align="center"),
volume], spacing=16), 440)
def lights_card(self):
rows = []
for name, on in self.lights.items():
rows.append(pz.row([
pz.container(pz.icon("lightbulb", size=16, color="#1f2937" if on else MUTED), width=34,
height=34, align_x="center", align_y="center").style(
background="#fde68a" if on else "#ffffff1a", radius=17,
bloom=("#fbbf24", 0.6) if on else None),
pz.column([pz.text(name, size=14, weight="semibold", color=WHITE),
pz.text(f"{round(self.brightness)}%" if on else "Off", size=11, color=MUTED)],
spacing=1, width="fill"),
ui.switch(on, lambda _v, name=name: self.toggle_light(name)),
], spacing=12, align="center"))
rows.append(pz.slider(0, 100, self.brightness, on_change=self.set_brightness, width="fill",
accent="#fde68a", bg="#ffffff33"))
return self.card("Lights", "sun", pz.column(rows, spacing=12), 330)
def climate(self):
ring = pz.column([
pz.text(f"{self.temperature:.1f}°", size=44, weight="bold", color=WHITE).transition(
scale=1.0, duration=200),
pz.text("Heating to 22°", size=12, color=MUTED),
], spacing=0, align="center")
buttons = pz.row([
pz.mouse_area(pz.container(pz.icon("minus", size=18, color=WHITE), width=44, height=44,
align_x="center", align_y="center").style(
background="#ffffff1f", radius=22), on_press=self.cooler).animate("shrink", on="press"),
pz.mouse_area(pz.container(pz.icon("plus", size=18, color=WHITE), width=44, height=44,
align_x="center", align_y="center").style(
background="#ffffff1f", radius=22), on_press=self.warmer).animate("shrink", on="press"),
], spacing=16)
dial = pz.container(ring, width=170, height=170, align_x="center", align_y="center").style(
radius=85, border=(6, "#fb923c"), bloom=("#fb923c", 0.5), background="#ffffff0d")
return self.card("Climate", "thermometer", pz.column([dial, buttons], spacing=14, align="center", width="fill"), 330)
def schedule(self):
events = (
("09:30", "Design review", "#22d3ee"),
("12:00", "Lunch with Sam", "#a3e635"),
("15:00", "Ship 1.2", "#f472b6"),
("18:30", "Climbing", "#fbbf24"),
)
rows = [pz.row([
pz.text(time, size=12, color=MUTED, font="mono", width=48),
pz.container(None, width=4, height=28).style(background=color, radius=2, bloom=(color, 0.6)),
pz.text(title, size=14, color=WHITE),
], spacing=12, align="center") for time, title, color in events]
return self.card("Today", "calendar", pz.column(rows, spacing=10), 440)
def header(self):
return pz.row([
pz.column([pz.text("Good evening, Kim", size=28, weight="bold", color=WHITE),
pz.text("Saturday · 3 rooms on · 21.5° inside", size=14, color=MUTED)], spacing=2),
pz.space(width="fill"),
pz.row([pz.icon("search", size=16, color=MUTED), pz.text("Search devices", size=13, color=MUTED)],
spacing=8, align="center").style(glass=GLASS, radius=20, padding=(10, 16), width=240),
], align="center", width=1124)
def view(self):
grid = pz.row([
pz.column([self.music(), self.schedule()], spacing=20),
self.lights_card(),
self.climate(),
], spacing=20, align="start")
content = pz.column([self.header(), pz.row(pz.stagger([grid], "fade_in_up", step=60))], spacing=24)
return pz.stack([
pz.shader(SHADER, width="fill", height="fill",
fallback=pz.Gradient(["#0b1026", "#5b1a4a", "#0f4c5c"], angle=135)),
pz.container(content, width="fill", height="fill", align_x="center", align_y="center"),
])
if __name__ == "__main__":
pz.run(Dashboard)