Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions calm-hub-ui/src/components/navbar/Navbar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,24 @@ describe('Navbar UI config', () => {
expect(screen.getByRole('link', { name: 'Support' })).toHaveAttribute('href', 'https://support.example.com');
});
});

// jsdom does no layout, so these guard the classes that set it (#3505).
describe('Navbar layout', () => {
it('keeps the logo in the flex flow below lg, so page actions cannot cover it', () => {
renderNavbar(makeState({}));
const center = screen.getByRole('link', { name: 'CALM Hub home' }).parentElement;

expect(center).not.toHaveClass('absolute');
expect(center).toHaveClass('lg:absolute', 'max-lg:shrink', 'min-w-0');
expect(screen.getByAltText('CALM Logo')).toHaveClass('object-contain');
});

it('stops the side groups shrinking under their content below lg', () => {
const { container } = renderNavbar(makeState({}));

for (const side of [container.querySelector('.navbar-start'), container.querySelector('.navbar-end')]) {
expect(side).toHaveClass('max-lg:w-auto', 'max-lg:flex-1', 'lg:min-w-0');
expect(side).not.toHaveClass('min-w-0');
}
});
});
13 changes: 8 additions & 5 deletions calm-hub-ui/src/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export function Navbar({ storage }: NavbarProps = {}) {

return (
<div className="navbar relative bg-base-100 border-b-2 border-base-200 text-primary-content gap-1">
<div className="navbar-start flex items-center gap-1 min-w-0">
{/* Below lg the logo stays in the flex flow: equal flex-1 sides keep it
centred, but neither side can shrink under its content, so page
actions in #navbar-actions push the logo aside instead of covering it. */}
<div className="navbar-start flex items-center gap-1 max-lg:w-auto max-lg:flex-1 lg:min-w-0">
<button
// Narrower on mobile with a pill, which must fit beside the centred logo.
className={`btn btn-ghost gap-2 text-primary shrink-0${environment ? ' px-2 lg:px-4' : ''}`}
Expand All @@ -53,12 +56,12 @@ export function Navbar({ storage }: NavbarProps = {}) {
</button>
{environment && <EnvironmentPill environment={environment} />}
</div>
<div className="navbar-center absolute left-1/2 -translate-x-1/2">
<Link to="/" className="btn btn-ghost min-w-0 px-1" aria-label="CALM Hub home">
<img src={LOGO_SRC[theme]} alt="CALM Logo" className="h-10 logo" />
<div className="navbar-center min-w-0 max-lg:shrink lg:absolute lg:left-1/2 lg:-translate-x-1/2">
<Link to="/" className="btn btn-ghost min-w-0 px-1 max-lg:shrink" aria-label="CALM Hub home">
<img src={LOGO_SRC[theme]} alt="CALM Logo" className="h-10 logo min-w-0 object-contain" />
</Link>
</div>
<div className="navbar-end flex items-center gap-1 min-w-0 shrink-0">
<div className="navbar-end flex items-center gap-1 shrink-0 max-lg:w-auto max-lg:flex-1 lg:min-w-0">
{/* Portal target for page-level actions (e.g. the diagram's
view-options menu), always visible across breakpoints. */}
<div id="navbar-actions" className="flex items-center" />
Expand Down
Loading