-
Notifications
You must be signed in to change notification settings - Fork 9
Component Popover
MeowLynxSea edited this page Jan 24, 2026
·
6 revisions
Popover 是一个点击触发的浮层容器,用来承载菜单/小面板,并且锚定在触发器(trigger)下方。
它的实现模型是:
-
Popover本体是一个.relative()容器。 - 菜单/面板是一个
.absolute()子元素,通过gpui::deferred(...)以较高优先级绘制在上层。
- 头像菜单、更多操作菜单
- 轻量设置面板(如“排序 / 视图 / 过滤”)
- 承载
DropdownMenu(DropdownMenu 是基于 Popover 的封装)
不适合:
- 需要全屏遮罩、焦点锁定、Esc 关闭等“对话框行为”的场景(这通常属于 app/widget 层)。
-
popover():构造器(默认会用 caller location 生成 id) -
id(...) / key(...):稳定 identity(建议在可重复渲染/列表中使用key(...)) -
open(bool):由调用方控制是否展开 -
placement(PopoverPlacement):-
BottomStart:触发器左下对齐 -
BottomEnd:触发器右下对齐
-
-
width(px(...)):固定宽度(未设置时由内容自然决定) -
bg(...) / border(...):覆盖默认 theme 色 -
trigger(...):触发器元素(按钮/图标/任意元素) -
content(...):浮层内容 -
on_close(|window, cx| ...):点击浮层外部自动触发(用于把open置为false)
- Popover 不“自带打开逻辑”:点击触发器如何切换
open完全由调用方决定。 - 点击浮层外部会触发
on_close(如果你没有提供on_close,Popover 不会自动关闭)。 - Popover 的关闭逻辑通常需要
window.refresh()(因为use_keyed_state更新后需要刷新帧)。
use gpui::{ElementId, px};
use yororen_ui::component::{button, label, popover, PopoverPlacement};
// In a view render:
let open = window.use_keyed_state(("demo", "popover-open"), cx, |_, _| false);
let is_open = *open.read(cx);
let view = popover()
.id(ElementId::from(("demo", "popover")))
.open(is_open)
.placement(PopoverPlacement::BottomStart)
.width(px(260.))
.on_close({
let open = open.clone();
move |window, cx| {
open.update(cx, |v, _| *v = false);
window.refresh();
}
})
.trigger(
button().child("Open").on_click({
let open = open.clone();
move |_ev, window, cx| {
open.update(cx, |v, _| *v = !*v);
window.refresh();
}
}),
)
.content(label("Popover content"));use yororen_ui::component::{button, popover, PopoverPlacement};
let view = popover()
.open(true)
.placement(PopoverPlacement::BottomEnd)
.trigger(button().child("⋯"))
.content("Right aligned popover");Yororen UI v0.3.0 · repository · Apache-2.0 · This wiki documents Yororen UI v0.3.0.
This wiki documents Yororen UI v0.3.0 — the headless-core, swappable-renderer build.