DEV Community

loading...

TIL: Using decorators in Storybook to document invalid inputs

ɥɔɐ⅂ ɐɥɔsɐS
Frontend developer in Cologne
・2 min read

Today I learned about Storybooks decorators and used them for documenting validation errors on inputs.

Decorators are Storybooks way to wrap a story into some extra HTML.
By that, a basic component can for example be documented in a better visual way, as suggested by Storybooks, by adding some space around a story.

Writing an input component

Now to my use-case: I was developing input components with Vue, while writing the related stories.
Besides showing the default state of an input, I alse wanted to show the invalid state.

As an example I'd have a component called InputText.vue in which I would simply pass down all the props and attrs to the input field.

<template>
  <div class="input-group">
    <label v-if="label" :for="id">{{ label }}</label>
    <input type="text" v-bind="{...$props, ...$attrs}" />
  </div>
</template>

...

<style>
...
input:invalid {
  border-color: red;
}
</style>
Enter fullscreen mode Exit fullscreen mode

With an InputText.stories.js as follows:

export default {
  title: "Forms/Inputs/Text",
  component: InputText,
  decorators: [],
};

const Template = (args) => ({
  props: Object.keys(args),
  components: { InputText },
  template: '<InputText v-bind="$props" />',
});

export const EmptyRequired = Template.bind({});
EmptyRequired.story = {
  name: "Required field",
  args: {
    id: "field1",
    label: "Some Label",
    required: true,
  },
};
Enter fullscreen mode Exit fullscreen mode

So the required attribute would end up at the components input tag, making it invalid with an empty value.

Per default the invalid state would never be shown in Storybook.

Sure, I could've added an extra class to my CSS, which probably wouldn't ever be used in the final application, so I wanted to avoid that.

Adding a decorator

Instead I used a decorator to wrap my story into a form tag with:

  decorators: [() => ({ template: "<form><story /></form>" })],
Enter fullscreen mode Exit fullscreen mode

By that I could make use of the browser built-in validation and have my possible validation states show up right away when setting the attribute required and no value.

This of course works not only with the required attribute, but also with something like an invalid e-mail address on type="email" inputs.

Discussion (0)