Storybook for Angular: Develop, document, and test UI components in isolation
—
Core types and interfaces for defining Angular component stories using Component Story Format (CSF) v2 and v3.
Metadata configuration for Angular component stories. This is the default export of a story file.
/**
* Metadata to configure the stories for a component.
* Used as the default export in story files.
*/
type Meta<TArgs = Args> = ComponentAnnotations<AngularRenderer, TransformComponentType<TArgs>>;Usage Example:
import type { Meta } from "@storybook/angular";
import { ButtonComponent } from "./button.component";
const meta: Meta<ButtonComponent> = {
title: "Example/Button",
component: ButtonComponent,
parameters: {
layout: "centered",
},
argTypes: {
backgroundColor: { control: "color" },
size: {
control: { type: "select" },
options: ["small", "medium", "large"],
},
},
};
export default meta;Story function type that represents a component example using CSF v2 format.
/**
* Story function that represents a CSFv2 component example.
* Functions that return story configuration objects.
*/
type StoryFn<TArgs = Args> = AnnotatedStoryFn<AngularRenderer, TransformComponentType<TArgs>>;Usage Example:
import type { Meta, StoryFn } from "@storybook/angular";
import { ButtonComponent } from "./button.component";
export const Primary: StoryFn<ButtonComponent> = (args) => ({
props: args,
template: `<app-button [primary]="primary" [label]="label"></app-button>`,
});
Primary.args = {
primary: true,
label: "Button",
};Story object type that represents a component example using CSF v3 format.
/**
* Story object that represents a CSFv3 component example.
* Objects with args, parameters, and other story configuration.
*/
type StoryObj<TArgs = Args> = StoryAnnotations<AngularRenderer, TransformComponentType<TArgs>>;Usage Example:
import type { Meta, StoryObj } from "@storybook/angular";
import { ButtonComponent } from "./button.component";
const meta: Meta<ButtonComponent> = {
title: "Example/Button",
component: ButtonComponent,
};
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
primary: true,
label: "Button",
},
};
export const Secondary: Story = {
args: {
label: "Button",
},
parameters: {
docs: {
description: {
story: "Secondary button variant",
},
},
},
};Type for story decorators that can modify or wrap story rendering.
/**
* Function type for story decorators
*/
type Decorator<TArgs = StrictArgs> = DecoratorFunction<AngularRenderer, TArgs>;Usage Example:
import type { Decorator } from "@storybook/angular";
import { moduleMetadata } from "@storybook/angular";
const withCommonModule: Decorator = moduleMetadata({
imports: [CommonModule],
});
export const decorators: Decorator[] = [withCommonModule];Type for story loaders that can load data before story rendering.
/**
* Function type for story loaders
*/
type Loader<TArgs = StrictArgs> = LoaderFunction<AngularRenderer, TArgs>;Usage Example:
import type { Loader } from "@storybook/angular";
const fetchUserData: Loader = async (context) => {
const userId = context.args.userId;
const userData = await fetch(`/api/users/${userId}`).then(res => res.json());
return { userData };
};
export const WithUserData: Story = {
loaders: [fetchUserData],
render: (args, { loaded: { userData } }) => ({
props: { ...args, userData },
template: `<user-profile [user]="userData"></user-profile>`,
}),
};Context object passed to decorators, loaders, and render functions containing story information.
/**
* Context object containing story information and parameters
*/
type StoryContext<TArgs = StrictArgs> = GenericStoryContext<AngularRenderer, TArgs>;Usage Example:
const dynamicDecorator: Decorator = (storyFn, context) => {
const story = storyFn();
// Access story information
console.log('Story ID:', context.id);
console.log('Story args:', context.args);
console.log('Story parameters:', context.parameters);
return {
...story,
template: `<div class="story-wrapper">${story.template}</div>`,
};
};Type for global preview configuration that applies to all stories.
/**
* Global preview configuration type
*/
type Preview = ProjectAnnotations<AngularRenderer>;Usage Example:
// .storybook/preview.ts
import type { Preview } from "@storybook/angular";
import { setCompodocJson } from "@storybook/addon-docs/angular";
import docJson from "../documentation.json";
setCompodocJson(docJson);
const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
},
decorators: [
moduleMetadata({
imports: [CommonModule],
}),
],
};
export default preview;Angular components with InputSignals and EventEmitters are automatically transformed for better type safety in stories.
/**
* Utility type that transforms InputSignal and EventEmitter types
* for better story argument type safety
*/
type TransformComponentType<T> = TransformInputSignalType<
TransformOutputSignalType<TransformEventType<T>>
>;
/**
* Transform InputSignal<T> to T
*/
type TransformInputSignalType<T> = {
[K in keyof T]: T[K] extends InputSignal<infer E>
? E
: T[K] extends InputSignalWithTransform<any, infer U>
? U
: T[K];
};
/**
* Transform OutputEmitterRef<T> to (e: T) => void
*/
type TransformOutputSignalType<T> = {
[K in keyof T]: T[K] extends OutputEmitterRef<infer E> ? (e: E) => void : T[K];
};
/**
* Transform EventEmitter<T> to (e: T) => void
*/
type TransformEventType<T> = {
[K in keyof T]: T[K] extends EventEmitter<infer E> ? (e: E) => void : T[K];
};These transformations ensure that:
InputSignal<string> properties become string in story argsEventEmitter<MouseEvent> properties become (e: MouseEvent) => void in story argsOutputEmitterRef<number> properties become (e: number) => void in story argsThe following types are re-exported from Storybook core for convenience:
type Args = Record<string, any>;
type ArgTypes = Record<string, ArgType>;
type Parameters = Record<string, any>;
type StrictArgs = Record<string, unknown>;Install with Tessl CLI
npx tessl i tessl/npm-storybook--angular