diff --git a/client/src/components/Layout/Navbar.test.tsx b/client/src/components/Layout/Navbar.test.tsx index 00363749e..4e8bd9af4 100644 --- a/client/src/components/Layout/Navbar.test.tsx +++ b/client/src/components/Layout/Navbar.test.tsx @@ -612,6 +612,27 @@ describe('Navbar layout (#1983)', () => { expect(pill.style.overflowX).toBe('auto'); }); + it('keeps both columns at their content width, so the actions never spill over the pill', () => { + withAddons(8); + const { container } = render(); + const nav = container.querySelector('nav') as HTMLElement; + const columns = Array.from(nav.children).filter(c => c.classList.contains('flex-1')); + // A min-w-0 column shrinks below its content and its justify-end children + // overflow leftwards across the pill (5.0.0-pre.1 feedback). + for (const c of columns) { + expect(c.classList.contains('min-w-0')).toBe(false); + expect(c.classList.contains('min-w-max')).toBe(true); + } + }); + + it('shows the prerelease badge in the brand column, beside the logo', () => { + seedStore(useAuthStore, { isPrerelease: true, appVersion: '5.0.0-pre.1' }); + const { container } = render(); + const nav = container.querySelector('nav') as HTMLElement; + const brandColumn = nav.children[0] as HTMLElement; + expect(brandColumn.contains(screen.getByText('5.0.0-pre.1'))).toBe(true); + }); + it('still renders every addon as a reachable link, however many there are', () => { withAddons(8); render(); diff --git a/client/src/components/Layout/Navbar.tsx b/client/src/components/Layout/Navbar.tsx index e40abb83b..1d49ee221 100644 --- a/client/src/components/Layout/Navbar.tsx +++ b/client/src/components/Layout/Navbar.tsx @@ -12,6 +12,7 @@ import InAppNotificationBell from './InAppNotificationBell.tsx' import HelpButton from '../Help/HelpButton' import { resolvePluginIcon } from '../shared/PluginIcon' import { visibleManagedNavItems } from '../../managed' +import { useCollapseOnOverflow } from '../../hooks/useCollapseOnOverflow' const ADDON_ICONS: Record = { CalendarDays, Briefcase, Globe, Compass, Bookmark } @@ -95,6 +96,16 @@ export default function Navbar({ tripTitle, tripId, onBack, showBack, onShare }: return translated !== key ? translated : addon.name } + const tabs = [{ id: '__trips', path: '/dashboard', label: t('nav.myTrips'), Icon: Briefcase }, + ...globalAddons.map(a => ({ id: a.id, path: `/${a.id}`, label: getAddonName(a), Icon: ADDON_ICONS[a.icon] || CalendarDays })), + ...pagePlugins.map(p => ({ id: `plugin:${p.id}`, path: `/plugins/${p.id}`, label: p.name, Icon: resolvePluginIcon(p.icon) })), + // Empty in this repository — see client/src/managed. + ...visibleManagedNavItems(user?.role === 'admin').map(m => ({ id: `managed:${m.id}`, path: m.path, label: m.label, Icon: m.Icon })) + ] + // Labels go when they no longer fit beside the logo and the actions; the + // title and aria-label on each tab keep it named. + const { ref: pillRef, collapsed: pillCollapsed } = useCollapseOnOverflow(tabs.map(tab => tab.label).join('|')) + return (