OTTODesign System

Code

Async fragment (Not Ready For Use)

Storybook group: Not Ready For Use · Sidebar path: Not Ready For Use/Async fragment · Extracted 28.09.2026

Version Tag Status API
v1 <oc-async-fragment-v1> Not Ready For Use, NOT allowed for generation -

Not Ready For Use, NOT allowed for generation. Do not use this component when generating OTTO apps, pages or PDFs.

API from Storybook controls (AsyncFragmentV1.stories.ts)

No generated API page exists for this component; these are the documented controls (argTypes).

Name Category Type Default Description
default slots Arbitrary DOM Content Default content for the light dom of the component. Will be used as fallback content if no async fragment is provided or if the async fragment fails to load.
url attributes string undefined The URL from which the async fragment will be fetched. This must be a valid URL string. The url must be either an URL without the origin like /path/to/content.html or a full URL like https://<subdomain>.otto.com/path/to/content.html.

If an origin is provided, it must match the origin of the current page and must be a subdomain of otto.de otherwise the url will be considered invalid and an error will be thrown.
base64-url attributes string undefined This can be used to provide a base64 encoded url for masking pourposes. Same validation rules apply as for the url property.
inactive attributes boolean false This can be used to prevent automatic fetching of the async fragment on component initialization. This is useful if you want to control the loading of the async fragment programmatically.
allowed-status-codes attributes number[] [] This can be used to specify which HTTP status codes are allowed for the async fragment fetch. If the response status code is not in this list, the fetch will be considered as failed and an error event will be dispatched.

This is used to allow error responses to be rendered as async fragment, for example server may respond with an error code while providing a valid error markup as response content.
discard-on-inactive attributes boolean false If set to true, the async fragment will be discarded when the component becomes inactive. This is useful if you want to free up memory when the component is not in use.
replacement-target attributes "self" | "parent" | "children" children The target mode for the external content replacement. This can be used to specify how the external content should be applied to the component.

- "self" will replace the component itself with the external content - "parent" will replace the parent of the component with the external content - "children" will replace the children of the component with the external content

in case of "self" or "parent" the component will be disconnected from the DOM and replaced with the external content. The "self" mode is used to mimic the behavior of an "esi:include" tag, where the component is replaced with the external content.

Overview (v1)

Source: ./src/components/async-fragment/v1/Overview.mdx

Async fragment

The async fragment component can be used to fetch and display async fragment from a specified URL. It works same way like async fragment in the sheet component, but can be placed anywhere in the DOM and will fetch and render the content on demand.

Also the component will automatically invoke potentially existing scripts and stylesheets And it will also process options from async fragment if they are provided in the async fragment markup.

Default variation

Story Default Mode:

<oc-async-fragment-v1 url="https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html">
  <p>...loading</p>
</oc-async-fragment-v1>

Configuration

The async fragment component is available in the main styling variants .. This component is configurable, allowing you to tailor its features and appearance to your specific needs. To explore all the available options and adjust the component, use the component configurator and see the changes affect the component in real-time.

Usage guidelines

Before integrating the async fragment component into your project, make sure you have correctly installed the OTTO components package. Look through the variations page for examples of possible component variations. Here, you can discover both common and specific variations that address different use cases.

Accessibility

The async fragment component comes with a set of built-in accessibility features to ensure a seamless experience for all users.

Configuration (v1)

Source: ./src/components/async-fragment/v1/Configuration.mdx

Async fragment V1 configuration

Configure the async fragment component with the controls below and see the changes live in the preview canvas. Click the Show code button within the preview canvas to see the source code for the current component configuration.

Story Default Mode:

<oc-async-fragment-v1 url="https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html">
  <p>...loading</p>
</oc-async-fragment-v1>

Interactive configurator (Storybook controls); every option is listed in the API section of this file.

Variations (v1)

Source: ./src/components/async-fragment/v1/Variations.mdx

Variations

Listed below are the most common variations of the async fragment component as well as specific component variations for different use cases.

You can explore all available options using the component configurator, adjust the component to your needs, and see the changes live in a preview canvas.

Default Mode

Story: not-ready-for-use-async-fragment-variations--default · tags: components, async-fragment, 1, variations

Default Component

Args: url=https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html, defaultSlot=<p>...loading</p>

<oc-async-fragment-v1 url="https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html">
  <p>...loading</p>
</oc-async-fragment-v1>

Replacement Self Mode

Story: not-ready-for-use-async-fragment-variations--replacement-self · tags: components, async-fragment, 1, variations

Replacement Self Mode

Args: url=https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html, defaultSlot=<p>...loading</p>, replacement-target=self, inactive=true

<p>Below this line component will render async fragment from the given url.</p>
<p>
  since the replacement target is set to "self", the component will be replaced with the
  external content once it is loaded. and the component itself will be removed from the DOM
  and replaced with the external content.
</p>

<hr />
<oc-async-fragment-v1 url="https://www.otto.de/assets-storybook/assets/sheet-content.rP5OITvp.html" replacement-target="self" inactive><p>...loading</p></oc-async-fragment-v1>
<hr />

<p>You can toggle active property and control the loading timing programmatically.</p>
Story source (TypeScript, verbatim from Storybook)
{
  name: "Replacement Self Mode",
  args: {
    url: asyncfragmentUrlDefault,
    defaultSlot: `<p>...loading</p>`,
    "replacement-target": "self",
    inactive: true
  },
  render(args) {
    const {
      defaultSlot,
      ...props
    } = args;
    return html`
      <p>Below this line component will render async fragment from the given url.</p>
      <p>
        since the replacement target is set to "self", the component will be replaced with the
        external content once it is loaded. and the component itself will be removed from the DOM
        and replaced with the external content.
      </p>

      <hr />
      <oc-async-fragment-v1 ${spread(props)}>${unsafeHTML(defaultSlot)}</oc-async-fragment-v1>
      <hr />

      <p>You can toggle active property and control the loading timing programmatically.</p>
    `;
  }
}

Interaction tests (AsyncFragmentV1.interactions.stories.ts)

Interaction test stories (automated tests, not usage patterns).

Fetch And Apply Async Fragment

Story: not-ready-for-use-async-fragment-interaction-tests--fetch-and-apply-async-fragment · tags: components, async-fragment, 1, interactions, play-fn

Story source (TypeScript, verbatim from Storybook)
{
  args: {},
  play: async ({
    canvasElement
  }) => {
    const element = canvasElement.querySelector("oc-async-fragment-v1")!;
    await waitFor("Async Compoenent to be mounted", async () => {
      await expect(element.inactive).toBe(false);
    });
    element.url = sheetContentDefault;
    const fetchEvent = waitForEvent(element, "oc-async-fragment-fetch");
    const parseEvent = waitForEvent(element, "oc-async-fragment-parse");
    const applyEvent = waitForEvent(element, "oc-async-fragment-apply");
    await waitFor("Lifecycle Events to Complete", async () => {
      await fetchEvent;
      await parseEvent;
      await applyEvent;
    });
    await waitFor("Async Fragment to be applied", async () => {
      await expect(element.innerHTML).toContain("Close Sheet");
    });
  }
}

Discard Async Fragment On Deactivation

Story: not-ready-for-use-async-fragment-interaction-tests--discard-async-fragment-on-deactivation · tags: components, async-fragment, 1, interactions, play-fn

Story source (TypeScript, verbatim from Storybook)
{
  args: {},
  play: async ({
    canvasElement
  }) => {
    const element = canvasElement.querySelector("oc-async-fragment-v1")!;
    element.innerHTML = `<p>...loading</p>`;
    await waitFor("Async Compoenent to be mounted", async () => {
      await expect(element.inactive).toBe(false);
    });
    element.discardOnInactive = true;
    element.url = sheetContentDefault;
    const fetchEvent = waitForEvent(element, "oc-async-fragment-fetch");
    const parseEvent = waitForEvent(element, "oc-async-fragment-parse");
    const applyEvent = waitForEvent(element, "oc-async-fragment-apply");
    await waitFor("Lifecycle Events to Complete", async () => {
      await fetchEvent;
      await parseEvent;
      await applyEvent;
    });
    await waitFor("Async Fragment to be applied", async () => {
      await expect(element.innerHTML).toContain("Close Sheet");
    });
    const discardEvent = waitForEvent(element, "oc-async-fragment-discard");
    element.inactive = true;
    await waitFor("Async Fragment to be discarded", async () => {
      await discardEvent;
      await expect(element.innerHTML).toContain("...loading");
    });
  }
}