본문으로 건너뛰기
언어

Input groupstandard

입력 앞뒤에 글자·아이콘·버튼을 붙이는 입력 묶음(input group)입니다. shadcn base-nova 의 `input-group` 을 그대로 싣습니다.

설치

pnpm
pnpm dlx shadcn@4.23.0 add @uikit/input-group

의존 아이템buttoninputtextarea

Default

input-group-example.tsx
"use client"
import { useState } from "react"import { toast } from "sonner"
import {  Example,  ExampleWrapper,} from "@/components/example"import { Button } from "@/components/ui/button"import {  ButtonGroup,  ButtonGroupText,} from "@/components/ui/button-group"import {  Card,  CardContent,  CardDescription,  CardFooter,  CardHeader,  CardTitle,} from "@/components/ui/card"import {  DropdownMenu,  DropdownMenuContent,  DropdownMenuItem,  DropdownMenuTrigger,} from "@/components/ui/dropdown-menu"import {  Field,  FieldDescription,  FieldGroup,  FieldLabel,} from "@/components/ui/field"import { Input } from "@/components/ui/input"import {  InputGroup,  InputGroupAddon,  InputGroupButton,  InputGroupInput,  InputGroupText,  InputGroupTextarea,} from "@/components/ui/input-group"import { Kbd, KbdGroup } from "@/components/ui/kbd"import {  Popover,  PopoverContent,  PopoverDescription,  PopoverHeader,  PopoverTitle,  PopoverTrigger,} from "@/components/ui/popover"import { Spinner } from "@/components/ui/spinner"import { Textarea } from "@/components/ui/textarea"import {  Tooltip,  TooltipContent,  TooltipTrigger,} from "@/components/ui/tooltip"import { ArrowUpIcon, CheckIcon, ChevronDownIcon, CodeIcon, CopyIcon, ExternalLinkIcon, EyeOffIcon, InfoIcon, MailIcon, MicIcon, RadioIcon, RefreshCwIcon, SearchIcon, SparklesIcon, StarIcon, TrashIcon } from "lucide-react"
export default function InputGroupExample() {  const [country, setCountry] = useState("+1")
  return (    <ExampleWrapper className="min-w-0">      <InputGroupBasic />      <InputGroupWithAddons />      <InputGroupWithButtons />      <InputGroupWithTooltip country={country} setCountry={setCountry} />      <InputGroupWithKbd />      <InputGroupInCard />      <InputGroupTextareaExamples />    </ExampleWrapper>  )}
function InputGroupBasic() {  return (    <Example title="Basic">      <FieldGroup>        <Field>          <FieldLabel htmlFor="input-default-01">            Default (No Input Group)          </FieldLabel>          <Input placeholder="Placeholder" id="input-default-01" />        </Field>        <Field>          <FieldLabel htmlFor="input-group-02">Input Group</FieldLabel>          <InputGroup>            <InputGroupInput id="input-group-02" placeholder="Placeholder" />          </InputGroup>        </Field>        <Field data-disabled="true">          <FieldLabel htmlFor="input-disabled-03">Disabled</FieldLabel>          <InputGroup>            <InputGroupInput              id="input-disabled-03"              placeholder="This field is disabled"              disabled            />          </InputGroup>        </Field>        <Field data-invalid="true">          <FieldLabel htmlFor="input-invalid-04">Invalid</FieldLabel>          <InputGroup>            <InputGroupInput              id="input-invalid-04"              placeholder="This field is invalid"              aria-invalid="true"            />          </InputGroup>        </Field>      </FieldGroup>    </Example>  )}
function InputGroupWithAddons() {  return (    <Example title="With Addons">      <FieldGroup>        <Field>          <FieldLabel htmlFor="input-icon-left-05">            Addon (inline-start)          </FieldLabel>          <InputGroup>            <InputGroupInput id="input-icon-left-05" />            <InputGroupAddon>              <SearchIcon className="text-muted-foreground" />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-icon-right-07">            Addon (inline-end)          </FieldLabel>          <InputGroup>            <InputGroupInput id="input-icon-right-07" />            <InputGroupAddon align="inline-end">              <EyeOffIcon />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-icon-both-09">            Addon (inline-start and inline-end)          </FieldLabel>          <InputGroup>            <InputGroupInput id="input-icon-both-09" />            <InputGroupAddon>              <MicIcon className="text-muted-foreground" />            </InputGroupAddon>            <InputGroupAddon align="inline-end">              <RadioIcon className="animate-pulse text-red-500" />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-addon-20">Addon (block-start)</FieldLabel>          <InputGroup className="h-auto">            <InputGroupInput id="input-addon-20" />            <InputGroupAddon align="block-start">              <InputGroupText>First Name</InputGroupText>              <InfoIcon className="ml-auto text-muted-foreground" />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-addon-21">Addon (block-end)</FieldLabel>          <InputGroup className="h-auto">            <InputGroupInput id="input-addon-21" />            <InputGroupAddon align="block-end">              <InputGroupText>20/240 characters</InputGroupText>              <InfoIcon className="ml-auto text-muted-foreground" />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-icon-both-10">Multiple Icons</FieldLabel>          <InputGroup>            <InputGroupInput id="input-icon-both-10" />            <InputGroupAddon align="inline-end">              <StarIcon />              <InputGroupButton aria-label="Copy"                size="icon-xs"                onClick={() => toast("Copied to clipboard")}              >                <CopyIcon />              </InputGroupButton>            </InputGroupAddon>            <InputGroupAddon>              <RadioIcon className="animate-pulse text-red-500" />            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-description-10">Description</FieldLabel>          <InputGroup>            <InputGroupInput id="input-description-10" />            <InputGroupAddon align="inline-end">              <InfoIcon />            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="input-label-10">Label</FieldLabel>          <InputGroup>            <InputGroupAddon>              <FieldLabel htmlFor="input-label-10">Label</FieldLabel>            </InputGroupAddon>            <InputGroupInput id="input-label-10" />          </InputGroup>          <InputGroup>            <InputGroupInput id="input-optional-12" aria-label="Optional" />            <InputGroupAddon align="inline-end">              <InputGroupText>(optional)</InputGroupText>            </InputGroupAddon>          </InputGroup>        </Field>      </FieldGroup>    </Example>  )}
function InputGroupWithButtons() {  return (    <Example title="With Buttons">      <FieldGroup>        <Field>          <FieldLabel htmlFor="input-button-13">Button</FieldLabel>          <InputGroup>            <InputGroupInput id="input-button-13" />            <InputGroupAddon>              <InputGroupButton>Default</InputGroupButton>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-button-14" />            <InputGroupAddon>              <InputGroupButton variant="outline">Outline</InputGroupButton>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-button-15" />            <InputGroupAddon>              <InputGroupButton variant="secondary">Secondary</InputGroupButton>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-button-16" />            <InputGroupAddon align="inline-end">              <InputGroupButton variant="secondary">Button</InputGroupButton>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-button-17" />            <InputGroupAddon align="inline-end">              <InputGroupButton aria-label="Copy" size="icon-xs">                <CopyIcon />              </InputGroupButton>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-button-18" />            <InputGroupAddon align="inline-end">              <InputGroupButton aria-label="Trash" variant="secondary" size="icon-xs">                <TrashIcon />              </InputGroupButton>            </InputGroupAddon>          </InputGroup>        </Field>      </FieldGroup>    </Example>  )}
function InputGroupWithTooltip({  country,  setCountry,}: {  country: string  setCountry: (value: string) => void}) {  return (    <Example title="With Tooltip, Dropdown, Popover">      <FieldGroup>        <Field>          <FieldLabel htmlFor="input-tooltip-20">Tooltip</FieldLabel>          <InputGroup>            <InputGroupInput id="input-tooltip-20" />            <InputGroupAddon align="inline-end">              <Tooltip>                <TooltipTrigger aria-label="Info"                  render={                    <InputGroupButton className="rounded-full" size="icon-xs" />                  }                >                  <InfoIcon />                </TooltipTrigger>                <TooltipContent>This is content in a tooltip.</TooltipContent>              </Tooltip>            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="input-dropdown-21">Dropdown</FieldLabel>          <InputGroup>            <InputGroupInput id="input-dropdown-21" />            <InputGroupAddon>              <DropdownMenu>                <DropdownMenuTrigger                  render={                    <InputGroupButton className="text-muted-foreground tabular-nums" />                  }                >                  {country}{" "}                  <ChevronDownIcon />                </DropdownMenuTrigger>                <DropdownMenuContent                  align="start"                  className="min-w-16"                  sideOffset={10}                  alignOffset={-8}                >                  <DropdownMenuItem onClick={() => setCountry("+1")}>                    +1                  </DropdownMenuItem>                  <DropdownMenuItem onClick={() => setCountry("+44")}>                    +44                  </DropdownMenuItem>                  <DropdownMenuItem onClick={() => setCountry("+46")}>                    +46                  </DropdownMenuItem>                </DropdownMenuContent>              </DropdownMenu>            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="input-secure-19">Popover</FieldLabel>          <InputGroup>            <Popover>              <InputGroupAddon>                <PopoverTrigger                  render={<InputGroupButton variant="secondary" size="icon-xs" />}                  aria-label="Info"                >                  <InfoIcon />                </PopoverTrigger>              </InputGroupAddon>              <PopoverContent align="start">                <PopoverHeader>                  <PopoverTitle>Your connection is not secure.</PopoverTitle>                  <PopoverDescription>                    You should not enter any sensitive information on this site.                  </PopoverDescription>                </PopoverHeader>              </PopoverContent>            </Popover>            <InputGroupAddon className="pl-1 text-muted-foreground">              https://            </InputGroupAddon>            <InputGroupInput id="input-secure-19" />            <InputGroupAddon align="inline-end">              <InputGroupButton aria-label="Star"                size="icon-xs"                onClick={() => toast("Added to favorites")}              >                <StarIcon />              </InputGroupButton>            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="url">Button Group</FieldLabel>          <ButtonGroup>            <ButtonGroupText>https://</ButtonGroupText>            <InputGroup>              <InputGroupInput id="url" />              <InputGroupAddon align="inline-end">                <InfoIcon />              </InputGroupAddon>            </InputGroup>            <ButtonGroupText>.com</ButtonGroupText>          </ButtonGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>      </FieldGroup>    </Example>  )}
function InputGroupWithKbd() {  return (    <Example title="With Kbd">      <FieldGroup>        <Field>          <FieldLabel htmlFor="input-kbd-22">Input Group with Kbd</FieldLabel>          <InputGroup>            <InputGroupInput id="input-kbd-22" />            <InputGroupAddon>              <Kbd>⌘K</Kbd>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput aria-label="Value" id="input-kbd-23" />            <InputGroupAddon align="inline-end">              <Kbd>⌘K</Kbd>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput              id="input-search-apps-24"              placeholder="Search for Apps..."            />            <InputGroupAddon align="inline-end">Ask AI</InputGroupAddon>            <InputGroupAddon align="inline-end">              <Kbd>Tab</Kbd>            </InputGroupAddon>          </InputGroup>          <InputGroup>            <InputGroupInput              id="input-search-type-25"              placeholder="Type to search..."            />            <InputGroupAddon align="inline-start">              <SparklesIcon />            </InputGroupAddon>            <InputGroupAddon align="inline-end">              <KbdGroup>                <Kbd>Ctrl</Kbd>                <Kbd>C</Kbd>              </KbdGroup>            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="input-username-26">Username</FieldLabel>          <InputGroup>            <InputGroupInput id="input-username-26" defaultValue="shadcn" />            <InputGroupAddon align="inline-end">              <div className="flex size-4 items-center justify-center rounded-full bg-green-500 dark:bg-green-800">                <CheckIcon className="size-3 text-white" />              </div>            </InputGroupAddon>          </InputGroup>          <FieldDescription className="text-green-700 dark:text-green-400">            This username is available.          </FieldDescription>        </Field>        <InputGroup>          <InputGroupInput            id="input-search-docs-27"            placeholder="Search documentation..."          />          <InputGroupAddon>            <SearchIcon />          </InputGroupAddon>          <InputGroupAddon align="inline-end">12 results</InputGroupAddon>        </InputGroup>        <InputGroup data-disabled="true">          <InputGroupInput            id="input-search-disabled-28"            placeholder="Search documentation..."            disabled          />          <InputGroupAddon>            <SearchIcon />          </InputGroupAddon>          <InputGroupAddon align="inline-end">            <InfoIcon />          </InputGroupAddon>        </InputGroup>        <FieldGroup className="grid grid-cols-2 gap-4">          <Field>            <FieldLabel htmlFor="input-group-11">First Name</FieldLabel>            <InputGroup>              <InputGroupInput id="input-group-11" placeholder="First Name" />              <InputGroupAddon align="inline-end">                <InfoIcon />              </InputGroupAddon>            </InputGroup>          </Field>          <Field>            <FieldLabel htmlFor="input-group-12">Last Name</FieldLabel>            <InputGroup>              <InputGroupInput id="input-group-12" placeholder="Last Name" />              <InputGroupAddon align="inline-end">                <InfoIcon />              </InputGroupAddon>            </InputGroup>          </Field>        </FieldGroup>        <Field data-disabled="true">          <FieldLabel htmlFor="input-group-29">            Loading (&quot;data-disabled=&quot;true&quot;)          </FieldLabel>          <InputGroup>            <InputGroupInput              id="input-group-29"              disabled              defaultValue="shadcn"            />            <InputGroupAddon align="inline-end">              <Spinner />            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>      </FieldGroup>    </Example>  )}
function InputGroupInCard() {  return (    <Example title="In Card">      <Card className="w-full">        <CardHeader>          <CardTitle>Card with Input Group</CardTitle>          <CardDescription>This is a card with an input group.</CardDescription>        </CardHeader>        <CardContent>          <FieldGroup>            <Field>              <FieldLabel htmlFor="email-input">Email Address</FieldLabel>              <InputGroup>                <InputGroupInput                  id="email-input"                  type="email"                  placeholder="you@example.com"                />                <InputGroupAddon align="inline-end">                  <MailIcon />                </InputGroupAddon>              </InputGroup>            </Field>            <Field>              <FieldLabel htmlFor="website-input">Website URL</FieldLabel>              <InputGroup>                <InputGroupAddon>                  <InputGroupText>https://</InputGroupText>                </InputGroupAddon>                <InputGroupInput id="website-input" placeholder="example.com" />                <InputGroupAddon align="inline-end">                  <ExternalLinkIcon />                </InputGroupAddon>              </InputGroup>            </Field>            <Field>              <FieldLabel htmlFor="feedback-textarea">                Feedback & Comments              </FieldLabel>              <InputGroup>                <InputGroupTextarea                  id="feedback-textarea"                  placeholder="Share your thoughts..."                  className="min-h-[100px]"                />                <InputGroupAddon align="block-end">                  <InputGroupText>0/500 characters</InputGroupText>                </InputGroupAddon>              </InputGroup>            </Field>          </FieldGroup>        </CardContent>        <CardFooter className="justify-end gap-2">          <Button variant="outline">Cancel</Button>          <Button>Submit</Button>        </CardFooter>      </Card>    </Example>  )}
function InputGroupTextareaExamples() {  return (    <Example title="Textarea">      <FieldGroup>        <Field>          <FieldLabel htmlFor="textarea-header-footer-12">            Default Textarea (No Input Group)          </FieldLabel>          <Textarea            id="textarea-header-footer-12"            placeholder="Enter your text here..."          />        </Field>        <Field>          <FieldLabel htmlFor="textarea-header-footer-13">            Input Group          </FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-header-footer-13"              placeholder="Enter your text here..."            />          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field data-invalid="true">          <FieldLabel htmlFor="textarea-header-footer-14">Invalid</FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-header-footer-14"              placeholder="Enter your text here..."              aria-invalid="true"            />          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field data-disabled="true">          <FieldLabel htmlFor="textarea-header-footer-15">Disabled</FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-header-footer-15"              placeholder="Enter your text here..."              disabled            />          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="prompt-31">Addon (block-start)</FieldLabel>          <InputGroup>            <InputGroupTextarea id="prompt-31" />            <InputGroupAddon align="block-start">              <InputGroupText>Ask, Search or Chat...</InputGroupText>              <InfoIcon className="ml-auto text-muted-foreground" />            </InputGroupAddon>          </InputGroup>          <FieldDescription>            This is a description of the input group.          </FieldDescription>        </Field>        <Field>          <FieldLabel htmlFor="textarea-header-footer-30">            Addon (block-end)          </FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-header-footer-30"              placeholder="Enter your text here..."            />            <InputGroupAddon align="block-end">              <InputGroupText>0/280 characters</InputGroupText>              <InputGroupButton                variant="default"                size="icon-xs"                className="ml-auto rounded-full"              >                <ArrowUpIcon />                <span className="sr-only">Send</span>              </InputGroupButton>            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="textarea-comment-31">Addon (Buttons)</FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-comment-31"              placeholder="Share your thoughts..."              className="min-h-[120px]"            />            <InputGroupAddon align="block-end">              <InputGroupButton variant="ghost" className="ml-auto" size="sm">                Cancel              </InputGroupButton>              <InputGroupButton variant="default" size="sm">                Post Comment              </InputGroupButton>            </InputGroupAddon>          </InputGroup>        </Field>        <Field>          <FieldLabel htmlFor="textarea-code-32">Code Editor</FieldLabel>          <InputGroup>            <InputGroupTextarea              id="textarea-code-32"              placeholder="console.log('Hello, world!');"              className="min-h-[300px] py-3"            />            <InputGroupAddon align="block-start" className="border-b">              <InputGroupText className="font-mono font-medium">                <CodeIcon />                script.js              </InputGroupText>              <InputGroupButton aria-label="Refresh cw" size="icon-xs" className="ml-auto">                <RefreshCwIcon />              </InputGroupButton>              <InputGroupButton aria-label="Copy" size="icon-xs" variant="ghost">                <CopyIcon />              </InputGroupButton>            </InputGroupAddon>            <InputGroupAddon align="block-end" className="border-t">              <InputGroupText>Line 1, Column 1</InputGroupText>              <InputGroupText className="ml-auto">JavaScript</InputGroupText>            </InputGroupAddon>          </InputGroup>        </Field>      </FieldGroup>    </Example>  )}