Storybook Channel - A deprecated package that provides shims for the internal channels module used for communication between Storybook Manager and Renderer
npx @tessl/cli install tessl/npm-storybook--channels@8.6.0Storybook Channels is a communication library that provides an EventEmitter-like interface for sending and receiving events between different parts of the Storybook ecosystem, particularly between the Storybook Manager and Renderer. It supports multiple transport mechanisms including PostMessage for iframe communication and WebSocket for real-time development communication.
Note: This package is deprecated and serves as a shim that re-exports functionality from storybook/internal/channels. Users are encouraged to migrate to the internal API structure introduced in Storybook v8.
npm install @storybook/channelsimport { Channel, PostMessageTransport, WebsocketTransport, createBrowserChannel, HEARTBEAT_INTERVAL, HEARTBEAT_MAX_LATENCY } from "@storybook/channels";For CommonJS:
const { Channel, PostMessageTransport, WebsocketTransport, createBrowserChannel, HEARTBEAT_INTERVAL, HEARTBEAT_MAX_LATENCY } = require("@storybook/channels");import { createBrowserChannel, Channel } from "@storybook/channels";
// Create a browser channel with default transports
const channel = createBrowserChannel({ page: 'manager' });
// Listen for events
channel.addListener('story-changed', (data) => {
console.log('Story changed:', data);
});
// Emit events
channel.emit('story-selected', { storyId: 'example-story' });
// Manual channel creation with custom transport
const customChannel = new Channel({
transport: new PostMessageTransport({ page: 'manager' })
});Storybook Channels is built around several key components:
createBrowserChannel for common setupsEvent management and communication coordination through a single Channel interface that works with multiple transport mechanisms.
class Channel {
constructor(input: ChannelArgs);
readonly isAsync: boolean;
hasTransport: boolean;
addListener(eventName: string, listener: Listener): void;
emit(eventName: string, ...args: any): void;
removeListener(eventName: string, listener: Listener): void;
once(eventName: string, listener: Listener): void;
removeAllListeners(eventName?: string): void;
}
type ChannelArgs = ChannelArgsSingle | ChannelArgsMulti;
interface ChannelArgsSingle {
transport?: ChannelTransport;
async?: boolean;
}
interface ChannelArgsMulti {
transports: ChannelTransport[];
async?: boolean;
}Communication transports for different environments including PostMessage for iframe communication and WebSocket for real-time development.
class PostMessageTransport {
constructor(config: Config);
setHandler(handler: ChannelHandler): void;
send(event: ChannelEvent, options?: any): Promise<any>;
}
class WebsocketTransport {
constructor(args: WebsocketTransportArgs);
setHandler(handler: ChannelHandler): void;
send(event: any): void;
}
interface Config {
page: 'manager' | 'preview';
}Convenience functions for creating configured channels and utility functions for common operations.
function createBrowserChannel(options: Options): Channel;
interface Options {
page: 'manager' | 'preview';
extraTransports?: ChannelTransport[];
}interface ChannelEvent {
type: string;
from: string;
args: any[];
}
interface ChannelTransport {
send(event: ChannelEvent, options?: any): void;
setHandler(handler: ChannelHandler): void;
}
type ChannelHandler = (event: ChannelEvent) => void;
interface Listener {
(...args: any[]): void;
}
interface EventsKeyValue {
[key: string]: Listener[];
}
interface BufferedEvent {
event: ChannelEvent;
resolve: (value?: any) => void;
reject: (reason?: any) => void;
}
/** WebSocket heartbeat interval in milliseconds (15000ms = 15 seconds) */
const HEARTBEAT_INTERVAL: number; // 15000
/** Maximum WebSocket heartbeat latency in milliseconds (5000ms = 5 seconds) */
const HEARTBEAT_MAX_LATENCY: number; // 5000
/** PostMessage transport key identifier for message routing */
const KEY: string; // 'storybook-channel'