# Story Authoring Convention — `@aurora/components`

This document is the single reference for humans **and** agents when writing a new `*.stories.ts`
file under `frontend/src/@aurora/components/**`. Follow it exactly — the `catalyst-component-catalog`
skill relies on these conventions to discover and interpret stories.

## File Naming and Location

- **Colocation (mandatory)**: the story lives next to the component.
  Example: `frontend/src/@aurora/components/data-table/components/table-search.component.ts`
  → `frontend/src/@aurora/components/data-table/components/table-search.stories.ts`.
- **File name**: `<component-kebab-name>.stories.ts`. The base must match the `.component.ts`
  sibling.
- **No central `stories/` tree**: do not create a parallel hierarchy. Refactors must be able to move
  a component and its story in a single diff.

## Type Imports — local shim, not `@storybook/angular`

Stories import `Meta<T>` and `StoryObj<T>` from the **local shim** at
`frontend/src/@aurora/story.types.ts` — NOT from `@storybook/angular`. Storybook is not
installed as a runtime in this project (see `catalyst-component-catalog/SKILL.md > Related
Skills`); the shim provides the exact CSF3 shape so stories typecheck as structured
documentation without a Storybook install. If/when Storybook is reintroduced, the shim is
deleted and imports are redirected to `@storybook/angular`.

## `Meta` Default Export

Every story file MUST default-export a `Meta<TComponent>` object:

```ts
import type { Meta, StoryObj } from '../../../story.types'; // relative path to frontend/src/@aurora/story.types
// ...adjust the number of `../` to reach `frontend/src/@aurora/story.types` from your story file.

const meta: Meta<TableSearchComponent> = {
  title: '@aurora/components/data-table/table-search',
  component: TableSearchComponent,
  tags: ['autodocs'],
  argTypes: { ... },
  args: { ... },
  parameters: { aurora: { ... } }, // see "Aurora Semantic Metadata" below
};

export default meta;
type Story = StoryObj<TableSearchComponent>;
```

### Title Path Format

`@aurora/<area>/<name>` — where:

- `<area>` is the folder segment(s) beneath `components/` (e.g. `components`, `data-table`,
  `data-table/column-toggle`).
- `<name>` is the kebab-cased component name.

Good:

- `@aurora/components/data-table/table-search`
- `@aurora/components/data-table/column-toggle`

Bad:

- `Data Table / Search` (no namespace, not scannable)
- `TableSearch` (missing area)

### `component`

Import the concrete component class. The catalog skill reads this to resolve the canonical import
path — it is NOT optional.

### `tags`

Always include `['autodocs']` unless you have a concrete reason to opt out. Autodocs enables the
Docs tab where `parameters.aurora` appears for AI consumption.

### `argTypes` and `args`

- Declare every meaningful `input()` / `output()` the component exposes.
- Provide a `description` on each argType — this is the prop's AI-readable doc.
- In `args`, set defaults that render the component in a sensible state.
- For outputs (`@Output()` / `output()`), declare them in `argTypes` with `action: '<outputName>'`
  (Storybook-compatible shorthand for action logging). Do NOT pass a mocked function in `args` —
  `fn()` from `storybook/test` only exists when Storybook is installed, which is not the case here.

## Aurora Semantic Metadata (OPTIONAL but strongly preferred)

Declare on the `Meta.parameters` object:

```ts
parameters: {
  aurora: {
    category: 'data-table',
    when: 'One sentence describing the primary use case.',
    whenNot: 'One sentence describing when a different component fits better, naming that alternative.',
  },
},
```

Shape rules:

- `category` — a coarse family grouping: `'data-table' | 'navigation' | 'form' | 'overlay' | ...`.
  Pick from existing categories before inventing new ones.
- `when` — the primary use case. One sentence. No "you can also..." laundry lists.
- `whenNot` — a scenario where a different `@aurora/components` export is the better fit. Name that
  alternative explicitly. This is what makes agent disambiguation work.
- All three fields must be non-empty strings. No `null`, no `undefined`, no empty strings.

Declare `parameters.aurora` whenever multiple `@aurora/components` could plausibly satisfy the same
requirement, or whenever the component is near-trivial but has a specific preferred use-case. Do NOT
declare it if every field would be a useless truism.

## Minimum Required Story Exports

Every `*.stories.ts` MUST export at least:

1. A `Default: StoryObj<T>` variant — renders with the `args` from the Meta.
2. One additional variant demonstrating a non-trivial state: a translated label, an edge-case
   value, an interaction in-progress, a disabled state, etc.

Interactive behavior (click, type, assert output emit) SHOULD be described in prose inside
`parameters.docs.description.story` on the relevant variant. **Do NOT declare a `play` function**:
`play` requires `storybook/test` utilities that only exist when Storybook is installed as a runtime
(which is not the case in this project — see SKILL.md). When Storybook is reintroduced, `play`
becomes the preferred way to encode these assertions; until then, descriptive prose is the
canonical documentation.

## Decorator Usage

**Global decorators** (theme, Transloco, router, HTTP) would normally be registered in
`.storybook/preview.ts`, but since Storybook is not installed in this project, per-story decorators
are not wired to any runtime. Authors should still structure their stories as if these globals
existed — when Storybook is reintroduced, the preview wiring is the only thing missing.

**Per-story decorators** (when Storybook is present) only for:

- Wrapping a composable or directive in a minimal host component (see "Proxy Host Pattern" below).
- Overriding a provider value in a specific variant.
- Adding layout context (e.g. a `matSidenavContainer` wrapper for sidenav stories).

## Proxy Host Pattern (composables and directives)

When the `@aurora/components` export is a composable (like `useBreadcrumbs()`) or a directive
(no standalone component to instantiate), write a minimal host component inside the story file and
use it as `Meta.component`:

```ts
@Component({
  selector: 'aurora-use-breadcrumbs-host',
  imports: [HlmBreadcrumbImports],
  template: `...uses the composable/directive...`,
})
class UseBreadcrumbsHost {
  readonly items = useBreadcrumbs([{ translation: 'navigation.Tags' }]);
}

const meta: Meta<UseBreadcrumbsHost> = {
  title: '@aurora/components/breadcrumb/use-breadcrumbs',
  component: UseBreadcrumbsHost,
  ...
};
```

The story title still follows `@aurora/<area>/<name>` — the `<name>` describes the composable, not
the host.

## Worked Example — `TableSearchComponent` (seed story)

The canonical seed story lives at
`frontend/src/@aurora/components/data-table/components/table-search.stories.ts`. It demonstrates:

- Imports `Meta` and `StoryObj` from the local shim (`../../../story.types`), not `@storybook/angular`
- Title format: `@aurora/components/data-table/table-search`
- `argTypes` with descriptions on every input; the output `search` uses `action: 'search'`
- `parameters.aurora` with `category: 'data-table'`, a concrete `when`, and a `whenNot` pointing to
  `TableFiltersComponent` as the alternative for column-scoped filtering
- Two additional variants: `TranslatedPlaceholder` (demonstrates a Transloco-sourced placeholder)
  and `FastDebounce` (short debounce documented via `parameters.docs.description.story` — the
  intended `play` interaction is described in prose, deferred to the day Storybook is reintroduced)

Read it as the reference implementation before authoring a new story.

## Checklist (agents: iterate on this before returning a story)

- [ ] File lives next to the `.component.ts` sibling (same directory)
- [ ] File name is `<component-kebab-name>.stories.ts`
- [ ] Imports `Meta` / `StoryObj` from the local shim at `frontend/src/@aurora/story.types` (use the correct relative path from the story's location)
- [ ] `Meta.title` follows `@aurora/<area>/<name>`
- [ ] `Meta.component` imports the concrete class
- [ ] `tags: ['autodocs']`
- [ ] Every meaningful `input()` / `output()` has an `argType` with `description`
- [ ] Outputs declared with `action: '<outputName>'`; no `fn()` in `args` (Storybook not installed)
- [ ] At least one `Default` story and one non-trivial variant
- [ ] `parameters.aurora.{category, when, whenNot}` declared whenever disambiguation value exists
- [ ] Interactive behavior documented in `parameters.docs.description.story`; NO `play` function (Storybook not installed)
- [ ] `pnpm --filter aurora-front exec tsc --noEmit -p tsconfig.app.json` passes (story typechecks against the shim)
