WingoUI
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime Picker
Forms
Address InputCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text Editor
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselImage CropperImage LightboxLocation MapQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Gravity Letters
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowPost Listing WizardPricing PageRegister PageSettings PageUsers Admin Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryThemeCredits

Inputs

Tag Input

InputsTag Input
SwitchTextarea
Live props
Field
label
description
error
required
invalid
disabled
readOnly
Content
placeholder
name
Appearance
size
variant
radius
chipVariant
tone
color
Behavior
maxNo limit
maxLengthNo limit
backspace
editable
addOnBlur
addOnPaste
allowDuplicates
restrictToSuggestions
openOnFocus
clearable
Code
import { TagInput } from "@/components/ui/tag-input"

<TagInput />
Pro

v1.0.0·Added in 1.0.0

A field that turns typed, pasted or suggested text into removable chips, for tags, keywords and email recipients.

Type a word and press Enter, a comma or a semicolon and it becomes a chip that slides in, with the caret moving along after it. Paste a list like emma@acme.com, michael@acme.com; olivia@acme.com and every entry becomes its own chip, duplicates once. A word that fails validation stays in the field, the text shakes and the reason shows as the field error until you change it; typing a tag that already exists makes the existing chip pulse instead of adding it again. With suggestions a list opens under the field as you type, matches in bold and diacritics ignored: Arrow Down and Up move through it, Enter picks the highlighted one, Escape closes it. Backspace in the empty field puts the last tag back as text to edit it (select mode highlights it first and a second Backspace removes it; remove mode deletes it at once). Arrow Left at the start of the text moves to the chips: Left and Right walk between them, Home and End jump, Delete or Backspace removes the focused chip and focuses its neighbour, Enter or F2 (or a double-click, or a second tap on a focused chip) edits it in place where Enter saves and Escape cancels, and Escape or Right past the last chip returns to the text. Cmd/Ctrl+Enter adds the text and submits the form. Every chip has an × to remove it and clearable adds a Clear all button; additions and removals are read out politely. At the maximum the text field hides and the description says the limit is reached. On a phone the text is 16px so iOS never zooms, the keyboard shows an Enter key (Done at the limit), commas typed on Android keyboards still split tags, the × buttons have a large touch area and the suggestions stay in the page under the field, above the keyboard.

Add to a project

npx wingo-ui@latest add tag-input

Pro item: the CLI needs a Pro account. See plans

Dependencies

motionlucide-reactbadgefieldlistboxuse-controllable-statemotiontext-matchtonesui-config

Files

  • components/ui/tag-input.tsx

See also

Multi SelectBadgeListboxInputSearch InputField
PreviousSwitchNext Textarea

Post a listing

Trek FX 2 city bike, New York

Title
Trek FX 2 city bike, 2021
bikevintage

["bike","vintage"]

⌫ edit+edit+blur+paste-dupes-restrict-openOnFocusname=tagsmaxLength=∞

↵Enter or , adds, ←Left arrow moves onto the tags, ⌫Delete edits the last oneType and press Enter or comma; double-tap a tag to edit it