feat(ui): add Classic, Smart, and Compact desktop navigation styles (#1642)

* feat(ui): add Classic, Smart, and Compact desktop navigation styles

Introduce a shared app-nav registry and reachable model so TopBar, the
command palette, and mobile menus share one destination source. Smart bar
is the default; Appearance gains a Navigation subsection with quick links.

* fix(e2e): stop clearing top-nav prefs on every reload

The desktop-navigation suite used addInitScript to wipe mode storage,
which re-ran on reload and undid the classic/compact values under test.

* fix(ui): harden nav PR docs and Compact quick-link coverage

Drop the partial docs-refresh import that left missing image assets and a stale Display screenshot, keep navigation-scoped operator docs against main, and add an E2E path that proves Compact quick-link add, persist, and render after reload.

* fix(ui): polish Compact quick links and menu mastheads

Align Smart/Compact menus with Theme chrome, keep pin labels always visible, and drive add capacity from persisted pins (max five) with a trailing + picker and per-pin remove.

* test(e2e): exact-match Compact Networking pin locator

Avoid Playwright strict-mode clash with Actions for Networking.

* fix(ui): simplify Compact quick link removal and fix + button trailing

Remove the (...) dropdown per quick link in Compact mode. Right-click
context menu remains as the sole on-bar removal affordance. Fix the +
add-button to trail quick links rather than pinning to the far right
by removing flex-1 from the quick-link rail.
This commit is contained in:
Anso
2026-07-16 21:48:03 -04:00
committed by GitHub
parent d8e4ede94f
commit 25586fc8ab
24 changed files with 1871 additions and 216 deletions
@@ -14,11 +14,13 @@ import {
import type { SectionId } from '@/components/settings';
import { SettingsSectionContent } from '@/components/settings/SettingsSectionContent';
import { BackChip, Kicker, Masthead } from './mobile-ui';
import type { NavDestination } from '@/lib/navigation/appNavRegistry';
interface MobileSettingsProps {
headerActions: ReactNode;
selectedSection: SectionId | null;
onSelectedSectionChange: (section: SectionId | null) => void;
quickLinkCandidates?: NavDestination[];
}
const NOOP = () => {};
@@ -27,6 +29,7 @@ export function MobileSettings({
headerActions,
selectedSection,
onSelectedSectionChange,
quickLinkCandidates,
}: MobileSettingsProps) {
const { isAdmin } = useAuth();
const { isPaid } = useLicense();
@@ -60,7 +63,12 @@ export function MobileSettings({
<span className="font-heading text-[30px] leading-[34px] text-stat-value">{item.label}</span>
</div>
<div className="flex-1 min-h-0 overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden px-4 pb-8 pt-4 flex flex-col gap-6">
<SettingsSectionContent sectionId={activeSection} onDirtyChange={NOOP} showDescription />
<SettingsSectionContent
sectionId={activeSection}
onDirtyChange={NOOP}
showDescription
quickLinkCandidates={quickLinkCandidates}
/>
</div>
</div>
);