# Header Widget

Level: organism.

## Purpose and use

Identify a record/detail screen and group its primary actions and section tabs.
Use a smaller heading composition when the page already has its own h1.

## Anatomy, behavior, and accessibility

- A back icon button, h1 title and optional status badge form the heading; actions
  occupy the trailing group and an optional Tab Horiz Row sits beneath it.
- Blank action/tab labels and blank status text are omitted. Disabled or loading
  actions do not emit. Back and action events do not perform navigation.
- An action may provide `iconName`; the Header Widget renders that owned icon
  before the still-visible action label. Omitting the field preserves the
  text-only button. The label remains the accessible name in both cases.
- `iconPosition: 'right'` moves that icon after the label (a dropdown chevron,
  as «Создать тендер» in Figma `jwmCEMZZjn9cieKYqxI6FL`, node `17982:207961`).
  `showLabel: false` renders an icon-only button; the label is then exposed
  as its `aria-label`. Both fields are optional and default to the previous
  leading-icon, visible-label behaviour.
- A-005: `badges` replaces the single success status badge with an ordered
  list of `{ label, appearance }` badges (size M), as «Внешний заказчик»
  (`clear`) and «Сбор заявок на участие» (`warning`) on the outer-customer
  tender page, Figma `jwmCEMZZjn9cieKYqxI6FL`, node `17265:117041`. `null`
  (default) keeps the previous `statusLabel` success badge; `showStatus: false`
  hides all badges; blank labels are omitted.
- A-005: an action may use `variant: 'secondary-danger'` for a destructive
  action such as «Отменить лот» with the `circle-close` icon (same node).
- Tab selection emits selectedTabIdChange and tabSelect through the child; the
  parent updates selectedTabId and page content. tabsAriaLabel names the tablist.
- The back button keeps backLabel as its accessible name. Use the record identity
  in the title and specific verbs for actions; supplied fixture names are examples.

- With `adaptive=true`, Header Widget measures its own inline size. Below 1024px
  (the same threshold as Table cards, so phones and the 780px tablet) it switches to a compact layout: the back
  button uses size S, the title uses `--typography-title-2-pig` (19/22) and
  wraps to at most two lines before truncating, badges move to a line under the
  title, and all actions collapse into one «more» (three dots) Dropdown to the
  right of the title; the back and «more» icons sit flush with the widget edges. Selecting a menu item emits the same `actionClick`;
  disabled or loading actions are disabled items. `adaptive` defaults to
  `false`, so existing consumers are unchanged.

## Open Questions

Adaptive compact layout (A-011, prototype under review): the reduced back-button
and title sizes are a local decision without Figma evidence for a mobile Header
Widget; the 1024px threshold is a component constant, not a token. Action
variants (primary, danger) are not distinguished inside the menu, and tabs keep
their desktop layout.

The single `statusLabel` badge stays success; other appearances go through
`badges` (A-005). Tab panel linkage and missing arrow-key navigation remain
the limitations of Tab Horiz Row.

## Local component contract

This is the active owned contract for `component.header-widget`. The API below
is verified against the current local implementation, focused test and story.
The Source commit `0112cba0779a2d2a4b6c7a17243201694344d70a` remains
migration provenance, not the runtime owner.

M-002 adds the optional `WblHeaderWidgetAction.iconName` field below. It is
implemented in the local component, covered by the focused test, and represented
in Storybook.

### Classes and selectors

- `WblHeaderWidgetComponent` — `wbl-header-widget` (src/app/design-system/patterns/header-widget/header-widget.component.ts).

### Inputs

- `WblHeaderWidgetComponent.title = input('673277 - Внуково - Коледино')`
- `WblHeaderWidgetComponent.showBackButton = input(true)`
- `WblHeaderWidgetComponent.backLabel = input('Назад')`
- `WblHeaderWidgetComponent.showStatus = input(true)`
- `WblHeaderWidgetComponent.statusLabel = input('Открыт')`
- `WblHeaderWidgetComponent.badges = input<WblHeaderWidgetBadge[] | null>(null)` (A-005)
- `WblHeaderWidgetComponent.showActions = input(true)`
- `WblHeaderWidgetComponent.actions = input<WblHeaderWidgetAction[]>(DEFAULT_ACTIONS)`
- `WblHeaderWidgetComponent.showTabs = input(true)`
- `WblHeaderWidgetComponent.tabs = input<WblTabHorizRowItem[]>(DEFAULT_TABS)`
- `WblHeaderWidgetComponent.selectedTabId = input(DEFAULT_TABS[0].id)`
- `WblHeaderWidgetComponent.tabsAriaLabel = input('Разделы карточки')`
- `WblHeaderWidgetComponent.adaptive = input(false)`
- `WblHeaderWidgetComponent.moreActionsLabel = input('Действия')`

### Public types and allowed values

```ts
/** A-005: one heading badge; several render in order after the title. */
type WblHeaderWidgetBadge = {
  label: string;
  appearance: WblBadgeAppearance;
};
type WblHeaderWidgetAction = {
  id: string;
  label: string;
  /** A-005 adds 'secondary-danger'. */
  variant?: 'primary' | 'secondary' | 'secondary-danger';
  /** Optional owned icon; leading unless iconPosition is 'right'. */
  iconName?: WblIconName;
  /** A-002: icon placement, defaults to 'left'. */
  iconPosition?: 'left' | 'right';
  /** A-002: false renders an icon-only button named by label. */
  showLabel?: boolean;
  disabled?: boolean;
  loading?: boolean;
};
type WblTabHorizRowItem = {
  id: string;
  label: string;
  disabled?: boolean;
  badge?: boolean;
  badgeLabel?: string | number;
  icon?: boolean;
};
```

### Models

- None.

### Outputs

- `WblHeaderWidgetComponent.backClick = output<void>()`
- `WblHeaderWidgetComponent.actionClick = output<WblHeaderWidgetAction>()`
- `WblHeaderWidgetComponent.selectedTabIdChange = output<string>()`
- `WblHeaderWidgetComponent.tabSelect = output<WblTabHorizRowItem>()`

### Slots and projection markers

- The exact template has no Angular content-projection slot.

### Local evidence

- Code: `src/app/design-system/patterns/header-widget/header-widget.component.ts`.
- Focused test: `src/app/design-system/patterns/header-widget/header-widget.component.spec.ts`.
- Public export: `export * from './patterns/header-widget/header-widget.component';` in `src/app/design-system/index.ts`.
- Storybook: `storybook/stories/header-widget.stories.ts` (`Design System/Patterns/wbl-header-widget`).

## Figma status

This runtime contract does not infer a Figma owner. Assembly evidence, when
verified, is maintained separately through the inventory-linked sidecar.

Read-only screen evidence in Figma file `uGBDiLA947AJwkuvpohikQ`, node
`16970:22753`, shows the M-002 primary action «Создать заявку» with the owned
`plus16` leading icon. This supports the optional action-level icon API; it does
not make `plus16` a reusable default or establish a Header Widget Figma owner.
The inventory entry therefore keeps `figmaSidecar: null`.

The local template forwards an action with `iconName: 'plus16'` as
`[leftIcon]="true"` and passes the exact icon name to Button. The focused test
covers this mapping, while the existing disabled/loading emission guard and
visible label remain intact. The updated Storybook action data contains the
icon-enabled primary action.

A-005 adds `badges` and the `secondary-danger` action variant; both are
covered by the focused test and the `BadgesAndDangerAction` story.

M-002 verification reported 38/38 focused unit tests passing together with the
application build, Storybook build, design-system check, and Memory check.

## Provenance

The archived source-document copy is historical evidence only. The active
resolver is local code/test/export and the exact Storybook story above.
