Input Group
Add additional information or actions to an input or textarea.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-6"> <InputGroup> <Input placeholder="Search..." /> <InputGroupAddon>{icon!(icondata::LuSearch)}</InputGroupAddon> <InputGroupAddon align="inline-end">"12 results"</InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="example.com" class="!pl-1" /> <InputGroupAddon> <InputGroupText>"https://"</InputGroupText> </InputGroupAddon> <InputGroupAddon align="inline-end"> <Tooltip value="This is content in a tooltip."> <Button class="rounded-full" size="icon-xs"> {icon!(icondata::LuInfo)} </Button> </Tooltip> </InputGroupAddon> </InputGroup> <InputGroup> <Textarea placeholder="Ask, Search or Chat..." /> <InputGroupAddon align="block-end" class="max-h-[42px]"> <Button variant="outline" class="rounded-full" size="icon-xs"> {icon!(icondata::LuPlus)} </Button> <DropdownMenu> <DropdownMenuTrigger> <Button>"Auto"</Button> </DropdownMenuTrigger> <DropdownMenuContent class="[--radius:0.95rem]"> <DropdownMenuItem>"Auto"</DropdownMenuItem> <DropdownMenuItem>"Agent"</DropdownMenuItem> <DropdownMenuItem>"Manual"</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> <InputGroupText class="ml-auto">"52% used"</InputGroupText> <Separator vertical=true class="!h-4" /> <Button variant="default" class="rounded-full" size="icon-xs" disabled=true> {icon!(icondata::LuArrowUp)} <span class="sr-only">"Send"</span> </Button> </InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="@shadcn" /> <InputGroupAddon align="inline-end"> <div class="bg-(--primary) text-(--primary-foreground) flex size-4 items-center justify-center rounded-full"> {icon!(icondata::LuCheck, class="size-3")} </div> </InputGroupAddon> </InputGroup> </div> } }
Icon
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupIconExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-6"> <InputGroup> <Input placeholder="Search..." /> <InputGroupAddon>{icon!(icondata::LuSearch)}</InputGroupAddon> </InputGroup> <InputGroup> <Input input_type="email" placeholder="Enter your email" /> <InputGroupAddon>{icon!(icondata::LuMail)}</InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="Card number" /> <InputGroupAddon>{icon!(icondata::LuCreditCard)}</InputGroupAddon> <InputGroupAddon align="inline-end">{icon!(icondata::LuCheck)}</InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="Card number" /> <InputGroupAddon align="inline-end"> {icon!(icondata::LuStar)} {icon!(icondata::LuInfo)} </InputGroupAddon> </InputGroup> </div> } }
Text
Display additional text information alongside inputs.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupTextExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-6"> <InputGroup> <InputGroupAddon> <InputGroupText>"$"</InputGroupText> </InputGroupAddon> <Input placeholder="0.00" /> <InputGroupAddon align="inline-end"> <InputGroupText>"USD"</InputGroupText> </InputGroupAddon> </InputGroup> <InputGroup> <InputGroupAddon> <InputGroupText>"https://"</InputGroupText> </InputGroupAddon> <Input placeholder="example.com" class="!pl-0.5" /> <InputGroupAddon align="inline-end"> <InputGroupText>".com"</InputGroupText> </InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="Enter your username" /> <InputGroupAddon align="inline-end"> <InputGroupText>"@company.com"</InputGroupText> </InputGroupAddon> </InputGroup> <InputGroup> <Textarea placeholder="Enter your message" /> <InputGroupAddon align="block-end"> <InputGroupText class="text-muted-foreground text-xs"> "120 characters left" </InputGroupText> </InputGroupAddon> </InputGroup> </div> } }
Button
Add buttons to perform actions within the input group.
use leptos::prelude::*; use singlestage::*; use std::time::Duration; #[component] pub fn InputGroupButtonExample() -> impl IntoView { let is_copied = RwSignal::new(false); let is_favorite = RwSignal::new(false); Effect::new(move || { if is_copied.get() { set_timeout(move || is_copied.set(false), Duration::from_secs(2)); } }); view! { <div class="grid w-full max-w-sm gap-6"> <InputGroup> <Input placeholder="https://x.com/shadcn" readonly=true /> <InputGroupAddon align="inline-end"> <Button aria_label="Copy" title="Copy" size="icon-xs" on:click=move |_| is_copied.set(true) > <Show when=move || is_copied.get() fallback=move || { icon!(icondata::LuCopy) } > {icon!(icondata::LuCheck)} </Show> </Button> </InputGroupAddon> </InputGroup> <InputGroup class="rounded-full"> <InputGroupAddon> <Popover> <PopoverTrigger> <Button class="rounded-full" variant="secondary" size="icon-xs"> {icon!(icondata::LuInfo)} </Button> </PopoverTrigger> <PopoverContent class="gap-1 text-sm max-w-2xs"> <p class="font-medium">"Your connection is not secure."</p> <p>"You should not enter any sensitive information on this site."</p> </PopoverContent> </Popover> </InputGroupAddon> <InputGroupAddon class="text-muted-foreground pl-1.5">"https://"</InputGroupAddon> <Input id="input-secure-19" /> <InputGroupAddon align="inline-end"> <Button aria_label="Bookmark this page" title="Bookmark this page" class="rounded-full" on:click=move |_| is_favorite.set(!is_favorite.get()) size="icon-xs" > <Show when=move || is_favorite.get() fallback=move || { { icon!(icondata::LuStar) } } > {icon!(icondata::LuStar, class="fill-blue-600 stroke-blue-600")} </Show> </Button> </InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="Type to search..." /> <InputGroupAddon align="inline-end"> <Button aria_label="Search" title="Search" variant="secondary"> "Search" </Button> </InputGroupAddon> </InputGroup> </div> } }
Tooltip
Add Add tooltips to provide additional context or help.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupTooltipExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-4"> <InputGroup> <Input placeholder="Enter password" input_type="password" /> <InputGroupAddon align="inline-end"> <Tooltip value="Password must be at least 8 characters"> <Button variant="ghost" aria_label="Info" size="icon-xs"> {icon!(icondata::LuInfo)} </Button> </Tooltip> </InputGroupAddon> </InputGroup> <InputGroup> <Input placeholder="Your email address" /> <InputGroupAddon align="inline-end"> <Tooltip value="We'll use this to send you notifications"> <Button variant="ghost" aria_label="Help" size="icon-xs"> {icon!(icondata::FiHelpCircle)} </Button> </Tooltip> </InputGroupAddon> </InputGroup> <InputGroup> <Tooltip side="left" value="Click for help with API keys"> <InputGroupAddon> <Button variant="ghost" aria_label="Help" size="icon-xs"> {icon!(icondata::FiHelpCircle)} </Button> </InputGroupAddon> </Tooltip> <Input placeholder="Enter API key" /> </InputGroup> </div> } }
Textarea
Input groups also work with textarea components. Use block-start or block-end for alignment.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupTextareaExample() -> impl IntoView { view! { <div class="grid w-full max-w-md gap-4"> <InputGroup> <Textarea id="textarea-code-32" placeholder="console.log('Hello, world!');" class="min-h-[200px]" /> <InputGroupAddon align="block-end" class="border-t"> <InputGroupText>"Line 1, Column 1"</InputGroupText> <Button size="sm" class="ml-auto" variant="default"> "Run" {icon!(icondata::FiCornerDownLeft)} </Button> </InputGroupAddon> <InputGroupAddon align="block-start" class="border-b"> <InputGroupText class="font-mono font-medium"> {icon!(icondata::BiJavascript)} "script.js" </InputGroupText> <Button class="ml-auto" size="icon-xs"> {icon!(icondata::LuRefreshCw)} </Button> <Button variant="ghost" size="icon-xs"> {icon!(icondata::LuCopy)} </Button> </InputGroupAddon> </InputGroup> </div> } }
Spinner
Show loading indicators while processing input.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupSpinnerExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-4"> <InputGroup disabled=true> <Input placeholder="Searching..." disabled=true /> <InputGroupAddon align="inline-end"> <Spinner /> </InputGroupAddon> </InputGroup> <InputGroup disabled=true> <Input placeholder="Processing..." disabled=true /> <InputGroupAddon> <Spinner /> </InputGroupAddon> </InputGroup> <InputGroup disabled=true> <Input placeholder="Saving changes..." disabled=true /> <InputGroupAddon align="inline-end"> <InputGroupText>"Saving..."</InputGroupText> <Spinner /> </InputGroupAddon> </InputGroup> <InputGroup disabled=true> <Input placeholder="Refreshing data..." disabled=true /> <InputGroupAddon> <Spinner>{icon!(icondata::LuLoader)}</Spinner> </InputGroupAddon> <InputGroupAddon align="inline-end"> <InputGroupText class="text-muted-foreground">"Please wait..."</InputGroupText> </InputGroupAddon> </InputGroup> </div> } }
Label
Add labels within input groups to improve accessibility.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupLabelExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-4"> <InputGroup> <Input id="email" placeholder="shadcn" /> <InputGroupAddon> <Label label_for="email">"@"</Label> </InputGroupAddon> </InputGroup> <InputGroup> <Input id="email-2" placeholder="shadcn@vercel.com" /> <InputGroupAddon align="block-start"> <Label label_for="email-2" class="text-(--foreground)"> "Email" </Label> <Tooltip class="ml-auto" value="We'll use this to send you notifications"> <Button variant="ghost" aria_label="Help" class="rounded-full" size="icon-xs" > {icon!(icondata::LuInfo)} </Button> </Tooltip> </InputGroupAddon> </InputGroup> </div> } }
Dropdown
Pair input groups with dropdown menus for complex interactions.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupDropdownExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-4"> <InputGroup> <Input placeholder="Enter file name" /> <InputGroupAddon align="inline-end"> <DropdownMenu> <DropdownMenuTrigger> <Button aria_label="More" title="More"> {icon!(icondata::FiMoreHorizontal)} </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuItem>"Settings"</DropdownMenuItem> <DropdownMenuItem>"Copy path"</DropdownMenuItem> <DropdownMenuItem>"Open location"</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </InputGroupAddon> </InputGroup> <InputGroup class="[--radius:1rem]"> <Input placeholder="Enter search query" /> <InputGroupAddon align="inline-end"> <DropdownMenu> <DropdownMenuTrigger> <Button class="!pr-1.5 text-xs"> "Search In..." {icon!(icondata::LuChevronDown, class="size-3")} </Button> </DropdownMenuTrigger> <DropdownMenuContent class="[--radius:0.95rem]"> <DropdownMenuItem>"Documentation"</DropdownMenuItem> <DropdownMenuItem>"Blog Posts"</DropdownMenuItem> <DropdownMenuItem>"Changelog"</DropdownMenuItem> </DropdownMenuContent> </DropdownMenu> </InputGroupAddon> </InputGroup> </div> } }
Button Group
Wrap input groups with button groups to create prefixes and suffixes.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupButtonGroupExample() -> impl IntoView { view! { <div class="grid w-full max-w-sm gap-6"> <ButtonGroup> <ButtonGroupText> <Label label_for="url">"https://"</Label> </ButtonGroupText> <InputGroup> <Input id="url" /> <InputGroupAddon align="inline-end">{icon!(icondata::LuLink2)}</InputGroupAddon> </InputGroup> <ButtonGroupText>".com"</ButtonGroupText> </ButtonGroup> </div> } }
Anatomy
Import all parts and piece them together.
use leptos::prelude::*; use singlestage::*; #[component] pub fn InputGroupAnatomy() -> impl IntoView { view! { <InputGroup> <Input /> <InputGroupAddon> <InputGroupText /> </InputGroupAddon> </InputGroup> } }
API Reference
InputGroup
The main component that wraps inputs and addons.
| Name | Type | Default | Description |
|---|---|---|---|
| disabled | bool | false | Toggle whether or not this input group should appear disabled. |
InputGroupAddon
Displays icons, text, buttons, or other content alongside inputs.
| Name | Type | Default | Description |
|---|---|---|---|
| align | String | "inline-start" | Set how child content should be aligned. Accepted values are inline-start | inline-end | block-start | block-end. |
Button
InputGroup uses a regular Button with slightly different behavior.
| Name | Type | Default | Description |
|---|---|---|---|
| button_type | String | "button" | Renamed <button> `type` attribute to avoid name collisions. |
| size | String | "xs" | Specify the size to render the button. Sizes: xs | icon-xs | sm | icon-sm. |
| variant | String | "ghost" | Specify the style of button to render. Variants: primary | secondary | outline | ghost | link | destructive |
InputGroupText
A styled wrapper for displaying text and icons in an InputGroup.