mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-07-18 21:50:55 +00:00
fix(#5583): keep mobile nav actions visible
This commit is contained in:
+1
-1
@@ -3100,7 +3100,7 @@
|
||||
.sidebar-nav .nav-tab svg{width:20px;height:20px;}
|
||||
.sidebar-nav .nav-tab.active{background:var(--accent-bg);}
|
||||
.sidebar-nav .nav-tab.active::before{left:-4px;top:50%;bottom:auto;transform:translateY(-50%);width:3px;height:16px;border-radius:0 2px 2px 0;}
|
||||
.sidebar-nav .dashboard-link:not(.nav-action-visible){display:none!important;}
|
||||
.sidebar-nav .dashboard-link:not(.nav-action-visible),.sidebar-nav [data-nav-action-mirror]:not(.nav-action-visible){display:none!important;}
|
||||
.sidebar .panel-view{height:100%;margin-left:52px;}
|
||||
.sidebar .panel-head{padding-right:52px;}
|
||||
.mobile-sidebar-close{display:inline-flex!important;position:absolute;right:4px;top:calc(4px + var(--app-titlebar-safe-top));width:44px;height:44px;z-index:4;background:var(--surface);border:1px solid var(--border);}
|
||||
|
||||
+23
-4
@@ -1312,16 +1312,29 @@ function _syncNavActionMirrors(){
|
||||
if(!sourceIds.has(mirror.getAttribute('data-nav-action-mirror')))mirror.remove();
|
||||
});
|
||||
sources.forEach(source=>{
|
||||
source.classList.add('nav-action-visible');
|
||||
const sourceVisible=(()=>{
|
||||
if(source.hidden||source.getAttribute('aria-hidden')==='true')return false;
|
||||
if(source.classList.contains('nav-tab-hidden'))return false;
|
||||
if(source.style&&(source.style.display==='none'||source.style.visibility==='hidden'))return false;
|
||||
if(typeof window!=='undefined'&&typeof window.getComputedStyle==='function'){
|
||||
const computed=window.getComputedStyle(source);
|
||||
if(computed&&(computed.display==='none'||computed.visibility==='hidden'))return false;
|
||||
}
|
||||
return true;
|
||||
})();
|
||||
let mirror=mirrors.find(el=>el.getAttribute('data-nav-action-mirror')===source.id);
|
||||
if(!mirror){
|
||||
mirror=source.cloneNode(true);
|
||||
_stripInlineEventHandlers(mirror);
|
||||
mirror.id=source.id+'Mobile';
|
||||
mirror.classList.remove('rail-btn');
|
||||
mirror.classList.add('nav-action-visible','has-tooltip--bottom');
|
||||
mirror.classList.add('has-tooltip--bottom');
|
||||
mirror.setAttribute('data-nav-action-mirror',source.id);
|
||||
mirror.addEventListener('click',e=>{e.preventDefault();if(mirror._navActionSource)mirror._navActionSource.click();});
|
||||
mirror.addEventListener('click',e=>{
|
||||
e.preventDefault();
|
||||
if(mirror._navActionSource)mirror._navActionSource.click();
|
||||
if(typeof closeMobileSidebar==='function')closeMobileSidebar();
|
||||
});
|
||||
const anchor=sidebar.querySelector('.dashboard-link,[data-dashboard-link]')||sidebar.querySelector('[data-panel="logs"]');
|
||||
sidebar.insertBefore(mirror,anchor||null);
|
||||
}else{
|
||||
@@ -1329,6 +1342,7 @@ function _syncNavActionMirrors(){
|
||||
_stripInlineEventHandlers(mirror);
|
||||
}
|
||||
mirror._navActionSource=source;
|
||||
mirror.classList.toggle('nav-action-visible',sourceVisible);
|
||||
const label=source.getAttribute('data-tooltip')||source.getAttribute('aria-label')||'';
|
||||
if(label)mirror.setAttribute('data-label',label);
|
||||
});
|
||||
@@ -1336,7 +1350,12 @@ function _syncNavActionMirrors(){
|
||||
function _initNavActionMirrors(){
|
||||
_syncNavActionMirrors();
|
||||
const rail=document.querySelector('.rail');
|
||||
if(rail&&window.MutationObserver)new MutationObserver(_syncNavActionMirrors).observe(rail,{childList:true});
|
||||
if(rail&&window.MutationObserver)new MutationObserver(_syncNavActionMirrors).observe(rail,{
|
||||
childList:true,
|
||||
subtree:true,
|
||||
attributes:true,
|
||||
attributeFilter:['class','style','hidden','aria-hidden','data-tooltip','aria-label'],
|
||||
});
|
||||
}
|
||||
if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',_initNavActionMirrors,{once:true});
|
||||
else _initNavActionMirrors();
|
||||
|
||||
@@ -402,7 +402,8 @@ def test_mobile_dashboard_link_uses_shared_visible_action_class():
|
||||
assert match is not None
|
||||
mobile_css = match.group(1)
|
||||
assert re.search(r"\.dashboard-link-visible,\s*\.nav-action-visible\{display:flex!important;\}", STYLE_CSS)
|
||||
assert ".sidebar-nav .dashboard-link:not(.nav-action-visible){display:none!important;}" in mobile_css
|
||||
assert ".sidebar-nav .dashboard-link:not(.nav-action-visible)" in mobile_css
|
||||
assert ".sidebar-nav [data-nav-action-mirror]:not(.nav-action-visible){display:none!important;}" in mobile_css
|
||||
assert ".sidebar-nav .dashboard-link.dashboard-link-visible{display:none!important;}" not in mobile_css
|
||||
assert ".sidebar-nav .dashboard-link:not(.dashboard-link-visible){display:none!important;}" not in mobile_css
|
||||
|
||||
@@ -445,6 +446,19 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
add: (...classes) => classes.forEach(c => this.classList._set.add(c)),
|
||||
remove: (...classes) => classes.forEach(c => this.classList._set.delete(c)),
|
||||
contains: c => this.classList._set.has(c),
|
||||
toggle: (cls, force) => {
|
||||
if (force === undefined) {
|
||||
if (this.classList._set.has(cls)) {
|
||||
this.classList._set.delete(cls);
|
||||
return false;
|
||||
}
|
||||
this.classList._set.add(cls);
|
||||
return true;
|
||||
}
|
||||
if (force) this.classList._set.add(cls);
|
||||
else this.classList._set.delete(cls);
|
||||
return !!force;
|
||||
},
|
||||
};
|
||||
}
|
||||
appendChild(child) { child.parentNode = this; this.children.push(child); return child; }
|
||||
@@ -508,6 +522,7 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
const source = new El('button');
|
||||
const dashboard = new El('button');
|
||||
let clicked = 0;
|
||||
let sidebarClosed = 0;
|
||||
source.id = 'hwxThemeCreatorRailBtn';
|
||||
source.classList.add('rail-btn', 'nav-tab', 'has-tooltip');
|
||||
source.setAttribute('data-tooltip', 'Theme Creator');
|
||||
@@ -519,6 +534,7 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
sidebar.appendChild(dashboard);
|
||||
let observerCallback = null;
|
||||
let observedRail = null;
|
||||
let observedOptions = null;
|
||||
|
||||
global.document = {
|
||||
readyState: 'complete',
|
||||
@@ -528,10 +544,18 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
return null;
|
||||
},
|
||||
};
|
||||
global.window = {};
|
||||
global.closeMobileSidebar = () => { sidebarClosed += 1; };
|
||||
global.window = {
|
||||
getComputedStyle(el) {
|
||||
return {
|
||||
display: el.hidden || (el.style && el.style.display === 'none') ? 'none' : '',
|
||||
visibility: (el.style && el.style.visibility) || '',
|
||||
};
|
||||
},
|
||||
};
|
||||
global.MutationObserver = window.MutationObserver = class {
|
||||
constructor(callback) { observerCallback = callback; }
|
||||
observe(target) { observedRail = target; }
|
||||
observe(target, options) { observedRail = target; observedOptions = options; }
|
||||
};
|
||||
|
||||
const helpers = Function(extractFn('_stripInlineEventHandlers') + '\\n' + extractFn('_syncNavActionMirrors') + '\\n' + extractFn('_initNavActionMirrors') + '; return { _initNavActionMirrors };')();
|
||||
@@ -539,14 +563,22 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
rail.appendChild(source);
|
||||
observerCallback();
|
||||
const mirror = sidebar.children.find(el => el.getAttribute('data-nav-action-mirror') === 'hwxThemeCreatorRailBtn');
|
||||
source.hidden = true;
|
||||
observerCallback();
|
||||
const mirrorHiddenWhenSourceHidden = !mirror.classList.contains('nav-action-visible');
|
||||
source.hidden = false;
|
||||
observerCallback();
|
||||
mirror.click();
|
||||
const mirrorBeforeDashboard = sidebar.children[0] === mirror;
|
||||
source.remove();
|
||||
observerCallback();
|
||||
console.log(JSON.stringify({
|
||||
observerArmed: observedRail === rail,
|
||||
observerAttributes: !!(observedOptions && observedOptions.attributes),
|
||||
observerSubtree: !!(observedOptions && observedOptions.subtree),
|
||||
sourceVisible: source.classList.contains('nav-action-visible'),
|
||||
mirrorVisible: mirror.classList.contains('nav-action-visible'),
|
||||
mirrorHiddenWhenSourceHidden,
|
||||
mirrorRailClass: mirror.classList.contains('rail-btn'),
|
||||
mirrorLabel: mirror.getAttribute('data-label'),
|
||||
mirrorOnclickAttribute: mirror.getAttribute('onclick'),
|
||||
@@ -554,6 +586,7 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
mirrorBeforeDashboard,
|
||||
mirrorRemoved: !sidebar.children.some(el => el.getAttribute('data-nav-action-mirror') === 'hwxThemeCreatorRailBtn'),
|
||||
clicked,
|
||||
sidebarClosed,
|
||||
}));
|
||||
"""
|
||||
)
|
||||
@@ -567,8 +600,11 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
pathlib.Path(path).unlink(missing_ok=True)
|
||||
assert out == {
|
||||
"observerArmed": True,
|
||||
"sourceVisible": True,
|
||||
"observerAttributes": True,
|
||||
"observerSubtree": True,
|
||||
"sourceVisible": False,
|
||||
"mirrorVisible": True,
|
||||
"mirrorHiddenWhenSourceHidden": True,
|
||||
"mirrorRailClass": False,
|
||||
"mirrorLabel": "Theme Creator",
|
||||
"mirrorOnclickAttribute": None,
|
||||
@@ -576,6 +612,7 @@ def test_extension_rail_actions_are_mirrored_to_mobile_nav():
|
||||
"mirrorBeforeDashboard": True,
|
||||
"mirrorRemoved": True,
|
||||
"clicked": 1,
|
||||
"sidebarClosed": 1,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user