Allow using basic markup in Storybook controls

Created on 22 March 2024, 3 months ago
Updated 10 May 2024, about 2 months ago

Problem/Motivation

When setting arguments via controls, I'd like to be able to use basic HTML as values. Currently these values are fully escaped when rendered.

Steps to reproduce

Add the following story:

{% set image_content %}
  <img src="https://picsum.photos/100/100" alt="Placeholder Image">
{% endset %}

{% set body_content %}
  <p>Avoid Deadly Backfeed & Help Keep Lineworkers Safe. Using a backup generator during an extended outage or winter storm can give you peace of mind.</p>
{% endset %}

{% set script %}
  <script>alert('DANGER!!!')</script>
{% endset %}

{% set props = {
  title: 'Beware of <em>backfeed</em>',
  media: image_content,
  body: body_content,
  script,
} %}

{% stories markup_test with {
  title: 'Components/Markup'
} %}
  {% story default with {
    name: 'Default',
    args: props
  } %}
    <h2>
      {{ title }}
    </h2>
    <figure>
      {{ media }}
    </figure>
    <div>
      {{ body }}
    </div>
    {{ script }}
  {% endstory %}

  {% story render_array with {
    name: 'Render Array',
    args: props
  } %}
    <h2>
      {{ {'#markup': title } }}
    </h2>
    <figure>
      {{ {'#markup': media } }}
    </figure>
    <div>
      {{ {'#markup': body } }}
    </div>
    {{ {'#markup': script } }}
  {% endstory %}

  {% story raw_filter with {
    name: 'Raw Filter',
    args: props
  } %}
    <h2>
      {{ title|raw }}
    </h2>
    <figure>
      {{ media|raw }}
    </figure>
    <div>
      {{ body|raw }}
    </div>
    {{ script|raw }}
  {% endstory %}

{% endstories %}

Observed Result

  1. Default: em, p and img are escaped. The script is not escaped on the initial render of the default argument. Script tags set by the user via controls do get escaped.
  2. Render Array: script is escaped but em, p and img are not. This is the desired result
  3. Raw Filter: no tags are escaped. A user can pass a script in via controls which will be executed.

Proposed resolution

Possibly render all strings with FormatableMarkup before passing to Twig or providing some mechanism to set which strings should allow markup?

✨ Feature request
Status

Active

Version

1.0

Component

Storybook

Created by

πŸ‡ΊπŸ‡ΈUnited States pixelwhip

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @pixelwhip
  • πŸ‡ΊπŸ‡ΈUnited States pixelwhip
  • πŸ‡ΊπŸ‡ΈUnited States agentrickard Georgia (US)
  • πŸ‡ΊπŸ‡ΈUnited States agentrickard Georgia (US)

    I was just able to do this in a story file, which solves a similar issue where drupal render attributes are not present.

      first: {
        visible: false,
        attributes: create_attribute(),
      },
    

    I wonder if we can make a simple: create_markup() Twig extension and a create_render_array() for the complex case in ✨ Story representation of Drupal render arrays Active

  • πŸ‡ΊπŸ‡ΈUnited States themarkahrens

    We are running into a similar situation where our component takes in a Drupal media entity for an image, so in the story, we are trying to pass an img tag as the content for an argument. However, when the story is rendered, Storybook is showing the img tag text instead of rendering the image.

  • πŸ‡ΊπŸ‡ΈUnited States agentrickard Georgia (US)

    I think the temporary solution for that render problem may be to use Twig blocks and embed to pass changes from the story file, but I am not thrilled by that option.

    e.g -- twig render template (template.twig)

    <% block image %>
      {{ image }}
    <% endblock %>
    
    -- story implementation
    
    <code>
    {% story my_story with {
        name: 'My story,
        image: '<img src="this.png"/>`
      } %}
      {% embed template.twig %}
        {% block image %}
          {{ image|raw ||
        {% endblock %}
      {% endembed %}
    {% endstory %}
    
  • πŸ‡ΊπŸ‡ΈUnited States liberatr Portland, OR

    I currently need to wrap all of the content in a "normal" drupal twig file in a block, or storybook won't print it out.

    At least as far as I can tell.

    It's a little repetitive.

  • πŸ‡ΊπŸ‡ΈUnited States cosmicdreams Minneapolis/St. Paul

    I'm trying to follow along here because I was considering creating a new ticket but this one sounds a lot like my issue.

    I'm trying to create a story that works with Storybook's arguments / controls. I can get a simple argument to work, but I can't get an argument that works with a slot to work.

    I'm eager to see an example that demonstrates it's possible.

Production build 0.69.0 2024