feat(ui): keep one side panel open per desktop sidebar in every HUD layout

The Cyber accordion now applies to both sidebars and every HUD layout:
opening a side panel collapses its peers, the layout normalizes restored
state to one owner, and collapsed panels are hidden on desktop. Phones keep
showing several panels per sheet.
This commit is contained in:
Sameh Khamis committed 2026-10-30 16:28:08 -07:00
1 parent 7307c11c74
commit 2035c767ce
12 files changed
+178 -214

No files matched your search

+11 -41
View File
@@ -2,50 +2,20 @@ import { readStylesheet } from './testSupport/readStylesheet.mjs';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import test from 'node:test';
import {
shouldExpandGlobalContextPanel,
shouldHideCollapsedRightPanels,
} from './rightRailPolicy.js';
import { shouldExpandGlobalContextPanel } from './rightRailPolicy.js';
test('Tactical HUD hides collapsed right-rail siblings while one panel is expanded', () => {
assert.equal(shouldHideCollapsedRightPanels({
hudVariant: 'tactical',
hasExpandedPanel: true,
}), true);
});
test('collapsed launchers remain when Tactical has no expanded panel', () => {
assert.equal(shouldHideCollapsedRightPanels({
hudVariant: 'tactical',
hasExpandedPanel: false,
}), false);
});
test('other HUD layouts keep collapsed right-rail launchers visible', () => {
assert.equal(shouldHideCollapsedRightPanels({
hudVariant: 'minimal',
hasExpandedPanel: true,
}), false);
assert.equal(shouldHideCollapsedRightPanels({
hudVariant: 'full',
hasExpandedPanel: true,
}), false);
});
test('desktop Display participates in Tactical exclusivity without changing mobile Display behavior', () => {
const ui = readFileSync(new URL('./ui/rightPanelRail.js', import.meta.url), 'utf8');
test('desktop side rails hide collapsed panels in every HUD layout, never on phones', () => {
const right = readFileSync(new URL('./ui/rightPanelRail.js', import.meta.url), 'utf8');
const left = readFileSync(new URL('./ui/leftPanelRail.js', import.meta.url), 'utf8');
const css = readStylesheet(new URL('../style.css', import.meta.url));
assert.match(ui, /const isMobile = windowRef\.matchMedia\('\(max-width: 720px\)'\)\.matches/);
assert.match(
ui,
/!panel\.classList\.contains\('collapsed'\)\s*&&\s*\(!isMobile \|\| panel\.id !== 'pp-toggles'\)/,
);
assert.doesNotMatch(
ui,
/panel\.id !== 'pp-toggles' && !panel\.classList\.contains\('collapsed'\)/,
);
assert.match(ui, /if \(exclusive && panel\.classList\.contains\('collapsed'\)\)\s*panel\.setAttribute\('aria-hidden', 'true'\)/);
for (const ui of [right, left]) {
assert.match(ui, /const isMobile = windowRef\.matchMedia\('\(max-width: 720px\)'\)\.matches/);
assert.match(ui, /const exclusive = !isMobile;/);
assert.match(ui, /if \(exclusive && panel\.classList\.contains\('collapsed'\)\)\s*panel\.setAttribute\('aria-hidden', 'true'\)/);
assert.doesNotMatch(ui, /hud\.variant === 'cyber'/);
}
assert.match(css, /#right-context-rail\.layout-exclusive > \[data-panel-id\]\.collapsed \{/);
assert.match(css, /#left-panel-stack\.layout-exclusive > \[data-panel-id\]\.collapsed \{/);
});
test('explicit Contacts, Space Missions, and Cockpit actions expand Global Context after success', () => {