Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using Storybook.js with Lit components is there a way to have the "Show Code" display the markup for the component with the properties?

I am using Storybook 7.0 and Lit 2.0. When I click "Show Code" in a story, it only displays the tag for the component and not any of the properties that were set. Is there a way to get the "Show Code" option to display the tags and all the properties that were set when using Lit?

import { html } from "lit";
import type { Meta, StoryObj } from "@storybook/web-components";
import { DateFormatterProps } from ".";
import ".";

const Template = (args: DateFormatterProps) => {
  return html`
    <date-formatter 
      .date=${args.date} 
      .showHoursAndMinutes=${args.showHoursAndMinutes}
      .showDateOnly=${args.showDateOnly}
      .digitOnlyFormat=${args.digitOnlyFormat}
      .showSeconds=${args.showSeconds}
      ></date-formatter>
  `;
}

const meta: Meta<DateFormatterProps> = {
  title: "Date Formatter",
  tags: ['autodocs'],
  render: Template,
  parameters: {
    docs: {
      description: {
        component: "",
      },
    },
  },
  argTypes: {
    date: { control: "date",  description: "Date to format, can be a date object or a string that is valid for the Date constructor" },
  }
};
export default meta;

type Story = StoryObj;
export const Default: Story = {
  args: {
    date: new Date(),
    showHoursAndMinutes: true,
    showDateOnly: false,
    digitOnlyFormat: false,
    showSeconds: false,
  }
};
like image 281
Tyler Avatar asked Sep 06 '25 08:09

Tyler


1 Answers

I am also looking for an answer. While I didn't find a perfect solution, this worked somewhat for my setup by setting preview.parameters.docs.source.transform in preview.js:

Update:

This is a more reliable solution that walks through the raw input line by line and assigns the correct args to the correct elements.

It needs to set up a regex to find the custom element tags (in this case I used /(?<=<eox-).*?((?=>| )|$)/gim).

transform: (code, storyContext) => {
  /**
   * Check which props belong to which tag
   * and create object
   */
  const undecorated = storyContext.undecoratedStoryFn(storyContext);
  let currentTag = undefined;
  const tags = {};
  undecorated.strings
    .map((string, index) => {
      const startOfTag = string.match(/(?<=<eox-).*?((?=>| )|$)/gim);
      if (startOfTag) {
        currentTag = `eox-${startOfTag}`;
      }
      const property = string
        .match(/(?<=\.).*?(?==)/gim)?.[0]
        ?.replaceAll(" ", "");
      const value = undecorated.values[index];
      if (property && value) {
        if (!tags[currentTag]) {
          tags[currentTag] = {};
        }
        tags[currentTag][property] = value;
      }
    })
    .filter((l) => l);

  /**
   * Inject prop for each tag in the rendered code
   */
  Object.keys(tags).forEach((tag) => {
    code = code.replace(
      `<${tag}`,
      `<${tag}\n  ${Object.keys(tags[tag])
        .map(
          (key, index) =>
            `.${key}='\$\{${
              typeof tags[tag][key] === "string"
                ? tags[tag][key]
                : JSON.stringify(tags[tag][key])
            }\}'`
        )
        .join("\n  ")}\n  `
    );
  });
  return code;
},

Previous solution:

transform: (code, storyContext) => {
  return code.replace(
    `<${storyContext.component}`,
    `<${storyContext.component} ${Object.entries(storyContext.args)
      .filter(([key]) => key !== "onLoadend")
      .map(
        ([key, value], index, row) =>
          `\n .${key}='\${${JSON.stringify(value)}}'${
            index + 1 === row.length ? "\n" : ""
          }`
      )
      .join("")}`
  );
},

This gets the rendered code and injects a stringified version of all the args after the opening tag, using the formatting .prop='${value}'. I tried omitting the quotes (like .prop=${value}), but that seems to mess up the syntax highlighting.

like image 93
Silvester Pari Avatar answered Sep 08 '25 23:09

Silvester Pari