feat: add a compact icon-only top navigation toggle (#1363)

* feat: add a compact icon-only top navigation toggle

Add a browser-local "Top navigation labels" preference under Settings >
Appearance. With it off, the desktop top navigation renders icon-only;
each destination keeps an aria-label, gains a hover/focus tooltip, and
stays reachable from the command palette. The setting defaults on, so
current behavior is preserved, and the mobile navigation always keeps
its labels.

Also left-align the desktop nav (previously centered) and shorten the
longest nav label from "Auto-Update" to "Update" so the bar scans faster.

* feat: let the icon-only top nav be left or centered

Add a "Top navigation alignment" preference under Settings > Appearance
that appears only when top navigation labels are off. It places the
icon-only bar against the left edge (the default) or centered. With
labels on, the nav always stays left so the longer labels read from the
edge. The choice is browser-local and persists per device.
This commit is contained in:
Anso
2026-06-12 10:49:36 -04:00
committed by GitHub
parent 2a4955f56d
commit 1b96f3b980
15 changed files with 391 additions and 38 deletions
@@ -217,7 +217,7 @@ describe('useViewNavigationState', () => {
expect(result.current.navItems.map(i => i.value)).toContain('global-observability');
});
it('shows Auto-Update and Schedules for a community admin (now free) but hides paid Console and Audit', () => {
it('shows Update and Schedules for a community admin (now free) but hides paid Console and Audit', () => {
mockCommunityAdmin();
const { result } = renderHook(() => useViewNavigationState());
const values = result.current.navItems.map(i => i.value);
@@ -225,6 +225,8 @@ describe('useViewNavigationState', () => {
expect(values).toContain('scheduled-ops');
expect(values).not.toContain('host-console');
expect(values).not.toContain('audit-log');
// The auto-updates nav item surfaces under the short label "Update".
expect(result.current.navItems.find(i => i.value === 'auto-updates')?.label).toBe('Update');
});
it('redirects a non-admin off the Logs view when reached via a deep-link event', () => {
@@ -123,7 +123,7 @@ export function useViewNavigationState(options?: UseViewNavigationStateOptions)
// admin-only operator view (the backend gates the same routes on admin).
if (isAdmin) items.push({ value: 'global-observability', label: 'Logs', icon: Activity });
if (isAdmin) {
items.push({ value: 'auto-updates', label: 'Auto-Update', icon: RefreshCw });
items.push({ value: 'auto-updates', label: 'Update', icon: RefreshCw });
items.push({ value: 'scheduled-ops', label: 'Schedules', icon: Clock });
}
if (isPaid) {