Installation
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
uvx django_shadcn@latest add input_group
Usage
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
<c-input-group>
<c-input-group.addon>
<c-icon name="search" />
</c-input-group.addon>
<c-input-group.input placeholder="Search..." />
</c-input-group>
The outline and the focus ring live on the group, not on the input. Use
c-input-group.input rather than a plain c-input so the group can pick up
focus and validation state.
Examples
Leading and trailing
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
<c-input-group>
<c-input-group.addon>
<c-input-group.text>$</c-input-group.text>
</c-input-group.addon>
<c-input-group.input placeholder="0.00" />
<c-input-group.addon align="inline-end">
<c-input-group.text>USD</c-input-group.text>
</c-input-group.addon>
</c-input-group>
With a button
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
<c-input-group.addon align="inline-end">
<c-input-group.button size="sm" variant="outline">Copy</c-input-group.button>
</c-input-group.addon>
Textarea with a block addon
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
<c-input-group>
<c-input-group.textarea placeholder="Write a message..." rows="3" />
<c-input-group.addon align="block-end" class="border-t">
<c-input-group.button size="sm">Send</c-input-group.button>
</c-input-group.addon>
</c-input-group>
Invalid
copied = false, 2000)
"
:aria-label="copied ? 'Copied' : 'Copy code'"
class="absolute right-3 top-3 z-10 inline-flex size-7 items-center justify-center rounded-md border border-border bg-background text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
>
<c-input-group.input aria-invalid="true" />
Notes
c-input-group.input, .textarea and .button render their own element
rather than wrapping c-input, c-textarea and c-button. cotton silently
drops the attrs spread when it lands on another component, and these
controls have to forward whatever you put on them.
Their sizes come from the group, not from c-button: xs, sm, icon-xs
and icon-sm.
Clicking an addon focuses the input, which needs Alpine. The addon carries
its own x-data, so it works without an Alpine scope around it.