Premiers pas avec Storybook dans React

Avez-vous déjà essayé de placer tous vos composants d’interface utilisateur à un endroit dans React ?

Si vous êtes nouveau dans le monde de React, vous ne le ferez probablement pas.

Qu’entend-on par là ?

Voir le réagir-belle-dnd exemples.

Ce que vous avez vu dans les exemples s’appelle des histoires. Et l’outil utilisé pour créer des histoires s’appelle Storybook.

Maintenant, vous avez compris de quoi nous allons parler dans cet article. Sans plus tarder, explorons.

Qu’est-ce que Storybook ?

Storybook est un environnement de développement isolé de l’interface utilisateur qui fournit un terrain de jeu pour vos composants. Nous pouvons jouer avec nos composants de différentes manières sans exécuter notre application principale. Nous pouvons exécuter le livre de contes dans son port avec la configuration.

Ce n’est pas limité à React. Nous pouvons utiliser storybook avec la plupart des frameworks frontaux comme Vue, Angular, Mithril, Marko, Svelte, etc.,

Vous pouvez en savoir plus sur le livre d’histoires ici.

Qu’est-ce qu’une histoire ?

Une histoire définit l’état rendu de votre composant. Si nous prenons un composant commun, nous pouvons l’utiliser de différentes manières avec des accessoires. Nous pouvons écrire une histoire pour chacun de ces états.

Disons que nous avons un composant Button.

Un bouton peut exister dans différents états comme désactivé, en cours de chargement, primaire, secondaire, petit, grand, moyen, etc., si on liste tous les états, alors il sera très difficile d’avancer dans le tutoriel. Je pense que vous le comprenez. Vous en obtiendrez plus lorsque vous commencerez à travailler avec le livre de contes.

Vous pouvez voir les histoires du bouton dans différents cas (Large, Medium, Small).

Configurer Storybook dans un projet

Nous allons mettre en place un livre d’histoires dans un projet de réaction.

Allons-y.

  • Créez un projet React avec la commande suivante. Vous pouvez nommer ce que vous voulez.
npx create-react-app storybook-demo
  • Maintenant, installez le livre de contes dans votre projet avec la commande suivante.
npx sb init

Nous avons terminé la configuration du livre d’histoires.

Le livre de contes nous fournit un serveur séparé.

Comment le démarrer ?

Le livre de contes ajoute automatiquement une commande dans notre fichier de script. Vous pouvez le vérifier dans le fichier package.json dans la section des scripts. Pour le moment, exécutez la commande suivante pour démarrer le serveur storybook.

npm run storybook

Storybook démarrera un nouveau serveur avec le port indiqué dans la section des scripts du fichier package.json. Il ouvrira automatiquement le livre d’histoires dans notre navigateur par défaut (identique au serveur de réaction).

Vous y verrez différentes histoires par défaut. Vous pouvez les supprimer si vous ne le souhaitez pas ou les conserver pour référence. Comme nous l’avons vu dans la section précédente, un bouton peut avoir plusieurs états, vous pouvez les voir dans le livre de contes (tous les états ne sont pas mentionnés). Nous allons écrire un grand nombre d’histoires pour le bouton dans la dernière section de ce didacticiel.

Explorez différentes sections du livre d’histoires et familiarisez-vous avec les différentes sections. Nous allons en couvrir quelques-uns dans le tutoriel.

Écrivons notre première histoire.

Tester le livre d’histoires

Nous avons vu le livre d’histoires en cours d’exécution et quelques exemples dedans.

  • Créez un dossier appelé Button dans le dossier src.
  • Créez des fichiers appelés Button.jsx, Button.css et constants.js
  • Placez le code respectif des extraits ci-dessous dans les fichiers.

Bouton.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 };

Bouton.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;
}

constantes.js

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

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

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

Quel est ce code ?

Nous avons écrit un composant commun pour Button qui peut être utilisé de différentes manières. Maintenant, nous avons un composant qui peut avoir différents états.

Écrivons notre première histoire en suivant les étapes ci-dessous.

  • Créez un fichier appelé Button.stories.jsx
  • Importez React et notre composant Button dans le fichier.
  • Maintenant, définissez un titre ou un chemin pour nos histoires de composants. Nous allons le définir à l’aide du code suivant.
export default {
   title: ‘common/Button’,
}

Le code ci-dessus placera toutes les histoires qui se trouvent dans le fichier actuel dans le répertoire common/Button/.

  • Exportez un bouton avec des accessoires obligatoires comme suit.
export const defaultButton = () => (
    <Button text=”Default Button” onClick={() => {}} />
);

Nous avons terminé notre première histoire. Exécutez le livre de contes avec la commande suivante et consultez le résultat.

npm run storybook

Nous écrirons plus d’histoires, à la fin, ne vous inquiétez pas.

En quoi est-ce utile dans le développement Frontend ?

Quel est le principal avantage d’utiliser un livre d’histoires ?

Disons que nous travaillons dans une équipe de 10 membres. Et nous devons vérifier les composants communs que tout le monde a écrits pour le projet de travail en cours.

Comment pouvons-nous faire cela?

Nous devons aller à chaque composant commun pour les vérifier. Mais cela prend du temps et n’est pas une méthode préférée pour nous. Voici notre nouveau livre d’histoires invité.

Comment l’utiliser pour surmonter notre problème?

Nous pouvons écrire des histoires pour les composants communs (tous les composants de l’interface utilisateur) à l’aide de storybook. Et chaque fois que votre coéquipier veut vérifier les composants communs des autres, il exécute simplement le serveur de livre de contes et y verra tous les composants de l’interface utilisateur, comme nous l’avons vu ci-dessus.

Nous pouvons faire beaucoup plus avec les composants rendus dans le livre de contes. Storybook a un concept appelé Addons qui donne des super pouvoirs à nos histoires.

Disons que nous devons vérifier la réactivité des composants de l’interface utilisateur dans le livre de contes lui-même, nous pouvons utiliser un addon appelé Viewport dans le livre de contes. Nous en apprendrons plus sur les addons dans les sections à venir.

Travailler avec Storybook

Dans cette section, nous allons écrire différentes histoires définissant différents états de notre composant commun Button.

Ecrire des histoires n’est pas si difficile. Une histoire définit un état d’un composant. Si vous voyez les accessoires d’un composant, vous comprendrez facilement les différents cas d’utilisation du composant.

Écrivons quelques histoires en donnant des accessoires optionnels.

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"
    />
);

Les trois histoires ci-dessus définissent différents cas d’utilisation de notre composant Button. Maintenant, c’est à vous d’ajouter d’autres cas d’histoires pour notre composant commun. Essayez d’ajouter disabledSamllRectangularButton, dangerButton, successDisabledButton, etc.,

Je ne vais pas fournir de code pour les cas ci-dessus. Il faut l’écrire soi-même pour le comprendre. Vous pouvez voir le code complet des histoires que nous avons écrit jusqu’à présent.

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"
    />
);

Maintenant, vous maîtrisez parfaitement l’écriture d’histoires pour un composant.

Passons à la section suivante où nous découvrirons les addons et comment ils dynamisent nos histoires.

Compléments de livre de contes

Nous aurons plusieurs addons disponibles par défaut. Dans la section, nous explorerons les addons les plus utiles pour notre développement.

Boostons nos histoires de boutons.

Les contrôles

Les contrôles ajoutent une fonctionnalité pour donner des accessoires personnalisés au composant dans le livre de contes lui-même. Pour notre composant Button, nous pouvons ajouter des contrôles pour modifier les différents accessoires du livre de contes.

Disons que nous devons trouver la meilleure couleur pour la couleur d’arrière-plan du bouton. Cela prendra du temps si nous le testons pour vérifier la couleur de fond en donnant un par un au composant. Au lieu de cela, nous pouvons ajouter un contrôle qui nous permet de choisir la couleur différente dans le livre de contes. Nous pouvons tester la couleur de fond dans le livre de contes lui-même.

Voyons comment ajouter des contrôles à nos histoires Button.

Tout d’abord, nous devons définir tous les accessoires sous le titre comme suit.

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"] },
        },
    },
};

Ensuite, séparez les accessoires du composant et donnez-leur les arguments suivants.

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

Vous pouvez voir les contrôles au bas de la fenêtre d’aperçu du composant.

Vous pouvez voir l’onglet des contrôles au bas de la fenêtre d’aperçu du composant. Jouez autour de lui.

Mettez à jour toutes les histoires comme ci-dessus. Tout cela ressemble davantage à la connaissance de la syntaxe des addons du livre de contes. Dans les argTypes, nous avons utilisé différents types de contrôles. Vous pouvez trouver tous les contrôles qui sont présents dans le livre de contes ici.

Les histoires de boutons mises à jour se présenteront comme suit.

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",
};

Actions

Les actions sont des événements en JavaScript. Nous pouvons cliquer sur un bouton qui est un événement en JavaScript. Nous pouvons effectuer certaines actions en cliquant sur un bouton en utilisant l’addon actions.

Avec les actions, nous pouvons tester si les événements fonctionnent correctement ou non. Le bouton désactivé ne peut pas être cliqué et le bouton activé doit être cliquable. Nous pouvons nous en assurer en utilisant les actions.

Voyons comment ajouter une action au clic sur le bouton.

Nous avons précédemment donné une fonction anonyme aux props onClick. Maintenant, nous devons le mettre à jour.

  • Importez l’action à partir de l’addon storybook à l’aide de l’instruction suivante.
import { action } from "@storybook/addon-actions";
  • Remplacez tous les () => {} par l’instruction suivante.
action("Button is clicked!")

Maintenant, allez dans le livre d’histoires et cliquez sur un bouton. Vous verrez le message imprimé sous l’onglet actions qui se trouve à côté de l’onglet contrôles. Le message ne sera pas imprimé si vous cliquez sur le bouton désactivé car il est désactivé.

Nous pouvons utiliser l’action pour différents événements comme onChange, onMouseOver, onMouseOut, etc., pour nous assurer qu’ils fonctionnent correctement. Essayez d’implémenter la même chose pour onChange pour un élément d’entrée.

Voir la documentation pour les actions ici.

Arrière plan

Nous pouvons changer l’arrière-plan de la fenêtre d’aperçu à l’aide de l’addon d’arrière-plan. Nous n’avons pas à écrire de code. Changez-le simplement dans le livre d’histoires. Vous pouvez voir le gif ci-dessous.

Fenêtre

Nous pouvons également tester la réactivité de nos composants dans le storybook. Voir le gif ci-dessous pour en savoir plus sur les options de fenêtre.

Documents

Nous pouvons documenter nos composants dans le livre de contes en utilisant l’addon docs. C’est plus utile quand on travaille en équipe. Ils liront le composant et le comprendront directement. Cela fait gagner beaucoup de temps aux développeurs.

Dans la fenêtre d’aperçu des composants des livres de contes, vous pouvez voir Docs en haut à droite de l’onglet Canvas. Il contiendra toutes les docs de toutes les histoires d’un composant. Nous devons utiliser Button.stories.mdx si nous voulons documenter pour le composant qui inclut à la fois le rendu du démarquage et du composant. Nous écrivons simplement du code de démarquage supplémentaire à l’intérieur avec les histoires des composants.

Nous écrivons un document pour nos histoires. Le code inclut le démarquage et le rendu des composants. Il ne s’agit que d’apprendre la syntaxe. Vous l’obtiendrez du premier coup d’œil.

Voyons le code doc Button.stories.mdx.

<!--- 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>

En savoir plus sur les composants de documentation ici.

Vous pouvez en savoir plus sur les modules complémentaires ici.

Conclusion

J’espère que vous avez apprécié le didacticiel et que vous avez appris le livre d’histoires. Et utilisez-le efficacement dans votre équipe pour rendre votre travail productif.

Nouveau sur React ? Consultez ces ressources d’apprentissage.

Bon codage 🙂