Libro de dibujo para pintar
Foto de Nico Smit en Unsplash

Storybook viene por defecto con un diseño propio. No obstante, mostraremos cómo cambiar esos estilos propios mediante lo que Storybook llama «Theming«, es decir, crearemos un tema que incorpore las características de una guía de estilos: marca, tipografías, colores, etc.

Instalación

Comprueba que tienes instalada la librería @storybook/theming en tu carpeta de node_modules, si no existe, puedes instalarla (con la misma versión de @storybook) mediante:

npm install --save-dev @storybook/theming[@version_sb_instalada]

Recursos

Habitualmente no solo cambiamos los estilos mediante los css, sino que además necesitamos apoyarnos en varios archivos que usan esos css y/o html: imágenes, vídeos, fuentes, … 

Por ejemplo, podemos necesitar imágenes para hacer valer nuestra marca, la imagen de icono de favoritos o favicon, otros css, diversas fuentes o tipos de texto y un largo etcétera.

Esos recursos han de «viajar» junto al bundle final (todo lo que se resulta en el outputPath) que se genera en el Storybook. Para ello, en el archivo de configuración «main.ts» lo configuramos para que copie (e incluso renombre) archivos que necesite no solo Storybook, sino también nuestros componentes creados. Es decir, servir archivos estáticos.

En nuestro caso pondremos una imagen de marca y la imagen de mis favoritos, así como copiar fuentes, y css de la siguiente manera:

staticDirs: [
  { from: '../src/assets/angular-frontenders-icon.svg', to: 'favicon.svg' },
  { from: '../src/assets', to: '/assets' },
  { from: '../src/fonts', to: '/fonts' },
  { from: '../src/styles/af-typography.css', to: 'af-typography.css' },
],

Vemos que existe una propiedad «staticDirs» en «main.ts», que nos permite copiar (incluso renombrar) archivos llevándolos al directorio destino.

Lo que hacemos en este caso es lo siguiente:

  1. Copiamos y renombramos nuestro archivo de icono de favoritos al directorio raíz final cambiando el nombre a «favicon.svg». De esta manera sobre-escribimos el favicon que Storybook trae por defecto.
  2. Copiamos todo el contenido de la carpeta assets (que contiene imágenes) al directorio assets de la ruta de salida.
  3. Copiamos todo el contenido de la carpeta fonts (contiene fuentes tanto para la UI de Storybook como para nuestros componentes).
  4. Copiamos el css que contiene la definición de las tipografías (básicamente los @font-face).

Otra manera de copiar recursos es usar dentro del project.json la propiedad de «assets» así como si quieres llevar estilos usar la propiedad «styles». No obstante, aquí no puedes renombrar los archivos en «assets», pero si tienes un archivo de sass para procesar sí que podrías usarlo.

Como norma, preferimos que esté dentro de «main.ts» toda esta funcionalidad para que esté centralizada en un punto y no esté disgregada en varios archivos.

Cabe la posibilidad de tener todos o algunos recursos fuera del output final, accediendo mediante su URL. Por ejemplo la imagen de marca obtenerla desde la URL https://angularfrontenders.com/wp-content/uploads/2018/12/angular-frontenders-simple.png.

Tema

Una vez visto cómo tener los recursos necesarios para nuestro tema, vamos a crearlo. Para ellos creamos un archivo llamado «af-theme.ts» (puedes llamarlo de otras maneras, en este caso, con el acrónimo de angular frontenders «af» más la palabra «theme» que indica que tiene la definición de un tema) dentro del directorio «.storybook» de la librería «storybook-host».

Importamos el «create» de la librería @storybook/theming/create y exportamos un objeto de tema con una configuración. De momento, la base de ese tema será «light» para tener un esquema de colores claro que trae por defecto (aunque puedes ponerlo como «dark» según lo que desees).

import { create } from '@storybook/theming/create';

export default create({
  base: 'light'
});

Marca

En este espacio especificamos cómo mostrar nuestra marca (brand), pudiendo mostrar nuestro logotipo u otra imagen que denote nuestra marca o bien otro significado, junto a un texto explicativo (tooltip), y la url a la que dirigirse al hacer clic abriendo o no una nueva pestaña del navegador.

Se muestra en la parte superior del sidebar.

export default create({
  base: 'light',
  brandTitle: 'Angular Frontenders | Experience',
  brandUrl: 'https://angularfrontenders.com',
  brandImage: 'assets/angular-frontenders-simple.png',
  brandTarget: '_blank',
});

Fíjate aquí la url del archivo «brandURL», que coincide con el destino final durante la copia de archivos estáticos del archivo «main.ts». Si no hubiéramos querido hacer la copia, podríamos haber puesto la url al archivo de la web:

brandImage: 'https://angularfrontenders.com/wp-content/uploads/2018/12/angular-frontenders-simple.png',

Fuentes

Es una mención especial las fuentes dado que seguramente querrás usar otra tipografía de la que viene por defecto y además no está instalada en el navegador del usuario final.

En nuestro caso hemos dividido entre la fuente de la UI de Storybook (Roboto) de la fuente que usan nuestros componentes (Anta).

Dentro de las fuentes que gestiona Storybook, diferencia entre fuente para la UI y la fuente que usa para mostrar código fuente. Así, nuestra configuración para el tema queda de la siguiente manera para que use la Roboto en la UI y la monospace en el código fuente:

export default create({
  …
  fontBase: 'Roboto, "Open Sans", sans-serif',
  fontCode: 'monospace',
  …
});

Ahora bien, hay que cargar dentro del site de Storybook todas las fuentes. Para ello creamos un archivo css que relacione la fuente con el archivo, declarando los «@font-face» necesarios:

/* Fonts for SB Theme (manager) */
@font-face { 
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./fonts/Roboto-Regular.woff2') format('woff2');
}
@font-face {
  font-family: 'Roboto';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url('./fonts/Roboto-Italic.woff2') format('woff2');
}
@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('./fonts/Roboto-Bold.woff2') format('woff2');
}
@font-face {
  font-family: 'Roboto';
  font-style: italic;
  font-weight: 700;
  font-display: swap;
  src: url('./fonts/Roboto-BoldItalic.woff2') format('woff2');
}

/* Fonts for SB Stories (preview) */
@font-face {
  font-family: 'Anta';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('./fonts/Anta-Regular.woff2') format('woff2');
}

Fíjate que la url de los archivos de fuente woff2 hacen referencia al directorio de destino puesto en «staticDirs» del archivo «main.ts».

Nota: Hemos puesto en el mismo archivo las fuentes para la UI de Storybook como para la de los componentes a modo de ejemplo, pero seguramente sea mejor tener una librería de estilos para tus componentes.

Ya solo queda cargar dicho css en el Storybook, para eso, creamos dos archivos «preview-head.html» (se carga para el preview del componente) y «manager-head.html» (se carga para la UI en general), y en ambos añadimos su carga:

<link rel="stylesheet" href="./af-typography.css">

En los estilos de un componente podemos llamar a su fuente, por ejemplo:

.af-button {
  font-family: Anta;
  min-width: 10em;
  padding: 1em;
}

Otras características del tema

Aparte de la marca y fuentes hay otras características que se pueden cambiar como los colores del texto, colores de la toolbar, de los formularios, etc.

Uso del tema

Una vez creado el tema solo queda importarlo para que se use en dos sitios, en el manager y en la documentación.

Manager

Modificamos el archivo «manager.ts» para incorporar el tema de la siguiente manera:

import { addons } from '@storybook/manager-api';
import afTheme from './af-theme';

addons.setConfig({
  …
  theme: afTheme
});

Preview

Modificamos el archivo «preview.ts» para incorporar el tema de la siguiente manera:

import type { Preview } from '@storybook/angular';
import afTheme from './theme';

const preview: Preview = {
  parameters: {
    …
    docs: {
      theme: afTheme
    }
  }
};

Resultado final

Storybook de Angular Frontenders aplicando temas
Aplicar estilos a Storybook

Resumen

Hemos visto que mediante los temas podemos modificar el estilo que viene por defecto en Storybook. Estilos tanto para la UI como para los componentes, así como diferenciando incluso dentro de SB los estilos de su UI como para la documentación.
Puedes ver el código en nuestro repo de github.