# Header & Announcement

## Header & Announcement

**Files:** `src/config/config.toml`, `src/config/menu.en.json`, `src/i18n/en.json`, page frontmatter · **Skill level:** Beginner

Every header bar has the logo, the menu, and a button ("Get a free quote"). On small screens the menu links and the button move into a slide-in panel, opened with a **Menu** button. Around the bar, Ecozen has four header layouts with different contact rows, backgrounds, and an optional announcement strip.

In the Tina edition, these settings are under **Site settings** at `/admin/`, and the words under **Interface labels**. In the Sanity edition, they are in the Studio under **Site settings > Settings**, and the words under **Interface labels** in each language.

### Choose A Header Layout
```toml
# src/config/config.toml
[settings.header]
  layout = "classic"   # classic | transparent | floating | promo
```

| Layout        | What it looks like                                                                                   | Demo page      |
| ------------- | ---------------------------------------------------------------------------------------------------- | -------------- |
| `classic`     | A dark top bar with your email, phone, opening hours, social icons, and the language switch, above a white header bar. The default, used by inner pages | `/home-two/`   |
| `transparent` | Sits over the photo at the top of the page, with white links and the light logo (`logoAlternate`). A thin info row above it shows your phone, hours, social icons, and the language switch, and a round phone icon sits next to the button. The info row is hidden on small screens. Once the info row has scrolled away, the bar turns solid | `/`, `/services/` |
| `floating`    | A white bar with rounded corners, set in from the edges over the photo at the top of the page. It stays set in while you scroll | `/home-three/` |
| `promo`       | A citrus announcement strip (see below), then a white bar with your phone number and opening hours beside the button (on wide screens) | `/home-four/`  |

**One page, another layout.** Add `headerLayout` to the page's frontmatter. It wins over `[settings.header] layout`:

```yaml
---
headerLayout: "promo"   # classic | transparent | floating | promo
title: "EV charging and home batteries"
---
```

Each demo homepage sets its own. The `transparent` and `floating` layouts sit over the first section, so use them only on pages that open with a full-width photo or dark band, such as a `photo` or `panel` hero. Three routes, `index.astro`, `home-three.astro`, and `services/index.astro`, also pass `headerTransparent={true}` to `<Base>`; it means the same as `headerLayout: "transparent"`, and a page's `headerLayout` wins over it (`/home-three/` sets `floating`). `npm run astro-check` reports a misspelled value in files that have a schema.

The contact details come from `[settings.contactInfo]` in `config.toml`, the social icons from the first four links in `src/config/social.json`, and the opening hours can be translated with `footer.hoursText` in the i18n files (see [Footer](/ecozen/customization/footer/#contact-layout)).

**Language switch:** in the top bar for `classic`, in the main bar for `floating` and `promo`, and for `transparent` in the info row on large screens and the main bar below them; it lists the language names from `src/config/language.json`, and in the main bar, phones show only its icon.

### The Header Button
```toml
[settings.navigationButton]
  enable = true
  label  = ""          # empty uses navigation.buttonLabel from src/i18n/en.json ("Get a free quote")
  url    = "/contact/"
```

To change the words in every language, edit `navigation.buttonLabel` in each file in `src/i18n/`. On small screens this button is hidden; the menu panel has its own button (see below).

### Sticky Header
```toml
[settings]
  stickyHeader = true   # the header bar stays at the top while you scroll
```

Only the header bar sticks. The announcement strip, the `classic` top bar, and the `transparent` info row sit above it and scroll away with the page. When the bar reaches the top of the window, only its colours change: `classic` and `promo` get a slightly see-through white background, and `transparent` turns solid. Its size and position never change, so nothing jumps while you scroll.

Set `stickyHeader = false` to let the header scroll away with the page. The `floating` bar is pinned to the top in both cases.

### The Announcement Strip
A citrus line at the very top of the page, for an offer or a seasonal campaign. It ends with an arrow link and a close button. When a visitor closes it, their browser remembers that until the text changes.

The `promo` layout always shows it. The `classic` layout shows it when you turn it on:

```toml
[settings.announcementBar]
  enable = true   # also show the strip above the classic header
  label  = ""     # empty uses header.announcement from src/i18n/en.json
```

The text is one line of Markdown. Its first link becomes the arrow link at the end, for example `Free roof survey this month. [Book yours](/contact/)`. The text comes from, in this order:

1. `headerAnnouncement` in the page's frontmatter, as `/home-four/` does:

   ```yaml
   headerAnnouncement: "Home charger fitted from $1,190 this month, with off-peak setup included. [Get a quote](/contact/)"
   ```

2. `[settings.announcementBar] label` in `config.toml`, the same in every language
3. `header.announcement` in each file in `src/i18n/`

For a site in several languages, leave `label` empty and use the i18n files, or `headerAnnouncement` in each language's page file. The close button's screen-reader name is `header.announcementClose`.

The `transparent` and `floating` layouts never show the strip.

### The Mobile Menu Panel
On phones and tablets, the menu links are hidden and the **Menu** pill button opens a panel from the right (from the left on right-to-left pages) with, from top to bottom:

- a round close button and your logo
- a short description
- the menu links. Dropdowns open as lists inside the panel, with a plus or minus sign, and a group inside a dropdown opens its own list. The **Services** mega menu shows each group's name as a small label, its links with their icons, and the mega menu's `cta` card with its button (see [Menus](/ecozen/customization/menus/))
- your address, phone, and email from `[settings.contactInfo]`. The phone and email are links
- up to four social icons from `src/config/social.json`
- a button, full width on phones

On large screens the **Menu** button and the panel are hidden, because the menu links sit in the header bar. Developers can show the button there too with `hideOffcanvas={false}` on `<Base>` in a page route; the panel then opens without the menu links.

The description and the button are set in `config.toml`:

```toml
[settings.headerOffcanvas]
  enable      = true
  description = ""   # empty uses headerOffcanvas.description from the i18n files

  [settings.headerOffcanvas.button]
    enable = true
    label  = ""      # empty uses headerOffcanvas.buttonLabel
    url    = "/contact/"
```

<Aside type="caution">
  Keep `enable = true`. Without the panel there is no menu on small screens.
</Aside>

The labels of the panel are in the i18n files: `navigation.menuLabel` is the text of the **Menu** button ("Menu"), `navigation.closeMenu` is the screen-reader name of the close button ("Close menu"), `navigation.mainLabel` names the menu for screen readers ("Main"), and `widgets.offcanvasLabel` names the panel ("Site menu"). Change them in every language file. `navigation.languageLabel` is the screen-reader name of the language switch.

The panel is a native `<dialog>`. A closed panel is hidden from the keyboard, so <kbd>Tab</kbd> never lands on links you can't see. Every link and button in the header and the panel shows a visible focus ring.

### Desktop Dropdowns And The Mega Menu
On large screens, every dropdown and the **Services** mega menu open in **one shared panel** under the header. When you move from one menu item to the next, the panel changes its size and content instead of closing and opening again, and a small pointer follows the item.

- **The Services mega menu** shows its link groups as text only. When there are two or more groups, the first one is in large type, with an arrow that appears on hover, and the others are compact lists. The links' icons and descriptions are not shown here. On screens 1320px and wider, the `cta` card sits on the right as a mint pane with a photo, title, text, and button. An optional bar along the bottom adds a line of text, a link, and your phone number.
- **A dropdown**, like **Pages**, is one list. An item that has its own links, like **Home**, shows a small arrow and opens them in a card beside it, a flyout. Flyouts open on hover or with a click.
- **Mouse:** hovering a menu item opens its panel, and moving away closes it after a short pause. A click also opens and closes it.
- **Keyboard:** <kbd>Enter</kbd>, <kbd>Space</kbd>, or <kbd>↓</kbd> on a menu item opens the panel and moves to its first link, and <kbd>↑</kbd> to its last. Inside the panel, <kbd>↑</kbd> and <kbd>↓</kbd> move between links, <kbd>→</kbd> opens a flyout and <kbd>←</kbd> closes it, <kbd>Home</kbd> and <kbd>End</kbd> jump to the first and last link, <kbd>Esc</kbd> closes a flyout or the panel and returns to the item that opened it, and <kbd>Tab</kbd> moves on.
- **Reduced motion:** for visitors who ask for less motion, the panel only fades, without sliding or resizing.

On small screens, the menu lives in the mobile menu panel described above.

You don't need to touch any code to use it: the panel is built from the same menu file (see [Menus](/ecozen/customization/menus/)). Developers find it in `src/layouts/components/global/header/`: `NavStage.astro` (the panel and its script), `NavStageDropdown.astro` and `NavStageList.astro` (a dropdown's list and its flyouts), and `NavStageMega.astro` (the mega menu's groups, photo pane, and bottom bar).

### Files For Developers
All in `src/layouts/components/global/header/`: `Header.astro` picks the layout, `TopBar.astro` draws the contact row (`variant="bar"` for `classic`, `variant="overlay"` for `transparent`), `AnnouncementStrip.astro` draws the strip, `Navbar.astro` and `MenuItem.astro` draw the menu, `LanguageSwitcher.astro` is the language switch, `NavbarToggler.astro` is the **Menu** button, and `DropdownMenu.astro` and `MegaMenu.astro` are the dropdowns and the Services menu inside the mobile panel. The panel itself is `src/layouts/components/widgets/Offcanvas.astro`, with its content in `HeaderOffcanvasContent.astro` in the same folder. Their styles are in `src/styles/navigation.css`.

### Menu Links
The links, the **Services** mega menu, and the dropdowns come from `src/config/menu.<language>.json`. See [Menus](/ecozen/customization/menus/) and [Navigation](../../features/navigation/).

### Do It With AI
```text
Set the header to the [classic | transparent | floating | promo] layout in [settings.header] of
src/config/config.toml, and remove headerLayout from the homepage files I keep (or set it to the
same value). Set the header button in config.toml to "[URL]" and change navigation.buttonLabel in
every file in src/i18n/ to "[LABEL]", translated. Write this announcement in header.announcement in
every i18n file: "[TEXT]" linking to "[URL]", and turn on [settings.announcementBar] if I use classic.
```