GlassIslands
ui.widgets.GlassBoxPlusieurs îlots de verre sur un même arrière-plan.
BEHAVIOR CONTRACT
Chaque échantillonnage de l'arrière-plan est indépendant : les calques ne déteignent pas les uns sur les autres.
RECORDED INTERACTION
Parcourt les îlots et le contenu en dessous.
// 回归目标:一个节点同时挂 ext.glass(backdrop_blur) 与 overflow_hidden +
// corner_radius(effect 链 backdrop_blur → rounded_clip,两个 requires_offscreen)
// 时,同帧存在两个这样的节点 → 后画节点的内容整体不可见(内容命令没落进
// 自己的 layer 作用域,玻璃背板合成盖在其上)。下游应用 Sidebar+Inspector 实拍。
pub fn buildGlassIslands(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
_ = scope;
const a = cx.allocator;
const c = try col(cx, 12);
try c.appendChild(a, try label(cx, "Two blur+rounded-clip islands — BOTH must show their content"));
const bd = try glassBackdrop(cx, 420);
// 高频黑白条纹靶压在 first 岛左边缘正下方(islands_row padding 24 → 岛左缘
// x=24):gi=0 承诺"仅 blur",blur(24) 把 8px 周期条纹平均成灰;rim 区若仍
// sharp 回退(glass.metal rim_sharp 漏 gi 门控的回归),岛左缘 8px 带会清晰
// 透出近黑条纹——e2e 按 rim/参照带 darkest pixel 差分断言。单条宽黑条不行:
// 黑条自身 blur 后也偏暗,sharp/blur 只差 ~25 灰阶,抓不住变异。
const rim_probe = try ui.box(cx, .{
.position = .absolute,
.width = .{ .px = 32 },
.height = .{ .grow = .{} },
.direction = .row,
.background = ui.Color.rgba(250, 250, 252, 255),
.gap = 4,
}, .{});
(try rim_probe.style.ensureExtFallible(a)).inset = .{ .left = .{ .px = 10 }, .top = .{ .px = 0 } };
for (0..4) |_| {
try rim_probe.appendChild(a, try ui.box(cx, .{
.width = .{ .px = 4 },
.height = .{ .grow = .{} },
.background = ui.Color.rgba(4, 4, 6, 255),
}, .{}));
}
try bd.appendChild(a, rim_probe);
const islands_row = try ui.box(cx, .{
.position = .absolute,
.width = .{ .grow = .{} },
.height = .{ .grow = .{} },
.direction = .row,
.justify = .space_between,
.padding = ui.Padding.all(24),
}, .{});
inline for (.{ "first", "second" }) |name| {
const island = try ui.box(cx, .{
.width = .{ .px = 220 },
.height = .{ .px = 320 },
.direction = .column,
.gap = 10,
.padding = ui.Padding.all(16),
// alpha 40:底色再低一档,rim-band 像素断言需要黑条 sharp/blur 的
// 对比窗口(96 时 37% 白把 sharp 黑抬到 ~160、blur ~190,抓不住回归)
.background = ui.Color.rgba(255, 255, 255, 40),
.border = .{ .width = 1, .color = ui.Color.rgba(255, 255, 255, 140), .radius = 12 },
.overflow_hidden = true,
}, .{});
const ext = try island.style.ensureExtFallible(a);
ext.corner_radius = ui.CornerRadius.uniform(12);
ext.glass = .{ .backdrop_blur = 24, .glass_intensity = 0 };
island.meta.ownership.meta.test_id = "story.glassislands." ++ name;
try island.appendChild(a, try ui.text(cx, "Island " ++ name, .{
.font_size = 15,
.font_weight = 700,
.color = ui.Color.rgba(20, 20, 28, 255),
}));
// 深色内容块:e2e 像素断言的靶(内容丢失 bug 下这里只剩白玻璃底)
const slab = try ui.box(cx, .{
.width = .{ .grow = .{} },
.height = .{ .px = 120 },
.background = ui.Color.rgba(24, 28, 40, 255),
}, .{});
(try slab.style.ensureExtFallible(a)).corner_radius = ui.CornerRadius.uniform(8);
slab.meta.ownership.meta.test_id = "story.glassislands." ++ name ++ ".slab";
try island.appendChild(a, slab);
try island.appendChild(a, try ui.text(cx, "content below the slab", .{
.font_size = 12,
.color = ui.Color.rgba(40, 44, 56, 255),
}));
try islands_row.appendChild(a, island);
}
try bd.appendChild(a, islands_row);
try c.appendChild(a, bd);
return c;
}Le code source tel quel de la story dans le Storybook (zenit 5f9add5+wip 2026-09-30). W désigne ui.widgets ; col / row / label sont de petits helpers de mise en page du Storybook.
GlassBoxProps
ui.widgets.GlassBoxfn GlassBox(props: GlassBoxProps) GlassBoxBuilderChamp
Type
Défaut
Description
title?[]const u8null—
subtitle?[]const u8null—
width?f32null—
height?f32null—
padding?Paddingnull—
body_gapf3212—
radiusf3218—
readabilityGlassBoxReadability.balanced.preferred.maximum.preferred—
emphasisGlassBoxEmphasis.subtle.regular.prominent.regular—
variantGlassBoxVariant.regular.clear.regular—
tint?Colornull—
interactiveboolfalseApple Liquid Glass interactive:hover 提亮高光、press 玻璃增厚 + 微放大。
scroll_edge?ScrollEdgeBindingnullscroll-edge effect:绑定 ScrollArea 后,内容滚过玻璃边缘时出现渐进 模糊/压暗带(随滚动位置实时驱动 + 插值平滑)。
*Node
ui.widgets.GlassBoxmount renvoie directement *Node : ajoutez-le à un parent.