Skip to content
ShineUI
Install

IconField

Search boxes and filter fields.

<sui-icon-field>Text inputsStable

About

Input with a Font Awesome icon before the text, after it or both: the toolbar search and filter pattern. Bare by default, so set aria-label and no label; add label, help or error when it sits in a form instead. clearable adds an X that empties the field. Form-associated: it posts name=value.

Usage

<sui-icon-field icon="fa-solid fa-magnifying-glass" name="q" placeholder="Search invoices" aria-label="Search invoices"></sui-icon-field> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); const el = document.querySelector("sui-icon-field"); el.addEventListener("suiChange", (e) => console.log(e.detail)); </script>
import { SuiIconField } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { return <SuiIconField icon="fa-solid fa-magnifying-glass" name="q" placeholder="Search invoices" aria-label="Search invoices" onSuiChange={(e) => console.log(e.detail)} />; }
<script setup> import { SuiIconField } from "@shineui/vue"; import "@shineui/core/shineui.css"; const onChange = (e) => console.log(e.detail); </script> <template> <SuiIconField icon="fa-solid fa-magnifying-glass" name="q" placeholder="Search invoices" aria-label="Search invoices" @sui-change="onChange" /> </template>
import { Component } from "@angular/core"; import { SuiIconField } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiIconField], template: `<sui-icon-field icon="fa-solid fa-magnifying-glass" name="q" placeholder="Search invoices" aria-label="Search invoices" (suiChange)="onChange($event)"></sui-icon-field>`, }) export class Example { onChange(e: CustomEvent) { console.log(e.detail); } }

Basic

There is no visible label, so aria-label on the element names the field; without one the placeholder does. Icons are decoration and hidden from screen readers.

<div style="display:flex;flex-direction:column;gap:12px;max-width:300px"> <sui-icon-field icon="fa-solid fa-magnifying-glass" name="q" placeholder="Search invoices" aria-label="Search invoices"></sui-icon-field> <sui-icon-field icon="fa-regular fa-calendar" end-icon="fa-solid fa-chevron-down" placeholder="Aug 1 to Aug 15, 2026" aria-label="Date range"></sui-icon-field> </div>

Sizes

md is the default, on the toolbar and in a form alike, one height with every other field; sm packs into table rows and lg is the roomier field for a sign-in or marketing page.

<div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:12px;align-items:end"> <sui-icon-field icon="fa-solid fa-magnifying-glass" size="lg" placeholder="Large" aria-label="Search, large"></sui-icon-field> <sui-icon-field icon="fa-solid fa-magnifying-glass" size="md" placeholder="Medium" aria-label="Search, medium"></sui-icon-field> <sui-icon-field icon="fa-solid fa-magnifying-glass" size="sm" placeholder="Small" aria-label="Search, small"></sui-icon-field> </div>

Clearable and states

The X shows only while there is a value. A read-only field keeps its value selectable and drops the X: that is the one edit it must refuse.

<div style="display:flex;flex-direction:column;gap:12px;max-width:300px"> <sui-icon-field icon="fa-solid fa-magnifying-glass" clearable value="Silver Hills" aria-label="Search customers"></sui-icon-field> <sui-icon-field icon="fa-solid fa-hashtag" clearable readonly value="INV-1043" aria-label="Invoice number"></sui-icon-field> <sui-icon-field icon="fa-solid fa-magnifying-glass" placeholder="Search" aria-label="Search" invalid></sui-icon-field> <sui-icon-field icon="fa-solid fa-magnifying-glass" placeholder="Search" aria-label="Search" disabled></sui-icon-field> </div>

A hint in the end slot

The end slot sits inside the field's edge after the clear control and the trailing icon, and the input gives up room for it only while it is filled. A press on the hint puts the caret in the input, so the key reads as part of the field; a small action in the slot keeps its own click.

USD
<div style="display:flex;flex-direction:column;gap:12px;max-width:300px"> <sui-icon-field icon="fa-solid fa-magnifying-glass" placeholder="Search" aria-label="Search the workspace"><sui-kbd slot="end" quiet aria-hidden="true">Ctrl K</sui-kbd></sui-icon-field> <sui-icon-field icon="fa-solid fa-magnifying-glass" clearable value="Silver Hills" aria-label="Search customers"><sui-kbd slot="end" quiet aria-hidden="true">/</sui-kbd></sui-icon-field> <sui-icon-field icon="fa-regular fa-money-bill-1" placeholder="0.00" aria-label="Amount"><span slot="end" style="font:460 13px var(--font-sans);color:var(--ink-muted)">USD</span></sui-icon-field> </div>

In a form

Bare, so the browser bubble is the message surface and the aria-label names it. An empty field posts an empty string. Give the field a label and the message surface moves onto the page, which is the example below.

Submit while empty to see the field block it.
<form id="if-form" style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;max-width:420px"> <sui-icon-field icon="fa-solid fa-magnifying-glass" name="q" required aria-label="Search invoices" placeholder="Search invoices" style="flex:1"></sui-icon-field> <sui-button type="submit" variant="brand" label="Search"></sui-button> <output id="if-out" style="flex-basis:100%;font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Submit while empty to see the field block it.</output> </form>
// setup(root): properties and events setup(root) { const form = root.querySelector('#if-form'); const out = root.querySelector('#if-out'); form.addEventListener('submit', (e) => { e.preventDefault(); out.textContent = [...new FormData(form)].map(([k, v]) => `${k}=${v || '(empty)'}`).join(' '); }); }

Labeled, for a form

Set label, help or error and the field draws the same shell the rest of the InputText family draws, so an invalid field has somewhere to say why. Set none of them and nothing is added, which is the toolbar shape above.

<div style="display:flex;flex-direction:column;gap:14px;max-width:320px"> <sui-icon-field icon="fa-solid fa-magnifying-glass" label="Find a customer" help="Name, email or account number." placeholder="Search"></sui-icon-field> <sui-icon-field icon="fa-solid fa-hashtag" label="Invoice number" required value="INV-10" error="No invoice matches that number."></sui-icon-field> </div>

Events

suiInput fires on every keystroke and suiChange on commit at blur or Enter. The X emits suiClear, then suiChange with an empty string, and puts focus back in the field. suiFocus and suiBlur follow the input, so a launcher can arm on focus without listening for the native focusin.

Idle.
<div style="display:grid;gap:10px;max-width:300px"> <sui-icon-field id="if-events" icon="fa-solid fa-magnifying-glass" clearable name="q" placeholder="Search customers" aria-label="Search customers"></sui-icon-field> <span id="if-log" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Idle.</span> </div>
// setup(root): properties and events setup(root) { const log = root.querySelector('#if-log'); const el = root.querySelector('#if-events'); el.addEventListener('suiFocus', () => { log.textContent = 'suiFocus'; }); el.addEventListener('suiBlur', () => { log.textContent = 'suiBlur'; }); el.addEventListener('suiInput', (e) => { log.textContent = `suiInput ${e.detail || '(empty)'}`; }); el.addEventListener('suiChange', (e) => { log.textContent = `suiChange ${e.detail || '(empty)'}`; }); el.addEventListener('suiClear', () => { log.textContent = 'suiClear'; }); }

Keyboard

KeyAction
TabMoves to the field, then to the clear control when there is text, then on.
Printable charactersType into the native input; suiInput fires on every keystroke.
Space EnterOn the clear control, empties the field and returns focus to it.

API

<sui-icon-field>

Properties

PropertyAttributeTypeDefaultDescription
autocompleteautocompletestringstring | undefinedNative autocomplete hint, as on the five other elements that wrap a native text input. inputmode and enterkeyhint set on the host reach the input the same way, and spellcheck and autocapitalize on the host apply to it as they do to any descendant.
clearableclearablebooleanfalseShows an X that empties the field when it has a value: the search pattern. A clear emits suiClear, then suiChange with an empty string, and returns focus to the field.
disableddisabledbooleanfalseDisables the field.
endIconend-iconstringstring | undefinedIcon at the end of the field, after the text, e.g. "fa-solid fa-chevron-down". It follows the reading direction, so it sits on the left under dir="rtl". icon is the one at the start.
errorerrorstringstring | undefinedError message under the field. Setting it paints the danger state and fails form validation.
helphelpstringstring | undefinedHelp text under the field.
iconiconstringstring | undefinedLeading icon, before the text, e.g. "fa-solid fa-magnifying-glass".
invalidinvalidbooleanfalseDanger border.
labellabelstringstring | undefinedLabel above the field. Leave it unset for the bare toolbar shape, which is this element's default and what it was built for: with no label, help or error the shell draws nothing at all and the field is the same box it has always been, measured rather than assumed; the host's aria-label or aria-labelledby names the input then, or the placeholder. Set one of the three and it draws the shell the other five elements in the InputText family draw, which is what this element was missing: it carried required and invalid with nowhere to say why. A visible label wins over both host attributes.
minLengthminlengthnumbernumber | undefinedNative minlength: a value shorter than this, once the user has typed, fails as tooShort.
namenamestringstring | undefinedForm control name. Reflected: form entry construction reads the content attribute, while all three framework bindings set properties, so an unreflected name posts nothing at all.
patternpatternstringstring | undefinedNative pattern: a regular expression the whole value must match. The browser checks it and the field reports patternMismatch on its validity, the way required reports valueMissing.
placeholderplaceholderstringstring | undefinedPlaceholder text.
readOnlyreadonlybooleanfalseDisplay only: the text can be selected and copied but not edited; the field still posts its value.
requiredrequiredbooleanfalseMarks the field required (valueMissing validity when empty). With no label set the browser's own bubble carries the message, named from the aria-label or the placeholder.
sizesize"lg" | "md" | "sm"'md'Control height: sm 28 for table rows, md 34 for forms and toolbars (the default, as on every other text field, the select family and the buttons, so a form built from defaults is one height), lg 42 for a sign-in or marketing page.
typetypeSuiInputType"email" | "password" | "search" | "tel" | "text" | "url"'text'Native input type. One union across the four elements that wrap a native text input.
valuevaluestring''Current value. Mutable; listen to suiInput / suiChange to observe edits.
widthwidthnumber | string | undefinedField width as a CSS length or a pixel number. Defaults to 100%.

Events

EventDetailReactVueDescription
suiBlurvoidonSuiBlur@sui-blurFires when the input loses focus, to the clear control and the end slot included. Does not bubble.
suiChangestringonSuiChange@sui-changeFires on commit (blur or Enter, native change) and after a clear; detail is the value.
suiClearvoidonSuiClear@sui-clearFires when the clear control empties the field.
suiFocusvoidonSuiFocus@sui-focusFires when the input takes focus, so a host can arm a launcher or a shortcut hint without listening for the native focusin on the element. Does not bubble.
suiInputstringonSuiInput@sui-inputFires on every keystroke; detail is the current value.

Methods

MethodSignatureDescription
select()select() => Promise<void>Selects the field text.
setFocus()setFocus() => Promise<void>Moves keyboard focus into the field.

Slots

SlotDescription
endTrailing content inside the field's edge: a shortcut hint, a unit, a small action. It sits after the clear control and the trailing icon, centred on the field's height, and the input gives up room for it only while it is filled. A press on it that lands on nothing focusable puts the caret in the input, so a sui-kbd hint reads and behaves as part of the field.

Types

SuiInputType typeThe native type values the text-input skin draws. One union for the whole family: the four elements that wrap a native text input each listed a different subset in prose, which read as a rule and was not one. Anything outside this set has its own element (sui-input-number, sui-date-picker, sui-color-picker) or its own skin.
No members.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also