--- templateEngineOverride: njk layout: layouts/page.njk title: Input Group description: Add icons, text, buttons, and helper content to inputs and textareas. toc: - label: Usage id: usage - label: Examples id: examples children: - label: Align id: example-align children: - label: inline-start id: align-inline-start - label: inline-end id: align-inline-end - label: block-start id: align-block-start - label: block-end id: align-block-end - label: Icon id: example-icon - label: Text id: example-text - label: Button id: example-button - label: Kbd id: example-kbd - label: Dropdown id: example-dropdown - label: Spinner id: example-spinner - label: Textarea id: example-textarea - label: Custom Input id: example-custom-input - label: RTL id: example-rtl --- {% from "macros/code_block.njk" import code_block %} {% from "macros/code_preview.njk" import code_preview %} {% from "dropdown-menu.njk" import dropdown_menu %} {% set spinner_icon %}{% lucide "loader-circle", { "role": "status", "aria-label": "Loading", "class": "animate-spin" } %}{% endset %} {% set code_default %}
12 results
https://
{% set trigger %}Auto{% endset %} {{ dropdown_menu( main_attrs={"class": "min-w-0"}, trigger=trigger, trigger_attrs={"class": "btn-xs-ghost"}, popover_attrs={"data-side": "top", "data-align": "start", "class": "min-w-28 [--radius:0.95rem]"}, items=[ { type: "item", label: "Auto" }, { type: "item", label: "Agent" }, { type: "item", label: "Manual" } ] ) }} 52% used
{% endset %} {{ code_preview("input-group-default", code_default | prettyHtml, class="w-full max-w-sm") }}

Usage

{% set code_usage %}
12 results
{% endset %} {{ code_block(code_usage | prettyHtml, "html") }}

Use .input-group on the root. The group owns the visible shell. Native controls stay semantic and become borderless children inside that shell.

The component has the following HTML structure:

<div class="input-group">
The root shell. Add role="group" and an accessible label only when the group itself needs to be named.
<input>, <textarea>, <select>
The native control. Use aria-invalid="true" for invalid state and disabled for disabled state.
<span>, <svg>, <kbd>
Decorative or helper content. Use aria-hidden="true" for decorative icons.
<button>, <div role="group">
Interactive actions. Use role="group" with an accessible label when multiple related actions share one side of the input.
<header>, <footer>
Header or footer addon rows for vertically oriented input groups.
data-align="start|end"
Optional visual placement. Values use logical direction, so start/end automatically flip in RTL. Use data-orientation="vertical" on the root for header/footer layouts.
[data-control]
Escape hatch for custom controls that are not native input, textarea, or select.

Examples

Align

Use data-align="start|end" on addon wrappers to position them inline. Use data-orientation="vertical" with header or footer for block placement.

inline-start

{% set code_align_inline_start %}

Icon positioned at the start.

{% endset %} {{ code_preview("input-group-inline-start", code_align_inline_start | prettyHtml, class="w-full max-w-sm") }}

inline-end

{% set code_align_inline_end %}

Icon positioned at the end.

{% endset %} {{ code_preview("input-group-inline-end", code_align_inline_end | prettyHtml, class="w-full max-w-sm") }}

block-start

{% set code_align_block_start %}
Full Name

Header positioned above the input.

{% lucide "file-code", { "class": "text-muted-foreground" } %} script.js

Header positioned above the textarea.

{% endset %} {{ code_preview("input-group-block-start", code_align_block_start | prettyHtml, class="w-full max-w-sm") }}

block-end

{% set code_align_block_end %}
USD

Footer positioned below the input.

0/280

Footer positioned below the textarea.

{% endset %} {{ code_preview("input-group-block-end", code_align_block_end | prettyHtml, class="w-full max-w-sm") }}

Icon

{% set code_icon %}
{% endset %} {{ code_preview("input-group-icon", code_icon | prettyHtml, class="w-full max-w-sm") }}

Text

{% set code_text %}
$ USD
https:// .com
@company.com
{% endset %} {{ code_preview("input-group-text", code_text | prettyHtml, class="w-full max-w-sm") }}

Button

{% set code_button %}
https://
{% endset %} {{ code_preview("input-group-button", code_button | prettyHtml, class="w-full max-w-sm") }}

Kbd

{% set code_kbd %}
⌘K
{% endset %} {{ code_preview("input-group-kbd", code_kbd | prettyHtml, class="w-full max-w-sm") }}

Dropdown

{% set code_dropdown %}
{% set trigger %}{% lucide "ellipsis" %}{% endset %} {{ dropdown_menu( main_attrs={"data-align": "end"}, trigger=trigger, trigger_attrs={"class": "btn-xs-icon-ghost", "aria-label": "Open file actions"}, popover_attrs={"data-align": "end", "class": "min-w-32"}, items=[ { type: "item", label: "Settings" }, { type: "item", label: "Copy path" }, { type: "item", label: "Open location" } ] ) }}
{% set trigger %}Search In... {% lucide "chevron-down", { "class": "size-3" } %}{% endset %} {{ dropdown_menu( main_attrs={"data-align": "end"}, trigger=trigger, trigger_attrs={"class": "btn-xs-ghost pr-1.5! text-xs"}, popover_attrs={"data-align": "end", "class": "min-w-32 [--radius:0.95rem]"}, items=[ { type: "item", label: "Documentation" }, { type: "item", label: "Blog Posts" }, { type: "item", label: "Changelog" } ] ) }}
{% endset %} {{ code_preview("input-group-dropdown", code_dropdown | prettyHtml, class="w-full max-w-sm") }}

Spinner

{% set code_spinner %}
{{ spinner_icon | safe }}
{{ spinner_icon | safe }}
Saving... {{ spinner_icon | safe }}
Please wait...
{% endset %} {{ code_preview("input-group-spinner", code_spinner | prettyHtml, class="w-full max-w-sm") }}

Textarea

{% set code_textarea %}
{% lucide "file-code", { "class": "text-muted-foreground" } %} script.js
{% endset %} {{ code_preview("input-group-textarea", code_textarea | prettyHtml, class="w-full max-w-md") }}

Custom Input

{% set code_custom %}
{% endset %} {{ code_preview("input-group-custom", code_custom | prettyHtml, class="w-full max-w-sm") }}

RTL

{% set code_rtl %}
١٢ نتيجة
{{ spinner_icon | safe }}
جاري الحفظ... {{ spinner_icon | safe }}
٠/٢٨٠

تذييل موضع أسفل منطقة النص.

{% endset %} {{ code_preview("input-group-rtl", code_rtl | prettyHtml, class="w-full max-w-sm") }}