Code Quality Help

Storybook

Purpose and Scope

Storybook serves as the primary environment for isolated component development, debugging, interactive documentation, and visual verification. It allows developers and stakeholders to explore each component’s API, states, and theming capabilities without launching a full host application. A complete, working Storybook story is an integral part of the Definition of Done for every exported component.

Storybook does not replace automated tests but complements them by providing a human‑readable, interactive showcase. It is also used as a communication tool between developers, designers, and QA.

Story File Conventions

Stories follow the colocation principle. For each component, a .stories.ts file exists in the same directory as the component source:

packages/filter/src/lib/ filter.component.ts filter.component.scss filter.component.spec.ts filter.component.stories.ts ...
  • Naming: The file must be named <component‑name>.stories.ts to be automatically detected by Storybook’s default glob.

  • Exports: The file must export a default metadata object and at least one named story (preferably multiple, covering different states).

  • TypeScript: Stories are fully typed using the component’s actual input and output types.

Story Requirements (Definition of Done)

Each component story must satisfy the following criteria:

Basic Story

At least one “Default” story that renders the component with its standard inputs and no special configuration. This acts as the baseline for review.

State Variations

Stories must cover all significant visual or behavioural states of the component. Examples include:

  • Loading, empty, error, or disabled states.

  • With different data sets (none, few items, many items).

  • Interactive states (focused, hovered, active) where applicable.

  • Variations that demonstrate the impact of each @Input()/input().

Stories must be named descriptively (e.g., WithLongText, Disabled, EmptyList).

Interactive Controls

All configurable inputs must be wired to Storybook Controls (via @storybook/addon-controls). This enables users to dynamically change props and observe the component’s response without editing code. For signal‑based inputs, the story must expose them as args:

import type {Meta, StoryObj} from '@storybook/angular'; import {FilterComponent} from './filter.component'; const meta: Meta<FilterComponent> = { title: 'Filter/FilterComponent', component: FilterComponent, argTypes: { filterKey: {control: 'text'}, items: {control: 'object'}, }, }; export default meta; type Story = StoryObj<FilterComponent>; export const Default: Story = { args: { filterKey: 'status', items: [ {id: '1', label: 'Active', active: true}, {id: '2', label: 'Inactive', active: false}, ], }, };

Demonstrating Theming and Customization

Every component must demonstrate its adherence to the two‑level CSS custom property cascade. The recommended approach:

  • Use Storybook Controls to let users modify global (--grain-*) and component‑specific (--component-*) custom properties in real time.

  • Alternatively, provide a “Themed” story that wraps the component in a decorator applying a pre‑defined set of overrides, showing how the component looks with a different font, color scheme, or border radius.

Example using a decorator to apply custom properties:

export const Themed: Story = { args: {...Default.args}, decorators: [ (story) => ({ ...story(), template: ` <div style="--grain-primary-color: #9c27b0; --filter-background: #f3e5f5;"> <story/> </div> `, }), ], };

Alternatively, a dedicated addon like @storybook/addon-themes may allow switching between several theme presets. The chosen method must be consistent across all libraries.

The Definition of Done requires that the theming story visibly differs from the default and clearly shows at least one overridden global variable and one component variable.

03 July 2026