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:
nesquena-hermesandMohamed Habib committed 2026-06-18 04:46:50 +00:00
1 parent d5f9e98252
commit 4ac9684223
4 files changed
+45 -7

No files matched your search

+6
View File
@@ -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
View File
@@ -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">&#9776;</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">&#9776;</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
View File
@@ -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;
+33
View File
@@ -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