CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-storybook--ui

Core Storybook UI - React based UI components that provide the core interface for Storybook

Pending
Overview
Eval results
Files

provider-system.mddocs/

Provider System

The provider system is the core abstraction that allows consumers to customize and configure the Storybook UI. It consists of a base Provider class that must be extended, along with React components for custom implementations. The Provider class uses concrete methods that throw errors rather than abstract methods.

Capabilities

Provider Base Class

Base class that defines the interface for providing UI elements, handling API initialization, and supplying configuration. All methods throw errors by default and must be implemented by subclasses.

/**
 * Base class for Storybook UI providers
 * All consumers must extend this class to use the Storybook UI
 */
class Provider {
  /**
   * Get UI elements by type - must be implemented by subclasses
   * @param type - Type identifier for the UI elements to retrieve (from @storybook/addons Types enum)
   * @returns Object containing UI elements for the specified type
   * @throws Error with message "Provider.getElements() is not implemented!" if not overridden
   */
  getElements(type: Types): any;
  
  /**
   * Handle API initialization - must be implemented by subclasses
   * @param api - The Storybook API instance
   * @throws Error with message "Provider.handleAPI() is not implemented!" if not overridden
   */
  handleAPI(api: unknown): void;
  
  /**
   * Return configuration object - has default implementation that returns empty object
   * @returns Configuration object for the Storybook UI
   * @note Logs error "Provider.getConfig() is not implemented!" but doesn't throw, returns {}
   */
  getConfig(): any;
}

Usage Examples:

import { Provider } from "@storybook/ui";

class MyProvider extends Provider {
  private stories = [];
  private config = { theme: 'light' };
  
  getElements(type) {
    // Must implement - will throw error if not overridden
    switch (type) {
      case 'TAB':
        return {
          component: MyTabComponent,
          props: { stories: this.stories }
        };
      case 'PANEL':
        return {
          component: MyPanelComponent,
          props: { theme: this.config.theme }
        };
      case 'TOOL':
        return {
          component: MyToolComponent,
          props: { addons: this.getAddons() }
        };
      default:
        return {};
    }
  }
  
  handleAPI(api) {
    // Must implement - will throw error if not overridden
    console.log('API initialized:', api);
    
    // Initialize stories if available
    if (this.stories.length > 0) {
      api.setStories(this.stories);
    }
  }
  
  getConfig() {
    // Optional - has default implementation that returns {}
    return {
      theme: this.config.theme,
      showNav: true,
      showPanel: true
    };
  }
  
  private getAddons() {
    return [
      { name: 'controls', component: ControlsAddon },
      { name: 'actions', component: ActionsAddon }
    ];
  }
}

// Example showing error behavior if methods not implemented
class IncompleteProvider extends Provider {
  // Missing getElements and handleAPI implementations
}

const incomplete = new IncompleteProvider();
try {
  incomplete.getElements('TAB'); // Throws: "Provider.getElements() is not implemented!"
} catch (error) {
  console.error(error.message);
}

try {
  incomplete.handleAPI({}); // Throws: "Provider.handleAPI() is not implemented!"
} catch (error) {
  console.error(error.message);
}

// getConfig() doesn't throw, but logs error and returns {}
const config = incomplete.getConfig(); // Logs: "Provider.getConfig() is not implemented!"
console.log(config); // {}

Root Component

React functional component that serves as the entry point for the Storybook UI application, wrapping the entire interface with necessary providers.

/**
 * Root component for the Storybook UI application
 * @param props - RootProps containing provider and optional history
 */
const Root: FunctionComponent<RootProps>;

interface RootProps {
  /** Provider instance that supplies UI elements and configuration */
  provider: Provider;
  /** Optional browser history instance for routing (currently unused in implementation) */
  history?: History;
}

Implementation Details:

  • Wraps the UI in HelmetProvider for document head management
  • Uses LocationProvider for routing functionality
  • Sets up emotion cache and theme providers
  • Renders the main App component with provider integration

Usage Examples:

import { Root, Provider } from "@storybook/ui";

class CustomProvider extends Provider {
  getElements(type) { 
    // Must implement
    return { component: MyComponent };
  }
  handleAPI(api) { 
    // Must implement
    console.log('API ready'); 
  }
}

// Basic usage (most common pattern)
function App() {
  const provider = new CustomProvider();
  return <Root provider={provider} />;
}

// With history parameter (currently unused by implementation)
function AppWithHistory() {
  const provider = new CustomProvider();
  const history = createBrowserHistory(); // Not currently used by Root component
  
  return <Root provider={provider} history={history} />;
}

Note: The history prop is included in the interface but is not currently used by the Root component implementation. This may be for future compatibility or legacy reasons.

Provider Implementation Requirements

All Provider subclasses must implement the following methods:

class MyProvider extends Provider {
  // REQUIRED: Must override, throws error otherwise
  getElements(type: Types) {
    // Return UI elements for the given type
    // Types include: 'TAB', 'PANEL', 'TOOL', 'TOOLEXTRA', 'PREVIEW', 'NOTES_ELEMENT'
    return {};
  }
  
  // REQUIRED: Must override, throws error otherwise  
  handleAPI(api: unknown) {
    // Handle API initialization and setup
    console.log('API initialized');
  }
  
  // OPTIONAL: Has default implementation that returns {}
  getConfig() {
    // Return configuration for the UI
    return {};
  }
}

Types

type Types = 'TAB' | 'PANEL' | 'TOOL' | 'TOOLEXTRA' | 'PREVIEW' | 'NOTES_ELEMENT';

interface History {
  push(path: string): void;
  replace(path: string): void;
  go(delta: number): void; 
  back(): void;
  forward(): void;
  listen(listener: Function): Function;
}

Install with Tessl CLI

npx tessl i tessl/npm-storybook--ui

docs

core-rendering.md

index.md

provider-system.md

tile.json