@omng/storybook
v4.1.2
Published
Custom design system by Omnilog
Downloads
49
Readme
Omnilog - Design System
Ce référentiel contient le projet permettant de créer un design system personnalisé pour Omnilog.
Storybook a été rajouté afin de visualiser par le biais d’interfaces les différents composants de manières isolés. Il est possible de modifier les propriétés d’un composant en quelques clics puis de simplement copier le code généré.
Have fun ! 🎉
📑 Sommaire
- 🔧 Installation
- 📖 Documentation officielle de Storybook
- 📐 Configuration du projet
- 📌 Pipelines GitLab
- 🤝 Contribution
- 🚀 Déploiement de Storybook
- 📦 Déploiement de la librairie
- 🦺 Publier une version beta
- 🌈 Génération des icônes SVG
- 🧪 Éxécution des tests unitaires
🔧 Installation
- Clonez le référentiel à l'aide de git :
git clone https://git.golinmo.com/bordeaux-tma/storybook
- Accédez au répertoire du projet :
cd storybook
- Installez les dépendances nécessaires à l'aide de yarn :
yarn install --frozen-lockfile
- Initialisez Husky :
yarn run prepare
- Démarrez le serveur de développement :
yarn start
- Ouvrez votre navigateur préféré et accédez à l'URL suivante :
http://localhost:6006
pour accèder à l'interface de Storybook. C'est ici que vous pourrez visualiser facilement tous les composants du design system.
📖 Documentation officielle de Storybook
La documentation officielle de Storybook peut être consultée ici : https://storybook.js.org/docs.
Elle fournit des informations détaillées sur l'utilisation de Storybook et de ses fonctionnalités.
📐 Configuration du projet
Ce projet est configuré avec les outils et les bonnes pratiques suivants :
- Commitlint pour des messages de commit structurés.
- Husky pour exécuter des scripts lors des événements Git (tels que les commits).
- ESLint pour linter et vérifier la syntaxe JavaScript.
- Stylelint pour linter et vérifier les styles CSS.
- Validate branch name pour vérifier le nommage de la branche.
- TypeScript pour ajouter une couche de typage sur JavaScript.
- Vite pour builder la librairie.
- Semantic Release pour gérer notamment les numéros de version et l'historique des modifications.
📌 Pipelines GitLab
Ce projet est configuré avec des pipelines GitLab qui exécute les étapes suivantes lorsqu'un push est effectué sur une Merge Request ou sur main :
- Vérification du code avec ESLint pour détecter les erreurs et les problèmes de syntaxe (voir .eslintrc).
- Vérification des styles avec Stylelint pour s'assurer de la conformité aux règles de styles définies (voir .stylelintrc).
- Vérification du code avec TypeSript pour s'assurer que les typages sont corrects (voir tsconfig.json).
- Éxécution des tests unitaires.
- Construction et déploiement de Storybook sur un site de développement.
- Construction et déploiement de la librairie sur npm.
Des pipelines sont également planifiés pour être exécutées à divers moments :
- Effectue un audit de vulnérabilité par rapport aux packages installés (voir package.json).
- Gestion automatique des mises à jour des dépendances (voir dependabot.yml).
🤝 Contribution
- Mettez-vous à jour
Rendez-vous sur la branche main et récupérez les dernières mises à jour :
git checkout main
git pull
Note: si vous rencontrez des problèmes pour mettre à jour la branche main, saisissez la commande suivante :
git checkout main
git reset --hard origin/main
- Création d'une nouvelle branche
Travaillez toujours sur une nouvelle branche en lui donnant un nom descriptif. Si vous êtes lié à un problème ou à une fonctionnalité spécifique, incluez le numéro du ticket Jira dans le nom de votre branche :
<type>/<id?>-<description>
Voici à quoi cela pourrait correspondre :
git checkout -b feat/123-add-button-component
Si vous n'avez pas de ticket associé, vous pouvez ignorer la saisie du numéro du ticket au sein de la branche :
git checkout -b fix/avatar-image
- Apportez vos modifications
Développez et testez vos modifications localement.
- Commitez vos modifications
Commitez via un message clair et concis décrivant un maximun la mise à jour apportée.
Format attendu :
<type>(<scope?>): <id?> <description>
<body?>
<footer?>
Voici à quoi cela pourrait correspondre :
git commit -m 'feat(Button): [PI-123] add Button component'
Note: si la mise à jour comporte un ou plusieurs changements cassants :
git commit -m 'build!: [PI-666] upgrade build' -m "BREAKING CHANGE: The files output during the build have been renamed."
Note: si la mise à jour n'est pas associé à un ticket :
git commit -m 'fix(Avatar): fix Avatar image'
Le message de validation doit suivre le format suivant : https://www.conventionalcommits.org/en/v1.0.0/
- Envoyer vos modifications vers GitLab
Envoyez vos modifications vers le référentiel précédemment cloné.
Lors de votre premier push, veillez à lier la branche distante avec votre branche locale :
git push --set-upstream origin <your-branch-name>
Pour tous les prochains push, il vous suffira d'effectuer cette commande :
git push
- Soumettre une Merge Request
Créez une MR par rapport au référentiel du projet d'origine. Décrivez clairement les changements et leurs motivations.
Une fois votre MR examinée et approuvée, elle sera fusionnée dans la branche principale main.
Lors de l'importation d'une ressource, veillez à bien utiliser son alias.
import { IconLoader } from '@components/Icon/Icons';
- Configuration Vite
Tout d'abord, ajouter cet alias dans le fichier ./vite.config.ts
:
export default defineConfig({
// [...]
resolve: {
alias: {
// [...]
"@alias": path.resolve(__dirname, "./src/alias"),
},
},
});
- Configuration TypeScript
Ajouter également cet alias dans le fichier ./tsconfig.json
:
{
"compilerOptions": {
// [...]
"paths": {
// [...]
"@alias/*": ["src/alias/*"],
},
}
}
- Configuration Eslint
Et pour finir, ajouter cet alias dans le fichier ./eslintrc
:
{
"rules": {
// [...]
"simple-import-sort/imports": {
// [...]
[
"^@(alias|assets|components|hooks|pages|src|stories|styles|tests|utils)?(/.*|$)"
],
},
}
}
Note: une erreur du linter sera remontée si les importations ne sont pas triées dans l'ordre en question.
Créer un nouveau dossier respectant la convention PascalCase dans ./src/components/
explicitant au mieux votre composant.
Une certaine structure est mise en place au sein du dossier, voici à quoi cela pourrait correspondre :
├── src/
│ ├── components/
│ │ ├── NewComponent/
│ │ │ ├── styles/
│ │ │ │ └── NewComponent.sass
│ │ │ │ └── ...
│ │ │ ├── tests/
│ │ │ │ └── NewComponent.test.tsx
│ │ │ │ └── ...
│ │ │ ├── constants.ts
│ │ │ ├── NewComponent.tsx
│ │ │ ├── types.ts
│ │ │ └── ...
│ │ └── ...
│ ├── stories/
│ │ ├── NewComponent.stories.tsx
│ │ └── ...
│ └── ...
└── ...
Placez la logique JavaScript du composant au sein du fichier NewComponent.tsx
.
Le composant doit avoir une classe par défaut. Elle commence par le préfix Omni suivi du nom du composant (exemple: OmniNewComponent
).
Note: la propriété data-testid
permet à testing-library de récupérer l'élément lors des tests unitaires, cette valeur doit être la même valeur que le nom de la classe.
// @components/NewComponent/NewComponent.tsx
import clsx from 'clsx';
import '@components/NewComponent/styles/NewComponent.scss';
/**
* NewComponent component.
*
* @param {NewComponentProps} props Props
* @return {JSX.Element}
*/
function NewComponent({ children, className, ...attr }: NewComponentProps): JSX.Element {
const classNames = clsx('OmniNewComponent', className);
return (
<div
data-testid="OmniNewComponent"
{...attr}
className={classNames}
>
<span className="OmniNewComponent__content OmniNewComponent__content--green">
{children}
</span>
</div>
);
}
export { NewComponent };
Pour que le composant soit accesible, il faut l'exporter dans ce fichier ./src/components/index.ts
:
// @components/index.ts
// Components.
// [...]
export * from '@components/NewComponent/NewComponent';
// Types.
// [...]
Placez tous les styles liés à ce composant au sein du fichier NewComponent.sass
.
Note: ce fichier se trouve dans le sous-dossier /styles
.
// @components/NewComponent/styles/NewComponent.sass
@use "@styles/functions" as *;
@use "@styles/mixins" as *;
@use "@styles/variables" as *;
.OmniNewComponent {
background-color: $color-white;
color: $color-red;
padding: to-rem(4);
@include bp-tablet {
padding: to-rem(6);
}
&__content {
background-color: $color-gray-extra-light;
&--green {
background-color: $color-green;
}
}
}
Le nommage des classes respectent la méthodologie BEM.
Pour que le style soit bien appliqué, il faut bien penser à l'importer dans le fichier du composant (NewComponent.tsx
).
Note: le concept de Mobile First est mis en place. Ainsi les composants sont tout d’abord créées pour petites résolutions (exemple: smartphones) puis évoluent ensuite progressivement pour s’adapter aux grandes résolutions (exemple: ordinateurs). Les breakpoints suivants sont disponibles: bp-tablet
(>= 768px), bp-laptop
(>= 1024px) et bp-desktop
(>= 1440px).
Afin de visualiser le composant par le biais de Storybook, il faut créer un fichier NewComponent.stories.tsx
dans le dossier ./src/stories
afin de créer de multiples histoires :
// @stories/NewComponent.stories.tsx
import type { Meta as MetaStorybook, StoryObj } from '@storybook/react';
import type { NewComponentProps } from '@src/index';
import { NewComponent } from '@src/index';
// Types.
type Meta = MetaStorybook<NewComponentProps>;
type Story = StoryObj<NewComponentProps>;
// Metadata.
const meta: Meta = {
component: NewComponent,
tags: ['autodocs'],
title: 'Composants/Group/NewComponent',
// [...]
};
export default meta;
// Stories.
export const NewComponentStory: Story = {
name: "Titre de l'histoire",
args: {
children: 'Texte',
className: 'my-custom-class',
},
};
Note: les histoires sont à écrire en français.
Plus de détails sur l'écriture d'histoires: "How to write stories".
Placez tous les tests unitaires liés à ce composant au sein du fichier NewComponent.test.tsx
.
Note: ce fichier se trouve dans le sous-dossier /tests
.
// @components/NewComponent/tests/NewComponent.test.tsx
import { composeStories } from '@storybook/react';
import type { NewComponentProps } from '@components/index';
import * as stories from '@stories/NewComponent.stories';
import { render, screen } from '@tests/index';
const { NewComponentStory } = composeStories(stories);
const props: NewComponentProps = {
id: 'my-custom-id',
};
describe('components/NewComponent', () => {
it('should renders the expected component', () => {
render(<NewComponentStory {...props} />);
const newComponent = screen.getByTestId('OmniNewComponent');
expect(newComponent).toHaveClass(`OmniNewComponent ${NewComponentStory.args.className}`);
expect(newComponent).toHaveAttribute('id', props.id);
// [...]
});
// [...]
});
Placez toutes les contantes globales liées à ce composant au sein du fichier constants.ts
.
Le nom des constantes est en majuscule préfixé par le nom du composant :
// @components/NewComponent/constants.ts
export const NEWCOMPONENT_CONSTANT_1 = ...
export const NEWCOMPONENT_CONSTANT_2 = ...
Pour que les constantes soient accessibles, il faut les exporter dans ce fichier ./src/utils/constants.ts
:
// @utils/constants.ts
// [...]
export * from '@components/NewComponent/constants';
Placez tous les types liés à ce composant au sein du fichier types.ts
.
// @components/NewComponent/types.ts
import type { HTMLAttributes } from 'react';
export type NewComponentProps = HTMLAttributes<HTMLDivElement>;
Pour que les types soient accessibles, il faut les exporter dans ce fichier ./src/components/index.ts
:
// @components/index.ts
// Components.
// [...]
// Types.
// [...]
export * from '@components/NewComponent/types';
🚀 Déploiement de Storybook
Le déploiement s'effectue automatiquement sur un registry privé CodeArtifact d'AWS lorsqu'une Merge Request est mergée sur la branche principale main.
Le projet est publié sur l'environnement de développement suivant : https://dev-storybook.offprod.app.golinmo.com/
📦 Déploiement de la librairie
Lorsqu'une montée de version est effectuée manuellement via la pipeline GitLab, semantic-release
s'occupe entre autre de publier la nouvelle version de la librairie sur npm (package @omng/storybook
).
Le design system est disponible ici : https://www.npmjs.com/package/@omng/storybook.
🦺 Publier une version beta
Lors de la phase de développement, il est parfois intérressant de déployer des versions beta pour tester correctement la librairie.
À noter qu'une autorisation est nécessaire pour publier une version de la sorte sur le package @omng/storybook
. Un administrateur de @omng/storybook
doit vous ajouter à l'équipe afin de bénéficier des droits adéquats.
Une fois réalisé, effectuez la commande suivante pour publier une version beta :
yarn run publish-beta
Il vous sera demander de nommer la version beta. Veillez à ajouter le suffix -beta.x
où x
représente un nombre entier positif (plus d'informations sur le nommage des versions : https://semver.org/).
Exemple de nommage par ordre de croissance :
4.0.0-beta.0 < 4.0.0-beta.1 < ... < 4.0.0-beta.12 < 4.0.0
🌈 Génération des icônes SVG
Les icônes SVG sont générées à partir de fichiers .svg
présents dans le dossier ./src/assets/icons
. Pour générer les icônes, il suffit d'exécuter la commande suivante :
yarn run generate-icons
Cette commande va générer les composants correspondants sous le nom Icon{name}.tsx
dans le dossier ./src/components/Icon/src
. Par la suite, ce composant est exporté via le fichier Icons.tsx
.
Cette génération des icones est possible grâce à différents packages gulp
installés. Pour plus d'informations veuillez consulter le fichier de configuration gulpfile.js.
Note: si vous désirez ajouter un style particulier à une icone, ajoutez un fichier Icon{name}.scss
dans le dossier ./src/components/Icon/styles
et n'oubliez pas d'ajouter ce fichier à la variables sassFiles
dans le fichier de configuration gulpfile.js
.
🧪 Éxécution des tests unitaires
Pour lancer les tests :
yarn run test
Pour lancer les tests, tout en surveillant les modifications afin de rééxécuter les tests modifiés :
yarn run test:watch
Pour lancer les tests, tout en collectant les pourcentages de couverture :
yarn run test:coverage