Header
Header is a sticky top navigation bar built as a compound component. It is meant for layout composition rather than variant switching, so the public API stays intentionally small: Header, HeaderContent, HeaderLeft, HeaderCenter, and HeaderRight.
Default header layout
Header with dropdown navigation
Header with centered search
Header used with a sidebar layout
Header with a custom background
Full-width header content
Usage
Default layout
Use HeaderContent with HeaderLeft and HeaderRight for the standard layout: branding and navigation on the left, actions on the right.
import {
Header,
HeaderContent,
HeaderLeft,
HeaderRight,
} from "@e-infra/design-system";
import { Avatar, AvatarImage, AvatarFallback } from "@e-infra/design-system";
import { Button } from "@e-infra/design-system";
import { Bell } from "lucide-react";
<Header>
<HeaderContent>
<HeaderLeft>
<Logo />
<nav className="flex items-center gap-4 text-sm font-medium">
<a href="/dashboard">Dashboard</a>
<a href="/projects">Projects</a>
<a href="/team">Team</a>
</nav>
</HeaderLeft>
<HeaderRight>
<Button variant="ghost" size="icon">
<Bell className="h-4 w-4" />
</Button>
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="User" />
<AvatarFallback>U</AvatarFallback>
</Avatar>
</HeaderRight>
</HeaderContent>
</Header>;Centered content
HeaderCenter is a flex item that fills the available space between the left and right sections. It works well for search bars and centered tools.
import {
Header,
HeaderContent,
HeaderLeft,
HeaderCenter,
HeaderRight,
} from "@e-infra/design-system";
import { Input } from "@e-infra/design-system";
import { Search } from "lucide-react";
<Header>
<HeaderContent>
<HeaderLeft>
<Logo />
<nav className="flex items-center gap-4 text-sm font-medium">
<a href="/dashboard">Dashboard</a>
<a href="/projects">Projects</a>
</nav>
</HeaderLeft>
<HeaderCenter>
<div className="relative w-full max-w-md">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-text" />
<Input type="search" placeholder="Search..." className="w-full pl-8" />
</div>
</HeaderCenter>
<HeaderRight>
<UserActions />
</HeaderRight>
</HeaderContent>
</Header>;Navigation menus
Use the NavigationMenu primitives for dropdown menus and multi-level navigation. NavigationMenu renders the viewport automatically by default, and NavigationMenuIndicator should be placed after NavigationMenuList when you want the active indicator arrow.
import {
Header,
HeaderContent,
HeaderLeft,
HeaderRight,
} from "@e-infra/design-system";
import {
NavigationMenu,
NavigationMenuList,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuTrigger,
NavigationMenuContent,
NavigationMenuIndicator,
} from "@e-infra/design-system";
<Header>
<HeaderContent>
<HeaderLeft>
<Logo />
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink href="/dashboard">Dashboard</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger>Analytics</NavigationMenuTrigger>
<NavigationMenuContent>
<div className="grid gap-3 p-4 w-100">...</div>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
<NavigationMenuIndicator />
</NavigationMenu>
</HeaderLeft>
<HeaderRight>
<UserActions />
</HeaderRight>
</HeaderContent>
</Header>;If you need to place the viewport manually, disable the automatic viewport and render NavigationMenuViewport yourself.
<NavigationMenu viewport={false}>
<NavigationMenuList>...</NavigationMenuList>
<NavigationMenuViewport />
</NavigationMenu>Sidebar layouts
When a sidebar already owns branding, use container={false} so the header can span the full width without an extra max-width wrapper.
import { Header, HeaderContent, HeaderRight } from "@e-infra/design-system";
import { Sidebar, SidebarHeader, SidebarContent } from "@e-infra/design-system";
<div className="flex min-h-screen">
<Sidebar>
<SidebarHeader>
<span className="font-semibold">Lab Management</span>
</SidebarHeader>
<SidebarContent>{/* navigation */}</SidebarContent>
</Sidebar>
<div className="flex-1">
<Header>
<HeaderContent container={false}>
<HeaderRight>
<UserActions />
</HeaderRight>
</HeaderContent>
</Header>
</div>
</div>;Full-width and custom backgrounds
Header accepts native className overrides, so you can apply gradients, transparent borders, or other visual treatments without changing the component implementation.
<Header className="bg-linear-to-r from-primary/90 to-secondary/90 border-transparent">
<HeaderContent>
<HeaderLeft>
<Logo />
<nav className="flex items-center gap-4 text-sm font-medium text-white/90">
<a href="#" className="hover:text-white">
Dashboard
</a>
</nav>
</HeaderLeft>
<HeaderRight>
<UserActions />
</HeaderRight>
</HeaderContent>
</Header>Components
| Component | Description |
|---|---|
Header | Root sticky header element rendered as header |
HeaderContent | Inner flex container with optional width constraint |
HeaderLeft | Left-aligned row for branding and navigation |
HeaderCenter | Center flex area for search or centered controls |
HeaderRight | Right-aligned row for actions and user controls |
Props
Header
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes<HTMLElement> | - | Native header props |
HeaderContent
| Prop | Type | Default | Description |
|---|---|---|---|
| container | boolean | true | Whether to constrain width to the container max-width |
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes<HTMLDivElement> | - | Native div props |
HeaderLeft
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes<HTMLDivElement> | - | Native div props |
HeaderCenter
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes<HTMLDivElement> | - | Native div props |
HeaderRight
| Prop | Type | Default | Description |
|---|---|---|---|
| className | string | - | Additional CSS classes |
| ...props | React.HTMLAttributes<HTMLDivElement> | - | Native div props |
Structure
| Part | Details |
|---|---|
| Outer wrapper | Sticky header with top positioning, border-bottom, blur, and z-50 layering |
| Content row | Flex container with h-14, horizontal padding, and responsive gap spacing |
| Left section | flex items-center gap-4 md:gap-6 for branding and navigation |
| Center section | flex flex-1 items-center justify-center for balanced centered content |
| Right section | ml-auto flex items-center gap-2 for action controls |
Behavior
| Behavior | Details |
|---|---|
| Sticky layout | Header stays pinned to the top of the viewport while scrolling |
| Width control | HeaderContent constrains width by default and can opt out with container={false} |
| Composition-first API | Layout is built by arranging the subcomponents rather than selecting from variants |
| Navigation menus | The header works with the NavigationMenu primitives for dropdowns and indicators |
| Custom styling | Native className props allow local overrides without changing the implementation |
Notes
HeaderCenteris optional, but it is the supported way to place centered content in this layout.- The previews above swap the e-INFRA CZ logo by theme with a
dark:hidden/hidden dark:blockimage pair. Hidden elements are excluded from the accessibility tree, so both images carry the samealtand the logo is announced exactly once in either theme. The gradient header is dark in both themes, so it always takes the white logo. NavigationMenuViewportis rendered automatically byNavigationMenuunless you setviewport={false}.- The header implementation is intentionally small; prefer composing the existing subcomponents over adding new header-specific props.