fix(#2124): stop the conversation-outline button colliding with the scroll control
The outline FAB was position:fixed at z-index 9999 and could stack on top of the scroll-to-bottom button. Anchor it inside the messages shell (position:absolute, z-index 12) so the two controls don't overlap. Co-authored-by: Mohamed Habib <Habib1001-m@users.noreply.github.com>
This commit is contained in:
1 parent
d5f9e98252
commit
4ac9684223
4 files changed
+45
-7
No files matched your search
@@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [v0.51.489] — 2026-06-18 — Release QY (outline button no longer collides with the scroll control)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **The conversation-outline toggle button no longer overlaps the scroll-to-bottom control (#2124).** The outline FAB was `position:fixed` at a high z-index and could stack on top of the scroll-to-bottom button in the bottom-right corner. It's now anchored inside the messages shell (`position:absolute`, lower z-index) so the two controls sit cleanly without colliding. Thanks @Habib1001-m.
|
||||||
|
|
||||||
## [v0.51.488] — 2026-06-18 — Release QW (rescue state.db user prompts that fall before a newer sidecar tail)
|
## [v0.51.488] — 2026-06-18 — Release QW (rescue state.db user prompts that fall before a newer sidecar tail)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
+5
-6
@@ -411,6 +411,11 @@
|
|||||||
<div class="messages-shell">
|
<div class="messages-shell">
|
||||||
<button id="jumpToSessionStartBtn" class="session-jump-btn session-jump-btn--start" aria-label="Jump to beginning of session" data-i18n-aria-label="session_jump_start_label" data-i18n-title="session_jump_start_label" onclick="jumpToSessionStart()" style="display:none"><span aria-hidden="true">↑</span><span data-i18n="session_jump_start">Start</span></button>
|
<button id="jumpToSessionStartBtn" class="session-jump-btn session-jump-btn--start" aria-label="Jump to beginning of session" data-i18n-aria-label="session_jump_start_label" data-i18n-title="session_jump_start_label" onclick="jumpToSessionStart()" style="display:none"><span aria-hidden="true">↑</span><span data-i18n="session_jump_start">Start</span></button>
|
||||||
<button id="scrollToBottomBtn" class="scroll-to-bottom-btn" style="display:none" onclick="scrollToBottom()" aria-label="Scroll to bottom" data-i18n-aria-label="session_jump_end_label" data-i18n-title="session_jump_end_label"><span aria-hidden="true">↓</span><span class="session-jump-btn__text" data-i18n="session_jump_end">End</span></button>
|
<button id="scrollToBottomBtn" class="scroll-to-bottom-btn" style="display:none" onclick="scrollToBottom()" aria-label="Scroll to bottom" data-i18n-aria-label="session_jump_end_label" data-i18n-title="session_jump_end_label"><span aria-hidden="true">↓</span><span class="session-jump-btn__text" data-i18n="session_jump_end">End</span></button>
|
||||||
|
<button id="outlineToggleBtn" type="button" hidden
|
||||||
|
onclick="toggleOutlinePanel()"
|
||||||
|
title="Conversation outline"
|
||||||
|
aria-label="Toggle conversation outline"
|
||||||
|
aria-controls="outlinePanelWrapper">☰</button>
|
||||||
<div class="messages" id="messages">
|
<div class="messages" id="messages">
|
||||||
<div class="empty-state" id="emptyState">
|
<div class="empty-state" id="emptyState">
|
||||||
<div class="empty-logo"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="80" height="80" aria-label="Hermes caduceus">
|
<div class="empty-logo"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="80" height="80" aria-label="Hermes caduceus">
|
||||||
@@ -1645,12 +1650,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Conversation Outline Panel (#2124): floating jump-to-question panel -->
|
|
||||||
<button id="outlineToggleBtn" type="button" hidden
|
|
||||||
onclick="toggleOutlinePanel()"
|
|
||||||
title="Conversation outline"
|
|
||||||
aria-label="Toggle conversation outline"
|
|
||||||
aria-controls="outlinePanelWrapper">☰</button>
|
|
||||||
<div id="outlinePanelWrapper" hidden
|
<div id="outlinePanelWrapper" hidden
|
||||||
role="navigation" aria-label="Conversation outline">
|
role="navigation" aria-label="Conversation outline">
|
||||||
<div class="outline-header">
|
<div class="outline-header">
|
||||||
|
|||||||
+1
-1
@@ -5864,7 +5864,7 @@ main.main.showing-logs > #mainLogs{display:flex;}
|
|||||||
|
|
||||||
/* ── Conversation Outline Panel (#2124) ─────────────────────────────────── */
|
/* ── Conversation Outline Panel (#2124) ─────────────────────────────────── */
|
||||||
#outlineToggleBtn{
|
#outlineToggleBtn{
|
||||||
position:fixed;bottom:120px;right:calc(var(--outline-workspace-offset, 0px) + 20px);z-index:9999;
|
position:absolute;bottom:60px;right:20px;z-index:12;
|
||||||
width:38px;height:38px;border-radius:50%;
|
width:38px;height:38px;border-radius:50%;
|
||||||
background:var(--surface);border:1px solid var(--border2);
|
background:var(--surface);border:1px solid var(--border2);
|
||||||
color:var(--text);cursor:pointer;
|
color:var(--text);cursor:pointer;
|
||||||
|
|||||||
@@ -17,6 +17,18 @@ CONFIG_PY = (ROOT / "api" / "config.py").read_text(encoding="utf-8")
|
|||||||
LOCALE_COUNT = 12
|
LOCALE_COUNT = 12
|
||||||
|
|
||||||
|
|
||||||
|
def _css_rule_body(selector):
|
||||||
|
rule = re.search(re.escape(selector) + r"\{(?P<body>[^}]*)\}", STYLE_CSS, re.S)
|
||||||
|
assert rule
|
||||||
|
return rule.group("body")
|
||||||
|
|
||||||
|
|
||||||
|
def _css_px(rule_body, property_name):
|
||||||
|
match = re.search(rf"{re.escape(property_name)}:(?P<value>\d+)px", rule_body)
|
||||||
|
assert match
|
||||||
|
return int(match.group("value"))
|
||||||
|
|
||||||
|
|
||||||
def test_outline_panel_html_and_i18n_contract():
|
def test_outline_panel_html_and_i18n_contract():
|
||||||
"""The panel shell, script tag, and locale keys must be present."""
|
"""The panel shell, script tag, and locale keys must be present."""
|
||||||
assert 'src="static/outline.js?v=__WEBUI_VERSION__"' in INDEX_HTML
|
assert 'src="static/outline.js?v=__WEBUI_VERSION__"' in INDEX_HTML
|
||||||
@@ -115,3 +127,24 @@ def test_outline_wrapper_hidden_attr_actually_hides():
|
|||||||
the panel (the close button / auto-close set wrapper.hidden=true). An explicit
|
the panel (the close button / auto-close set wrapper.hidden=true). An explicit
|
||||||
#outlinePanelWrapper[hidden]{display:none} rule restores the expected behavior."""
|
#outlinePanelWrapper[hidden]{display:none} rule restores the expected behavior."""
|
||||||
assert "#outlinePanelWrapper[hidden]{display:none;}" in STYLE_CSS
|
assert "#outlinePanelWrapper[hidden]{display:none;}" in STYLE_CSS
|
||||||
|
|
||||||
|
|
||||||
|
def test_outline_fab_stacks_with_scroll_controls():
|
||||||
|
"""The outline FAB shares the messages-shell positioning context with the
|
||||||
|
scroll controls, so composer height changes cannot make the controls overlap
|
||||||
|
in the bottom-right corner. (#4381)"""
|
||||||
|
shell_start = INDEX_HTML.index('<div class="messages-shell">')
|
||||||
|
messages_start = INDEX_HTML.index('<div class="messages" id="messages">', shell_start)
|
||||||
|
shell_controls = INDEX_HTML[shell_start:messages_start]
|
||||||
|
assert 'id="outlineToggleBtn"' in shell_controls
|
||||||
|
assert shell_controls.index('id="scrollToBottomBtn"') < shell_controls.index('id="outlineToggleBtn"')
|
||||||
|
|
||||||
|
outline_css = _css_rule_body("#outlineToggleBtn")
|
||||||
|
scroll_css = _css_rule_body(".scroll-to-bottom-btn")
|
||||||
|
assert "position:absolute" in outline_css
|
||||||
|
assert "position:fixed" not in outline_css
|
||||||
|
assert _css_px(outline_css, "right") == _css_px(scroll_css, "right")
|
||||||
|
|
||||||
|
outline_gap = _css_px(outline_css, "bottom")
|
||||||
|
scroll_top = _css_px(scroll_css, "bottom") + _css_px(scroll_css, "height")
|
||||||
|
assert outline_gap > scroll_top
|
||||||
Reference in new issue
Block a user