adjoe Engineers’ Blog
 /  Frontend  /  Writing Stories with Storybook to Visualize React Frontend Dashboard Components
decorative purple image with colorful elements
Frontend

Writing Stories with Storybook to Visualize React Frontend Dashboard Components

In my last article, I explained how your codebase should look in order to seamlessly integrate and use Storybook to document and interact with your components. I also took you through the process of how we integrated Storybook in our new dashboard project, explained how to solve common integration problems, and demonstrated how to automatically upload your documentation to Chromatic, Storybook’s own hosting service.

In this article, I’ll explain the process of writing stories with Storybook for both simple components, like buttons, and more complex state-based components, like filters and dropdowns.

What Is a Story?

When we talk about writing stories with Storybook, a story describes and visualizes a component’s specific state. A component can have multiple stories, based on which states the component can support. Different stories are normally used to show how the component transforms based on which properties are given to it. 

Screenshot of a button story with four substories in Storybook in article about writing stories with Storybook

A story itself has two views: Canvas and Docs.

The Canvas view shows the single story with controls below it. With these controls, you can set all of the component’s properties. This view can also be used to interact with the component. You can change the size of the page to see media queries in action, zoom in and out, switch to dark mode, show the grid, and more.

 The Canvas view also supports various add-ons you can install for your Storybook. You can find a ton of different add-ons here.

Screenshot of the Canvas page of a Button story in Storybook

The Docs view is the documentation page of the component.

Here, you can view the written description of the component. You’ll see a list of all supported properties, as well as prop comments set in the code to explain these. 

The Docs view will show all stories on one page, and you can also view code examples for integration.

Screenshot of the Docs page of a button story in Storybook
Screenshot of the substories in the Docs page of a button story in Storybook
Screenshot of the code example of a button story in Storybook

How Do I Write a Story for a Simple Component?

Storybook provides you with a clear structure of how a story should look like.

The story exports a default object typed as a ComponentMeta, which includes the field’s title and component. The title is responsible for the placement of the story in your Storybook. A title string “Common/Button” will create the component story under the folder “Common” entitled “Button.” In the component field, you pass the actual component to render as a React ComponentType.


Then you can create a template, which is the actual component-rendering function. It will return JSX, which will be used to render the component in the story, passing the properties as arguments. This template can return anything you want and is also where you’ll add the necessary logic or state for more complex components later on. For example, you could wrap your button component in a box here and give it a different background, if you want.


Lastly, the actual stories will be created by binding your template to ComponentStory constants.With this, you can create any number of stories for your component and change the arguments of the template according to your needs.

Let’s use a simple component as an example – a simple wrapper of the MUI button.

interface IButtonProps {
 variant: 'text' | 'outlined';
 onClick: () => void;
 children: React.ReactNode;
}
export const MyButton: FC<IButtonProps> = ({ variant, onClick, children }) => (
 <Button variant={variant} onClick={onClick}>
   {children}
 </Button>
);

Out of this component, you can easily create two stories that show different variants.

First, create a new file next to the component and name it “Button.stories.tsx.” Then, create your default export.

export default {
 title: 'Common/Button',
 component: MyButton,
} as ComponentMeta<typeof MyButton>;

In TypeScript, you have to make sure that you type the object correctly and add the typeof component as a generic.

Next, add the template. In this case, it renders the button with a simple text as the child and passes the arguments to it with prop spreading.

const Template: ComponentStory<typeof MyButton> = args => (
 <MyButton {...args}>Button</MyButton>
);

And then you can define your stories with bindings by setting the variant in the args to what you need. The onClick definition is in this case not necessary – you can just assign a function that does nothing, or you could make a console log.

export const DemoOutlined = Template.bind({});
DemoPrimary.args = {
 onClick: () => {},
 variant: 'outlined',
};


export const DemoText = Template.bind({});
DemoSecondary.args = {
 onClick: () => {},
 variant: 'text',
};

How Do I Write Stories for Complex Components?

While simple components, like buttons, do not need any logic to visualize them with stories, more complex components – for example, a select component – will need both a state and state change logic in order to function correctly in the story. In this case, you will need to expand the template with values, state, and change listeners.

Let’s take this simplified select component as an example.

export interface IMySelectProps {
 label?: string;
 values: { name: string; value: string }[];
 selectedValue: string;
 onChange: (event: SelectChangeEvent<string>) => void;
}


export const MySelect: FC<IMySelectProps> = ({
 label,
 values,
 selectedValue,
 onChange,
}) => {
 return (
   <Select value={selectedValue} label={label} onChange={onChange}>
     {values.map(value => (
       <MenuItem value={value.value} key={value.name}>
         {value.name}
       </MenuItem>
     ))}
   </Select>
 );
};

This component doesn’t function on its own; it requires logic on its parent component in order for the user to see and select options. 

Let’s now create a story for it.

First, create a new file called “MySelect.stories.tsx” next to the Select Component file. Then, like in the button story, create the default export object.

export default {
 title: 'Common/Select',
 component: MySelect,
 argTypes: { onChange: { action: 'onChange callback was called with' } },
 args: {
   label: 'Fruit Select',
   values: [
     { name: 'Banana', value: 'banana' },
     { name: 'Lemon', value: 'lemon' },
     { name: 'Orange', value: 'orange' },
   ],
 },
} as ComponentMeta<typeof MySelect>;

You can add two new fields next to the title and component fields used previously.

argTypes lets you set argument options for your story manually. Here, you can add descriptions for the arguments and, like in this case, add an action to it. The action will automatically trigger in the action section of the canvas, and will output the defined string together with the function’s passed parameters.
In args, you can set default arguments that do not change per story. In this case, add the label and values, so it will be set for all of this component’s stories.

Next up, create the story template.

const Template: ComponentStory<typeof MySelect> = args => {
 const { onChange, values } = args;
 const [value, setValue] = useState('banana');


 const onSelectChange = (event: SelectChangeEvent<string>) => {
   onChange(event);
   setValue(event.target.value);
 };
 return (
   <MySelect selectedValue={value} onChange={onSelectChange} values={values} />
 );
};

First, First, you need onChange and values, which you get from args by destructuring.

Create a state, which will save your current selected value as a string, with a default value. 

In order to trigger the action correctly, you need to call the onChange function of the args. Then you can set the state to the selected value from the component.
Instead of spreading the args, assign the state value, the custom change function, and the values from the default args.

Finally, create a simple demo to show the story in Storybook.

export const Demo = Template.bind({});

The result is a fully functioning select dropdown component you can try out in your Storybook.

Screenshot of the dropdown component in Storybook

What’s Next?

You should now have the tools and knowledge to create your own visual stories for your components – regardless of whether they function without external logic or whether they need additional logic in the parent.

After discussing the process of writing stories with Storybook, read my third and final article. I’ll be showing you how to utilize Storybook’s features of documentation to document your components, as well as give you a brief overview of Chromatic’s visual-regression testing tool.

Senior Business Intelligence Analyst (f/m/d)

  • adjoe
  • Playtime Supply
  • Full-time
adjoe is a leading mobile ad platform developing cutting-edge advertising and monetization solutions to meet the diverse needs of app publishers. Being part of the applike group ecosystem plus the significant financial backing from Bertelsmann empowers us to do this. At adjoe, we are proud of our advanced tech stack and dynamic and innovative workforce.

Meet Your Team: Playtime Supply

The Playtime Supply team focuses on creating great experiences for the 200+ million users who interact with Playtime. This includes everything from the gamified experiences within the mobile apps to the dashboards used to configure and customise these experiences. From the unique product features and ML algorithms to the analytical systems used to analyse their effects. Our cross-functional team has all the expertise needed to realise our product goals.
What you will do
  • You will use data-insights to find opportunities for our product to improve and grow.
  • You will be part of an international, English-speaking team that builds our disruptive Ad Tech platform
  • You create, analyze and communicate reports and statistics by using queries and dashboards that our BI team builds.
  • You will participate in building and maintaining models that will be used in order to provide business insights through our dashboard
  • You drill into data from various sources (Redshift, Spark, SQL, Athena, S3, Druid event streams, AWS data pipeline) and write scripts to improve the processes
  • You are a strong communicator,can explain complex things in simple words,and know how to deal with stakeholders
  • You are able to express technical issues comprehensively in business language
  • You have to understand all the different parts of our product to help our product to achieve better results and provide incredible experience to our publishers and end-users.
  • Who you are
  • You have at least 5 years of experience in the field
  • You have excellent analytical & communication skills and like to use these on Python, Scala or Julia as well as on Spreadsheets
  • You are fluent in English
  • Strong knowledge in at least one programming language that can be used for BI
  • You’re interested in big data and have outstanding experience in SQL
  • Experienced in using Power BI/Tableau/Quicksight or other tools for creating a dashboard for quick analysis.
  • You are self-confident and competent in communicating with clients
  • Plus: You got in touch with java or you build already some basic android apps in your free time
  • Plus: Knowledge about Mobile App analytics (e.g. adjust, appsflyer etc.)
  • Plus: Knowledge about SDK and basic understanding of the SDK integration process.
  • Heard of Our Perks?
  • Work-Life Package: 2 remote days per week, 30 vacation days, 3 weeks per year of remote work, flexible working hours, dog-friendly kick-ass office in the center of the city.
  • Relocation Package: Visa & legal support, relocation bonus, reimbursement of German Classes costs, and more.
  • Happy Belly Package: Monthly company lunch, tons of free snacks and drinks, free breakfast & fresh delicious pastries every Monday
  • Physical & Mental Health Package: In-house gym with a personal trainer, various classes like Yoga with expert teachers & free of charge access to our EAP (Employee Assistance Program) to support your mental health and well-being
  • Activity Package: Regular team and company events, and hackathons.
  • Education Package: Opportunities to boost your professional development with courses and training directly connected to your career goals 
  • Wealth building: virtual stock options for all our regular employees
  • Skip writing cover letters. Tell us about your most passionate personal project, your desired salary and your earliest possible start date. We are looking forward to your application!

    We welcome applications from people who will contribute to the diversity of our company.

    Build our signature product

    See vacancies