use gpui::{
App, Bounds, Context, Render, Window, WindowBounds, WindowOptions, deferred, div, point,
prelude::*, px, rgb, rgba, size,
};
struct BlurExample;
fn busy_background() -> impl IntoElement {
let palette = [
0xef4444, 0xf97316, 0xeab308, 0x22c55e, 0x06b6d4, 0x3b82f6, 0x8b5cf6, 0xec4899,
];
let mut next = 0usize;
div()
.absolute()
.inset_0()
.flex()
.flex_col()
.children((0..9).map(|_| {
div().flex().flex_1().children(
(0..8)
.map(|_| {
let hex = palette[next % palette.len()];
next += 1;
div()
.flex_1()
.h_full()
.bg(rgb(hex))
.flex()
.items_center()
.justify_center()
.text_color(rgb(0xffffff))
.text_xl()
.child("◆")
})
.collect::<Vec<_>>(),
)
}))
}
fn frosted_panel() -> impl IntoElement {
div()
.absolute()
.left(px(60.))
.top(px(120.))
.w(px(360.))
.h(px(200.))
.rounded_xl()
.bg(rgba(0xffffff30))
.backdrop_blur(px(24.))
.border_1()
.border_color(rgba(0xffffff60))
.flex()
.items_center()
.justify_center()
.text_color(rgb(0x111111))
.text_2xl()
.child("backdrop_blur(24px)")
}
fn deferred_popover() -> impl IntoElement {
deferred(
div()
.absolute()
.left(px(260.))
.top(px(260.))
.w(px(300.))
.h(px(150.))
.rounded_lg()
.bg(rgba(0x1e293b66))
.backdrop_blur(px(12.))
.border_1()
.border_color(rgba(0xffffffaa))
.flex()
.items_center()
.justify_center()
.text_color(rgb(0xffffff))
.text_xl()
.child("deferred + backdrop_blur"),
)
}
fn content_blurred() -> impl IntoElement {
div()
.absolute()
.left(px(120.))
.top(px(420.))
.w(px(280.))
.h(px(120.))
.blur(px(5.))
.bg(rgb(0x0f172a))
.rounded_lg()
.flex()
.items_center()
.justify_center()
.text_color(rgb(0xfacc15))
.text_3xl()
.child("blur(5px) content")
}
fn content_blurred_rich() -> impl IntoElement {
div()
.absolute()
.left(px(120.))
.top(px(580.))
.w(px(280.))
.h(px(120.))
.blur(px(6.))
.bg(rgb(0x1e293b))
.rounded_lg()
.flex()
.items_center()
.justify_center()
.gap_3()
.children(
[0xef4444, 0x22c55e, 0x3b82f6]
.into_iter()
.map(|hex| div().w(px(48.)).h(px(48.)).rounded_md().bg(rgb(hex))),
)
}
fn nested_content_blurred() -> impl IntoElement {
div()
.absolute()
.left(px(740.))
.top(px(80.))
.w(px(290.))
.h(px(220.))
.blur(px(3.))
.bg(rgb(0x1e293b))
.rounded_xl()
.flex()
.flex_col()
.items_center()
.justify_center()
.gap_4()
.text_color(rgb(0xe2e8f0))
.text_xl()
.child("outer blur(3px)")
.child(
div()
.w(px(190.))
.h(px(100.))
.blur(px(8.))
.bg(rgb(0xf59e0b))
.rounded_lg()
.flex()
.items_center()
.justify_center()
.text_color(rgb(0x111111))
.text_2xl()
.child("inner blur(8px)"),
)
}
const SEAM_COLORS: [u32; 4] = [0xef4444, 0x22c55e, 0x3b82f6, 0xeab308];
fn seam_block(i: usize, hex: u32, blur_each: bool) -> impl IntoElement {
let block = div().flex_1().h_full();
let block = if blur_each { block.blur(px(5.)) } else { block };
block
.bg(rgb(hex))
.flex()
.items_center()
.justify_center()
.text_color(rgb(0xffffff))
.text_2xl()
.child(format!("{}", i + 1))
}
fn adjacent_per_block_blur() -> impl IntoElement {
div()
.absolute()
.left(px(740.))
.top(px(350.))
.w(px(290.))
.h(px(110.))
.bg(rgb(0x050505))
.flex()
.children(
SEAM_COLORS
.into_iter()
.enumerate()
.map(|(i, hex)| seam_block(i, hex, true)),
)
}
fn adjacent_group_blur() -> impl IntoElement {
div()
.absolute()
.left(px(740.))
.top(px(510.))
.w(px(290.))
.h(px(110.))
.bg(rgb(0x050505))
.blur(px(5.))
.flex()
.children(
SEAM_COLORS
.into_iter()
.enumerate()
.map(|(i, hex)| seam_block(i, hex, false)),
)
}
fn caption(text: &'static str, left: f32, top: f32) -> impl IntoElement {
div()
.absolute()
.left(px(left))
.top(px(top))
.px_2()
.py_1()
.rounded_md()
.bg(rgba(0x000000cc))
.text_color(rgb(0xffffff))
.text_sm()
.child(text)
}
impl Render for BlurExample {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div()
.relative()
.size_full()
.bg(rgb(0x000000))
.child(busy_background())
.child(frosted_panel())
.child(content_blurred())
.child(content_blurred_rich())
.child(nested_content_blurred())
.child(adjacent_per_block_blur())
.child(adjacent_group_blur())
.child(caption("nested content blur", 740., 50.))
.child(caption(
"adjacent — blur each block (seams, = CSS)",
740.,
322.,
))
.child(caption(
"adjacent — blur the parent (one group, clean)",
740.,
482.,
))
.child(deferred_popover())
}
}
fn main() {
gpui_ce_platform::application().run(|cx: &mut App| {
cx.activate(true);
cx.on_window_closed(|cx, _| {
if cx.windows().is_empty() {
cx.quit();
}
})
.detach();
let bounds = Bounds {
origin: point(px(100.), px(100.)),
size: size(px(1060.), px(760.)),
};
cx.open_window(
WindowOptions {
window_bounds: Some(WindowBounds::Windowed(bounds)),
..Default::default()
},
|_, cx| cx.new(|_| BlurExample),
)
.expect("failed to open window");
});
}