Files
sencho/frontend/src/hooks/__tests__/use-top-nav-align.test.ts
T
Anso 1b96f3b980 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.
2026-06-12 10:49:36 -04:00

51 lines
1.9 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { useTopNavAlign, TOP_NAV_ALIGN_KEY } from '../use-top-nav-align';
describe('useTopNavAlign (left default)', () => {
beforeEach(() => localStorage.clear());
afterEach(() => localStorage.clear());
it('defaults to left when no value is stored', () => {
const { result } = renderHook(() => useTopNavAlign());
expect(result.current[0]).toBe('left');
});
it('reads center only when explicitly set to center', () => {
localStorage.setItem(TOP_NAV_ALIGN_KEY, 'center');
const { result } = renderHook(() => useTopNavAlign());
expect(result.current[0]).toBe('center');
});
it('treats any unknown value as left', () => {
localStorage.setItem(TOP_NAV_ALIGN_KEY, 'something-else');
const { result } = renderHook(() => useTopNavAlign());
expect(result.current[0]).toBe('left');
});
it('setAlign persists and switches', () => {
const { result } = renderHook(() => useTopNavAlign());
act(() => result.current[1]('center'));
expect(result.current[0]).toBe('center');
expect(localStorage.getItem(TOP_NAV_ALIGN_KEY)).toBe('center');
act(() => result.current[1]('left'));
expect(result.current[0]).toBe('left');
});
it('reacts to a storage event from another tab', () => {
const { result } = renderHook(() => useTopNavAlign());
expect(result.current[0]).toBe('left');
act(() => {
window.dispatchEvent(new StorageEvent('storage', { key: TOP_NAV_ALIGN_KEY, newValue: 'center' }));
});
expect(result.current[0]).toBe('center');
});
it('syncs a second hook in the same tab via the settings-changed event', () => {
const a = renderHook(() => useTopNavAlign());
const b = renderHook(() => useTopNavAlign());
act(() => a.result.current[1]('center'));
expect(b.result.current[0]).toBe('center');
});
});