IndiaCN UI

Navbar

Government website header with a utility bar, brand, navigation and actions.

Introduction

UX4G specifies a two-tier header for government sites: a primary utility bar carrying the Government of India mark and site-wide controls, over a white bar carrying brand, navigation and actions.

The parts are slots rather than a single configured component, because a header is the piece every site changes most.

Installation

npx shadcn@latest add https://indiacn.in/r/navbar.json
import {
Navbar,
NavbarUtilityBar,
NavbarGovBadge,
NavbarSkipLink,
NavbarSeparator,
NavbarMain,
NavbarBrand,
NavbarNav,
NavbarLink,
NavbarActions,
NavbarToggle,
} from '@/components/ui/navbar';

Example

The preview is far narrower than a real header, so this example carries three links rather than the six a site would. Note also that the collapse breakpoint is a viewport query, not a container one — inside this box the desktop layout still applies even though the box is narrow.

Page content starts here. Tab from the top to reach the skip link.
NavbarDefault
'use client';

import { Search as SearchIcon } from 'lucide-react';

import { Button } from '@/components/ui/button';
import {
  Navbar,
  NavbarActions,
  NavbarBrand,
  NavbarLink,
  NavbarMain,
  NavbarNav,
  NavbarSeparator,
  NavbarSkipLink,
  NavbarToggle,
  NavbarUtilityBar,
} from '@/components/ui/navbar';
import { Label2, Title2 } from '@/components/ui/typography';

const LINKS = [
  { label: 'About us', href: '#about' },
  { label: 'Citizen Corner', href: '#citizen', hasMenu: true },
  { label: 'Resources', href: '#resources', hasMenu: true },
];

export default function Component() {
  return (
    <div className='relative w-full overflow-hidden rounded-md border border-neutral-100'>
      <Navbar>
        <NavbarUtilityBar>
          <NavbarSkipLink href='#main-demo' />
          <NavbarSeparator />
          <Label2>Accessibility</Label2>
        </NavbarUtilityBar>

        <NavbarMain className='relative'>
          <NavbarBrand href='#home'>
            <Title2 className='text-primary font-semibold'>Sewa Setu</Title2>
          </NavbarBrand>

          <NavbarNav>
            {LINKS.map(link => (
              <NavbarLink
                key={link.label}
                href={link.href}
                hasMenu={link.hasMenu}
                active={link.label === 'About us'}
              >
                {link.label}
              </NavbarLink>
            ))}
          </NavbarNav>

          <NavbarActions>
            <Button variant='text' iconButton aria-label='Search'>
              <SearchIcon />
            </Button>
            <Button variant='outlined' size='sm' className='hidden sm:inline-flex'>
              Login
            </Button>
            <Button size='sm' className='hidden sm:inline-flex'>
              Signup
            </Button>
            <NavbarToggle />
          </NavbarActions>
        </NavbarMain>
      </Navbar>

      <div id='main-demo' className='p-6'>
        <Label2 className='text-neutral-600'>
          Page content starts here. Tab from the top to reach the skip link.
        </Label2>
      </div>
    </div>
  );
}

NavbarSkipLink is hidden until it receives focus, then appears in the utility bar. That is the only arrangement that works: it has to be the first thing a keyboard user reaches, and invisible to everyone else.

Point it at your main landmark and give that landmark the matching id:

<NavbarSkipLink href="#main" />
...
<main id="main" tabIndex={-1}></main>

Without tabIndex={-1} on the target, some browsers move the viewport but not focus, so the next Tab returns to the header.

The tricolour

NavbarGovBadge draws the flag from a theme token rather than shipping an image, so installing the component needs no asset file.

The token is defined once and deliberately not redefined in .dark — saffron, white and green are the flag, not a palette we retint for dark mode. If you need it elsewhere, the utility is bg-tricolour.

Measurements

value
utility bar#613af5 (primary), 41px
main bar#ffffff (neutral-0), 72px
content width1440px max

Responsive behaviour

Below lg the navigation collapses behind NavbarToggle and opens as a stacked panel beneath the header rather than an overlay, so it never traps focus and never covers the content it links to. NavbarMain needs className="relative" for the panel to anchor to it.

API Reference

PropTypeDefaultDescription
startReactNode<NavbarGovBadge />Leading content
childrenReactNodeTrailing controls
PropTypeDefault
hrefstringhttps://www.india.gov.in
labelstringGovernment of India
PropTypeDescription
activebooleanMarks the current page, and sets aria-current
hasMenubooleanShows a chevron for a link that opens a menu

Other parts

NavbarBrand, NavbarNav, NavbarActions, NavbarSeparator and NavbarSecondaryRow are layout slots. NavbarToggle reads its expanded state from the navbar and controls NavbarNav by id.

On this page