OTTODesign System

Components

Search field

The search field component is a special component to provide search functionality to a feature.

Configurator

LiveSearch field: search button, background, placeholder, search term and screen reader labels
HTML
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

Usage

Anatomy

1 2 3
4 5 6
  1. Container
  2. Placeholder
  3. Search icon (empty field)
  4. Input
  5. Clear button
  6. Search button
LiveAnatomy
HTML
<div class="anatomy" style="display:block">
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<span class="anatomy-pin" style="left:0;top:50%">1</span>
<span class="anatomy-pin" style="left:30%;top:-14px">2</span>
<span class="anatomy-pin" style="left:calc(100% - 26px);top:-14px">3</span>
<div class="anatomy" style="display:block">
<oc-search-field-v1><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<span class="anatomy-pin" style="left:18%;top:-14px">4</span>
<span class="anatomy-pin" style="left:calc(100% - 76px);top:-14px">5</span>
<span class="anatomy-pin" style="left:calc(100% - 26px);top:-14px">6</span>
<ol class="anatomy-key"><li data-n="1">Container</li><li data-n="2">Placeholder</li><li data-n="3">Search icon (empty field)</li><li data-n="4">Input</li><li data-n="5">Clear button</li><li data-n="6">Search button</li></ol>

Variants

By default, the search field comes with stacked-background, but it is also available as over-color variant with canvas-background. The over-color variant can be used on frame or on colored blocks.

Default, on canvas

over-color, on frame

Livedefault and over-color variant
HTML
<p class="demo-label">Default, on canvas</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">over-color, on frame</p>
<oc-search-field-v1 over-color><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

The search button is optional and can be hidden. If you want to show the search button you can choose between secondary or primary.

search-button-type secondary

search-button-type primary

search-button-type none

Livesearch button variants
HTML
<p class="demo-label">search-button-type secondary</p>
<oc-search-field-v1 search-button-type="secondary"><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">search-button-type primary</p>
<oc-search-field-v1 search-button-type="primary"><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">search-button-type none</p>
<oc-search-field-v1 search-button-type="none"><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

The placeholder of the search is "Wonach suchst du?" per default, but can be edited. It is hidden as soon as input is provided.

Default placeholder

Custom placeholder

Liveplaceholder variants
HTML
<p class="demo-label">Default placeholder</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">Custom placeholder</p>
<oc-search-field-v1><input type="search" placeholder="Nach Marken suchen" spellcheck="false"></oc-search-field-v1>

Behavior

States

Empty (hover and focus it)

Filled

over-color, empty

over-color, filled

LiveStates
HTML
<p class="demo-label">Empty (hover and focus it)</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">Filled</p>
<oc-search-field-v1><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">over-color, empty</p>
<oc-search-field-v1 over-color><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">over-color, filled</p>
<oc-search-field-v1 over-color><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

Interaction

Clicking or tapping on the search field focuses the search field. While typing, the clear and search buttons are shown. The clear button deletes the input, but this can also be done using the ESC key. The search button submits the input, but this can also be done by pressing the ENTER key. If the text exceeds the size of the input field, it slides out to the left to prevent it from being abbreviated. The input is not checked by a spellchecker.

1 · click/tap to focus

2 · type

3 · click/tap ⓧ to delete, 🔍 to send

Liveinteraction desktop or mobile
HTML
<p class="demo-label">1 · click/tap to focus</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">2 · type</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">3 · click/tap ⓧ to delete, 🔍 to send</p>
<oc-search-field-v1><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

1 · TAB to focus

2 · type

3 · ESC to delete, SPACE or ENTER to send

Liveinteraction with keyboard
HTML
<p class="demo-label">1 · TAB to focus</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">2 · type</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<p class="demo-label">3 · ESC to delete, SPACE or ENTER to send</p>
<oc-search-field-v1><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

Long input scrolls inside the field

Livetyping text behavior
HTML
<p class="demo-label">Long input scrolls inside the field</p>
<oc-search-field-v1><input type="search" value="Das hier ist ein sehr, sehr, sehr langer Input." placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

Fitting

The search field width uses fill-parent. The height is fixed.

Width: fill-parent · height: 1.5rem + 2 × 12px

Livefitting
HTML
<p class="demo-label">Width: fill-parent · height: 1.5rem + 2 × 12px</p>
<oc-search-field-v1><input type="search" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>

Placement

By default, place the search field on canvas. To place it on frame or colored blocks use the over-color variant.

Best Practices

DoUse the search field only for searches. Use a text field for other types of input.
Wonach suchst du?
Don'tUse a text field for searches.

Accessibility

By default, the search button has the aria-label "Suche abschicken," and the clear button has the aria-label "Suchbegriff löschen." These labels can be edited.

1 2
  1. aria-label: Suchbegriff löschen
  2. aria-label: Suche abschicken
Livedefault aria-labels
HTML
<div class="anatomy" style="display:block;max-width:360px;margin:28px auto">
<oc-search-field-v1 clear-button-aria-label="Suchbegriff löschen" search-button-aria-label="Suche abschicken"><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<span class="anatomy-pin" style="left:calc(100% - 76px);top:-14px">1</span>
<span class="anatomy-pin" style="left:calc(100% - 26px);top:calc(100% + 14px)">2</span>
<ol class="anatomy-key"><li data-n="1">aria-label: Suchbegriff löschen</li><li data-n="2">aria-label: Suche abschicken</li></ol>

The focus order of the search field is as follows:

1 2 3
  1. Input field
  2. Clear button
  3. Search button (tab through it)
LiveFocus order
HTML
<div class="anatomy" style="display:block;max-width:360px;margin:28px auto">
<oc-search-field-v1><input type="search" value="Sneaker" placeholder="Wonach suchst du?" spellcheck="false"></oc-search-field-v1>
<span class="anatomy-pin" style="left:0;top:50%">1</span>
<span class="anatomy-pin" style="left:calc(100% - 76px);top:-14px">2</span>
<span class="anatomy-pin" style="left:calc(100% - 26px);top:-14px">3</span>
<ol class="anatomy-key"><li data-n="1">Input field</li><li data-n="2">Clear button</li><li data-n="3">Search button (tab through it)</li></ol>

For more information on accessibility, refer to the technical documentation.

Status

Implementation

Note: For full technical documentation of this component, visit Storybook/Search field.

Live demo

Vorschläge

Sneaker Damen Sneaker Herren Sneaker weiß

Beliebt bei OTTO

LiveReal OTTO components, rendered by the OTTO component runtime
HTML
<div style="max-width:560px;margin:0 auto;display:grid;gap:24px">
<div class="on-frame" style="margin:0;padding:16px;border-radius:12px;display:grid;gap:16px">
  <oc-search-field-v1 over-color><input type="search" value="Sneak" placeholder="Wonach suchst du?" spellcheck="false" aria-label="Suche"></oc-search-field-v1>
<div style="display:grid;gap:8px">
  <p class="oc-copy-75 oc-text-color-secondary" style="font-weight:700">Vorschläge</p>
  <div>
    <oc-row-v2 as-button hide-divider icon-left="search" icon-right="arrow-right">Sneaker Damen</oc-row-v2>
    <oc-row-v2 as-button icon-left="search" icon-right="arrow-right">Sneaker Herren</oc-row-v2>
    <oc-row-v2 as-button icon-left="search" icon-right="arrow-right">Sneaker weiß</oc-row-v2>
<div style="display:grid;gap:12px">
  <p class="oc-copy-75 oc-text-color-secondary" style="font-weight:700">Beliebt bei OTTO</p>
    <oc-chip-v3><button>Sofa</button></oc-chip-v3>
    <oc-chip-v3><button>Kopfhörer</button></oc-chip-v3>
    <oc-chip-v3><button>Sessel</button></oc-chip-v3>
    <oc-chip-v3><button>Waschmaschine</button></oc-chip-v3>

Code

Version Tag Status API
v1 <oc-search-field-v1> Stable, allowed for generation SearchFieldV1

Overview (v1)

Search field

The search field component is a special component to provide search functionality to a feature. Please note that this component acts as a style-only-component and is only providing necessary styling and events. You need to implement the actual search functionality yourself.

Default variation
HTML
<oc-search-field-v1>
<input
    type="search"
    placeholder="Wonach suchst du?"
    spellcheck="false"
  />
</oc-search-field-v1>
Configuration

The search field component is available in just one variant but can have 3 types of search-button styles without, primary and secondary. It also provides over-color which is intended to use, whenever the component is used on colored surfaces. 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 search field 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.

Info

See the Search field UX documentation for detailed user experience guidelines.

Layout considerations

This component has visual overflow. It extends beyond its bounding box and is clipped by parent containers with overflow: hidden. Ensure the parent container has sufficient padding to accommodate the component's full visual area.

Accessibility

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

Events

The component comes with a set of events that can be used for your search functionality.

Name Purpose Returns
oc-search-field-input Whenever the search field component receives input or the input changes, this event fires. { searchTerm: string | undefined }
oc-search-field-clear Whenever the search field's input has been cleared manually via the clear-button, or ESC this event fires void
oc-search-field-search Whenever the search field component's search-button has been clicked or the Enter-Button has been pressed, while the search field is not empty, this event fires. { searchTerm: string | undefined }

Configuration (v1)

Search field configuration

Configure the search field 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.

HTML
<oc-search-field-v1>
<input
    type="search"
    placeholder="Wonach suchst du?"
    spellcheck="false"
  />
</oc-search-field-v1>

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

API v1

Search Field v1 API

API: <oc-search-field-v1> (SearchFieldV1)

The search field component is a special component to provide search functionality to a feature. Take note that this component acts as a style-only-component and only provides necessary styling and events. You need to implement the actual search functionality yourself.

Attributes / properties
Attribute Type Default Required Description
search-button-type "primary" | "secondary" | "none" "secondary" no Selects the style of the search button to be used.
over-color boolean false no Indicates whether the search field is displayed with an over-color style.

This style is intended to be used on colored backgrounds.
clear-button-aria-label string "Suchbegriff löschen" no Sets the aria-label for the clear button.
search-button-aria-label string "Suche abschicken" no Sets the aria-label for the search button.
Slots
Slot Required Description
default yes The input element for the search field.

Note: The only supported input type is search.
Events
Event Detail type Description
oc-search-field-input CustomEvent<{ searchTerm: string | undefined; }> Triggered when there is input in the search field.
oc-search-field-clear CustomEvent<void> Triggered when the clear button is pressed.
oc-search-field-search CustomEvent<{ searchTerm: string | undefined; }> Triggered when the search button is pressed.
oc-property-change OcSearchFieldV1Events["oc-property-change"] Whenever a property value changes, this event triggers. Use this event to track all property changes within the component.

Refer to the Events documentation for more information.
oc-mount { component: string; } Fired when the component is mounted to the DOM. The event is fired when the onMount hook of the component is called by the runtime.
oc-unmount { component: string; } Fired when the component is unmounted from the DOM. The event is fired when the function returned by the onMount hook of the component is called by the runtime.

Variations (v1)

Variations

Listed below are the most common variations of the search field 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

Story: components-search-field-variations--default · tags: components, search-field, 1, variations

Default Component

HTML
<oc-search-field-v1>
<input
    type="search"
    placeholder="Wonach suchst du?"
    spellcheck="false"
  />
</oc-search-field-v1>
Over-Color

Story: components-search-field-variations--over-color · tags: components, search-field, 1, variations

Over-Color Variation

Args: over-color=true, search-button-type=primary

HTML
<oc-search-field-v1 over-color search-button-type="primary">
<input
    type="search"
    placeholder="Wonach suchst du?"
    spellcheck="false"
  />
</oc-search-field-v1>
Custom Aria Labels

Story: components-search-field-variations--custom-aria-label · tags: components, search-field, 1, variations

Custom Aria-Labels

Args: over-color=true, search-button-type=primary, clear-button-aria-label=Suchbegriff ins Nirvana schicken, search-button-aria-label=Suchbegriff übersenden

HTML
<oc-search-field-v1 over-color search-button-type="primary" clear-button-aria-label="Suchbegriff ins Nirvana schicken" search-button-aria-label="Suchbegriff übersenden">
<input
    type="search"
    placeholder="Wonach suchst du?"
    spellcheck="false"
  />
</oc-search-field-v1>
Demo: Search Buttons

Story: components-search-field-variations--demo-search-buttons · tags: components, search-field, 1, variations

Multiple Search-Fields showcasing the Search Button Variation

Over-Color Variation

Primary search button

Secondary search button

Without search button

Default Variation

Primary search button

Secondary search button

Without search button

HTML
<div style="display: flex; flex-direction: column; gap: 16px;">
<div
  style="display: flex; flex-direction: column; gap: 8px; outline: 1px dashed gray; padding: 16px;"
>
  <h3>Over-Color Variation</h3>
  <p>Primary search button</p>
  <oc-search-field-v1 search-button-type="primary" over-color
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
  <p>Secondary search button</p>
  <oc-search-field-v1 search-button-type="secondary" over-color
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
  <p>Without search button</p>
  <oc-search-field-v1 search-button-type="none" over-color
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
<div
  style="display: flex; flex-direction: column; gap: 8px; outline: 1px dashed gray; padding: 16px; background-color: var(--oc-semantic-color-canvas-background);"
>
  <h3>Default Variation</h3>
  <p>Primary search button</p>
  <oc-search-field-v1 search-button-type="primary"
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
  <p>Secondary search button</p>
  <oc-search-field-v1 search-button-type="secondary"
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
  <p>Without search button</p>
  <oc-search-field-v1 search-button-type="none"
    ><input
  type="search"
  placeholder="Wonach suchst du?"
  spellcheck="false"
/>
</oc-search-field-v1
  >
Story source (TypeScript, verbatim from Storybook)
{
  name: "Demo: Search Buttons",
  argTypes: hideControlsBadge(Metadata),
  parameters: {
    controls: {
      disabled: true
    }
  },
  render(args) {
    const {
      defaultSlot
    } = args;
    return html` <div style="display: flex; flex-direction: column; gap: 16px;">
      <div
        style="display: flex; flex-direction: column; gap: 8px; outline: 1px dashed gray; padding: 16px;"
      >
        <h3>Over-Color Variation</h3>
        <p>Primary search button</p>
        <oc-search-field-v1 search-button-type="primary" over-color
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >

        <p>Secondary search button</p>
        <oc-search-field-v1 search-button-type="secondary" over-color
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >

        <p>Without search button</p>
        <oc-search-field-v1 search-button-type="none" over-color
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >
      </div>

      <div
        style="display: flex; flex-direction: column; gap: 8px; outline: 1px dashed gray; padding: 16px; background-color: var(--oc-semantic-color-canvas-background);"
      >
        <h3>Default Variation</h3>
        <p>Primary search button</p>
        <oc-search-field-v1 search-button-type="primary"
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >

        <p>Secondary search button</p>
        <oc-search-field-v1 search-button-type="secondary"
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >

        <p>Without search button</p>
        <oc-search-field-v1 search-button-type="none"
          >${unsafeHTML(defaultSlot)}</oc-search-field-v1
        >
      </div>
    </div>`;
  }
}

Interaction tests (SearchFieldV1.interactions.stories.ts)

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

Should Have Focus

Story: components-search-field-interaction-tests--should-have-focus · tags: components, search-field, 1, interactions, play-fn

Story source (TypeScript, verbatim from Storybook)
{
  args: {},
  play: async ({
    canvasElement
  }) => {
    const input: HTMLInputElement = canvasElement.querySelector("input[type='search']")!;
    await userEvent.tab();
    await expect(document.activeElement, "Active focused element").toBe(input);
  }
}

Should Have Value On Input

Story: components-search-field-interaction-tests--should-have-value-on-input · tags: components, search-field, 1, interactions, play-fn

Story source (TypeScript, verbatim from Storybook)
{
  args: {},
  play: async ({
    canvasElement
  }) => {
    const input: HTMLInputElement = canvasElement.querySelector("input[type='search']")!;
    await userEvent.type(input, "Hello World");
    await expect(input.value, "Current input value").toBe("Hello World");
  }
}

Should Clear Value On Clear Button Click And Focus

Story: components-search-field-interaction-tests--should-clear-value-on-clear-button-click-and-focus · tags: components, search-field, 1, interactions, play-fn

Story source (TypeScript, verbatim from Storybook)
{
  args: {},
  play: async ({
    canvasElement
  }) => {
    const [searchFieldElement] = Array.from(canvasElement.getElementsByTagName("oc-search-field-v1"));
    const input: HTMLInputElement = canvasElement.querySelector("input[type='search']")!;
    await userEvent.type(input, "Hello World");
    await expect(input.value, "Current input value").toBe("Hello World");
    const clearButton: HTMLOcIconButtonV3Element = searchFieldElement.shadowRoot!.querySelector(".search-field__icon-button-controls__clear")!;
    await userEvent.click(clearButton);
    await expect(input.value, "Current input value").toBe("");
    await expect(document.activeElement, "Active focused element").toBe(input);
    await expect(input.selectionStart).toBe(0);
  }
}