Storybook: Sous-histoires/Hiérarchie

Créé le 28 avr. 2016  ·  79Commentaires  ·  Source: storybookjs/storybook

Ce serait bien de pouvoir avoir des "Substories" ou une Hiérarchie d'histoires. Mon cas implique diverses mini "applications" contenues dans le même référentiel. Une solution simple serait une option pour afficher les magasins nommés comme ui.core.foo et ui.core.bar comme :

└── core
    ├── bar
    └── foo

Avec la prise en charge de l'expansion et de la réduction des nœuds.

stories feature request merged ui

Commentaire le plus utile

Salut les gars!

Malgré le fait qu'une telle fonctionnalité ne soit pas prévue dans un avenir proche, cela ne signifie pas que nous ne pouvons pas obtenir un tel comportement via l'API Storybook Addons

Voici un tel addon :



Chapitres du livre de contes

Chapitres du livre de contes

Ajoute des niveaux illimités d'imbrication pour les (sous-)histoires

preview

Pour ajouter un niveau d'imbrication supplémentaire, mettez simplement .chapter(name) dans vos histoires :

// stories.js:

storiesOf('React App', module)
    .chapter('Left panel')
        .add('Button 1', fn(1))
        .add('Button 2', fn(2))
        .chapter('Bottom Panel')
            .add('Input 3', fn(3))
            .add('Input 4', fn(4))
            .endOfChapter()
        .chapter('Header Panel')
            .add('Input 5', fn(5))
            .add('Input 6', fn(6))
            .endOfChapter()
        .endOfChapter()
    .chapter('Right panel')
        .add('Button 7', fn(7))
        .add('Button 8', fn(8))
        .endOfChapter()

Caractéristiques

  • La structure hiérarchique des Substories
  • Compatible avec Knobs , addWithInfo et d'autres addons
  • Utilisez storyDecorator pour terminer tous les chapitres

Page de démonstration

Projet

Exemple


Tout commentaire sera très apprécié! :)

Tous les 79 commentaires

À l'heure actuelle, nous n'avons aucun plan pour mettre cela en œuvre. C'est parce que cela rend la navigation plus difficile. Vous pouvez nommer les types d'histoires avec des points comme "ui.core", "ui.app". Ensuite, vous pouvez les filtrer selon vos besoins.

S'il y a beaucoup d'histoires, vous pouvez commencer quelques instances de livre de contes. Vous pouvez le faire en ayant deux répertoires de configuration de storybook. Mais, de toute façon, c'est un cas extrême.

Je suis prêt à admettre ce point, et j'ai pensé que je ferais juste une configuration différente et l'exécuterais sur un port différent et ainsi de suite...

Mais je pense qu'il serait bien mieux de permettre à Storybook de prendre plusieurs fichiers de configuration... puis de basculer entre les fichiers de configuration nommés, peut-être en rechargeant...

Quant à l'interface utilisateur pour changer de configuration, elle n'apparaîtrait que si votre fichier de configuration "chargeait" d'autres fichiers de configuration, et il pourrait s'agir d'éléments de la barre latérale en haut ou en bas de la navigation de la barre latérale.

Quoi qu'il en soit, je pense que pour les applications plus volumineuses, si vous ne pouvez pas (ou ne le faites pas) séparer les configurations, c'est un peu fou.

L'ajout de configurations supplémentaires semble être trop complexe. Qu'en est-il d'une bascule pour la vue classique/hiérarchie ? Je suis heureux de lancer une implémentation au cours des prochains jours.

Ce serait également une fonctionnalité très précieuse pour moi, mais pour l'organisation des types de composants au sein d'une seule application plutôt que pour plusieurs applications.

Je serais plus qu'heureux de fournir de l'aide pour façonner une implémentation qui pourrait fonctionner pour les deux cas d'utilisation si cela peut aller de l'avant.

@travi L'une de nos autres idées est de fournir un menu déroulant juste en dessous de la zone de filtre pour sélectionner la catégorie.

Une catégorie est attribuée dans le config.js et un ensemble de fichiers différent. Ainsi, nous pouvons avoir une autre couche de regroupement.

Je pense que ce type de solution serait suffisant pour satisfaire mes besoins à ce stade. De plus, je pense que la convention d'espacement des noms mentionnée ci-dessus pourrait toujours être un moyen raisonnable d'attribuer la catégorie qui pourrait être interprétée dans les choix de la liste déroulante. Une telle solution permettrait aux liens entre les catégories de rester simples également.

La façon dont nous contournons cela dans l'application que je construis (des centaines de composants, organisés à l'intérieur de zones lâches de "piliers") est avec un script qui écrit dynamiquement les histoires pour la zone sur laquelle nous travaillons actuellement.

find.file(
  /\.story\.js/,
  path.resolve(__dirname, '../src/app/components', targetComponentPath),
  function(files) {
    var requires = files.map(function(file) {
      return "require('" + path.relative(__dirname, file) + "');";
    });
    fs.writeFileSync(path.resolve(__dirname, '../.storybook/stories.js'), requires.join("\n"));
  }
);

Cela signifie que Storybook n'a même pas besoin de construire les autres composants. J'aimerais un certain niveau de support pour cela en tant qu'option intégrée.

201 pourrait aider à ce sujet.

des mises à jour sur celui-ci?

+1

Je pense que c'est une fonctionnalité très utile !

+1

+1

+1

+1

+1

+1

Salut @arunoda , y a-t-il eu des progrès sur le front de la mise en œuvre des catégories ?

Sinon, quelqu'un d'autre a-t-il un exemple d'application qui bascule entre deux configurations de livre de contes ?

+1 J'ai absolument besoin d'un niveau d'imbrication supplémentaire :/

+1

+1

+1

+1

+1

+1

ressemble bien à la croissance de votre application, la liste des composants s'agrandit également et vous avez besoin d'un peu plus d'imbrication. 1 niveau de plus couvrirait déjà beaucoup de cas

+1

Salut les gars!

Malgré le fait qu'une telle fonctionnalité ne soit pas prévue dans un avenir proche, cela ne signifie pas que nous ne pouvons pas obtenir un tel comportement via l'API Storybook Addons

Voici un tel addon :



Chapitres du livre de contes

Chapitres du livre de contes

Ajoute des niveaux illimités d'imbrication pour les (sous-)histoires

preview

Pour ajouter un niveau d'imbrication supplémentaire, mettez simplement .chapter(name) dans vos histoires :

// stories.js:

storiesOf('React App', module)
    .chapter('Left panel')
        .add('Button 1', fn(1))
        .add('Button 2', fn(2))
        .chapter('Bottom Panel')
            .add('Input 3', fn(3))
            .add('Input 4', fn(4))
            .endOfChapter()
        .chapter('Header Panel')
            .add('Input 5', fn(5))
            .add('Input 6', fn(6))
            .endOfChapter()
        .endOfChapter()
    .chapter('Right panel')
        .add('Button 7', fn(7))
        .add('Button 8', fn(8))
        .endOfChapter()

Caractéristiques

  • La structure hiérarchique des Substories
  • Compatible avec Knobs , addWithInfo et d'autres addons
  • Utilisez storyDecorator pour terminer tous les chapitres

Page de démonstration

Projet

Exemple


Tout commentaire sera très apprécié! :)

@UsulPro sympa !

@UsulPro Storybook Chapters est une solution brillante. Merci!

@UsulPro semble être exactement ce que je cherchais, merci !

Salut tout le monde! Je n'essaie pas de rivaliser avec storybook-chapters ), mais j'ai proposé une petite solution légèrement différente qui vous permet de basculer entre différents groupes d'histoires avec un bouton dans le preview fenêtre. C'est utile pour nous en particulier parce que nous voulons pouvoir basculer facilement entre une sorte de related components view à la documentation de bootstrap et à detailed components view quoi le livre de contes est bien adapté et nous avoir une tonne de composants à montrer. Je considérerais cela comme une version allégée de la configuration de plusieurs instances de livre de contes :

Si cela vous est utile, vous pouvez le vérifier ici - https://github.com/majapw/storybook-addon-toggle

J'ai construit sur l'incroyable storybook-chapters de @UsulPro pour créer un chargeur de livre de contes qui reflétera la hiérarchie de vos fichiers de composants sous forme de chapitres de Storybook : storybook-filepath-chapters

Avec cela, je peux mettre mes histoires dans un fichier ou un dossier _stories directement en ligne avec mes composants. Le chargeur trouve tous les fichiers d'histoire et les mappe dans une structure de navigation correspondante.

Merci pour les commentaires chaleureux, les gars!

Vraiment cool de voir les storybook-filepath-chapters @hadfieldn ! ??

J'aime storybook-addon-toggle comme exemple, qu'il est souhaitable d'avoir la possibilité de construire une hiérarchie non seulement en profondeur mais aussi en haut. En fait, techniquement, c'est possible, mais je pense qu'il est difficile de choisir la meilleure façon (en restant dans l'API des addons). Cela peut peut-être être fait à l'aide de décorateurs (comme @majapw) ou via des panneaux d'addon.

Je ne prévois pas encore d'ajouter une hiérarchie sur les histoires, mais l'addon storybook-chapters a maintenant une API , est capable de simplifier la construction d'une telle hiérarchie :

enable / disable pour afficher/masquer vos histoires



ça marche comme ça :


-

ajoutez enable() / disable() à vos histoires. En argument, spécifiez le rappel auquel la fonction de contrôle sera transférée.

let toLight = () => {};
let toDark = () => {};

storiesOf('Heroes Lightside', module)
    .enable((en) => { toLight = en; })
    .add('Yoda', info('Yoda'))
    .add('Mace Windu', info('Mace Windu'));

storiesOf('Heroes Darkside', module)
    .disable((en) => { toDark = en; })
    .add('Darth Sidious', info('Darth Sidious'))
    .add('Darth Maul', info('Darth Maul'));

alors vous pouvez utiliser toLight(false) pour masquer Heroes Lightside et toDark(true) pour afficher les Heroes Darkside histoires. Vous voudrez peut-être mettre toLight et toDark dans certains décorateurs ou peut-être pour rappeler d'autres histoires. Je vais montrer l'exemple le plus simple possible :

storiesOf('Choose Your Side', module)
    .add('Lightside', () => {
        toLight();
        toDark(false);
        return (<div>{'Lightside selected'}</div>);
    })
    .add('Darkside', () => {
        toDark();
        toLight(false);
        return (<div>{'Darkside selected'}</div>);
    });

Nous avons donc maintenant 3 séries d'histoires : Choose Your Side , Heroes Lightside et Heroes Darkside . Des deux derniers, un seul est visible et le premier permet de basculer.

dans la prochaine version, je prévois d'ajouter la possibilité de contrôler la visibilité des histoires via un panneau d'extensions personnalisable

-

Avec la fonction d'activation/désactivation, vous pouvez créer une navigation personnalisée avec votre logique préférée.

exemple complet ici

Nous allons implémenter un navigateur hiérarchique, mais aimerions comprendre comment la communauté pense que cela devrait être fait :

  • UX sage
  • Comment configurer les groupes

Côté UX, j'aime cette idée : http://multi-level-push-menu.make.rs/demo/basichtml/basichtml.html

Configuration que je ne connais pas encore. Nous pourrions utiliser l'exploration de fichiers et mettre en miroir le système de fichiers, ou nous pourrions faire quelque chose comme ceci : https://github.com/sm-react/storybook-chapters/issues/1#issue -215446017

@ndelangen avez-vous pensé (au moins facultativement ?) à permettre de définir la navigation en dehors des stories ? Il me semble qu'il pourrait être utile de traiter l'apparence de l'histoire (la zone de prévisualisation / l'iframe) et la façon dont vous souhaitez organiser la navigation (le gestionnaire) comme des préoccupations distinctes.

@jackmccloy Je suis intéressé, pouvez-vous m'en dire plus sur ce que vous voulez dire ?

J'ai mentionné dans un autre numéro, mais mon objectif avec les catégories serait de m'aligner principalement sur la conception atomique . pattern lab est l'approche officielle du guide de style pour la conception atomique, mais l'ajout de catégories au livre de contes comblerait la dernière lacune restante.

J'organise déjà mes composants dans des dossiers de niveau supérieur pour ces catégories, donc pouvoir charger des composants dans des catégories basées sur des dossiers de niveau supérieur serait également une bonne chose pour le tournage.

@travi Pouvez-vous me donner une impression de la mise en page de votre dossier ?

Je suis vraiment intéressé à améliorer le livre de contes dans ce but précis, mais je suis intéressé par ce qui serait techniquement requis pour lire cette catégorisation à partir de votre structure de dossiers.

c'est essentiellement

project root
|
+--
|  +-- atoms
|  |  +-- foo
|  |    +-- index.js // the component
|  |    +-- stories.js
...
|  +-- molecules
|  |  +-- bar
|  |    +-- index.js
|  |    +-- stories.js
...
|  +-- organisms
|  |  +-- baz
|  |    +-- index.js
|  |    +-- stories.js

Est ce que ça aide? j'ai plusieurs composants sous chaque dossier de niveau supérieur, parfois regroupés par un autre niveau de dossier. heureux de fournir plus de détails si cela peut être utile

ok, donc ce que nous pourrions faire est de définir un indicateur dans config.js . quelque chose comme autoDiscoverStories ou plus. Ce qui signifierait que vous n'avez pas à importer les histoires manuellement et que les dossiers du système de fichiers seraient utilisés comme catégories.

@ndelangen Je suppose que ce que je pense est ceci : en ce moment, notre conversation

Une possibilité :
Actuellement, chaque histoire est ajoutée en deux étapes - une première étape où une catégorie est attribuée, et une deuxième étape où un titre est attribué, c'est-à-dire

storiesOf('storyCategory', module).add('storyTitle', () => <Component />)

Vous pouvez enchaîner l'ajout de plusieurs histoires à la même catégorie, mais la structure limite la flexibilité dans une certaine mesure - toutes les histoires doivent avoir une catégorie et un titre, et les catégories sont d'un "niveau supérieur" aux titres.

Mais si les histoires pouvaient être définies d'une manière légèrement différente, c'est-à-dire

const storyData = {
  category: "category",
  title: "storyTitle",
}
stories.add(() => <Component />, storyData)

nous pourrions expérimenter plus facilement différentes options de navigation.

La navigation par défaut pourrait rester telle quelle. C'est une valeur par défaut sensée, et cela fonctionne probablement assez bien pour la plupart d'entre nous. storyData pourrait même être facultatif - les histoires sans catégorie pourraient apparaître au niveau supérieur, et les histoires sans titre pourraient par défaut être le displayName du composant.

Mais la communauté pourrait expérimenter différentes manières d'organiser ses histoires en (a) ajoutant des champs de métadonnées supplémentaires à stroyData et/ou (b) en modifiant la façon dont le panneau de navigation s'affiche en fonction des champs de métadonnées.

Quelques idées:

// add an additional level to the hierarchy called subCategory
const stroyData = {
  category: "Buttons",
  subCategory: "Blue",
  title: "BlueButton",
}
stories.add(() => <BlueButton />, storyData)

// add tags to a story that you could then filter by
const stroyData = {
  category: "Buttons",
  tags: ["button", "homepage"],
  title: "HomepageButton",
}
stories.add(() => <HomepageButton />, storyData)

// have a story to appear in multiple categories
const stroyData = {
  categories: ["Buttons", "Homepage Elements"],
  title: "HomepageButton",
}
stories.add(() => <HomepageButton />, storyData)

Joli! c'est tout à fait hors de la boîte, et en effet extensible. Je vais y réfléchir un peu. ??

Impressionnant. Faites-moi savoir ce que vous décidez - je vais intervenir où je peux, quelle que soit la direction que vous choisissez d'aller - grand fan du projet

La proposition de @jackmccloy est géniale, merci pour cette bonne idée !

Cependant, cela semble décourager un cas d'utilisation fort pour Storybooks qui considère l'interface utilisateur comme une série de "cas de test visuels" et définit facilement les états de l'interface utilisateur comme des histoires individuelles en utilisant un appel add() par état.

L'enregistrement des métadonnées de l'histoire dans l'appel add() impression d'ajouter la catégorie au mauvais niveau. J'aimerais voir la même proposition, mais en utilisant la fonction storiesOf() :

storiesOf({
  title: Component,
  category: "My Category"
}, module)
  .add("when empty", () => <List items=[] />)
  .add("with items", () => <List items=["one", "two", "three"] />)
  .add("etc.", () => <List items={etc} />);

J'aime l'idée de pouvoir simplement prendre le titre du Component.displayName et toutes les autres idées sur les sous-catégories ou l'ajout d'un composant à plusieurs catégories, je voudrais juste préserver la simplicité de l'ajout d'états.

une chose à garder à l'esprit, quel que soit l'endroit où la catégorie est définie, est qu'un autre fichier doit pouvoir s'ajouter à la catégorie. si une catégorie ne pouvait être définie qu'à partir d'un seul fichier, je pense que ce serait très limitatif

Je suis d'accord @travi - c'est pourquoi la catégorie étant simplement une chaîne (qui, j'imagine, correspondrait à une clé de dictionnaire) est attrayante.

J'imagine que je pourrais définir mes catégories à un seul endroit pour éviter les fautes de frappe comme celles-ci :

// categories.js
export const Layouts = "Layouts";
export const Components = "Components";
export const Styles =  "Styles";

// DashboardLayout.story.js
import { Layouts } from "../categories";
import DashboardLayout from "./DashboardLayout";

storiesOf({
  title: DashboardLayout,
  category: Layouts
}, module)
  .add("default", () => <DashboardLayout />);

mais ce serait un détail de mise en œuvre laissé à mon application.

@theinterned @jackmccloy J'aime vos suggestions.

Je réfléchis à la façon dont vous pourriez utiliser vos suggestions dans une hiérarchie de profondeur arbitraire. Peut-être qu'au lieu de category / subCategory cela pourrait être path avec un tableau de composants de chemin. (Je sais que vous n'aviez pas nécessairement l'intention de donner des détails là-bas, vous n'aviez que des riffs sur vos idées.)

J'aime aussi l'idée d'une option de configuration pour utiliser le système de fichiers pour créer la hiérarchie de navigation. Avec cette option activée, l'argument path serait facultatif.

Il s'agit davantage d'un objectif étendu, mais il peut être bon que chaque page d'histoires de la hiérarchie soit chargée en tant que bloc séparé, afin de garder le livre de contes léger au fur et à mesure qu'il s'agrandit. Il serait également intéressant de permettre au chargeur de contes de s'exécuter avec un dossier de système de fichiers spécifique en tant que contexte racine, afin qu'il puisse créer un livre de contes avec uniquement les histoires définies dans ce dossier plutôt que toutes les histoires de l'ensemble du projet.

Que pensez-vous de la définition / de l'enregistrement des catégories dès le départ dans votre configuration ?

// config.js
import { configure, addCategory } from '@kadira/storybook';

function init() {
  require('../src/stories');
  addCategory({
    id: 'atom',
    name: 'Atoms',
    index: 0
  });
  addCategory({
    id: 'molecule',
    name: 'Molecules',
    index: 1
  })
}

configure(init, module);
// component.story.js
import Component from "./Component";

storiesOf({
  title: Component,
  category: 'atom'
}, module)
  .add("default", () => <DashboardLayout />);

On peut aussi bien supporter un tableau : category: ['atom', 'deprecated'] , pourquoi pas ?

Cela aiderait à s'assurer que les catégories sont placées dans le bon ordre, ce qui est important dans la conception atomique.

Récupérer les catégories de la configuration serait bien, les chaînes magiques sont mauvaises

cela a du sens pour moi.

aussi, +1 pour tirer la catégorie de l'histoire de ce qui a été défini dans la configuration plutôt que d'espérer faire correspondre les chaînes

@ndelangen définir des catégories à l'avance afin que nous puissions contrôler la commande serait ÉNORME ! Mais je pense qu'il serait important de faire en sorte que les catégories _peuvent_ être définies dans la configuration, pas qu'elles _doit_ y être définies.

Une chose que j'aime à propos de Storybook, c'est que je peux savoir si un composant est dans Storybook simplement en vérifiant s'il y a un fichier story.jsx co-localisé avec le composant. Cette garantie -
que si un fichier story.jsx existe, une histoire existe - c'est une histoire importante qui ne devrait pas être annulée par des catégories prédéfinies, imo.

De ce point de vue, avoir besoin d'un id et d'un index pour les catégories dans la configuration pourrait même ne pas être nécessaire - quelque chose comme ça (en supposant qu'il utilise le plugin d'options) pourrait fonctionner

setOptions({
  categoryOrder: [
    "First Category",
    "Second Category",
    "Third Category",
});

First Category , Second Category et Third Category sont garantis pour apparaître en premier, deuxième et troisième, et toutes les autres catégories déclarées dans les histoires apparaîtront par ordre alphabétique après ces trois.

Cette approche pourrait également être un moyen intelligent de contrôler l'imbrication à profondeur arbitraire, en faisant quelque chose comme ceci :

categoryOrder: [
  {
    "Atoms": [
      {
        "Buttons": []
      }
    ],
  }, {
    "Molecules": [],
}],

Les histoires avec la catégorie "Boutons" apparaîtraient à l'intérieur de Atoms -> Buttons . Les histoires avec la catégorie "Atoms" apparaîtraient à l'intérieur de Atoms , en dessous de Buttons (mais pas à l'intérieur), etc.

Les utilisateurs obtiendraient un niveau de profondeur sans aucune configuration (comme maintenant) et des niveaux de profondeur arbitraires avec une configuration minimale. Surtout, ce sont les catégories qui ont de la profondeur (définies au niveau de la configuration) plutôt que les histoires elles-mêmes (c'est-à-dire que les histoires ne définiraient que leur catégorie - elles ne définiraient pas où cette catégorie apparaît dans la hiérarchie).

@theinterned Je suis d'accord avec vous concernant la nécessité de préserver la simplicité de l'ajout d'états. Je n'y avais pas pensé, probablement parce que j'utilise beaucoup l'addon de boutons. Donc pour moi, j'essaie d'avoir une relation 1-1 entre les composants et les histoires, et mes titres d'histoires sont descriptifs du composant plutôt que descriptifs de l'état dans lequel se trouve le composant.

Une solution potentielle qui pourrait fonctionner pour les deux cas d'utilisation serait de faire quelque chose comme ça

const storyData = {
  category: "category",
  title: "first item",
}
stories.add(() => <Component />, storyData)
  .add(() => <Component />, {title: "second item"})
  .add(() => <Component />, {title: "third item"})

où (a) l'ordre des histoires peut être contrôlé à partir de l'endroit où elles sont déclarées (au lieu d'avoir besoin d'une configuration externe) et (b) le storyData peut préserver l'objet précédent, en écrasant uniquement les valeurs qui sont explicitement passés.

Juste une pensée.

Bien que je serais ravi de ne voir que les catégories de haut niveau, si les choses vont assez loin pour prendre en charge les catégories imbriquées, il convient de noter qu'il n'est pas prudent de supposer que les noms de catégorie seraient uniques entre différentes catégories.

en poursuivant l'exemple de conception atomique, il est courant d'avoir une sous-catégorie du même nom dans chacune des catégories de niveau supérieur d'atomes, de molécules et d'organismes. dans la démo du laboratoire de modèles , les formulaires en sont un bon exemple. les éléments de champ individuels sont répertoriés sous les atomes, la combinaison du champ et de l'étiquette est répertoriée sous les molécules et plusieurs champs regroupés sous une forme complète sont affichés sous les organismes.

Une réflexion intéressante serait de se demander si la catégorie pouvait être définie avec un rappel qui récupère le titre, l'histoire et le chemin d'accès au fichier de l'histoire ... et aussi quelques métadonnées que l'utilisateur peut transmettre pour configurer le rappel.

storyData = {
  title: Component,
  category: ({ title, story, storyPath, meta }) => someCategoryPath,
  meta: { ..whateverMeta }
}

La seule exigence est que le rappel doit renvoyer un objet définissant un chemin de catégorie vers l'histoire :

storyData.category() //=> returns the below array

// a simple category path might look like:
[ "One category" ];

// The path for a story nested three categories deep would look like:
[ "Parent Category",  "Child Category", "Grandchild category where the story lives" ];

Cela permettrait aux gens d'écrire n'importe quel système de catégories qu'ils veulent.

Si vous souhaitez avoir une configuration globale, vous pouvez l'enregistrer dans le rappel et utiliser les métadonnées personnalisées pour configurer les catégories / sous-catégories avec lesquelles vous souhaitez enregistrer l'histoire.

categories: [
  {
    "Atoms": [
      {
        "Buttons": []
      }
    ],
  }, {
    "Molecules": [],
}];

function setCategory({ meta }) {
  const { categroyPath } = meta; // maybe a dot path string like "Atoms.Buttons" ?
  const category = categroyPath.split('.'); // [ "Atoms", "Buttons" ]
  return validatePath(category, categories); // categories["Atoms"]["Buttons"] is a valid path
}

Si vous souhaitez définir la structure des catégories en fonction de la structure du fichier, vous disposez des informations de chemin pour le faire.

function setCategory({ storyPath }) {
  // for story path `src/components/Atoms/MyComponent.story.js`
  let folders =storyPath.split('/'); // [ "src", "components", "Atoms", "MyComponent.story.js" ];
  folders = without(folders, 'src'); // ["components", "Atoms", "MyComponent.story.js" ];
  folders.pop(); // [ "components", "Atoms" ]
  return folders;
}

Si vous souhaitez simplement utiliser un nom de catégorie simple, vous pouvez en utiliser un ! (Et peut-être que la catégorie pourrait prendre l'une d'une simple chaîne, d'un tableau décrivant un chemin de catégorie ou d'un rappel qui renvoie un chemin de catégorie).

Maintenant, le ciel est la limite !

sur une note similaire, pour définir l'ordre de tri, je suggérerais une fonction addCategorySort vous pourriez enregistrer qui prend la structure arborescente des catégories générée en chargeant toutes les histoires et la trie.

import { configure, addCategorySort } from "@kadira/storybook";

addCategorySort( categories => /* sort logic here */ );

configure(loadStories, module);

@travi Je n'avais pas envisagé la nécessité de catégories nommées en double, mais je conviens que c'est important. Des idées sur une solution? C'est ce qui me vient à l'esprit, mais il y a peut-être une meilleure solution :

const storyData = {
  categories: ["Buttons"],  // any category with the title "buttons"
}

const storyData = {
  categories: ["Atoms.Buttons"],  // any category with the title "buttons" that also has the parent category "atoms"
}

@theinterned Je creuse l'approche, mais je m'inquiète du fait que cela pourrait rendre les choses plus difficiles / moins intuitives pour les utilisateurs typiques (qui ont besoin / veulent quelque chose qui fonctionne bien hors de la boîte) au profit de l'utilisateur expérimenté (qui veut quelque chose qui fonctionne parfaitement avec un peu d'effort).

@jackmccloy ouais ... Je suis d'accord pour dire que la mise en œuvre d'une fonction ne devrait pas être une exigence pour tout le monde. Mais il semble qu'il existe un certain nombre de cas d'utilisation différents que les gens cherchent à prendre en charge et donc un système de rappel semble être un bon moyen de fournir une extensibilité à chacun pour personnaliser son propre cas d'utilisation.

Pour apaiser l'inquiétude que cela rende le « chemin du bonheur » plus difficile, je recommande ce qui suit :

  1. Soit storydData.category accepter une chaîne, auquel cas la catégorie serait une catégorie de niveau supérieur.
  2. Soit storydData.category accepter un tableau où les éléments du tableau sont le chemin d'accès à la catégorie :
// given
storydData.category = ["grand parent", "parent", "story category"];
// category tree would look like:
categories = {
  "grand parent": {
    "parent": {
      "story category": /* the story lives here */
    }
  }
};
  1. Laissez les données de l'histoire accepter une fonction comme décrit ci-dessus (https://github.com/storybooks/react-storybook/issues/151#issuecomment-292689536).
  2. Nous pourrions en fait écrire quelques gestionnaires de catégories qui couvrent certains des cas d'utilisation courants que nous avons ici (conception atomique, basée sur des dossiers ...);

De même pour le tri, nous pouvons prendre en charge la stratégie par défaut (alpha sans doute) par défaut et s'il y a un besoin, nous pourrions fournir d'autres stratégies de tri prédéfinies (tri basé sur une forme d'objet, index de tri dans les métadonnées, etc...) ;

@ndelangen, que

Lorsque je reçois un avis que le travail a commencé par quelqu'un et que sa solution est viable, je supprime l'étiquette PR needed . Donc, c'est actuellement sur la feuille de route, mais aucun travail n'a encore été fait.

Si vous voulez vous lancer, ce serait la bienvenue !

@jackmccloy puis-je également rejoindre et participer à ce travail si cela ne vous dérange pas ?

@UsulPro 100%, je serais ravi à ce sujet. Je prévois de commencer à y jeter un coup d'œil dimanche après-midi (heure de New York). Si vous êtes en ligne en même temps, lmk et nous pouvons déplacer la convo vers Slack. Sinon, je posterai ici avec quelques réflexions après avoir creusé un peu

@jackmccloy @usulpro Je suis également très intéressé à travailler là-dessus.

@theinterned Ce serait génial ! Connexion en slack?

@UsulPro désolé - une mauvaise grippe

J'ai une journée de hack à venir au travail vendredi et j'ai l'intention de travailler là-dessus à ce moment-là. Avez-vous eu l'occasion de vous lancer ? Je serais heureux de me synchroniser sur Slack. Je suis sur le canal SB.

Si vous n'avez besoin que d'un seul niveau d'imbrication, React Storybook Addon Chapters peut répondre à vos besoins.

J'ai publié la première version de l'excellente implémentation de @igor-dv de la hiérarchie des histoires et j'aimerais avoir vos commentaires sur l'alpha afin que nous puissions l'améliorer avant de la diffuser à la communauté au sens large :

https://gist.github.com/shilman/947a3d1d4cfdf5c3a8bb06d3d4eb84cf

@ 1i1it @andrubot @arunoda @atnovember @danielbartsch @franzihubrick @hadfieldn @iaanvn @imsnif @isuvorov @jackmccloy @joeruello @johnnyghost @lnmunhoz @majapw @markopavlovic @mystetskyivlad @mzedeler @ndelangen @nirhart @ noahprince22 @revolunet @sethkinast @theinterned @thesisb @travi @usulpro @yangshun @zeroasterisk @zvictor

Juste une petite bizarrerie que j'ai remarquée avec la hiérarchie des histoires :
Selon qu'un répertoire a des sous-répertoires, le résultat du clic sur un répertoire change.
S'il y a des sous-répertoires, le dossier se développera, mais s'il est au niveau de l'histoire, l'histoire sera automatiquement sélectionnée.
Un utilisateur peut souhaiter afficher le contenu de dir sans sélectionner une histoire à l'intérieur.
autoselectdir

Mettre à jour:

Peut être lié à ce problème dans react-treebeard
https://github.com/alexcurtis/react-treebeard/issues/33
Cela pourrait valoir la peine d'explorer les PR là-bas pour le repo storybooks/react-treebeard

Dans l'implémentation précédente, lors de la sélection d'un kind sa première histoire était sélectionnée automatiquement. Donc cette fonctionnalité que je voulais préserver. Mais peut-être qu'avec la hiérarchie, cela ressemble déjà à un bug.

image

Dans l'image, Component 5 n'est pas un répertoire - c'est un kind .

En fait, je n'aime pas non plus ce comportement...

Les noms de longues histoires s'enroulent étrangement
image

Le redimensionnement de la barre latérale pour qu'il soit vraiment petit provoque le débordement du volet d'aperçu.
shrunk

est-il possible de combiner des dossiers hiérarchiques avec des histoires individuelles ? J'ai des histoires que je veux au niveau supérieur, sinon j'ai un dossier avec un seul élément

Actuellement, si vous faites cela

storiesOf('Something', module).add('top story');
storiesOf('Something.Chapter', module).add('substory');

Ensuite, il crée 2 entrées pour 'Something', une avec un dossier et une avec un élément

@TheSisb , merci, sera corrigé dans la version officielle.

@psimyn , dans l'implémentation actuelle, ce n'est pas possible.. mais cela pourrait être modifié.. @UsulPro l'a également mentionné dans le PR initial.
OMI ce n'est pas un bon comportement (et apporte plus de complexité). En le comparant à chaque IDE, il existe des espaces de noms (répertoires/dossiers/paquets) et il peut y avoir des éléments dans ces espaces de noms (ou à proximité) avec le même nom.
Quoi qu'il en soit, s'il s'agit d'un comportement souhaité de la communauté, il devrait être modifié, mais je ne voudrais pas que ce soit un frein à la sortie =)

C'est exactement la solution dont j'avais besoin !!! merci +1

@psimyn Veuillez ouvrir un nouveau numéro décrivant la fonctionnalité ? Ce problème sera bientôt clos avec la sortie de 3.2.0

est-il désormais possible d'avoir plusieurs niveaux d'imbrication avec le nouveau format CSF ?

@ gaurav5430 c'est possible depuis un certain temps, voir notre exemple ici :

CSF :

import React from 'react';
import { linkTo } from '@storybook/addon-links';
import { Welcome } from '@storybook/react/demo';

export default {
  title: 'Other/Demo/Welcome',
  component: Welcome,
};

export const ToStorybook = () => <Welcome showApp={linkTo('Other/Demo/Button')} />;
ToStorybook.storyName = 'to Storybook';

Salut @ndelangen
Merci, je reçois cela d'ici : https://storybook.js.org/docs/basics/writing-stories/#story -hierarchy

Je pense que ce que je veux, c'est la possibilité de créer des sous-dossiers basés sur story.name et pas seulement le titre d'exportation par défaut

export default {
  title: 'Other/Demo/Welcome',
  component: Welcome,
};

export const ToStorybook = () => <Welcome showApp={linkTo('Other/Demo/Button')} />;
ToStorybook.story = { name: 'to/Storybook' };

apparaîtrait sous la forme Other/Demo/Welcome/To/Storybook

Je pense qu'une solution de contournement pour le problème ci-dessus serait de créer plusieurs fichiers d'histoire et d'exporter par défaut avec la hiérarchie correcte dans chacun d'eux.

comme dans one.stories.js :

export default {
  title: 'Other/Demo/Welcome/One',
  component: Welcome,
};

export const ToStorybookOne = () => <Welcome showApp={linkTo('Other/Demo/Button')} />;

et en two.stories.js

export default {
  title: 'Other/Demo/Welcome/Two',
  component: Welcome,
};

export const ToStorybookTwo = () => <Welcome showApp={linkTo('Other/Demo/Button')} />;

De cette façon, les deux histoires apparaîtraient comme prévu dans la structure de dossiers du livre de contes

@ gaurav5430 c'est l'utilisation recommandée, et non une solution de contournement. ??

@ gaurav5430 c'est l'utilisation recommandée, et non une solution de contournement. ??

Oui, j'hésitais juste à le faire car ces deux fichiers concernent des états différents du même composant. Dans mon cas, le composant a 2 états principaux et plusieurs sous-états basés sur ces 2 états principaux. Habituellement, je conserverais tous les états du composant dans le même fichier, mais dans ce cas, j'aurais besoin d'un fichier séparé pour la hiérarchie dans les histoires.

Cette page vous a été utile?
0 / 5 - 0 notes