Komma igång med Storybook i React

Har du någonsin försökt placera alla dina UI-komponenter på en plats i React?

Om du är ny i React-världen kommer du förmodligen inte att göra det.

Vad menas med det?

Se den reagera-vackert-dnd exempel.

Det du har sett i exemplen kallas berättelser. Och verktyget som används för att skapa berättelser heter Storybook.

Nu har du förstått vad vi ska prata om i den här artikeln. Låt oss utan dröjsmål utforska.

Vad är Storybook?

Storybook är en användargränssnitt isolerad utvecklingsmiljö som ger en lekplats för dina komponenter. Vi kan leka med våra komponenter på olika sätt utan att köra vår huvudapp. Vi kan köra sagoboken i dess hamn med installationen.

Det är inte begränsat till React. Vi kan använda storybook med de flesta frontend-ramverk som Vue, Angular, Mithril, Marko, Svelte, etc.,

Du kan hitta mer om sagoboken här.

Vad är en berättelse?

En berättelse definierar det renderade tillståndet för din komponent. Om vi ​​tar en gemensam komponent kan vi använda den på olika sätt med rekvisita. Vi kan skriva en berättelse för var och en av dessa stater.

Låt oss säga att vi har en knappkomponent.

En knapp kan existera i olika tillstånd som inaktiverad, laddning, primär, sekundär, liten, stor, medium, etc.. Om vi ​​listar ner alla tillstånd, kommer det att vara mycket svårt att gå vidare i handledningen. Jag tror att du förstår det. Du kommer att få det mer när du börjar arbeta med sagoboken.

Du kan se berättelserna om knappen i olika fall (Large, Medium, Small).

Ställa in Storybook i ett projekt

Vi sätter upp en sagobok i ett reaktionsprojekt.

Nu går vi.

  • Skapa ett reaktionsprojekt med följande kommando. Du kan namnge vad du vill.
npx create-react-app storybook-demo
  • Installera nu sagoboken i ditt projekt med följande kommando.
npx sb init

Vi har slutfört installationen av sagoboken.

Sagoboken tillhandahåller en separat server för oss.

Hur startar man det?

Sagoboken lägger automatiskt till ett kommando i vår manusfil. Du kan kontrollera det i filen package.json i skriptsektionen. Kör tills vidare följande kommando för att starta sagoboksservern.

npm run storybook

Storybook kommer att starta en ny server med porten angiven i skriptsektionen i filen package.json. Det kommer automatiskt att öppna sagoboken i vår standardwebbläsare (samma som reaktionsservern).

Du kommer att se olika historier i den som standard. Du kan ta bort dem om du inte vill eller behålla dem som referens. Som vi diskuterade i föregående avsnitt kan en knapp ha flera tillstånd, du kan se dem i sagoboken (inte alla tillstånd nämns). Vi kommer att skriva en stor uppsättning berättelser för knappen i det sista avsnittet av denna handledning.

Utforska olika avsnitt av sagoboken och bekanta dig med de olika avsnitten. Vi kommer att täcka några av dem i handledningen.

Låt oss skriva vår första berättelse.

Testar sagobok

Vi har sett sagoboken köra och några exempel i den.

  • Skapa en mapp som heter Button inuti src-mappen.
  • Skapa filer som heter Button.jsx, Button.css och constants.js
  • Placera respektive kod från nedanstående utdrag i filerna.

Button.jsx

import React, { Component } from "react";
import PropTypes from "prop-types";

import "./Button.css";

import { buttonTypes, buttonVariants, buttonSizes } from "./constants";

class Button extends Component {
    static defaultProps = {
        isDisabled: false,
        type: "filled",
        variant: "oval",
        size: "medium",
        backgroundColor: "#1ea7fd",
        textColor: "#ffffff",
    };

    static buttonTypes = buttonTypes;
    static buttonVariants = buttonVariants;
    static buttonSizes = buttonSizes;

    renderButton = () => {
        const {
            text,
            isDisabled,
            type,
            variant,
            size,
            backgroundColor,
            textColor,
            onClick,
        } = this.props;
        return (
            <button
                onClick={onClick}
                className={`default ${variant} ${size} ${
                    isDisabled ? "disabled" : ""
                }`}
                style={
                    type === buttonTypes.outline
                        ? {
                              border: `1px solid ${backgroundColor}`,
                              color: "#000000",
                              backgroundColor: "transparent",
                          }
                        : {
                              backgroundColor: `${backgroundColor}`,
                              border: `1px solid ${backgroundColor}`,
                              color: textColor,
                          }
                }
                disabled={isDisabled}
            >
                {text}
            </button>
        );
    };

    render() {
        return this.renderButton();
    }
}

Button.propTypes = {
    text: PropTypes.string,
    isDisabled: PropTypes.bool,
    type: PropTypes.oneOf([buttonTypes.outline, buttonTypes.filled]),
    variant: PropTypes.oneOf([buttonVariants.oval, buttonVariants.rectangular]),
    size: PropTypes.oneOf([
        buttonSizes.small,
        buttonSizes.medium,
        buttonSizes.large,
    ]),
    backgroundColor: PropTypes.string,
    textColor: PropTypes.string,
    onClick: PropTypes.func,
};

export { Button };

Button.css

.default {
    border: none;
    cursor: pointer;
    background-color: transparent;
}

.default:focus {
    outline: none;
}

.disabled {
    opacity: 0.75; 
    cursor: not-allowed;
}
.small {
    font-size: 12px;
    padding: 4px 8px;
}

.medium {
    font-size: 14px;
    padding: 8px 12px;
}

.large {
    font-size: 16px;
    padding: 12px 16px;
}

.oval {
    border-radius: 4px;
}

.rectangular {
    border-radius: 0;
}

constants.js

export const buttonTypes = {
    outline: "outline",
    filled: "filled",
};

export const buttonVariants = {
    oval: "oval",
    rectangular: "rectangular",
};

export const buttonSizes = {
    small: "small",
    medium: "medium",
    large: "large",
};

Vad är det för kod?

Vi har skrivit en gemensam komponent för Button som kan användas på olika sätt. Nu har vi en komponent som kan ha olika tillstånd.

Låt oss skriva vår första berättelse genom att följa stegen nedan.

  • Skapa en fil som heter Button.stories.jsx
  • Importera React och vår Button-komponent till filen.
  • Definiera nu en titel eller väg till våra komponentberättelser. Vi kommer att definiera det med hjälp av följande kod.
export default {
   title: ‘common/Button’,
}

Ovanstående kod kommer att placera alla berättelser som finns i den aktuella filen i common/Button/-katalogen.

  • Exportera en knapp med obligatorisk rekvisita enligt följande.
export const defaultButton = () => (
    <Button text=”Default Button” onClick={() => {}} />
);

Vi har avslutat vår första berättelse. Kör sagoboken med följande kommando och se resultatet.

npm run storybook

Vi kommer att skriva fler berättelser, i slutändan, oroa dig inte.

Hur är det användbart i Frontend-utveckling?

Vad är den största fördelen med att använda en sagobok?

Låt oss säga att vi arbetar i ett team på 10 medlemmar. Och vi måste kontrollera vanliga komponenter som alla har skrivit för det aktuella arbetsprojektet.

Hur kan vi göra det?

Vi måste gå till alla vanliga komponenter för att kontrollera dem. Men det är tidskrävande och inte ett föredraget sätt för oss. Här kommer vår nya gästsagobok.

Hur ska man använda det för att övervinna vårt problem?

Vi kan skriva berättelser för de vanliga komponenterna (alla UI-komponenter) med hjälp av storybook. Och närhelst din lagkamrat vill kontrollera andras vanliga komponenter, kör de helt enkelt storybook-servern och kommer att se alla UI-komponenter där som vi har sett ovan.

Vi kan göra mycket mer med de renderade komponenterna i sagoboken. Storybook har ett koncept som heter Addons som ger superkrafter till våra berättelser.

Låt oss säga att vi måste kontrollera reaktionsförmågan hos UI-komponenterna i själva sagoboken, vi kan använda ett tillägg som heter Viewport i sagoboken. Vi kommer att lära oss mer om tilläggen i de kommande avsnitten.

Arbeta med Storybook

I det här avsnittet kommer vi att skriva olika berättelser som definierar olika tillstånd för vår gemensamma komponentknapp.

Att skriva berättelser är inte så svårt. En berättelse definierar ett tillstånd för en komponent. Om du ser rekvisita för en komponent kommer du lätt att förstå olika användningsfall för komponenten.

Låt oss skriva några berättelser genom att ge valfria rekvisita.

export const largeButton = () => (
    <Button text="Large Button" onClick={() => {}} size="large" />
);
export const outlineSmallButton = () => (
    <Button
        text="Outline Small Button"
        onClick={() => {}}
        size="small"
        type="outline"
    />
);
export const rectangularLargeButton = () => (
    <Button
        text="Rectangular Large Button"
        onClick={() => {}}
        size="large"
        variant="rectangular"
    />
);


export const disabledButton = () => (
    <Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);


export const warningButton = () => (
    <Button
        text="Warning Button"
        onClick={() => {}}
        backgroundColor="orange"
    />
);

Ovanstående tre berättelser definierar olika användningsfall av vår komponentknapp. Nu är det din tur att lägga till några andra fall av berättelser för vår gemensamma komponent. Försök att lägga till disabledSamllRectangularButton, dangerButton, successDisabledButton, etc..,

Jag kommer inte att tillhandahålla kod för ovanstående fall. Du måste skriva det på egen hand för att förstå det. Du kan se den fullständiga berättelsekoden som vi har skrivit hittills.

import React from "react";

import { Button } from "./Button";

export default {
    title: "src/common/Button",
};

export const defaultButton = () => (
    <Button text="Default Button" onClick={() => {}} />
);

export const largeButton = () => (
    <Button text="Large Button" onClick={() => {}} size="large" />
);

export const outlineSmallButton = () => (
    <Button
        text="Outline Small Button"
        onClick={() => {}}
        size="small"
        type="outline"
    />
);

export const rectangularLargeButton = () => (
    <Button
        text="Rectangular Large Button"
        onClick={() => {}}
        size="large"
        variant="rectangular"
    />
);

export const disabledButton = () => (
    <Button text="Disabled Button" onClick={() => {}} isDisabled={true} />
);

export const warningButton = () => (
    <Button
        text="Disabled Button"
        onClick={() => {}}
        backgroundColor="orange"
    />
);

Nu har du fullt grepp om att skriva berättelser för en komponent.

Låt oss hoppa in i nästa avsnitt där vi kommer att lära oss om tillägg och hur de förstärker våra berättelser.

Storybook-tillägg

Vi kommer att ha flera tillägg tillgängliga som standard. I avsnittet kommer vi att utforska de mest användbara tilläggen för vår utveckling.

Låt oss förstärka våra Button-berättelser.

Kontroller

Kontroller lägger till en funktion för att ge anpassade rekvisita till komponenten i själva sagoboken. För vår knappkomponent kan vi lägga till kontroller för att ändra de olika rekvisita i sagoboken.

Låt oss säga att vi måste ta reda på den bästa färgen för knappens bakgrundsfärg. Det kommer att vara tidskrävande om vi testar det för att kontrollera bakgrundsfärgen genom att ge en efter en till komponenten. Istället kan vi lägga till en kontroll som gör att vi kan välja olika färger i sagoboken. Vi kan testa bakgrundsfärgen i själva sagoboken.

Låt oss se hur du lägger till kontroller i våra Button-berättelser.

Först måste vi definiera alla rekvisita under titeln enligt följande.

export default {
    title: "src/common/Button",
    argTypes: {
        text: { control: "text" },
        backgroundColor: { control: "color" },
        isDisabled: { control: "boolean" },
        size: {
            control: { type: "select", options: ["small", "medium", "large"] },
        },
        type: {
            control: { type: "select", options: ["filled", "outline"] },
        },
        variant: {
            control: { type: "select", options: ["oval", "rectangular"] },
        },
    },
};

Separera sedan rekvisita från komponenten och ge dem som argument enligt följande.

export const outlineSmallButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
    text: "Outline Small Button",
    size: "small",
    type: "outline",
};

Du kan se kontrollerna längst ned i komponentförhandsgranskningsfönstret.

Du kan se kontrollfliken längst ned i komponentförhandsgranskningsfönstret. Lek runt det.

Uppdatera alla historier enligt ovan. Det här är mer som att känna till syntaxen för sagobokstilläggen. I argTypes har vi använt olika typer av kontroller. Du kan hitta alla kontroller som finns i sagoboken här.

Uppdaterade knappberättelser kommer att se ut som följer.

import React from "react";

import { Button } from "./Button";

export default {
    title: "src/common/Button",
    argTypes: {
        text: { control: "text" },
        backgroundColor: { control: "color" },
        isDisabled: { control: "boolean" },
        size: {
            control: { type: "select", options: ["small", "medium", "large"] },
        },
        type: {
            control: { type: "select", options: ["filled", "outline"] },
        },
        variant: {
            control: { type: "select", options: ["oval", "rectangular"] },
        },
    },
};

export const defaultButton = (args) => <Button {...args} onClick={() => {}} />;
defaultButton.args = {
    text: "Default Button",
};

export const largeButton = (args) => (
    <Button {...args} onClick={() => {}} size="large" />
);
largeButton.args = {
    text: "Large Button",
};

export const outlineSmallButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
outlineSmallButton.args = {
    text: "Outline Small Button",
    size: "small",
    type: "outline",
};

export const rectangularLargeButton = (args) => (
    <Button {...args} onClick={() => {}} />
);
rectangularLargeButton.args = {
    text: "Rectangular Large Button",
    size: "large",
    variant: "rectangular",
};

export const disabledButton = (args) => <Button {...args} onClick={() => {}} />;
disabledButton.args = {
    text: "Disabled Button",
    isDisabled: true,
};

export const warningButton = (args) => <Button {...args} onClick={() => {}} />;
warningButton.args = {
    text: "Warning Button",
    backgroundColor: "orange",
};

Åtgärder

Åtgärder är händelser i JavaScript. Vi kan klicka på en knapp som är en händelse i JavaScript. Vi kan göra några åtgärder på knappklick med hjälp av action-tillägget.

Med åtgärder kan vi testa om händelserna fungerar som de ska eller inte. Inaktiverad knapp kan inte klickas och aktiverad knapp måste vara klickbar. Vi kan säkerställa det med hjälp av åtgärderna.

Låt oss se hur du lägger till åtgärder för att klicka på knappen.

Vi har gett anonym funktion till onClick rekvisita tidigare. Nu måste vi uppdatera den.

  • Importera åtgärden från storybook-tillägget med följande uttalande.
import { action } from "@storybook/addon-actions";
  • Ersätt alla () => {} med följande påstående.
action("Button is clicked!")

Gå nu till sagoboken och klicka på en knapp. Du kommer att se meddelandet utskrivet under fliken åtgärder bredvid kontrollfliken. Meddelandet skrivs inte ut om du klickar på avaktiverad-knappen eftersom den är inaktiverad.

Vi kan använda åtgärden för olika händelser som onChange, onMouseOver, onMouseOut, etc.., för att se till att de fungerar korrekt. Försök att implementera samma sak för onChange för ett indataelement.

Se dokumentationen för åtgärder här.

Bakgrund

Vi kan ändra bakgrunden i förhandsgranskningsfönstret med hjälp av bakgrundstillägget. Vi behöver inte skriva någon kod. Ändra det bara i sagoboken. Du kan se gif:en nedan.

Viewport

Vi kan också testa känsligheten hos våra komponenter i sagoboken. Se gif-filen nedan för att ta reda på alternativen för visningsport.

Dokument

Vi kan dokumentera våra komponenter i sagoboken med hjälp av tillägget docs. Det är mer användbart när vi arbetar i ett team. De kommer att läsa komponenten och förstå den direkt. Det sparar mycket tid för utvecklarna.

I storybooks förhandsgranskningsfönster för komponenter kan du se Dokument längst upp till höger på fliken Canvas. Den kommer att innehålla alla dokument för alla berättelser om en komponent. Vi måste använda Button.stories.mdx om vi vill dokumentera för komponenten som inkluderar både markdown och komponentrendering. Vi skriver bara lite extra markdown-kod inuti den tillsammans med komponentberättelserna.

Vi skriver ett dokument för våra berättelser. Koden inkluderar markdown och komponentrendering. Det är bara att lära sig syntaxen. Du kommer att få det första anblicken.

Låt oss se Button.stories.mdx doc-koden.

<!--- Button.stories.mdx -->

import {
    Meta,
    Story,
    Preview,
    ArgsTable
} from '@storybook/addon-docs/blocks';

import { Button } from './Button';

<Meta title="MDX/Button" component={Button} />

# Button Documentation

With `MDX` we can define a story for `Button` right in the middle of our
Markdown documentation.

<ArgsTable of={Button} />

export const Template = (args) => <Button {...args} />

## Default Button
We can write the documentation related to the Default Button
<Preview>
    <Story name="Default Button" args={{
        text: 'Default Button'
    }}>
    {Template.bind({})}
   </Story>
</Preview>

## Large Button
We are writing sample docs for two stories, you can write rest of them
<Preview>
    <Story name="Large Button" args={{
        text: "Large Button",
        }}>
        {Template.bind({})}
    </Story>
</Preview>

Läs mer om dokumentationskomponenterna här.

Du kan ta reda på mer om tillägg här.

Slutsats

Hoppas du tyckte om handledningen och lärde dig om sagoboken. Och använd det effektivt i ditt team för att göra ditt arbete produktivt.

Ny på React? Kolla in dessa lärresurser.

Glad kodning 🙂