npm package: @htc-class/storylite
Description: > An _incredibly_ bare-bones knock-off of Storybook with several **serious and > fundamental** flaws. But it's FAST! 🚀
Author: Jared Henderson
Latest version: 2.0.1

# StoryLite

> An _incredibly_ bare-bones knock-off of Storybook with several **serious and
> fundamental** flaws. But it's FAST! 🚀

## Installation

```bash
npm install @htc-class/storylite
```

## Usage

**StoryLite** isn't a separate web-app running on a separate port like Storybook. Instead,
it's a lite, dev-only drop-in replacement for your app where you can work on your
components with the same bundler, stack, etc. Therefore, at the root of your app, you need
to _conditionally load_ it, approximately like so:

```tsx
import React from 'react';
import { queryParam } from '@htc-class/storylite';
import AllStories from '../stories';
import App from './App';

const App: React.FC = () => {
  if (process.env.NODE_ENV === `DEVELOPMENT` && queryParam(`storylite`)) {
    return <AllStories />;
  } else {
    return <App />;
  }
};

export default App;
```

The `queryParam()` helper shown above is just a convenience function to help you test if
the current URL has a query parameter. So the way to activate and view your StoryLite
session is by adding `?storylite=1` to the browser's address bar. To end your session,
either manually remove the query parameter, or click the close button in the StoryLite UI.

It is recommended that you have a folder called `stories/` which will have a directory
structure something like this:

```
stories/
  - ComponentA.stories.tsx
  - ComponentB.stories.tsx
  - index.tsx
```

The `stories/index.tsx` file will be the place where you gather and list all of your
individual stories. It might look something like this:

```tsx
import React from 'react';
import { Stories } from '@htc-class/storylite';
import ButtonStories from './Button.stories';
import BlockStories from './Block.stories';
import LoginStories from './Login.stories';

const AllStories: React.FC = () => {
  return <Stories stories={[ButtonStories, BlockStories, LoginStories]} />;
};

export default AllStories;
```

The `<Stories />` main component takes an array of `StoryMeta` objects, each of which has
a type like this:

```ts
export interface StoryMeta {
  name: string;
  component: React.FC;
  layout?: 'centered' | 'fullscreen' | 'padded';
  bgColor?: string;
}
```

Then, as shown above, each component has it's own story file, like
`stories/Button.stories.tsx`. Smaller components that you may want to view in multiple
states might have a story file like this, which uses the `<StoryGroup />` and `<Story />`
helper components:

```tsx
import React from 'react';
import { Story, StoryGroup, StoryMeta } from '@htc-class/storylite';
import Button from '../components/Button';

const ButtonStories: React.FC = () => (
  <StoryGroup>
    <Story title="Default">
      <Button />
    </Story>
    <Story title="Secondary">
      <Button secondary />
    </Story>
  </StoryGroup>
);

const meta: StoryMeta = {
  name: `<Button />`,
  component: ButtonStories,
  layout: `padded`,
};

export default meta;
```

Or, if you have a component that is a full-width or full-screen block or element, it
probably makes sense to have a dedicated story file with only one permutation, like so:

```tsx
import { StoryMeta } from '@htc-class/storylite';
import React from 'react';
import Block from '../components/Block';

const BlockStories: React.FC = () => <Block />;

const meta: StoryMeta = {
  name: `<Block />`,
  component: BlockStories,
  layout: `fullscreen`,
};

export default meta;
```

Of course, you don't technically need separate files for each component, the
`BlockStories` example above could be inlined into the main `stories/index.tsx` file like
so:

```tsx
import React from 'react';
import { Stories } from '@htc-class/storylite';
import ButtonStories from './Button.stories';
import LoginStories from './Login.stories';
import Block from '../components/Block';

const AllStories: React.FC = () => {
  return (
    <Stories
      stories={[
        ButtonStories,
        {
          name: `<Block />`,
          component: Block,
          layout: `fullscreen`,
        },
        LoginStories,
      ]}
    />
  );
};

export default AllStories;
```