Menu


Search field


A text field for filtering or searching, with a magnifier before the text, a clear control after it and an optional key hint at the end.

Customize the preview


Choices
Show
Flags
View

Options


Search field options
ChoiceValuesDefaultWhat it does
sizesmbk-search--size-<value>lgmdsmmd
lg is 48 tall with larger text, for a search that leads a page; md and sm are the input’s two heights, with their padding, icons and text. Small text never goes under 16 px on a phone.
errorsmbk-search--errorOn or offOff
The query is invalid. Draws the danger border, kept while focused, and the error icon.

Partssmbk-search__controlsmbk-search__clearsmbk-search__kbd

Examples


Usage

The input well with a magnifier; the clear control appears once there is text.

With a query

The clear control empties the field and puts focus back in it.

With a key hint

A Kbd at the end shows the shortcut that jumps to the field, a space between its keys. It gives way to the clear control once there is text.

Error

The danger border and the warning icon say the query cannot be searched.

Read only

Flat on the page, with no clear control and no key hint.

Disabled

Dimmed and out of reach; the key hint fades too.

Guidelines


Purpose

A text field whose value filters or searches something. It looks like the input and adds the two things a search needs: a magnifier that says what the field is for, and a clear control that empties it in one press. It can also show the key that jumps to it.

When to use

  • Filtering a list, a table or a sidebar on the page.
  • A site search box.

When not to use

  • For any value that is not a query. Use the input.
  • To pick a value from a list by typing part of it. Use a combobox, which suggests matches as the reader types.

Usage rules

Do

  • Show results or filter as the person types when the set is small; wait for Enter when a search is expensive.
  • Show the key hint only on the one search field the shortcut reaches.

Don't

  • Put a search field inside a form that submits on Enter unless that is what searching does.
Do

Show the key hint on the one search field the shortcut reaches, so the hint is true.

Don't

The same hint on two fields promises a shortcut that can only reach one of them.

Anatomy

  • The block, always on the input's well: its markup carries the input's classes as well as its own.
  • The magnifier, the input's icon part, always present.
  • The control part, a native search control, which is also the input's control part.
  • In error, the input's error icon, a warning sign after the query.
  • The clear part, a cross button at the field's icon size inside a box the size of the least target a press needs, shown when there is something to clear.
  • The kbd part, an optional small Kbd at the far end naming the key that jumps to the field, shown while the field is empty.

Behavior

Typing filters or searches, as the page decides. The clear control shows only while the field holds text, and the key hint only while it is empty, so the end of the field holds one of them at a time; pressing the clear control empties the field, calls back, and puts focus back in the field. Escape empties a field holding text in every browser, Safari too, and the page hears it as a change; in an empty field Escape is left to the page. The padding, the icon sizes, hover, focus, error, read-only, disabled and the md and sm sizes are the input's own, because the field is built on the input; a change to the input changes the search field too. The large size is the search field's own: 48 tall, with larger text and wider side padding, for a search that leads a page; its icons, clear control and key hint stay the medium field's. A read-only field shows neither the clear control nor the key hint, and Escape leaves it as it is. A disabled field fades its key hint with the media disabled opacity.

The key hint shows whatever the shortcut is, with a space between keys, e.g. "⌘ K". It is only a picture of the keys: the page that shows it must also wire the shortcut, or the hint is a promise the field does not keep.

The clear control is offered only when the field is given onClear. A field whose value the page does not control is emptied by the component when cleared; a field whose value the page controls must be emptied by the page in onClear. onChange passes the browser's own event, as the native field does.

Accessibility


What it does for you

  • In development, a search field with no name logs a warning in the console.
  • The clear control is a real button with an accessible name, "Clear search", and a box of 24 by 24 px, the least a press needs. Pressing it empties the field and puts focus back in the field.
  • The browser's own clear control is hidden so there is one, styled, in the same place in every browser.
  • The key hint is hidden from assistive technology.
  • Escape empties a field holding text in every browser, Safari too, and the page hears it as a change.

What you must do

  • Give it a label like any input; a search landmark around it helps when it is the page's search.
  • Change the clear control's name with clearLabel for a page in another language.
  • When the page wires the shortcut, name it on the control with aria-keyshortcuts, which is where a screen reader looks for it. The hint alone is only a picture of the keys.

How to test

  • Type in the field: the clear control appears at its end. Tab to it and press Enter or Space: the field empties and focus is back in it.
  • Press Escape in a field holding text: it empties. In an empty field, Escape is left to the page.
  • With a screen reader, the field is read with its label as a search field, and the clear control as the button "Clear search". The key hint is not read.
  • With text at 200% and the page 320 pixels wide, the text and the clear control stay inside the field.
  • In a forced-color mode, the focus border and the text stay visible.

Keyboard

Search field keys
KeyWhat it does
Tab
Moves focus to the field, then to the clear control when it shows.
Escape
Empties a field holding text. In an empty or read-only field, it is left to the page.
EnterorSpace
On the clear control, empties the field and puts focus back in it.

Source


The files the search field is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
search-field.css
/* smbk-search — Search field. Figma "Search Field" 4212:26902.
 * Built on the input: the block always sits on an smbk-input well, and the
 * magnifier is the input's icon part. This stylesheet adds only what a search
 * needs: a clear control, an optional key hint and the large size. The
 * padding, the icon sizes, hover, focus, error, read-only, disabled and the
 * small size are the input's own, so a change to the input reaches the
 * search field. */

.smbk-search__control {
  appearance: none;
}

.smbk-search__control::-webkit-search-cancel-button,
.smbk-search__control::-webkit-search-decoration {
  appearance: none;
}

/* The cross is the field's icon size, inside a 24 px box, the least a press needs; the box reaches past
   the cross into the gap and the padding, so the cross sits where Figma draws it. */
.smbk-search__clear {
  box-sizing: border-box;
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: var(--smbk-size-target-min);
  height: var(--smbk-size-target-min);
  margin: calc((var(--smbk-size-icon-md) - var(--smbk-size-target-min)) / 2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--smbk-color-text-subtlest);
  cursor: pointer;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
  touch-action: manipulation;
}

.smbk-search__clear > .smbk-icon {
  font-size: var(--smbk-size-icon-md);
}

.smbk-input--size-sm .smbk-search__clear {
  margin: calc((var(--smbk-size-icon-sm) - var(--smbk-size-target-min)) / 2);
}

.smbk-input--size-sm .smbk-search__clear > .smbk-icon {
  font-size: var(--smbk-size-icon-sm);
}

.smbk-search__clear:focus-visible {
  outline: var(--smbk-focus-ring-width) solid var(--smbk-color-border-focus);
  outline-offset: 0;
  border-radius: var(--smbk-radius-full);
}

.smbk-search:has(.smbk-input__control:disabled) .smbk-search__clear {
  color: var(--smbk-color-text-disabled);
  pointer-events: none;
}

/* ---- large (lg): 48 tall, Body LG, a wider side padding; the icons, the gap, the corner, the clear
   box and the key hint stay the md field's. Two classes, so it wins over the input's md rules
   whichever stylesheet loads first. ---- */

.smbk-input.smbk-search--size-lg {
  height: var(--smbk-size-control-lg);
  padding: 0 var(--smbk-space-inset-xl);
  font-family: var(--smbk-typography-body-lg-font-family);
  font-size: var(--smbk-typography-body-lg-font-size);
  font-weight: var(--smbk-typography-body-lg-font-weight);
  line-height: var(--smbk-typography-body-lg-line-height);
  letter-spacing: var(--smbk-typography-body-lg-letter-spacing);
}

/* The key hint is a small Kbd at the far end. */
.smbk-search__kbd {
  flex-shrink: 0;
}

.smbk-search:has(.smbk-input__control:disabled) .smbk-search__kbd {
  opacity: var(--smbk-opacity-disabled);
}

/* ---- touch: the clear button takes an invisible press area ----
   On a touch screen an invisible area, centred on it, takes the press out to the comfortable target in each direction
   it falls short of it; its look, its focus ring and its place stay as drawn. */

@media (pointer: coarse) {
  .smbk-search__clear {
    position: relative;
  }

  .smbk-search__clear::after {
    content: '';
    position: absolute;
    inset: min(0%, (100% - var(--smbk-size-target-comfortable)) / 2);
  }

  /* Right after the value, halfway into the gap: the well's gap less the margin the cross gives back round its icon. */
  .smbk-input > :is(.smbk-input__control, .smbk-combobox__values) + .smbk-search__clear::after {
    inset-inline-start: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), (var(--smbk-space-inline-md) + (var(--smbk-size-icon-md) - var(--smbk-size-target-min)) / 2) / -2);
  }

  .smbk-input--size-sm > :is(.smbk-input__control, .smbk-combobox__values) + .smbk-search__clear::after {
    inset-inline-start: max(min(0%, (100% - var(--smbk-size-target-comfortable)) / 2), (var(--smbk-space-inline-sm) + (var(--smbk-size-icon-sm) - var(--smbk-size-target-min)) / 2) / -2);
  }
}
Tokens it reads
Search field tokens
Token and CSSValuePreviewFoundation
size.target.min--smbk-size-target-min24pxSize
size.icon.md--smbk-size-icon-md20pxSize
color.text.subtlest--smbk-color-text-subtlestlight: #606a75dark: #7c8692changes with themeColor
size.icon.sm--smbk-size-icon-sm16pxSize
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
radius.full--smbk-radius-full9999pxRadius
color.text.disabled--smbk-color-text-disabledlight: #7c8692dark: #606a75changes with themeColor
size.control.lg--smbk-size-control-lgcomfortable: 48pxcompact: 40pxchanges with densitySize
space.inset.xl--smbk-space-inset-xlcomfortable: 16pxcompact: 12pxchanges with densitySpacing
typography.body-lg--smbk-typography-body-lg-font-family--smbk-typography-body-lg-font-size--smbk-typography-body-lg-font-weight--smbk-typography-body-lg-line-height--smbk-typography-body-lg-letter-spacing--smbk-typography-body-lg-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 20pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
opacity.disabled--smbk-opacity-disabled0.5Opacity
size.target.comfortable--smbk-size-target-comfortable44pxSize
space.inline.md--smbk-space-inline-mdcomfortable: 8pxcompact: 6pxchanges with densitySpacing
space.inline.sm--smbk-space-inline-smcomfortable: 6pxcompact: 4pxchanges with densitySpacing
Manifest
search-field.manifest.json
{
  "name": "search-field",
  "block": "smbk-search",
  "summary": "A text field for filtering or searching, with a magnifier before the text, a clear control after it and an optional key hint at the end.",
  "adapt": "css",
  "axes": {
    "size": {
      "values": [
        "lg",
        "md",
        "sm"
      ],
      "default": "md",
      "description": "lg is 48 tall with larger text, for a search that leads a page; md and sm are the input’s two heights, with their padding, icons and text. Small text never goes under 16 px on a phone."
    }
  },
  "flags": {
    "error": {
      "description": "The query is invalid. Draws the danger border, kept while focused, and the error icon."
    }
  },
  "parts": [
    "control",
    "clear",
    "kbd"
  ],
  "figmaNodeId": "4212:26902"
}