# Header & Mobile Action Bar

## Header & Mobile Action Bar

**Files:** `src/config/config.toml`, `src/config/menu.en.json`, `src/i18n/en.json`, `src/content/sections/english/announcement-bar.md`, page frontmatter · **Skill level:** Beginner

Every header has the logo, the menu with its **Services** and **Areas** dropdowns, your phone number, the light/dark button, and one main button ("Get a price"). On phones the menu folds into a menu button, and a bar with **Call** and the main button sits at the bottom of the screen. Homio has four header layouts and an optional announcement bar above them.

<div class="border border-dark">
  ![Homio header with the Services menu open](/images/homio/header.jpg)
</div>

### Choose A Header Layout
```toml
# src/config/config.toml
[settings.layout]
  # default  | logo, menus with dropdowns (trades mega menu, areas), phone pill, sunflower button
  # simple   | the same menus, phone, one button; transparent over a full-bleed hero photo (`band` hero)
  # centered | a white rounded bar floating over the hero photo, menus centred, phone, button
  # utility  | a brand-green strip with a call line above a bar with the menus and one green button
  header = "default"
```

| Layout     | What it looks like                                                                                   | Demo page          |
| ---------- | ---------------------------------------------------------------------------------------------------- | ------------------ |
| `default`  | A white bar: logo, menu, phone pill, light/dark button, and the large sunflower button at the end. Used by the inner pages | `/`                |
| `simple`   | The same menu, phone, and a smaller button. Above a `band` hero (a full-width photo) it is transparent with white links, and turns solid once the page scrolls. On any other page it is a plain solid bar | `/home-handyman/`  |
| `centered` | A white rounded bar that floats over the hero photo, with the menu in the middle                    | `/home-cleaning/`  |
| `utility`  | A slim brand-green strip with "Need help this week? Call us: (number)" above a white bar with the menu and one green button. The phone pill moves into the strip | `/home-commercial/` |

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

```yaml
---
title: "Handyman"
headerLayout: "simple" # default | simple | centered | utility
---
```

The demo homepages set their own this way (`src/content/homepage/english/home-*.md`), and so does `/elements/`. A misspelled value is caught by `npm run astro-check` in files with a schema. The `simple` layout is meant for pages that open with the `band` hero; see [Homepages](/homio/customization/homepages/).

The utility strip's text comes from `utilityBar.help` and `utilityBar.callUs` in `src/i18n/en.json` and `fr.json`. The strip and the announcement bar scroll away; only the main bar stays pinned.

### The Services Mega Menu
The **Services** item fills itself from your services: one column per trade (Cleaning, Repairs, Windows, Carpets, Outdoor), with the trade name as a small heading and up to six services under it. A row at the bottom holds **All services** and the item's own links ("Who we serve", "How it works").

It comes from this item in `src/config/menu.en.json`:

```json
{
  "enable": true,
  "name": "Services",
  "url": "/services/",
  "hasChildren": true,
  "source": "trades",
  "limit": 6,
  "children": [
    { "enable": true, "name": "Who we serve", "url": "/industries/" },
    { "enable": true, "name": "How it works", "url": "/how-it-works/" }
  ]
}
```

- `"source": "trades"` builds the columns from `src/content/services/`: the trades and their order from `trades:` in `services/english/-index.md`, and each service from its `trade` and `order` fields. A new service appears in the menu without a menu edit. A service with `draft: true` is left out.
- `"limit"` is the most services shown per trade.
- `"children"` are the extra links in the bottom row.

### The Areas Menu
```json
{
  "enable": true,
  "name": "Areas",
  "url": "/areas/",
  "hasChildren": true,
  "source": "areas",
  "limit": 8
}
```

`"source": "areas"` lists your service areas from `src/content/areas/`, in their `order`, up to `limit`, then an **All areas (4)** link to `/areas/`. Above six areas the list splits into two columns. Add or remove an area file and the menu follows. See [Service Areas](/homio/customization/service-areas/).

The other dropdowns (**Company**, **Pages**) are plain lists you write yourself: see [Menus](/homio/customization/menus/).

On wide screens all dropdowns open in one panel under the header: hover or click an item, and move between items without the panel closing. The keyboard works too: <kbd>Enter</kbd> or <kbd>Space</kbd> on a menu item opens it, <kbd>Tab</kbd> moves through its links, and <kbd>Esc</kbd> closes it.

### The Phone Pill
The round phone icon in the header calls `[business] phone`. From 1320 px wide it also shows `phoneDisplay` beside the icon. It is hidden when `phone` is empty, and the `utility` layout shows the number in its green strip instead. On an area page with its own local number, the header uses that number. See [Business Info](/homio/customization/business-info/).

### The Main Button
```toml
[settings.navigationButton]
  enable = true
  label  = ""        # i18n `navigation.buttonLabel` ("Get a price"); a value here replaces it in every language
  url    = "/book/"  # Primary header button, hidden on this page itself; the mobile action bar uses the same button
```

To change the words in both languages, edit `navigation.buttonLabel` in `src/i18n/en.json` ("Get a price") and `src/i18n/fr.json` ("Obtenir un prix"). The button is hidden on the page it links to, so `/book/` doesn't show a button to itself.

**A different button on one page.** A `primaryCta` block in the page's frontmatter changes the header button, the phone action bar, the announcement link, and the footer link to the booking page, on that page only. The commercial homepage uses it to send every action to its walkthrough form:

```yaml
primaryCta:
  label: "Request a walkthrough"
  url: "#walkthrough" # a section id on this page, or a path
  announcement: "hide" # link (swap the bar's booking link) | hide | keep
```

**A text link before the button.** `[settings.navigationSecondaryLink]` adds a plain link ("Contact") before the button in every header layout, from 1320 px wide. It ships off:

```toml
[settings.navigationSecondaryLink]
  enable = false
  label  = ""          # navigation.secondaryLabel ("Contact")
  url    = "/contact/"
```

### Sticky Header
```toml
[settings]
  stickyHeader = true # Keeps the header pinned while scrolling (the announcement bar scrolls away)
```

With `true`, the header stays at the top while you scroll, and a thin line appears under it once the page moves. `false` lets it scroll away with the page.

### The Announcement Bar
A thin bar above the header for an offer or a notice, with one link and a close button. It ships **off**. Turn it on in `src/content/sections/english/announcement-bar.md` (and `french/`):

```yaml
---
enable: false # Show the strip above the header on every page
id: "autumn-2026" # Change it when the message changes: visitors who closed the old one see the new one
text: "Autumn deep cleans: book by **Oct 31** and get the oven clean free." # Inline markdown and {phone} work
link:
  enable: true
  label: "Price your visit"
  url: "/book/"
dismissible: true # Visitors can close it; the choice is kept in their browser
start: "" # Optional first day, YYYY-MM-DD
end: "2026-10-31" # Optional last day, YYYY-MM-DD
hideOn: ["/book/"] # Path prefixes where the bar stays hidden (no language prefix)
tone: "ink" # ink | mist
---
```

- `tone`: `ink` is a near-black bar, `mist` a light green one.
- `start` and `end` show the bar only between those dates. `end` is also checked in the visitor's browser, so an old build doesn't show an expired offer.
- The text is a sample offer: replace it, or keep `enable: false`.

### The Mobile Menu
Below 1024 px wide, the menu links fold into a menu button (three lines) at the right of the header. It opens a full panel with:

- the menu items. Dropdowns open as lists inside the panel, with the trades and areas
- a **Call** button and the main button, side by side
- the language switch (En / Fr) and the light/dark button

### The Mobile Action Bar
On phones (below 768 px), a bar is fixed to the bottom of the screen with **Call** and the main button, so a visitor can call or get a price from anywhere on the page.

<div class="border border-dark">
  ![Homio on a phone with the Call and Get a price bar at the bottom](/images/homio/mobile-bar.jpg)
</div>

```toml
# src/config/config.toml
[settings.mobileActionBar]
  enable = true
  showCall = true   # Phone from [business] phone; hidden when it is empty
  showText = false  # Text-message button; needs [business] sms
  hideOn = [
    "/book/",
    "/contact/",
  ]                 # Path prefixes where the bar is not rendered (language prefix ignored)
  hideNearFooter = true # Slide away while the footer is visible
```

- The main button is the header's (`[settings.navigationButton]`, or the page's `primaryCta`).
- `showText = true` adds a **Text** button that opens a text message to `[business] sms`. The bar then has three buttons.
- `hideOn` leaves the bar out on pages that already are the action. `"/book/"` also covers `/book/thanks/`, and `/fr/book/` in French.
- The bar also slides away while a form field has focus, and while the menu or a dialog is open. The cookie banner and the back-to-top button sit above it.
- The button labels are `mobileBar.call` and `mobileBar.text` in the i18n files.

<Aside type="tip">
  Check the bar at 375 px wide after you change the button label. A long label
  next to **Call** can wrap. "Get a price" or "Book now" fit well.
</Aside>

### Files For Developers
All in `src/layouts/components/global/`: `header/Header.astro` picks the layout and adds the announcement bar and the utility strip, `header/SiteHeader.astro` draws the bar, the dropdown panel, and the mobile menu, `header/MegaTrades.astro` and `header/MegaAreas.astro` are the Services and Areas panels, `header/UtilityBar.astro` is the green strip, and `MobileActionBar.astro` is the bottom bar. The announcement bar is `src/layouts/components/widgets/AnnouncementBar.astro`. The menu data is built in `src/lib/utils/menu.ts`, and the styles are in `src/styles/navigation.css`.

### Do It With AI
```text
Set the header to the [default | simple | centered | utility] layout in [settings.layout] of
src/config/config.toml, and list the page files that set their own headerLayout. Change the
header button: url "[URL]" in [settings.navigationButton], and navigation.buttonLabel in
src/i18n/en.json and fr.json to "[LABEL]" / "[FRENCH LABEL]". Keep the label short enough for
the mobile action bar.
```

```text
Turn on the announcement bar: in src/content/sections/english/announcement-bar.md and
french/, set enable: true, text "[TEXT]", the link "[LABEL]" to [URL], end "[YYYY-MM-DD]",
and a new id. On phones, also show a Text button in the mobile action bar
([settings.mobileActionBar] showText = true) with our text number [NUMBER] in [business] sms.
```