npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ilo-org/maestro

v1.0.1

Published

Maestro is a library for building front-end component libraries for [Drupal](https://www.drupal.org/) using [Storybook](https://storybook.js.org/).

Downloads

71

Readme

Maestro

Maestro is a library for building front-end component libraries for Drupal using Storybook.

It includes a collection of utilities for bundling Twig templates and JavaScript files so that you can develop components in isolation using the same syntax and conventions you'd use in a Drupal theme.

Inspiration and alternatives

Pre-requisites

Before using Maestro, you should have basic knowledge of the following:

Installation

npm i @ilo-org/maestro

Setup

The Maestro package has three major exports.

  • @ilo-org/maestro - The main export that introduces a Maestro object
  • @ilo-org/maestro/storybook - The storybook decorators/helpers
  • @ilo-org/maestro/plugin - A vite plugin that helps to compile the twig components

To start with Maestro, you need a html storybook template using Vite as a builder tool

npx storybook@latest init --type="html"

After your Storybook project is scaffolded, you can start adding Maestro.

Vite plugin

First, we need to add the vite plugin from Maestro to Storybook's vite.config.js

// vite.config.js

import { defineConfig } from "vite";
import { join } from "node:path";

import { UIPatterns } from "@ilo-org/maestro/plugin";

export default defineConfig({
  plugins: UIPatterns({
    namespaces: {
      components: join(__dirname, "..", "src/components"),
    },
  }),
});

The Vite plugin takes the following properties.

| property | description | required | | ------------ | ----------------------------------------------------------------------------------------------------- | -------- | | namespaces | A key-value pair of the namespace for your components and the directory it should point to | Yes | | globals | A key-value pair of global variables that should be available to the Twig templates | No | | dynamics | An array of Twig templates names that use dynamic includes. See more info below. | No |

Storybook decorators

To enable Drupal's JS API in the storybook, you need first to add Behavior Decorator to the storybook's preview file

// .storybook/preview.js

import { BehaviorDecorator } from "@ilo-org/maestro/storybook";

/** @type { import('@storybook/html').Preview } */
const preview = {
  decorators: [BehaviorDecorator],
};

export default preview;

and then you need to inject the head property to the storybook config and merge the vite config with the plugin mentioned above

// .storybook/vite.config.js

import { mergeConfig } from "vite";
import alternate from "./vite.config.js";

import { head } from "@ilo-org/maestro/storybook";


/** @type { import('@storybook/html-vite').StorybookConfig } */
const config = {
  stories: [
    "../stories/**/*.mdx",
    "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)",
  ],
  staticDirs: ["../public"],
  core: {
    builder: "@storybook/builder-vite",
  },
  addons: [...],
  framework: {
    name: getAbsolutePath("@storybook/html-vite"),
    options: {},
  },
  viteFinal: (config) => {
    return mergeConfig(alternate, config);
  },
  previewHead: head,
};
export default config;

Creating a story

Component structure

Let's assume that your components are structured something like this:

📦accordion
┣ 📜accordion.behavior.js
┣ 📜accordion.component.yml
┣ 📜accordion.js
┣ 📜accordion-item.twig
┗ 📜accordion.twig

Here we have a Twig template, a JS file for interactivity, a behaviors file for attaching the JavaScript to the component instance and a pattern definitions file accordion.component.yml that determines the fields and settings that can be passed from Drupal to the component.

Story structure

To create a story you need to use the main Maestro object. Maestro has a create method that accepts the following:

  • component (actual twig component)
  • pattern definition (ui pattern definition in yaml)

And in return, you get the object.

{
  meta: {...}
  stories: [...],
}

The stories key will always have 1 element, which is the Default story, and if the pattern definition has any variants, you will get all other stories in an array

Here's an example of how to create a story

import Accordion from "../components/accordion/accordion.twig";
import AccordionPatterns from "../components/accordion/accordion.pattern.yml";
import { Maestro } from "@ilo-org/maestro";

const story = Maestro.create(Accordion, AccordionPatterns);

const Meta = {
  title: "Components/Content/Accordion",
  tags: ["autodocs"],
  ...story.meta,
};

const [Default, Scrollable, Focus] = story.stories;

export default Meta;

export { Default, Scrollable, Focus };

In this example, Maestro builds a component using the Twig template and then derives stories to create based on the pattern definitions file.

Any JavaScript is loaded and attached to the component automatically.

Including sub-components

Twig includes work automatically. For example, assuming our accordion.twig component uses an accordion-item.twig component, then it would look like this:

<ul>
  {% for item in items %} {% include "@components/accordion/accordion-item.twig"
  with { label: item.label ... } %} {% endfor %}
</ul>

In this example, Maestro will import the accordion-item.twig template into the accordion.twig template so that it can be rendered correctly.

Dynamic includes

Dynamic includes are small caveat to this rule and require some additional setup. Consider the following example.

{# my-dynamic-component.twig #}
<div>
  {% for item in items %}
    {% include '@components/' ~ item.component ~ '/' ~ item.component ~ '.twig' with item.componentdata %}
  {% endfor %}
</div>

Here, the component is importing sub-component dynamically based on the arguments passed to it. Maestro can handle this situation as well with some additional configuration to its Vite plugin.

// vite.config.js

export default defineConfig({
  plugins: UIPatterns({
    ...
    dynamics: ["my-dynamic-component"]
  }),
});

Simply pass an array of components that use dynamic imports to the dynamics property of the Vite plugin and you're off to the races.

Variants

There are a few rules for variants:

  • Variants will inherit any setting from the default definition
  • Variants named default will be ignored because Default is generated by the pattern definition itself

Contributing

Maestro is a package of the ILO Design System, which is an open-source project. We welcome your contributions! Before submitting a pull request, please take a moment to review our Contribution Guidelines.

License

Maestro is licensed under the Apache 2.0 License.