Skip to content

Input Group ​

Combines an input or textarea field with related elements, such as buttons, icons, or labels, to create a cohesive and interactive form control. Input Groups help visually associate related functionality with a single field.

Usage ​

Use Input Groups when you want to attach supplementary actions or indicators to a form field, such as a submit button, a search icon, or a unit label. Make sure the grouping is intuitive and does not compromise accessibility or clarity of the main input.

API Reference ​

Component attribute(s) ​

x-h-input-group
x-h-input-group-addon
x-h-input-group-text

Attributes ​

x-h-input-group ​

AttributeValuesRequiredDescription
data-sizesm
default
falseChanges the size of the input.

x-h-input-group-addon ​

AttributeValuesRequiredDescription
data-aligninline-start
inline-end
block-start
block-end
falseAligns the addon relative to the group. See note.
data-disabledbooleanfalseDisables the addon.

Focus Navigation

In order to achieve proper focus navigation, place the group addon after the input and then set the align prop to position it.

Validation timing ​

By default the group shows its control's native-constraint errors (for example required) only after the user interacts with it or attempts to submit, not on page load. To validate on load instead, set data-validate="immediate" on a wrapping x-h-fieldset, x-h-field, or any ancestor element. Setting aria-invalid="true" on the grouped control always shows the error immediately. See Fieldset for details.

Data Slots ​

SlotElement
input-groupx-h-input-group
input-group-addonx-h-input-group-addon
input-group-textx-h-input-group-text

Examples ​

html
<div x-h-input-group>
  <input x-h-input.group placeholder="Search..." />
  <div x-h-input-group-addon data-align="inline-start">
    <svg x-h-lucide role="presentation" data-lucide="search"></svg>
  </div>
  <div x-h-input-group-addon data-align="inline-end">12 results</div>
</div>

Search bar with tags ​

html
<div x-h-input-group>
  <input x-h-input.group placeholder="Search..." />
  <div x-h-input-group-addon data-align="inline-start">
    <svg x-h-lucide role="presentation" data-lucide="search"></svg>
  </div>
  <div x-h-input-group-addon data-align="inline-end">
    <div x-h-tag-group>
      <div x-h-tag>Ctrl</div>
      <span>+</span>
      <div x-h-tag>F</div>
    </div>
  </div>
</div>

Search bar with buttons and popover ​

html
<div x-h-input-group>
  <input x-h-input.group placeholder="https://..." />
  <div x-h-input-group-addon data-align="inline-start">
    <button x-h-button.addon x-h-popover-trigger data-size="icon-sm" aria-label="info">
      <svg x-h-lucide role="presentation" data-lucide="info"></svg>
    </button>
    <div class="p-4" x-h-popover>This is a popover with some info.</div>
  </div>
  <div x-h-input-group-addon data-align="inline-end">
    <button x-h-button.addon>Go</button>
  </div>
</div>

Search bar with spinner ​

html
<div x-h-input-group>
  <input x-h-input.group placeholder="Searching..." disabled />
  <div x-h-input-group-addon data-align="inline-end">
    <span x-h-spinner></span>
  </div>
</div>

Password with visibility toggle ​

html
<div x-h-input-group>
  <input x-h-input.group type="password" />
  <div x-h-input-group-addon data-align="inline-end">
    <button x-h-button.addon data-size="icon-sm" aria-label="toggle password visibility">
      <svg x-h-icon data-icon="eye" role="presentation"></svg>
    </button>
  </div>
</div>

Invalid ​

Reacts to the native invalid state or to the aria-invalid attribute.

html
<div x-h-input-group>
  <input x-h-input.group placeholder="Search..." aria-invalid="true" />
  <div x-h-input-group-addon data-align="inline-start">
    <svg x-h-lucide role="presentation" data-lucide="search"></svg>
  </div>
  <div x-h-input-group-addon data-align="inline-end">12 results</div>
</div>

Disabled ​

Set the native disabled attribute on the grouped input and data-disabled="true" on the addon(s).

html
<div x-h-input-group>
  <input x-h-input.group placeholder="Search..." disabled />
  <div x-h-input-group-addon data-align="inline-start" data-disabled="true">
    <svg x-h-lucide role="presentation" data-lucide="search"></svg>
  </div>
  <div x-h-input-group-addon data-align="inline-end" data-disabled="true">12 results</div>
</div>

Read-only ​

Set the native readonly attribute on the grouped input. The group shows a dashed border.

html
<div x-h-input-group>
  <input x-h-input.group value="Read-only value" readonly />
  <div x-h-input-group-addon data-align="inline-start">
    <svg x-h-lucide role="presentation" data-lucide="search"></svg>
  </div>
  <div x-h-input-group-addon data-align="inline-end">12 results</div>
</div>

Textarea with top and bottom toolbars ​

html
<div x-h-input-group>
  <textarea x-h-textarea.group placeholder="Message..."></textarea>
  <div x-h-input-group-addon data-align="block-start" class="border-b">
    <button x-h-button.addon data-size="icon-sm" data-variant="transparent" aria-label="make bold">
      <svg x-h-lucide role="presentation" data-lucide="bold"></svg>
    </button>
    <button x-h-button.addon data-size="icon-sm" data-variant="transparent" aria-label="make italic">
      <svg x-h-lucide role="presentation" data-lucide="italic"></svg>
    </button>
    <button x-h-button.addon data-size="icon-sm" data-variant="transparent" aria-label="make underline">
      <svg x-h-lucide role="presentation" data-lucide="italic"></svg>
    </button>
    <span x-h-separator data-orientation="vertical"></span>
    <button x-h-button.addon data-size="icon-sm" data-variant="transparent" aria-label="make underline">
      <svg x-h-lucide role="presentation" data-lucide="link"></svg>
    </button>
  </div>
  <div x-h-input-group-addon data-align="block-end" class="border-t">
    <button id="attachFile" x-h-button.addon x-h-menu-trigger.dropdown data-size="icon-sm" data-variant="outline" class="rounded-full" aria-label="Attach">
      <svg x-h-lucide role="presentation" data-lucide="plus"></svg>
    </button>
    <ul x-h-menu data-align="top-start" aria-labelledby="attachFile">
      <li x-h-menu-item>List</li>
      <li x-h-menu-item>Text snippet</li>
      <li x-h-menu-item>Upload file</li>
    </ul>
    <span x-h-input-group-text class="ml-auto">0/300</span>
    <button x-h-button.addon data-size="icon-sm" data-variant="primary" class="rounded-full" aria-label="Send">
      <svg x-h-lucide role="presentation" data-lucide="arrow-up"></svg>
    </button>
  </div>
</div>