DEV Community 👩‍💻👨‍💻

DEV Community 👩‍💻👨‍💻 is a community of 964,423 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
ɥɔɐ⅂ ɐɥɔsɐS
ɥɔɐ⅂ ɐɥɔsɐS

Posted on

TIL: Using decorators in Storybook to document invalid inputs

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.

Top comments (0)

Take a look at this:

Settings

Go to your customization settings to nudge your home feed to show content more relevant to your developer experience level. 🛠