new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Storybook · API · all subjects

configuration

142 notes in this subject, read out of this brain and free to use. This is page 2 of 3.

experimentalReview feature React only

The experimentalReview feature is experimental and React-specific. Type: boolean. Default: false. It enables the experimental agentic review feature, which allows you to review the work an AI agent has done in your Storybook. This feature builds on changeDetection, which must also be enabled (it is enabled by default).

highlight feature

The highlight feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the Highlight feature.

interactions feature

The interactions feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the Interactions feature for debugging interaction tests.

legacyDecoratorFileOrder feature

The legacyDecoratorFileOrder feature can be configured in main.js features. Type: boolean. It applies decorators from preview.js before decorators from addons or frameworks.

measure feature

The measure feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the Measure feature.

outline feature

The outline feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the Outline feature.

sidebarOnboardingChecklist feature

The sidebarOnboardingChecklist feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the onboarding checklist sidebar widget.

menuOnboardingChecklist feature

The menuOnboardingChecklist feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables a link to the onboarding guide in the menu.

toolbars feature

The toolbars feature can be configured in main.js features. Type: boolean.

viewport feature

The viewport feature can be enabled or disabled in main.js features configuration. Type: boolean. Default: true. Enables the Viewport feature.

angularFilterNonInputControls feature Angular only

The angularFilterNonInputControls feature is Angular-specific. Type: boolean. It filters non-input controls in Angular.

logLevel main.js configuration field

The logLevel field in main.js|ts configuration controls Storybook's logs in the browser terminal. It accepts the values 'debug', 'error', 'info', 'trace', or 'warn'. The default value is 'info'. This field is useful for debugging.

managerHead alternative: manager-head.html

If you do not need to programmatically adjust the manager head, you can add scripts and styles to a manager-head.html file instead of using the managerHead configuration function.

managerHead configuration key type and purpose

The managerHead configuration key is a function with type signature (head: string) => string. It allows you to programmatically adjust the manager's HTML <head> element in your Storybook, for example to load a custom font or add a script. It is most often used by addon authors.

previewAnnotations example implementation

Example from @storybook/nextjs framework's preset.ts: const previewAnnotations: StorybookConfig['previewAnnotations'] = (entry = []) => [...entry, import.meta.resolve('@storybook/nextjs/preview')]; This shows how frameworks extend the preview annotations array.

previewAnnotations intended usage

previewAnnotations is mostly used by Storybook frameworks during preset configuration. Storybook users and addon authors should add scripts to preview.js instead of using previewAnnotations in main.js.

previewAnnotations main.js configuration field

previewAnnotations is a field in main.js|ts configuration that accepts either an array of strings or a function. The function takes two parameters: config (an array of strings) and options (Options object), and returns either an array of strings or a Promise resolving to an array of strings. This field is used to add additional scripts to run in the story preview.

previewBody use case

previewBody can be used to conditionally add scripts or styles to the preview body depending on the environment. This is particularly useful for addon authors who need to dynamically modify the preview body based on runtime conditions.

previewBody main config key

previewBody is a main configuration key with type (body: string) => string. It programmatically adjusts the preview <body> of your Storybook. It is most often used by addon authors. The function takes a string parameter and returns a modified string. If you don't need programmatic adjustment, you can add scripts and styles to preview-body.html instead.

previewHead use case

previewHead can be used to conditionally add scripts or styles to the preview head depending on the environment or other conditions.

previewHead alternative: preview-head.html

If you don't need to programmatically adjust the preview head, you can add scripts and styles to preview-head.html instead of using previewHead.

previewHead configuration key

previewHead is a main.js|ts configuration option that takes a function with type (head: string) => string. It programmatically adjusts the preview <head> of your Storybook. This is most often used by addon authors.

Using a function for refs configuration

The refs configuration supports a function-based approach that allows dynamically configuring refs based on runtime configuration.

Disabling refs for package dependencies

Some package dependencies automatically compose their Storybook in yours. You can disable this automatic composition behavior by setting the disable property to true for the specific package name in the refs configuration.

refs configuration purpose

The refs configuration field in main.js|ts is used to configure Storybook composition, which allows composing multiple Storybooks together.

refs configuration type definition

The refs field in main.js|ts accepts an object where keys are reference identifiers and values can be either: (1) an object with properties title (string, required), url (string, required), expanded (boolean, optional), and sourceUrl (string, optional); (2) a function that receives a config object with title, url, expanded, and sourceUrl properties and returns an object with title, url, expanded, and sourceUrl; or (3) an object with a disable boolean property to disable composition.

Non-CSF source file to CSF transpilation example

Example of a non-CSF source file that generates stories dynamically: ```ts // Button.variants.js|ts import { variantsFromComponent, createStoryFromVariant } from '../utils'; import { Button } from './Button'; export const generateStories = () => { const variants = variantsFromComponent(Button); return variants.map((variant) => createStoryFromVariant(variant)); }; ``` This gets transpiled to a CSF file like: ```js // virtual:Button.variants.js|ts import { Button } from './Button'; export default { component: Button, }; export const Primary = { args: { primary: true, }, }; ```

Custom indexer use cases

Common use cases for custom indexers include: (1) Generating stories dynamically from fixture data or API endpoints; (2) Generating stories with an alternative API extending the CSF format; (3) Defining stories in non-JavaScript languages by converting template files to CSF (examples include `@storybook/addon-svelte-csf` for Svelte and `storybook-vue-addon` for Vue); (4) Processing arbitrary content like URL collections and rendering them as sidebar links.

URL collection indexer and Vite plugin example

A custom indexer to process a collection of URLs and render them as sidebar links. First, create a URL collection file (e.g., `src/MyLinks.url.js`) with URLs listed as named exports: ```js export default {}; export const DesignTokens = 'https://www.designtokens.org/'; export const CobaltUI = 'https://cobalt-ui.pages.dev/'; export const MiseEnMode = 'https://mode.place/'; export const IndexerAPI = 'https://github.com/storybookjs/storybook/discussions/23176'; ``` Then create a Vite plugin to transform URL files into CSF components: ```ts import * as acorn from 'acorn'; import * as walk from 'acorn-walk'; import { defineConfig, type Plugin } from 'vite'; function StorybookUrlLinksPlugin(): Plugin { return { name: 'storybook-url-links', async transform(code: string, id: string) { if (id.endsWith('.url.js')) { const ast = acorn.parse(code, { ecmaVersion: 2020, sourceType: 'module', }); const namedExports: string[] = []; let defaultExport = 'export default {};'; walk.simple(ast, { ExportNamedDeclaration(node: acorn.ExportNamedDeclaration) { if (node.declaration && node.declaration.type === 'VariableDeclaration') { node.declaration.declarations.forEach((declaration) => { if ('name' in declaration.id) { namedExports.push(declaration.id.name); } }); } }, ExportDefaultDeclaration(node: acorn.ExportDefaultDeclaration) { defaultExport = code.slice(node.start, node.end); }, }); return { code: ` import RedirectBack from '../../.storybook/components/RedirectBack.svelte'; ${namedExports .map((name) => `export const ${name} = () => new RedirectBack();`) .join('\n')} ${defaultExport} `, map: null, }; } }, }; } ```

URL indexer configuration example

Update your Storybook configuration to include the custom URL indexer: ```ts import type { StorybookConfig } from '@storybook/your-framework'; import type { Indexer } from 'storybook/internal/types'; const urlIndexer: Indexer = { test: /\.url\.js$/, createIndex: async (fileName, { makeTitle }) => { const fileData = await import(fileName); return Object.entries(fileData) .filter(([key]) => key != 'default') .map(([name, url]) => { return { type: 'docs', importPath: fileName, exportName: name, title: makeTitle(name) .replace(/([a-z])([A-Z])/g, '$1 $2') .trim(), __id: `url--${name}--${encodeURIComponent(url as string)}`, tags: ['!autodocs', 'url'], }; }); }, }; const config: StorybookConfig = { stories: ['../src/**/*.stories.@(js|ts|svelte)', '../src/**/*.url.js'], framework: { name: '@storybook/svelte-vite', options: {}, }, experimental_indexers: async (existingIndexers) => [urlIndexer, ...existingIndexers], }; export default config; ```

Custom indexer implementation with JSON fixture data example

An example indexer that generates stories for components based on JSON fixture data, looking for `*.stories.json` files: ```ts const jsonStoriesIndexer: Indexer = { test: /\.stories\.json$/, createIndex: async (fileName, { makeTitle }) => { const content = JSON.parse(await fs.readFile(fileName, 'utf-8')); const entries: IndexInput[] = []; Object.entries(content).forEach(([componentName, componentData]: [string, any]) => { const { componentPath, stories } = componentData; Object.entries(stories).forEach(([storyName, storyConfig]: [string, any]) => { entries.push({ type: 'story', importPath: `virtual:jsonstories--${fileName}--${componentName}`, exportName: storyName, title: makeTitle(`${componentName}/${storyName}`), }); }); }); return entries; }, }; ```

Vite plugin for JSON stories transformation example

A Vite plugin to transform JSON stories into CSF: ```ts import type { PluginOption } from 'vite'; import fs from 'fs/promises'; function JsonStoriesPlugin(): PluginOption { return { name: 'vite-plugin-storybook-json-stories', load(id) { if (!id.startsWith('virtual:jsonstories')) { return; } const [, fileName, componentName] = id.split('--'); const content = JSON.parse(fs.readFileSync(fileName)); const { componentPath, stories } = getComponentStoriesFromJson(content, componentName); return ` import ${componentName} from '${componentPath}'; export default { component: ${componentName} }; ${stories.map((story) => `export const ${story.name} = ${story.config};\n`)} `; }, }; } ```

importPath requirement for CSF files

The value of `importPath` in an `IndexInput` must resolve to a CSF file. Custom indexers are often necessary because the input is not CSF. Therefore, you will likely need to transpile the input to CSF so that Storybook can read it in the browser and render your stories. For Webpack-based projects, custom importPaths are not supported and you must transpile the source file to CSF and leave `importPath` empty to use the original `fileName`.

IndexInput type definition

IndexInput is an object representing a story to be added to the stories index with the following properties: - `exportName` (Required): string - The export to add as an entry in the index - `importPath` (Optional): string - Default: The original `fileName` passed to createIndex. The file to import from, e.g. the CSF file. Custom `importPath`s are only supported in Vite-based projects; Webpack-based projects require transpilation to CSF. - `type` (Required): 'story' - The type of entry - `subtype` (Experimental, Optional): 'story' | 'test' - Default: 'story'. The subtype of the story entry when type is 'story'. Use to mark an entry as a test. - `rawComponentPath` (Optional): string - The raw path/package of the file that provides `meta.component` - `metaId` (Optional): string - Default: Auto-generated from title. Custom id for meta of the entry. If specified, the export default (meta) in the CSF file must have a corresponding `id` property. - `name` (Optional): string - Default: Auto-generated from exportName. The name of the entry. - `tags` (Optional): string[] - Tags for filtering entries in Storybook and its tools - `title` (Optional): string - Default: Auto-generated from the meta of importPath. Determines the location of the entry in the sidebar. Should use the `makeTitle` function from IndexerOptions when specifying. - `__id` (Optional): string - Default: Auto-generated from title/metaId and exportName. Custom id for the story of the entry. If specified, the story in the CSF file must have a corresponding `__id` property.

IndexerOptions type definition

IndexerOptions has the following structure: - `makeTitle` (Required): `(userTitle?: string) => string` - A function that takes a user-provided title and returns a formatted title for the index entry, which is used in the sidebar. If no user title is provided, one is automatically generated based on the file name and path.

createIndex function signature and parameters

The `createIndex` function has the type `(fileName: string, options: IndexerOptions) => Promise<IndexInput[]>`. It accepts a single CSF file and returns a list of entries to index. The `fileName` parameter is a string representing the name of the CSF file used to create entries to index. The `options` parameter is of type `IndexerOptions`.

Indexer test property

The `test` property is a required RegExp that is run against file names included in the `stories` configuration. It should match all files to be handled by this indexer.

Indexer type definition

An Indexer object has the following properties: - `test` (Required): RegExp - A regular expression run against file names that should match all files to be handled by this indexer - `createIndex` (Required): `(fileName: string, options: IndexerOptions) => Promise<IndexInput[]>` - Function that accepts a single CSF file and returns a list of entries to index

Indexer purpose and functionality

Indexers are responsible for building Storybook's index of stories—the list of all stories and a subset of their metadata like `id`, `title`, `tags`, and more. The index can be read at the `/index.json` route of your Storybook. Custom indexers allow you to customize how Storybook indexes and parses files into story entries, adding flexibility to how stories can be written and where they come from.

Indexers API function signature

Indexers are defined as a function with the type `(existingIndexers: Indexer[]) => Promise<Indexer[]>`. The function returns the full list of indexers, including the existing ones, which allows you to add your own indexer to the list or replace an existing one.

Transpiling to CSF architecture

The transpilation process works in two stages: (1) During indexing, Storybook uses the `stories` configuration to find files matching the indexer's `test` property, passes each to `createIndex` function to generate index entries; (2) During browser rendering, when a user navigates to a story URL, the builder plugin transpiles the source file to CSF and serves it, then the UI imports and renders the story from the CSF file using the `exportName` property.

experimental_indexers configuration property

The indexers API is experimental and must be specified by the `experimental_indexers` property of `StorybookConfig` in main.js|ts configuration.

makeTitle function usage for custom titles

When specifying a title in IndexInput, you must use the `makeTitle` function provided in `IndexerOptions` to use Storybook's default naming behavior. You should not specify a title most of the time, so that your indexer will use the default naming behavior. When you do specify a title, call `makeTitle(userTitle)` to format it properly.

JSON fixture data example for stories

Example JSON fixture data file format for generating stories: ```json { "Button": { "componentPath": "./button/Button.jsx", "stories": { "Primary": { "args": { "primary": true } }, "Secondary": { "args": { "primary": false } } } }, "Dialog": { "componentPath": "./dialog/Dialog.jsx", "stories": { "Closed": {}, "Open": { "args": { "isOpen": true } } } } } ```

staticDirs with configuration objects

staticDirs can use configuration objects with from and to properties to define source and destination directories for static files.

staticDirs main configuration

The staticDirs field in main.js|ts configuration sets a list of directories of static files to be loaded by Storybook. It accepts an array of either strings or configuration objects. Type is (string | { from: string; to: string })[].

Vite publicDir interaction with staticDirs

When using Vite-based frameworks, additional directories may be copied to the build directory because of Vite's own static asset handling. You can set Vite's publicDir option to false to disable this behavior and prevent unintended directory copying.

swc main.js configuration key

The swc key in main.js|ts configuration customizes Storybook's SWC setup for Webpack-based projects. Its type is a function: (config: swc.Options, options: Options) => swc.Options | Promise<swc.Options>. It is enabled via the @storybook/addon-webpack5-compiler-swc addon and is supported on all frameworks except Angular, Create React App, Ember.js and Next.js.

SWC Options type in main.js

The Options type for the swc configuration key has the structure: { configType?: 'DEVELOPMENT' | 'PRODUCTION' }. The configType property is optional. There are other options that are difficult to document; developers should introspect the type definition for more information.

stories field in main.js|ts - type and requirement

The stories field is required in the main configuration. It accepts either an array of strings or StoriesSpecifier objects, or an async function that takes an array and returns an array. Type: (string | StoriesSpecifier)[] | async (list: (string | StoriesSpecifier)[]) => (string | StoriesSpecifier)[]

stories field purpose

The stories field configures Storybook to load stories from specified locations. The intention is to colocate a story file along with the component it documents, such as Button.ts and Button.stories.ts in the same directory.

picomatch glob syntax for stories

The glob patterns in the stories field use the syntax supported by picomatch. You can use this to implement different naming conventions for story files, though some addons may assume Storybook's default naming convention.

StoriesSpecifier interface definition

StoriesSpecifier is an object type with the following fields: directory (string, required) indicating where to start looking for story files relative to project root; files (string, optional, default '**/*.@(mdx|stories.@(js|jsx|mjs|ts|tsx))') a glob relative to the directory that matches filenames to load; titlePrefix (string, optional, default '') a prefix used when auto-titling stories.

stories loading order with array of globs

When using an array of globs, Storybook loads stories from the project as found by the glob patterns. Stories are loaded in the order they are defined in the array, which allows control over the order stories appear in the sidebar.

Custom logic for loading stories

You can implement custom logic in the stories field by using an async function. However, this may de-optimize or break Storybook's static analysis of the configuration file, which is used to improve performance.

tags field in main.js/ts configuration

The tags field is a configuration option in main.js or main.ts that allows you to define custom tags for your stories or alter the default configuration of built-in tags. The type is { [tagName: string]: { defaultFilterSelection?: 'include' | 'exclude' } }.

tags[tagName].defaultFilterSelection configuration

The defaultFilterSelection property within a tag configuration has type 'include' | 'exclude'. When set to 'include', stories with this tag are selected as included by default in the Storybook sidebar filter. When set to 'exclude', stories with this tag are selected as excluded by default and must be explicitly included by selecting the tag in the sidebar filter menu. If not set, the tag has no default selection.

tags[tagName] configuration

The tagName key within the tags configuration is a string that represents the name of the tag. This can be any static (not created dynamically) string, and can be either a built-in tag or a custom tag of your own design.

viteFinal Options type

The Options parameter for viteFinal has the type { configType?: 'DEVELOPMENT' | 'PRODUCTION' }. The configType property is optional and can be either 'DEVELOPMENT' or 'PRODUCTION'. There are other options available that are difficult to document, and the type definition should be introspected for more information.

viteFinal main config field

The viteFinal field in main.js/ts configuration is a function that customizes Storybook's Vite setup when using the Vite builder. It takes two parameters: config (Vite.InlineConfig) and options (Options), and returns either Vite.InlineConfig or Promise<Vite.InlineConfig>. The function signature is (config: Vite.InlineConfig, options: Options) => Vite.InlineConfig | Promise<Vite.InlineConfig>.

Give your agent this brain