Tema Wingsuit de Drupal (tailwindcss + storybook)

índice.png
Solucionex
12
Ago 21

Wingsuit (repositorio de github aquí) es un tema de drupal que integra tailwindcss, ui_patterns (componentes), atomic design, storybook y alpinejs (aunque permite variaciones con bootstrap también, por ejemplo). En este post se describe brevemente el funcionamiento de la versión con tailwindcss.

Nota: En este artículo los términos "componente" y "patrón" son básicamente intercambiables.

Nota importante: La raíz del tema no es el propio tema de Drupal, si no que son configuraciones base tanto para drupal como storybook. El tema de Drupal se encuentra en [...]/wingsuit/apps/drupal.

Requisitos

  • Node ^12
  • Yarn ^1.22 (aunque puede funcionar con npm directamente también)
  • PHP ^7.0.0

Instalación

La documentación oficial cita que la manera de instalarlo es usando el comando npx @wingsuit-designsystem/cli init. Aunque hay que tener un poco de cuidado con esto, ya que descarga la versión más actual disponible, que en el caso de cuando se hicieron las pruebas para este artículo era una alpha en la que fallaban algunas cosas. Actualmente parece estar más estable.

El comando anterior instala un tema starter kit, o sea, que se puede modificar e integrar en el control de versiones directamente. Hay que mover la carpeta generada a /[docroot]/themes/custom/ y compilar los archivos del tema iniciales con yarn run build:drupal desde la carpeta del tema. Una vez hecho esto, el tema puede ser activado en Drupal.

Aparte, es necesario instalar un parche para el core, ya que wingsuit usa su propio stream wrapper (wingsuit:) para archivos:

"patches": { "drupal/core": { "Stream wrapper reference in JS library causes error in _locale_parse_js_file()": "https://www.drupal.org/files/issues/2020-05-08/2735717-28.patch" } } en composer.json

Puesta en marcha

  • Instalar dependencias de node: yarn install en [docroot]/themes/custom/wingsuit
  • Ejecutar storybook: yarn run dev:storybook en [docroot]/themes/custom/wingsuit
  • Storybook con DDEV: Si se usa DDEV, Storybook puede lanzarse directamente desde el contenedor, para que no sea necesario instalar nada en la máquina real, por ejemplo. Para ello, basta con seguir estos pasos:
    • Incluir el número de puerto en la llamada a storybook: Añadir -p [PUERTO] en el comando "dev:storybook" del archivo package.json
    • Incluir un archivo "docker-compose.storybook.yml" en la carpeta .ddev para añadir que el contenedor "web" abra dicho puerto además de los normales: version: '3.6' services: web: ports: - [PUERTO]:[PUERTO]
  • Compilar archivos del tema de Drupal:
    • Desarrollo (monitorización de cambios y compilación automática): yarn run dev:drupal en [docroot]/themes/custom/wingsuit
    • Producción: yarn run build:drupal en [docroot]/themes/custom/wingsuit

Nota: durante el desarrollo es recomendable tener a la vez lanzados los comandos de storybook y el watch del tema de drupal en distintas terminales.

Componentes por defecto

Lios compnentes se encuentran en la carpeta [docroot]/themes/custom/wingsuit/source/default/patterns

1 - Atoms

  • Alerta: Componente que se usa en los status messages de Drupal
  • Botón: Enlace con forma de botón (aunque soporta ser renderizado como botón)
  • Formulario: Renderiza elementos de formulario (no el formulario en sí, son los inputs)
  • Hamburguesa: Icono de hamburguesa para menús de móvil
  • Titular: Renderiza titulares de página con etiqueta y tamño personalizables
  • Imagen: Renderiza una imagen. Opcionalmente puede renderizarse como imagen css
  • Enlace: Renderiza un enlace
  • Logo: Renderiza el logo de la web
  • Imagen de prueba: Renderiza una imagen de prueba en el tamaño que se le pase
  • Texto html: Renderiza texto wysiwig.
  • SVG: Renderiza un icono svg
  • Vídeo: Renderiza un vídeo html5

2 - Molecules

  • Elemento acordeón: Elemento desplegable sin js (¿por qué no se usa un \<details>? No lo sé)
  • Avatar: Imagen recortada en redondo con pie de foto y posible botón. No probado
  • Banner: Imagen de fondo con texto encima
  • Grupo de botones: Varios botones agrupados. No probado
  • Tarjeta: Normalmente se usa como elemento de listados. Tiene variante normal (vertical) u horizontal
  • Hero: Banner a ancho completo con imagen y título grande. Normalmente se usa para CTA. No probado
  • Selector de idioma: Permite elegir entre varios idiomas. No probado
  • Menú: Menú, principal o footer
  • Paginación: Paginación de listados

3 - Organisms

  • Sección columnas: Sirve para usarse como sección de LB
  • Contenedor: Contenedor genérico con anchura y padding configurables
  • Pie: Contiene el pie completo de la web
  • Rejilla: Sirve para crear rejillas, se usa en los listados como por ejemplo de views
  • Cabecera: Contiene la cebecera completa de la web
  • Carrusel: Genera un carrusel con los elementos que se le pasen. Puede usarse como sección de LB también

El archivo *.wingsuit.yml de los componentes

Los archivos .wingsuit.yml son la definición de la estructura del componente, y se usan tanto para la configuración de parámetros en storybook como el mapeo de campos en drupal. A la hora de la verdad, funcionan como los archivos .pattern.yml que se usan normalmente para componentes sin wingsuit.

En este documento se describen solamente las opciones de alto nivel que no sean triviales (ej: descripción):

  • fields: Campos del componente (ej: imagen, título, entradilla)
  • variants: Define las variantes que tiene el componente actual (ej: default, horizontal)
  • settings: Datos para generar el formulario de configuración del componente (ej: Alineación: Centro / Izquierda / Derecha)
  • configuration: Valores reales a usar dentro del componente a partir de lo configurado en el formualrio (ej:alignment "Centro" -> text-center)

Nota importante: tras hacer cambios en cualquier archivo .wingsuit.yml es necesario limpiar la caché de Drupal.

Creación de nuevos componentes

Para generar nuevos componentes, usar npx ws generate-component desde la carpeta del tema.

Las distintas opciones guiadas para genera el componente son:

  • Which app should be used?: Solo existe la opción de Storybook
  • Where would you like this new component?: Nivel de atomic design donde se generará el nuevo componente
  • What shall we name it?: Nombre del componente
  • What type of component would you like to create?: Normalmente hay que elegir entre "Wingsuit component (UI Pattern)" y "Wingsuit component (UI Pattern) with presentation template". La diferencia entre ambos es que el segundo genera una "demo" en storybook, pero no se ha llegado a comprobar bien la funcionalidad, ya que la otra opción también genera entrada en storybook, pero sin demo
  • Do you need a CSS file?: Elegir si se requiere css específico para el componente
  • Do you need an javascript attach event handler?: Elegir si se requiere js específico para el componente
  • How do you want to document your component?: Elegir "Automatic"

Invocación de componentes desde plantillas

La mejor manera de saber cómo hay que llamar a un componente es buscar ese componente en storybook y pulsar en la pestaña "Docs". Debajo de las configuraciones aparecerá el código necesario para invocarlo.

Nota importante: En el caso de componentes que contengan bloques de twig, como "container", si se quiere modificar el contenido de los bloques, hay que usar "embed" en lugar de "include" (storybook siempre muestra "include").

Nota importante: En caso de invocar componentes directamente desde twig, no se incorporan automáticamente las bibliotecas (css/js específico del componente). Se supone que se puede usando la función de twig "pattern()" (requiere el módulo "twig_tweak" y no se ha probado esta funcionalidad).

Invocación de componentes desde Drupal

Es necesario el módulo wingsuit_companion. Nota: este módulo solo debería usarse junto al tema wingsuit, si no aparecerá un warning en todas las páginas (ademnás de que no haría nada).

Desde Layout Builder

Requiere el módulo ui_patterns_layout_builder.

Permite añadir componentes como secciones de Layout Builder. Aunque permite añadir cualquiera, el que se usará en el 90% de los caso es "Columns section", que está hecho precisamente para usarse de este modo. Otro componente que puede usarse aquí sin riesgo es el de slider (hará que todos los bloques que se metan en dicha sección actúen como diapositivas del slider).

Nota: existe un módulo llamado "component_blocks" que se supone que permite añadir componentes directamente como bloques de lb, pero en las pruebas petardeaba ¯\_(ツ)_/¯.

Desde Views

Requiere los módulos ui_patterns_views y ui_patterns_views_style.

Desde la página de configuración de una vista, elegir Patrón como opción de Formato (normalmente el que se usa en este caso es el componente grid para crear la rejilla de elementos) y Patrón como opción de Mostrar. En ambos hay que elegir el componente a usar y sus configuraciones y mapeos de campos.

Nota: es necesario añadir los campos a mostrar en la vista y mapearlos en el componente en Configuración de Mostrar, si no se mapean no se mostrarán.

Desde gestionar presentación

Formateador de campo

Requiere el módulo ui_patterns_field_formatters.

Permite usar patrones directamente como formateadores de campo, pudiendo seleccionar variante y mapear campos desde el mismo formulario (por ejemplo para usar el componente rich_text).

Conjuntos de campos

Requiere el módulo field_group y ui_patterns_field_group. Permite crear grupos de campos directamente como patrones. Normalmente se usará esta modalidad para mapear a componentes, ya que muchos de ellos requieren varios campos (ej: card). Para usarlo, pulsar el botón "Add field group", seleccionar el componente, guardar, meter los campos que se quieran dentro del componente y entonces, pulsar en la configuración del grupo para hacer el mapeo (se supone que si no se hace en este orden peta, según el aviso del propio módulo). Puede usarse para sliders o tarjetas, por ejemplo.

Notas sobre Tailwindcss

Hay que recordar que, se purgan del css resultante todas las clases css que no estén en los componentes (plantillas twig o .yml) o en las propias plantillas de drupal, y no vale hacer concatenaciones en twig (ej: text-{{ color }}-500), ya que al no existir la clase css en sí dentro de la plantilla la purgará igualmente del css resultante.