New
Storybook for full-stack developersAutomate with Chromatic
Star75,295
Back to integrations
Add your integration
Categories
  • ⭐️ Popular
  • 🧩 Essentials
  • 🛠 Code
  • ⚡️ Data & state
  • ✅ Test
  • 💅 Style
  • 🎨 Design
  • ⚙️ Appearance
  • 🗄 Organize
How to install addons Create an addon
@tramvai/storybook-addon
Storybook addon for tramvai apps
npm install @tramvai/storybook-addon
Last updated about 9 hours ago
227
Downloads per week
Readme View on GitHub

@tramvai/storybook-addon

Storybook addon for tramvai apps

Installation

You need to install @tramvai/storybook-addon:

npm install @tramvai/storybook-addon

And connect addon in the storybook configuration file:

module.exports = {
  addons: ["@tramvai/storybook-addon"]
}

Features

  • Providers for DI container
  • Providers for router
  • Providers for react-query
  • Page actions support
  • tramvai babel configuration
  • tramvai postcss configuration

How to

Access to DI container

import { LOGGER_TOKEN } from '@tramvai/tokens-common';

export const Page = () => {
  const logger = useDi(LOGGER_TOKEN);

  logger.info('render');

  return (
    <h1>Page</h1>
  );
}
import type { TramvaiStoriesParameters } from '@tramvai/storybook-addon';
import { Page } from './page';

// You can pass to DI container any reducers, providers and modules
const parameters: TramvaiStoriesParameters = {
  tramvai: {
    stores: [],
    initialState: {},
    providers: [],
    modules: [],
  },
};

export default {
  title: 'Page',
  component: Page,
  parameters,
};

export const PageStory = () => <Page />;

Router hooks and components

import { Link, useUrl } from '@tramvai/module-router';

export const Page = () => {
  const url = useUrl();

  return (
    <>
      <h1>Page at {url.pathname}</h1>
      <p>
        <Link url="/third/">to third page</Link>
      </p>
    </>
  );
}
import type { TramvaiStoriesParameters } from '@tramvai/storybook-addon';
import { Page } from './page';

// You can pass to router current route and url
const parameters: TramvaiStoriesParameters = {
  tramvai: {
    currentRoute: { name: 'second', path: '/second/' },
  },
};

export default {
  title: 'Page',
  component: Page,
  parameters,
};

export const PageStory = () => <Page />;

React Query

import { createQuery, useQuery } from '@tramvai/react-query';


const query = createQuery({
  key: 'base',
  fn: async () => {
    return { foo: 'bar' };
  },
});

export const Page = () => {
  const { data, isLoading } = useQuery(query);

  return (
    <>
      <h1>Page</h1>
      <p>
        {isLoading ? 'Loading...' : data.foo}
      </p>
    </>
  );
}
import type { TramvaiStoriesParameters } from '@tramvai/storybook-addon';
import { Page } from './page';

// You can pass to router QueryClient default options
const parameters: TramvaiStoriesParameters = {
  tramvai: {
    reactQueryDefaultOptions: {
      queries: {
        refetchOnMount: false,
        refetchOnReconnect: false,
        refetchOnWindowFocus: false,
      },
    },
  },
};

export default {
  title: 'Page',
  component: Page,
  parameters,
};

export const PageStory = () => <Page />;

Page actions running

import { declareAction } from '@tramvai/core';

const serverAction = declareAction({
  name: 'server-action',
  fn() {
    console.log('server action');
  },
  conditions: {
    onlyServer: true,
  },
});

const browserAction = declareAction({
  name: 'browser-action',
  fn() {
    console.log('browser action');
  },
  conditions: {
    onlyBrowser: true,
  },
});

export const Page = () => {
  return (
    <h1>Page</h1>
  );
}

Page.actions = [serverAction, browserAction];
import type { TramvaiStoriesParameters } from '@tramvai/storybook-addon';
import { Page } from './page';

// Actions with `onlyBrowser` condition will be executed
const parameters: TramvaiStoriesParameters = {
  tramvai: {
    actions: Page.actions,
  },
};

export default {
  title: 'Page',
  component: Page,
  parameters,
};

export const PageStory = () => <Page />;

Http clients with real requests

import { declareAction } from '@tramvai/core';

const httpRequestAction = declareAction({
  name: 'http-request-action',
  async fn() {
    return this.deps.httpClient.get('/');
  },
  deps: {
    httpClient: HTTP_CLIENT,
  },
});

export const Page = () => {
  return (
    <h1>Page</h1>
  );
}

Page.actions = [httpRequestAction];
import { HttpClientModule } from '@tramvai/module-http-client';
import type { TramvaiStoriesParameters } from '@tramvai/storybook-addon';
import { Page } from './page';

// HttpClientModule is required for real requests
const parameters: TramvaiStoriesParameters = {
  tramvai: {
    actions: Page.actions,
    modules: [HttpClientModule],
  },
};

export default {
  title: 'Page',
  component: Page,
  parameters,
};

export const PageStory = () => <Page />;

How to provide environment variables?

This addon provides a few important defaults:

  • Mock provider for ENV_MANAGER_TOKEN
  • Read env.development.js content from application root

So, any variables from env.development.js will be registered in envManager.

If you want to add custom variables for some stories, pass options for CommonTestModule (from @tramvai/test-mocks package) in story parameters:

const parameters: TramvaiStoriesParameters = {
  tramvai: {
    options: {
      env: {
        FOO: 'BAR',
      },
    },
  },
};

Contribute

For testing changes in this plugin locally, you need a few steps:

  1. [tramvai repo] Copy examples-standalone/storybook application to different folder, e.g. storybook-app
  2. [storybook-app] Update there all tramvai dependencies in package.json
  3. [tramvai repo] Copy plugin build output from packages/tramvai/storybook-addon/lib
  4. [storybook-app] Paste into the storybook-app/node_modules/@tramvai/storybook-addon/lib folder
  5. [storybook-app] Run storybook in nested folder cd storybook && npm run storybook
Join the community
5,867 developers and counting
WhyWhy StorybookComponent-driven UI
Open source software
Storybook

Maintained by
Chromatic
Special thanks to Netlify and CircleCI