CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook--preview-web

Deprecated preview web functionality for Storybook that re-exports APIs from @storybook/preview-api

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

Storybook Preview Web

Storybook Preview Web is a deprecated facade package that provides web-specific preview functionality for Storybook. This package served as a compatibility layer during the transition to @storybook/preview-api and is scheduled for removal in Storybook 8.0.

⚠️ Deprecation Notice: This package is deprecated and will be removed in Storybook 8.0. Users should migrate to importing directly from @storybook/preview-api.

Package Information

  • Package Name: @storybook/preview-web
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @storybook/preview-web
  • Status: Deprecated (scheduled for removal in v8.0)

Core Imports

import { 
  PreviewWeb, 
  DocsContext, 
  simulatePageLoad, 
  simulateDOMContentLoaded,
  composeStory,
  composeStories,
  setProjectAnnotations
} from "@storybook/preview-web";

For CommonJS:

const { 
  PreviewWeb, 
  DocsContext, 
  simulatePageLoad, 
  simulateDOMContentLoaded,
  composeStory,
  composeStories,
  setProjectAnnotations
} = require("@storybook/preview-web");

Basic Usage

import { 
  PreviewWeb, 
  DocsContext, 
  simulatePageLoad, 
  simulateDOMContentLoaded,
  composeStory
} from "@storybook/preview-web";

// Initialize preview web instance (sets up global __STORYBOOK_PREVIEW__)
const preview = new PreviewWeb();

// DocsContext is typically created internally by Storybook
// but shows the required constructor signature
const docsContext = new DocsContext(
  channel,
  store,
  renderStoryToElement,
  csfFiles
);

// Simulate page events for testing
simulatePageLoad(document.body);
simulateDOMContentLoaded();

// Compose story for testing
import * as ButtonStories from './Button.stories';
const Primary = composeStory(ButtonStories.Primary, ButtonStories.default);
const renderedStory = Primary({ label: 'Hello World' });

Migration Guide

From (deprecated):

import { PreviewWeb, DocsContext } from "@storybook/preview-web";

To (recommended):

import { PreviewWeb, DocsContext } from "@storybook/preview-api";

Capabilities

Preview Management

Core preview functionality for managing Storybook's preview environment and story rendering.

class Preview<TRenderer extends Renderer> {
  constructor();
  // Core preview functionality methods
}

class PreviewWithSelection<TFramework extends AnyFramework> extends Preview<TFramework> {
  constructor();
  // Selection and navigation functionality
}

class PreviewWeb<TFramework extends AnyFramework> extends PreviewWithSelection<TFramework> {
  constructor();
  // Web-specific preview implementation
  // Sets up global __STORYBOOK_PREVIEW__ instance
}

Documentation Context

Documentation context management for rendering stories in documentation mode.

class DocsContext<TRenderer extends Renderer> {
  constructor(
    channel: Channel,
    store: StoryStore<TRenderer>,
    renderStoryToElement: DocsContextProps<TRenderer>['renderStoryToElement'],
    csfFiles: CSFFile<TRenderer>[]
  );
  
  // Core documentation methods
  referenceMeta(metaExports: ModuleExports, attach: boolean): void;
  resolveOf<TType extends ResolvedModuleExportType>(
    moduleExportOrType: ModuleExport | TType,
    validTypes?: TType[]
  ): ResolvedModuleExportFromType<TType, TRenderer>;
  storyIdByName(storyName: StoryName): StoryId;
  storyById(id?: StoryId): PreparedStory<TRenderer>;
  componentStories(): PreparedStory<TRenderer>[];
  getStoryContext(story: PreparedStory<TRenderer>): StoryContextForLoaders<TRenderer>;
  loadStory(id: StoryId): Promise<PreparedStory<TRenderer>>;
}

interface DocsContextProps<TRenderer extends Renderer> {
  // Meta and story resolution
  referenceMeta: (metaExports: ModuleExports, attach: boolean) => void;
  resolveOf<TType extends ResolvedModuleExportType>(
    moduleExportOrType: ModuleExport | TType,
    validTypes?: TType[]
  ): ResolvedModuleExportFromType<TType, TRenderer>;
  
  // Story lookup and access
  storyIdByName: (storyName: StoryName) => StoryId;
  storyById: (id?: StoryId) => PreparedStory<TRenderer>;
  componentStories: () => PreparedStory<TRenderer>[];
  
  // Story context and rendering
  getStoryContext: (story: PreparedStory<TRenderer>) => StoryContextForLoaders<TRenderer>;
  loadStory: (id: StoryId) => Promise<PreparedStory<TRenderer>>;
  renderStoryToElement: (
    story: PreparedStory<TRenderer>,
    element: HTMLElement,
    callbacks: RenderContextCallbacks<TRenderer>,
    options: StoryRenderOptions
  ) => () => Promise<void>;
  
  // Communication and configuration
  channel: Channel;
  projectAnnotations: NormalizedProjectAnnotations<TRenderer>;
}

type DocsRenderFunction<TRenderer extends Renderer> = (
  docsContext: DocsContextProps<TRenderer>,
  docsParameters: Parameters,
  element: HTMLElement
) => Promise<void>;

interface RenderContextCallbacks<TRenderer extends Renderer> {
  showMain: () => void;
  showError: (error: { title: string; description: string }) => void;
  showException: (err: Error) => void;
}

interface StoryRenderOptions {
  autoplay?: boolean;
  forceInitialArgs?: boolean;
}

Page Simulation

Utilities for simulating browser events, primarily used for testing and initialization.

/**
 * Simulates a page load event by executing scripts in a container
 * @param $container - The container element to process scripts from
 */
function simulatePageLoad($container: any): void;

/**
 * Simulates a DOM content loaded event on the document
 */
function simulateDOMContentLoaded(): void;

Testing Utilities

Functions for composing and testing individual stories in isolation, useful for unit testing components.

/**
 * Composes a single story for use in testing environments
 * @param storyExport - The story export from a CSF file
 * @param metaExport - The meta export from the same CSF file  
 * @param projectAnnotations - Global project configuration
 * @returns Composed story function ready for testing
 */
function composeStory<TRenderer extends Renderer>(
  storyExport: StoryAnnotation<TRenderer>,
  metaExport: Meta<TRenderer>,
  projectAnnotations?: ProjectAnnotations<TRenderer>
): ComposedStory<TRenderer>;

/**
 * Composes all stories from a CSF module for testing
 * @param csfExports - All exports from a CSF file
 * @param projectAnnotations - Global project configuration
 * @returns Object with all composed stories keyed by export name
 */
function composeStories<TRenderer extends Renderer>(
  csfExports: ModuleExports,
  projectAnnotations?: ProjectAnnotations<TRenderer>
): ComposedStoryModule<TRenderer>;

/**
 * Sets global project annotations for story composition
 * @param projectAnnotations - Global configuration to apply to all composed stories
 */
function setProjectAnnotations<TRenderer extends Renderer>(
  projectAnnotations: ProjectAnnotations<TRenderer>
): void;

Configuration Management

Legacy configuration composition functionality (marked for removal).

/**
 * Composes multiple configuration objects into project annotations
 * @deprecated Marked for removal in 7.0, used for builder-vite compatibility
 */
function composeConfigs<TRenderer extends Renderer>(
  moduleExportList: ModuleExports[]
): ProjectAnnotations<TRenderer>;

Types

/**
 * Type alias for web-specific project annotations
 */
type WebProjectAnnotations = ProjectAnnotations;

/**
 * Composed story ready for testing with args, parameters, and play functions
 */
interface ComposedStory<TRenderer extends Renderer> extends StoryFn<TRenderer> {
  args: Args;
  parameters: Parameters;
  play?: (context: StoryContext<TRenderer>) => Promise<void> | void;
  storyName: string;
}

/**
 * Module containing all composed stories from a CSF file
 */
interface ComposedStoryModule<TRenderer extends Renderer> {
  [storyName: string]: ComposedStory<TRenderer>;
}

/**
 * Core story annotation with metadata
 */
interface StoryAnnotation<TRenderer extends Renderer> {
  args?: Partial<Args>;
  parameters?: Parameters;
  decorators?: DecoratorFunction<TRenderer>[];
  loaders?: LoaderFunction<TRenderer>[];
  play?: (context: StoryContext<TRenderer>) => Promise<void> | void;
  render?: StoryFn<TRenderer>;
  name?: string;
}

/**
 * Meta configuration for a CSF file
 */
interface Meta<TRenderer extends Renderer> {
  title?: string;
  component?: TRenderer['component'];
  subcomponents?: Record<string, TRenderer['component']>;
  args?: Partial<Args>;
  argTypes?: ArgTypes;
  parameters?: Parameters;
  decorators?: DecoratorFunction<TRenderer>[];
  loaders?: LoaderFunction<TRenderer>[];
  render?: StoryFn<TRenderer>;
  play?: (context: StoryContext<TRenderer>) => Promise<void> | void;
}

/**
 * Prepared story with all enhancements applied
 */
interface PreparedStory<TRenderer extends Renderer> {
  id: StoryId;
  name: StoryName;
  title: ComponentTitle;
  kind: ComponentTitle;
  story: StoryName;
  parameters: Parameters;
  initialArgs: Args;
  argTypes: ArgTypes;
  args: Args;
  component: TRenderer['component'];
  subcomponents: Record<string, TRenderer['component']>;
  tags: Tag[];
  globals: Globals;
  moduleExport: ModuleExport;
  originalStoryFn: StoryFn<TRenderer>;
  undecoratedStoryFn: LegacyStoryFn<TRenderer>;
  unboundStoryFn: LegacyStoryFn<TRenderer>;
  applyLoaders: (context: StoryContextForLoaders<TRenderer>) => Promise<StoryContext<TRenderer>>;
  playFunction?: (context: StoryContext<TRenderer>) => Promise<void> | void;
}

/**
 * Story context for loaders phase
 */
interface StoryContextForLoaders<TRenderer extends Renderer> {
  id: StoryId;
  name: StoryName;
  title: ComponentTitle;
  kind: ComponentTitle;
  story: StoryName;
  parameters: Parameters;
  initialArgs: Args;
  argTypes: ArgTypes;
  args: Args;
  component: TRenderer['component'];
  subcomponents: Record<string, TRenderer['component']>;
  tags: Tag[];
  globals: Globals;
  viewMode: ViewMode;
}

/**
 * Global log level configuration
 */
declare var LOGLEVEL: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent' | undefined;

Architecture

This package uses a simple facade pattern:

  • Re-export Pattern: All functionality is re-exported from @storybook/preview-api/dist/preview-web
  • Deprecation Warning: Shows deprecation notice when imported using @storybook/client-logger
  • Compatibility Layer: Maintains backward compatibility during ecosystem migration
  • Zero Implementation: Contains no original implementation, only facade functionality

Error Handling

The package itself doesn't throw specific errors, but re-exported functionality may throw:

DocsContext Errors

  • "Cannot attach a CSF file that has not been referenced": When calling attachCSFFile() with an unreferenced CSF file
  • "No primary story attached to this docs file": When accessing primary story without using <Meta of={} />
  • "No CSF file attached to this docs file": When resolving meta or component without attached CSF file
  • "No story found with that name: ${storyName}": When calling storyIdByName() with non-existent story name
  • "Called storyById for story that was never loaded: ${storyId}": When accessing unloaded story by ID

Composition Errors

  • Invalid story/meta exports: When composeStory receives malformed CSF exports
  • Missing project annotations: When required global configuration is not provided via setProjectAnnotations

Preview Initialization Errors

  • Story index loading failures: When Preview cannot fetch or parse story index
  • Module import failures: When dynamic imports of story modules fail
  • Render function errors: When story render functions throw during execution

Common Solutions

// Always check if DocsContext has required attachments
try {
  const story = docsContext.storyById('example-story');
} catch (error) {
  console.error('Story not found or not loaded:', error.message);
}

// Ensure project annotations are set before composing stories
import { setProjectAnnotations } from "@storybook/preview-web";
setProjectAnnotations(globalConfig);

Common Use Cases

Story Preview Setup

import { PreviewWeb } from "@storybook/preview-web";

const preview = new PreviewWeb();
// Preview is automatically set up as global __STORYBOOK_PREVIEW__

Documentation Context Creation

import { DocsContext } from "@storybook/preview-web";

// Note: DocsContext requires channel, store, renderStoryToElement, and csfFiles
// This is typically created internally by Storybook

Test Environment Setup

import { simulatePageLoad, simulateDOMContentLoaded } from "@storybook/preview-web";

// In test setup
simulateDOMContentLoaded();
simulatePageLoad(document.body);

Story Testing

import { composeStory, composeStories } from "@storybook/preview-web";
import * as stories from "./Button.stories";

// Test individual story
const { Primary } = composeStories(stories);
test('renders primary button', () => {
  const button = Primary();
  expect(button).toBeTruthy();
});

// Or compose single story
const ComposedPrimary = composeStory(stories.Primary, stories.default);
test('renders composed story', () => {
  const result = ComposedPrimary({ label: 'Test' });
  expect(result).toBeTruthy();
});

Dependencies

  • @storybook/client-logger: Used for deprecation warnings
  • @storybook/preview-api: Source of all re-exported functionality

Package Configuration

{
  "main": "dist/entry.js",
  "module": "dist/entry.mjs", 
  "types": "dist/entry.d.ts",
  "exports": {
    ".": {
      "types": "./dist/entry.d.ts",
      "require": "./dist/entry.js",
      "import": "./dist/entry.mjs"
    }
  }
}
Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@storybook/preview-web@7.6.x
Publish Source
CLI
Badge
tessl/npm-storybook--preview-web badge