This package has been deprecated

Author message:

Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

@funda/storybook-wrapper-helper
TypeScript icon, indicating that this package has built-in type declarations

2.1.0 • Public • Published

Storybook wrapper helper

Installation

  1. npm install --save-dev @funda/storybook-wrapper-helper (depending on your project configuration, you may want to install this as a regular dependency)
  2. register the 'storybook-addon-designs' addon in storybook main.js
  3. import story and book functions in your story and follow the usage docs

Register storybook addon example

// main.js
module.exports = {
  addons: ['storybook-addon-designs'],
}

Why?

Why where these wrapper components created? Why not write stories just like I see in the storybook documentation?

As long as wrappers do not confuse the developer, any steps that can be taken to reduce the amount of code that the developer is copying and pasting, the better. This will reduce errors and will make writing stories more enjoyable. This makes stories look more cohesive and reduces distractions for a book (a collection of stories) where most of the stories have their own templates and args.

Storybook stories will also go through improvements between Story Component Format (SCF) v2 SCF v3, and breaking changes between Vue v2 and Vue v3. While updating a single story through a breaking change is a trivial task, reformatting every story written, would take a lot of time. This should allow us to move through the breaking changes by only changing the internals of a function that generates a story.

For more information on why this will still be relevant for the forseeable future, please read the roadmap.

Usage

All configuration here is built from functional components, so a developer will be able to easily debug any storybook configuration by seeing the output of each of these functions. While the helper functions could further abstract a storybook implementation, this crosses a line where obfuscation begins to be a hinderance when a developer is debugging, or joining this project for the first time.

Single story book

If you just have a single story, then you can use the story function directly. Any information that you need in your story needs to be added as parameters to the story function.

import { story, book } from '@funda/storybook-wrapper-helper';

// import your component that you are going to test
import SaveBox from '../SaveBox.vue';

const bookSettings = book({
    // define the folder structure for your component
    title: 'Advertisement/Create/Save Box',
    component: { SaveBox },
});

export default bookSettings;

export const Default = story({
    // all of the work that the book function does for you is included here
    ...bookSettings,
    args: {
        disabled: false,
        canBuy: false,
        waiting: false,
    },
});

Multi-story book

import { story, defaultStory, book } from '@funda/storybook-wrapper-helper';

// import your component that you are going to test
import UiUploadButton from '../UiUploadButton.vue';


const bookSettings = book({
    title: 'UI/Buttons/Upload',
    component: { UiUploadButton },
    // this will show up on the docs tab in storybook
    description: 'A generic upload button',
    // these will be the default arguments and will be merged with args at the
    // story level.
    defaultArgs: {
        uploadText: 'Upload a file',
        errorMessage: '',
        accept: '*',
        multiple: false,
        showFileNames: false,
    }
});

export default bookSettings;

// These stories simply rely on the values generated by the book function, and
// extend or override values when needed.

export const Default = story(bookSettings);
export const DifferentUploadText = story({
    ...bookSettings,
    description: 'An upload button that suggests the user add an image',
    args: {
        uploadText: 'Add an image',
    },
});

// This uploadButtonStory function will return all the information storybook
// needs to make a story. Args can be passed in to override any default values
function uploadButtonStoryWithMargin(args) {
    return defaultStory({
        // all of the work that the book function does for you is included here
        ...bookSettings,
        // a default template that shows what the component looks like if a
        // margin is added into the component
        defaultTemplate: '<UiUploadButton v-bind="$props" class="mt-3"></UiUploadButton>',
        ...args,
    });
}

// For these stories, we are using the defaultStories that have a custom
// template. Since the uploadButtonStoryWithMargin function already includes the
// bookSettings, we do not need to do that.

export const DifferentUploadValidation = uploadButtonStoryWithMargin({
    description: 'An upload button that allows any kind of video type',
    args: {
        accept: 'video/*',
        uploadText: 'Add a video',
    },
});
export const Error = uploadButtonStoryWithMargin({
    args: {
        errorMessage: 'The image that you tried to upload is too small',
    },
});
export const MultipleSelection = uploadButtonStoryWithMargin({
    description: 'An upload button that allows the user to upload more than one thing',
    args: {
        multiple: true,
    },
});
export const ShowFileNames = uploadButtonStoryWithMargin({
    args: {
        showFileNames: true,
        multiple: true,
    },
});

A full example

This is an example of a component that makes use of every option in the story function configuration.

import { story, book } from '@funda/storybook-wrapper-helper';

// import your component that you are going to test
import SaveBox from '../SaveBox.vue';
import SuccessNotification from '../SuccessNotification.vue';

const bookSettings = book({
    // define the folder structure for your component
    title: 'Advertisement/Create/Save Box',
    component: { SaveBox },
    // when @close and @save are triggered, it will be logged in the actions pane
    events: ['close', 'save', 'mouse-in-zone'],
    design: [
        {
            type: 'figma',
            url: 'https://www.figma.com/file/file-key',
        },
        {
            type: 'link',
            url: 'https://www.figma.com/file/file-key-2',
        },
    ],
    description: "A save box for an advertisement",
    links: [
      {
        name: "Business requirements document",
        value: "https://intranet.funda.nl/example/SaveBox/documentation"
      },
    ],
    // add a little bit of margin around all our stories
    decorators: ['<div class="m-3"><story/></div>'],
});

export default bookSettings;

export const Default = story({
    // all of the work that the book function does for you is included here
    ...bookSettings,
    // arguments for our component
    args: {
        disabled: false,
        canBuy: false,
        waiting: false,
    },
    // allow us to use the SuccessNotification in our custom template
    additionalComponents: { SuccessNotification },
    description: 'A custom description for this component',
    // wrap this story in a custom div that constrains the max width
    decorators: ['<div style="max-width: 800px;"><story/></div>'],
    // set our background color to a custom shade of blue
    parameters: {
      backgrounds: {
        default: 'custom-blue',
        values: [
            {
                name: 'custom-blue',
                value: '#139ec1'
            }
        ]
      },
    },
    // include our SuccessNotification, overriding the default slot in our
    // SaveBox component. Note that the props and actions must be bound in this
    // template or you will disconnect them from the story.
    template: `
      <SaveBox
        v-bind="$props"
        @close="close"
        @save="save"
        @mouse-in-zone="mouseInZone"
     >
        <SuccessNotification>You did it!</SuccessNotification>
      </SaveBox>
    `
});

Automatic features

If you specify a book that has a title that starts with page (case insensitive), the layout of the story will be full screen to closer emulate what the page will look like (especially on mobile devices). This can be overwritten at the story level.

const bookSettings = book({
    title: 'Page/Home',
    component: { ... }
});

Typescript

This project is written in TypeScript, which provides helpful hints to developers consuming this package. Even if you are not using TypeScript in your project, editors like VSCode include the ability to enable type checking in normal JS files.

While storybook does have some TypeScript support for the components that you are testing, there seems to be no complete TypeScript definition for the interface that defines stories in @storybook/vue. Ideally, this project imports types from the @storybook/vue and/or @storybook/csf packages and extends them to fit the needs of this wrapper, but for now, the plan is to define all types here until the API has been proven to work in a variety of situations across several Funda applications.

Getting started

  • npm install
  • npm run build (if you want to check the build output)

The directory src/lib is where you will spend most of your time. All remaining directories are just there to help you focus on building the component in an efficient way.

Contributing

How to push your changes

This repo uses conventional commits and uses commitlint to enforce it. This means that you need to follow a set of rules otherwise you don't be able to commit. This is required for automating the release of the package.

Examples of commit messages:

  • feat(branch_name): new feature added
  • fix(branch_name): fix added

PS: It is recommended to use the terminal for commit, if you use any GUI it might be necessary to update you local variable PATH on your GUI. Reference: Husky issues

Releasing a new version

This project uses semantic-release a tool that will automatically releases, increment the package version and generate a changelog entry based on the new commits. Simply following the commitlint standard and merging your changes into main will release the project.

Consuming the package locally

If don't want to publish a new version and you just want to test it locally you can use npm run link-local on the package and then npm link @funda/storybook-wrapper-helper on the project.

Keep in mind that some tools don't understand file symlink (what npm link uses) and that can cause problems.

Ownership

This codebase is owned by FE Cluster

For questions about this codebase contact a frontend engineer or email devteam-frontend@funda.nl

Readme

Keywords

none

Package Sidebar

Install

npm i @funda/storybook-wrapper-helper

Weekly Downloads

0

Version

2.1.0

License

MIT

Unpacked Size

207 kB

Total Files

19

Last publish

Collaborators

  • dine
  • jpsc