Habitualmente no basta con crear las stories para que el usuario vea cómo funciona un determinado componente. Se necesita también explicar cómo se instala y se configura, sus características, casos de uso, y un largo etcétera.

En este artículo vamos a ver cómo crear esas páginas de Storybook en Nx Angular monorepo con documentación extra para dar más información al usuario, són, los documentos MDX.

Ya en el artículo de configuración, hacíamos mención a cómo configurar Storybook para que supiera incluir los archivos mdx y la forma de crearlos en el «main.ts». Así como también usar los estilos creados mediante un tema en el «preview.ts».

No hablaremos sobre cómo escribir con todo detalle contenido de un MDX (markdown y  Javascript/JSX) si no más bien a usarlos en Storybook.

Storybook proporciona tres formas de poder generar documentación: crearla de forma automática (autodocs: true), no generarla (autodocs: false), o generarla según decidamos (autodocs: ‘tag’).

Generación automática

En el archivo «main.ts» tenemos la propiedad autodocs dentro de docs:

const config: StorybookConfig = {
  ...
  docs: {
    autodocs: true,
    defaultName: 'Documentación',
  },
  ...
};

Con esta configuración, se genera la documentación de forma automática y el contenido de los documentos se genera con una estructura predefinida:

  1. Título
  2. Subtítulo (meta-componente.parameters.componentSubtitle)
  3. Descripción (meta-componente.parameters.docs.description.component)
  4. Story primaria: La primera story dentro del archivo de stories.
  5. Controles
  6. Stories (con una descripción por story: story.parameters.docs.description.story)

El código sería el siguiente en el archivo de «*.stories.ts»:

...
const meta: Meta = {
  component: TextButtonComponent,
  parameters: {
    componentSubtitle: 'Componente para iniciar una acción',
    docs: {
      description: {
        component: 'Botón rectangular que contiene un texto indicando la acción. Además puede visualizarse de dos maneras para indicar su propósito: primario o secundario.'
      }
    }
  },
  title: 'Componentes/Botones',
  ...
};

export default meta;
type Story = StoryObj;

export const Primary: Story = {
  name: 'Botón primario o principal',
  parameters: {
    docs: {
      description: {
        story: 'Estilo de botón primario usado para guiar al usuario en un flujo. Usar uno por página.'
      }
    }
  },
  args: {
    label: 'clica aquí!',
    type: 'primary'
  }
};
Documentación generada automáticamente con título, subtítulo, descripción, nombre story y descripción story
Documentación generada automáticamente con título, subtítulo, descripción, nombre story y descripción story

Nota: Si no existe una descripción a nivel del documento (meta-componente.parameters.docs.description.component) Storybook puede obtenerlo a partir de comentarios (siguiendo nomenclatura JSDoc) en la clase TextButtonComponent y activando compoDoc.

Plantillas

Se puede cambiar la estructura que Storybook genera para documentación mediante la creación de una plantilla. Dicha plantilla se puede activar a nivel general (para toda la documentación) o para algunas stories en concreto.

Ejemplo de creación

Creamos un archivo mdx llamado «documentationTemplate.mdx» en una carpeta «doc-templates» dentro de «.storybook» que será la base sobre la cual se creará la documentación con el siguiente contenido:

import { Meta, Title, Primary, Controls, Stories, Subtitle, Description } from '@storybook/blocks';

<Meta isTemplate />

<Title />

<Subtitle />

<Description />

## Implementación por defecto

<Primary />

## Inputs

El componente acepta las siguientes entradas o inputs (props):

<Controls />

---

## Variaciones del componente

A continuación se enumeran variaciones adicionales del componente.

<Stories />

No hemos hecho más que lo mismo que ya generaba pero añadiendo más texto a cada sección. Podéis consultar la sección de doc-blocs donde hallaréis más tipos de bloques.

A continuación le decimos a Storybook que toda la documentación generada automáticamente la haga a partir de esa plantilla, para eso editamos el archivo «preview.ts» de la siguiente manera:

import afTheme  from './themes/af-theme';
import DocumentationTemplate from './doc-templates/documentationTemplate.mdx';

const preview: Preview = {
  parameters: {
    ...
    docs: {
      theme: afTheme,
      page: DocumentationTemplate
    }
  }
};

Generación semi-automática

Esta opción nos permitirá generar aquella documentación para las stories que indiquemos de forma automática.  La estructura de la presentación es la misma que si fuera automática, así como la creación de plantillas.

Para trabajar de este modo, en el archivo de configuración main.ts asignamos el valor «tag» en la propiedad «docs.autodocs» de la siguiente manera:

const config: StorybookConfig = {
…
   docs: {
    autodocs: ‘tag’,
    defaultName: 'Documentación',
  },
 …
};

Ahora solo queda que indiquemos qué documentación queremos que se genere yendo al meta componente y en su propiedad «tags» (que es un array) añadir el valor «autodocs»:

const meta: Meta<TextButtonComponent> = {
  component: TextButtonComponent,
  tags: ['autodocs'],
  parameters: {
    componentSubtitle: 'Componente para iniciar una acción',
    docs: {
      description: {
        component: 'Botón rectangular que contiene un texto indicando la acción. Además puede visualizarse de dos maneras para indicar su propósito: primario o secundario.'
      }
    }
  },
  title: 'Componentes/Botones',
 };

Obviamente si no añadimos ese valor a la propiedad «tags», no se generará su documentación.

Sin generación automática

Con la siguiente configuración en el archivo «main.ts» no se genera la documentación automáticamente:

const config: StorybookConfig = {
  ...
  docs: {
    autodocs: false
  },
  ...
};

Tabla de contenidos

Esta es una feature muy chula que se activa de forma sencilla y que aparece en toda la documentación como una tabla de contenidos dentro de esa página de documentación. No solo podemos ver los titulares sino que haciendo clic podemos ir directamente a esa sección. Para activarla basta con hacer lo siguiente en el archivo «preview.ts»:

const preview: Preview = {
  parameters: {
  ...
    docs: {
      theme: afTheme,
      page: DocumentationTemplate,
      toc: {
        contentsSelector: '.sbdocs-content',
        headingSelector: 'h1, h2, h3',
        ignoreSelector: '#primary',
        title: 'Tabla de Contenidos',
        disable: false,
        unsafeTocbotOptions: {
          orderedList: false
        }
      }
    }
  }
};

Si la quieres deshabilitar para algún documento en concreto sólo tienes que setear a «true» la propiedad parameters.docs.toc.disable : true del meta-componente.

Tabla de contenidos en documentación
Tabla de contenidos en documentación

Generación manual

Hemos visto cómo Storybook crea la documentación sin emplear mucho tiempo. Ahora bien, a veces interesa crearla de forma manual (escribiendo documentación unattached) para varios casos como por ejemplo:

  1. Introducción a la documentación: quiénes somos, qué pretendemos, …
  2. Tutoriales
  3. Misma documentación que la generada automáticamente.
  4. Etc

Tanto si hemos configurado o no la generación automática, siempre se puede crear archivos mdx de forma manual, ya sea con la misma estructura que la automática o no.
Aquí vemos un ejemplo de un mdx:

import { Meta } from '@storybook/blocks';

<Meta title="Componentes/Botones/Librería" />

# Buttons

Librería de botones de Angular Frontenders.

## Instalación

 `npm install @af/buttons`

 ## Tipos de botones

 ### Text button

 Componente: TextButtonComponent

 Descripción: Botón textual con capacidad de ser primario o secundario.

Resumen

Hemos visto como generar la documentación de forma automática: generarla siempre, nunca o solo para aquellas stories que nos interese. Además podemos generarla de forma manual para dar más información al usuario final. Como último detalle, a cada documento podemos hacer que se visualice una tabla de contenidos para que el usuario pueda ver la estructura del documento incluso poder navegar o acceder rápidamente al punto que más le interese.

Puedes ver el código en nuestro repo de github.