fix: repair resource tab and slash menu regressions

This commit is contained in:
lix-2026
2026-05-20 17:47:09 +08:00
parent bbd9dab701
commit 4c62ea7e35
8 changed files with 404 additions and 17 deletions
+67 -5
View File
@@ -1899,12 +1899,12 @@ const SPIKE_STYLE: &str = r#"
}
.slash-menu {
position: absolute;
position: fixed;
top: 24px;
left: 24px;
z-index: 11;
width: min(316px, calc(100% - 48px));
max-height: min(430px, calc(100vh - 180px));
z-index: 130;
width: min(316px, calc(100vw - 16px));
max-height: min(430px, calc(100vh - 16px));
display: grid;
gap: 0;
padding: 8px;
@@ -3381,6 +3381,14 @@ mod tests {
Some(5)
);
}
#[test]
fn slash_menu_css_uses_viewport_overlay_layer() {
assert!(STYLE.contains(".slash-menu"));
assert!(STYLE.contains("position: fixed;"));
assert!(STYLE.contains("z-index: 130;"));
assert!(!STYLE.contains("z-index: 11;"));
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -5480,6 +5488,56 @@ fn floating_toolbar_anchor_from_selection() -> Option<FloatingToolbarAnchor> {
})
}
fn slash_menu_anchor_style() -> String {
const MENU_WIDTH: f64 = 316.0;
const MENU_HEIGHT: f64 = 430.0;
const GAP: f64 = 8.0;
let viewport_width = window()
.and_then(|win| win.inner_width().ok())
.and_then(|value| value.as_f64())
.unwrap_or(1024.0)
.max(320.0);
let viewport_height = window()
.and_then(|win| win.inner_height().ok())
.and_then(|value| value.as_f64())
.unwrap_or(768.0)
.max(240.0);
let selection_rect = window()
.and_then(|win| win.get_selection().ok().flatten())
.and_then(|selection| selection.get_range_at(0).ok())
.map(|range| range.get_bounding_client_rect())
.filter(|rect| rect.top() > 0.0 || rect.left() > 0.0 || rect.height() > 0.0);
let (raw_top, raw_left, raw_anchor_top) = if let Some(rect) = selection_rect {
(rect.bottom() + GAP, rect.left(), rect.top())
} else if let Some(block) = hovered_block_from_selection() {
if let Some(stage) = editor_stage_element() {
let stage_rect = stage.get_bounding_client_rect();
(
stage_rect.top() + block.top + block.height + GAP,
stage_rect.left() + content_text_left(stage_rect.width()),
stage_rect.top() + block.top,
)
} else {
(24.0, 24.0, 24.0)
}
} else {
(24.0, 24.0, 24.0)
};
let clamped_left = raw_left.clamp(GAP, (viewport_width - MENU_WIDTH - GAP).max(GAP));
let below_limit = viewport_height - GAP;
let clamped_top = if raw_top + MENU_HEIGHT > below_limit {
(raw_anchor_top - MENU_HEIGHT - GAP).clamp(GAP, below_limit - 120.0)
} else {
raw_top.clamp(GAP, below_limit - 120.0)
};
format!("top:{clamped_top:.1}px;left:{clamped_left:.1}px;")
}
fn image_toolbar_anchor_from_image(image: &Element) -> Option<ImageToolbarAnchor> {
let stage = editor_stage_element()?;
let rect = image.get_bounding_client_rect();
@@ -10762,7 +10820,11 @@ fn App(mount_options: MountOptions) -> impl IntoView {
{move || {
if slash_open.get() {
view! {
<div class="slash-menu" data-testid="mnote-leptos-tiptap-slash-menu">
<div
class="slash-menu"
data-testid="mnote-leptos-tiptap-slash-menu"
style=slash_menu_anchor_style()
>
<div class="slash-list">
{move || {
let query = slash_query.get().trim().to_ascii_lowercase();