# AppHeader Component

<!-- status-badge-start -->

![Status: Stable](https://img.shields.io/badge/-Stable-brightgreen)

<!-- status-badge-end -->

A Vue component for the App Header of the City of Philadelphia's web applications — top trusted-site
banner, main navbar (branding, links, search, mobile burger menu), and an optional alert banner.

## Features

- 🎯 TypeScript support with full type definitions
- 🎨 Customizable options for sticky nav, showing / hiding trusted site, slots for mobile menu, navbar branding, nav links and search
- ♿ Accessibility features: ARIA roles, keyboard navigation
- 📏 Responsive design for mobile and desktop

## Installation

```bash
pnpm add @phila/phila-ui-app-header @phila/phila-ui-core
# or
npm install @phila/phila-ui-app-header @phila/phila-ui-core
```

Import core styles in your main entry file (e.g., `main.js|ts`):

```typescript
import "@phila/phila-ui-core/styles/template-light.css";
```

## Usage

```vue
<script setup lang="ts">
import { AppHeader } from "@phila/phila-ui-app-header";
import MyMobileMenu from "./MyMobileMenu.vue";
import MyTranslationComponent from "./MyTranslationComponent.vue";
import MyServicesComponent from "./MyServicesComponent.vue";

const navLinks = [
  {
    text: "Services",
    href: "/services",
    subNav: MyServicesComponent,
  },
  {
    text: "Departments",
    href: "/departments",
    subLinks: [
      { text: "Department 1", href: "/departments/department-1" },
      { text: "Department 2", href: "/departments/department-2" },
    ],
  },
  {
    text: "About",
    href: "/about",
  },
];
const navbarBrand = {
  brandingImage: {
    href: "/",
    src: "https://www.phila.gov/assets/images/city-of-philadelphia-logo-medium-white.png",
    altText: "City of Philadelphia",
  },
  brandingLink: {
    text: "Mayor Cherelle L. Parker",
    href: "https://phila.gov/departments/mayor",
  },
};
</script>

<template>
  <AppHeader :sticky="true" :show-trusted-site="true" :links="navLinks" :navbar-brand="navbarBrand">
    <template #mobile-nav>
      <MyMobileMenu />
    </template>
    <template #translations>
      <MyTranslationComponent />
    </template>
  </AppHeader>
</template>
```

### Props

| Prop              | Type               | Default      | Description                                                                                                                                                                                             |
| ----------------- | ------------------ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | `string`           | `"main-nav"` | Base id used to derive internal element ids and the visibility group for the burger/search/links.                                                                                                       |
| `sticky`          | `boolean`          | `true`       | Whether the navbar stays fixed to the top of the viewport on desktop.                                                                                                                                   |
| `compactMobile`   | `boolean`          | `false`      | Uses shorter mobile sizing (navbar, burger, logo, trusted banner) below 1024px.                                                                                                                         |
| `navbarBrand`     | `NavbarBrandProps` | `undefined`  | `{ brandingImage?: {src, href, altText}, brandingLink?: {text, href}, logo?: Partial<LogoProps> }` — renders the default branding block. Omit and use the `navbar-brand` slot instead for full control. |
| `links`           | `NavLink[]`        | `undefined`  | `{ text, href, subLinks?, subNav? }[]` — top-level nav links. `subNav` renders a custom flyout component; `subLinks` renders a plain link list.                                                         |
| `showTrustedSite` | `boolean`          | `true`       | Shows/hides the ".gov" trusted-site banner above the navbar.                                                                                                                                            |
| `bannerTitle`     | `string`           | `undefined`  | Title for the optional `AlertBanner` shown below the navbar.                                                                                                                                            |
| `bannerMessage`   | `string`           | `undefined`  | Message for the optional `AlertBanner`. The banner only renders if `bannerTitle` or `bannerMessage` is set.                                                                                             |
| `translations`    | `Component`        | `undefined`  | Component rendered in the trusted-site banner's translation slot when `languages` isn't set and the `translations` slot isn't used.                                                                     |
| `languages`       | `Language[]`       | `undefined`  | `{ code, title, lang? }[]` — when set, renders the built-in `LanguageSwitcher` instead of `translations`.                                                                                               |
| `locale`          | `string`           | `undefined`  | Currently selected language `code`, paired with the `update:locale` emit.                                                                                                                               |
| `className`       | `string`           | `undefined`  | Additional CSS classes.                                                                                                                                                                                 |

### Slots

Most consumers only need `translations`, `mobile-nav`, and possibly `navbar-end`. The rest are
escape hatches that replace an entire section of the navbar for full control.

| Slot            | Description                                                                                                  |
| --------------- | ------------------------------------------------------------------------------------------------------------ |
| `translations`  | Replaces the translation control in the trusted-site banner (falls back to `languages`/`translations` prop). |
| `mobile-nav`    | Content rendered inside the mobile burger menu.                                                              |
| `search-panel`  | Content rendered inside the navbar's search flyout.                                                          |
| `navbar-end`    | Extra content at the far end of the navbar (only rendered if provided).                                      |
| `navbar-toggle` | Replaces the entire mobile burger button (default renders `NavbarBurger` + `mobile-nav`).                    |
| `navbar-left`   | Replaces the entire left side of the navbar (default renders `navbar-brand`).                                |
| `navbar-brand`  | Replaces just the branding block (default renders `NavbarBrand` from the `navbarBrand` prop).                |
| `navbar-right`  | Replaces the entire right side of the navbar (default renders `navbar-links` + `navbar-search`).             |
| `navbar-links`  | Replaces the nav links block (default renders `NavbarLinks` from the `links` prop).                          |
| `navbar-search` | Replaces the search block (default renders `NavbarSearch` wrapping the `search-panel` slot).                 |

### Events

| Event           | Payload  | Description                                                       |
| --------------- | -------- | ----------------------------------------------------------------- |
| `update:locale` | `string` | Emitted with the selected language `code` from `LanguageSwitcher` |

### Flyout sub-navigation

The NavBar component supports flyout sub-navigations. You can provide a Vue component for the `subNav` property of a nav link to render custom content in the flyout. Your component should be wrapped by the `nav-flyout` class so it can be positioned correctly below the navbar.

```vue
<template>
  <div class="nav-flyout">
    <h3>Custom Sub-Navigation</h3>
    <ul>
      <li><a href="/custom-link-1">Custom Link 1</a></li>
      <li><a href="/custom-link-2">Custom Link 2</a></li>
    </ul>
  </div>
</template>
```

### Other exports

`AppHeader` composes several components also exported individually for advanced use:
`NavBar`, `NavbarBrand`, `NavbarBrandLogo`, `NavbarBurger`, `NavbarSearch`, `NavbarLinks`,
`AlertBanner`, `TrustedSite`, `LanguageSwitcher`, and `NavbarInfo` (not currently wired into
`AppHeader`'s own props — use it directly if you need an info tooltip elsewhere).

## Development

### Install Dependencies

```bash
pnpm install
```

### Run Demo

```bash
pnpm dev
```

### Build Library

```bash
pnpm build
```

### Type Check

```bash
pnpm type-check
```

## Test locally in your development environment

```bash
npm pack
cp ./dist/*.tgz ~/path/to/your/local/npm/repo
cd ~/path/to/your/local/npm/repo
npm install *.tgz
```

## Publishing to NPM

Follow the [release instructions](../../RELEASE.md) using changesets.

## License

MIT
