Tag Input
<quiet-tag-input>
Allows users to add and remove tags by typing and pressing Enter.
Use tag inputs when users need to enter multiple, freeform values in a single field. They're ideal for things like keywords, labels, and categories where the input isn't constrained to a predefined list.
<quiet-tag-input label="Pet names" placeholder="Type a name" with-clear > <span slot="description"> Type each cat's name and press <kbd>Enter</kbd> </span> </quiet-tag-input>
Examples Jump to heading
Labels and descriptions Jump to heading
You can use the label and description attributes to provide plain text labels and
descriptions for the tag input. If you want to provide HTML, use the label and
description slots instead.
<quiet-tag-input placeholder="Add a treat"> <span slot="label">Favorite treats</span> <span slot="description"> Type a treat and press <kbd>Enter</kbd> to add it </span> </quiet-tag-input>
Providing an initial value Jump to heading
Use the value attribute to pre-populate tags with a comma-separated list. To add or remove tags
after initialization, use the addTag() and removeTag() methods or set the
value property directly.
<quiet-tag-input label="Favorite nap spots" placeholder="Add a nap spot" value="Cardboard box, Sunbeam, Laundry basket" with-clear ></quiet-tag-input>
You can change the delimiter used to parse the value attribute with the
delimiter property.
Adding a clear button Jump to heading
Add the with-clear attribute to show a clear button when the tag input has tags. This allows
users to quickly remove all tags at once.
<quiet-tag-input label="Grocery list" placeholder="Add an item" value="Tuna, Catnip, Wet food" with-clear ></quiet-tag-input>
Start and end content Jump to heading
Use the start and end slots to add presentational icons or text. Avoid interactive
elements such as buttons, links, etc. Works well with
<quiet-icon> and <svg> elements.
<quiet-tag-input label="Favorite toys" placeholder="Add a toy" with-clear> <quiet-icon slot="start" name="tag"></quiet-icon> </quiet-tag-input> <br> <quiet-tag-input label="Pet sitters" placeholder="Add an email" with-clear> <quiet-icon slot="start" name="mail"></quiet-icon> <quiet-icon slot="end" name="send"></quiet-icon> </quiet-tag-input>
Filled and unstyled tag inputs Jump to heading
Use the appearance attribute to change the visual style of the tag input. Options are
normal (default), filled, and unstyled.
<quiet-tag-input label="Normal" appearance="normal" placeholder="Add a cat" ></quiet-tag-input> <br> <quiet-tag-input label="Filled" appearance="filled" placeholder="Add a cat" ></quiet-tag-input> <br> <quiet-tag-input label="Unstyled" appearance="unstyled" placeholder="Add a cat" ></quiet-tag-input>
Pill-shaped tag inputs Jump to heading
Add the pill attribute to give the tag input rounded edges. Tags inside will also become
pill-shaped.
<quiet-tag-input label="Hobbies" placeholder="Add a hobby" value="Napping, Knocking things off tables, Zooming at 3 AM" pill with-clear ></quiet-tag-input>
Changing the size Jump to heading
Use the size attribute to change the tag input's size. Available sizes are xs,
sm, md (default), lg, and xl.
<quiet-select label="Select a size" value="xs" style="max-width: 18rem; margin-block-end: 2rem;"> <option value="xs">Extra small</option> <option value="sm">Small</option> <option value="md">Medium</option> <option value="lg">Large</option> <option value="xl">Extra large</option> </quiet-select> <quiet-tag-input size="xs" label="Cat breeds" description="Size changes dynamically based on selection above" placeholder="Add a breed" value="Persian, Siamese" id="tag-input__size" with-clear ></quiet-tag-input> <script> const tagInput = document.getElementById('tag-input__size'); const select = tagInput.previousElementSibling; select.addEventListener('quiet-change', () => { tagInput.size = select.value; }); </script>
Disabling the tag input Jump to heading
Add the disabled attribute to disable the tag input. Existing tags will still be visible but
cannot be removed.
<quiet-tag-input label="Feeding schedule" description="This tag input is disabled" value="Breakfast, Dinner" disabled ></quiet-tag-input>
Readonly Jump to heading
Add the readonly attribute to make the tag input read-only. Existing tags are visible but
cannot be added or removed. Unlike disabled, a readonly tag input can still receive focus and
its value is included in form submissions.
<quiet-tag-input label="Things to do" description="These roles are managed by your furry friend" value="Nap supervisor, Treat inspector, Box tester" readonly ></quiet-tag-input>
Showing labels on the side Jump to heading
With the
quiet-side-label utility, you can
show labels on the side instead of on top of the tag input. You can control the width of the label by
setting the --label-width custom property.
<quiet-tag-input class="quiet-side-label" style="--label-width: 10ch;" label="Indoor cats" placeholder="Add a cat" ></quiet-tag-input> <br> <quiet-tag-input class="quiet-side-label" style="--label-width: 10ch;" label="Outdoor cats" placeholder="Add a cat" ></quiet-tag-input>
Allowing duplicates Jump to heading
By default, duplicate values are silently rejected. Add the allow-duplicates attribute to allow
the same value to be added more than once.
<quiet-tag-input label="Cat sounds" description="The same sound can be added more than once" placeholder="Add a sound" allow-duplicates with-clear ></quiet-tag-input>
Limiting the number of tags Jump to heading
Use the max attribute to set a maximum number of tags. Once the limit is reached, no more tags
can be added.
<quiet-tag-input label="Top 3 nap spots" description="You can add up to 3 nap spots" placeholder="Add a nap spot" max="3" with-clear ></quiet-tag-input>
Changing the delimiter Jump to heading
By default, typing a comma will create a tag from the preceding text. You can change the delimiter
character(s) using the delimiter attribute. Each character in the string is treated as a
separate delimiter. Set delimiter="" to disable delimiter-based tag creation
entirely.
Pasting text that contains delimiters will automatically split the pasted text into individual tags.
<quiet-tag-input label="Comma-separated cats" description="Type a comma or press Enter to add a cat" placeholder="Add a cat" with-clear ></quiet-tag-input>
Use a custom delimiter such as a space:
<quiet-tag-input label="Space-separated cats" description="Type a space or press Enter to add a cat" placeholder="Add a cat" delimiter=" " with-clear ></quiet-tag-input>
You can also use multiple delimiter characters. In this example, both commas and semicolons will create tags:
<quiet-tag-input label="Multiple delimiters" description="Commas and semicolons both work" placeholder="Add a cat" delimiter=",;" with-clear ></quiet-tag-input>
To disable delimiter-based tag creation, set delimiter to an empty string:
<quiet-tag-input label="Enter only" description="Only pressing Enter adds a cat" placeholder="Add a cat" delimiter="" with-clear ></quiet-tag-input>
Customizing tag values and display Jump to heading
Override the getTagValue() method to transform typed text into a stored value, and the
getTagContent() method to customize how tags are rendered. The
getTagContent() method receives the tag's value and returns a string.
In this example, typing "Sleepy Kittens" will store the value as sleepy-kittens and
display the tag as #sleepy-kittens.
<quiet-tag-input label="Hashtags" description="Values are converted to slugs and shown with a # prefix" placeholder="Add one or more hashtags" with-clear id="tag-input__custom" ></quiet-tag-input> <script> const tagInput = document.getElementById('tag-input__custom'); tagInput.getTagValue = (query) => query.trim().toLowerCase().replace(/\s+/g, '-'); tagInput.getTagContent = (value) => `#${value}`; </script>
Rejecting tags Jump to heading
The quiet-create event is cancelable. Call event.preventDefault() to reject a tag
before it gets added. This is useful for custom validation, such as ensuring tags match a specific format.
<quiet-tag-input label="Pet sitters" description="Only valid email addresses are accepted" placeholder="Add a cat sitter's email" with-clear id="tag-input__reject" ></quiet-tag-input> <script> const tagInput = document.getElementById('tag-input__reject'); tagInput.addEventListener('quiet-create', event => { const email = event.detail.value; if (!email.includes('@') || !email.includes('.')) { event.preventDefault(); } }); </script>
Validation Jump to heading
The required attribute can be used to enable validation using the
Constraint Validation API.
<form action="about:blank" method="get" target="_blank"> <quiet-tag-input name="tags" label="Required cats" placeholder="Add at least one cat" required ></quiet-tag-input> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form>
Min and max validation Jump to heading
Use the min and max attributes to validate the number of tags. The
max attribute also prevents adding tags beyond the limit. Validation messages are shown after
the user interacts with the form control or when the form is submitted.
<form action="about:blank" method="get" target="_blank"> <quiet-tag-input name="tags" label="Favorite tricks" description="Add between two and five tricks your cat likes to do" placeholder="Add a trick" min="2" max="5" with-clear ></quiet-tag-input> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form>
Using custom validation Jump to heading
Use the setCustomValidity() method to make the tag input invalid and show a custom error
message on submit. This will override all other validation parameters. To clear the error, call the method
with an empty string.
<form action="about:blank" method="get" target="_blank" id="tag-input__custom-validation"> <quiet-tag-input name="tags" label="Dinner menu" description="Don't forget the wet food!" placeholder="Add a meal" with-clear ></quiet-tag-input> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> </form> <script type="module"> import { allDefined } from '/dist/quiet.js'; await allDefined(); const form = document.getElementById('tag-input__custom-validation'); const tagInput = form.querySelector('quiet-tag-input'); tagInput.setCustomValidity('The schedule must include "Wet food"'); tagInput.addEventListener('quiet-change', () => { const hasWetFood = tagInput.value.some( (tag) => tag.toLowerCase() === 'wet food' ); if (hasWetFood) { tagInput.setCustomValidity(''); } else { tagInput.setCustomValidity('The schedule must include "Wet food"'); } }); </script>
Styling validation Jump to heading
You can style valid and invalid tag inputs using the user-valid and
user-invalid custom states. These styles are only shown after the user interacts with
the form control or when the form is submitted.
<form action="about:blank" method="get" target="_blank" class="tag-input__validation-custom"> <quiet-tag-input name="tags" label="Required cats" placeholder="Add at least one cat" required ></quiet-tag-input> <br> <quiet-button type="submit" variant="primary">Submit</quiet-button> <quiet-button type="reset">Reset</quiet-button> </form> <style> .tag-input__validation-custom { quiet-tag-input:state(user-valid) { outline: solid 2px var(--quiet-constructive-stroke-mid); outline-offset: .5rem; } quiet-tag-input:state(user-invalid) { outline: solid 2px var(--quiet-destructive-stroke-mid); outline-offset: .5rem; } } </style>
API Jump to heading
Importing Jump to heading
The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.
To manually import <quiet-tag-input> from the CDN, use the following code.
import 'https://cdn.quietui.org/v5.0.0/components/tag-input/tag-input.js';
To manually import <quiet-tag-input> from a self-hosted distribution, use the
following code. Remember to replace /path/to/quiet with the appropriate local path.
import '/path/to/quiet/components/tag-input/tag-input.js';
Slots Jump to heading
Tag Input supports the following slots. Learn more about using slots
| Name | Description |
|---|---|
label
|
The tag input's label. For plain-text labels, use the label attribute instead.
|
description
|
The tag input's description. For plain-text descriptions, use the description attribute
instead.
|
start
|
An icon or similar element to place before the input. Works great with
<quiet-icon>.
|
end
|
An icon or similar element to place after the input. Works great with
<quiet-icon>.
|
Properties Jump to heading
Tag Input has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties
| Property | Description | Reflects | Type | Default |
|---|---|---|---|---|
query
|
The current text in the tag input's text box. Useful for reading when handling
quiet-input events. (Property only)
|
|
string
|
''
|
label
|
The tag input's label. |
|
string
|
|
description
|
The tag input's description. |
|
string
|
|
name
|
The name of the tag input for form submission. |
|
string
|
|
value
|
The tag input's value as an array of strings. Can be set via attribute as a delimiter-separated string. |
|
string[]
|
|
placeholder
|
Placeholder text for the input. |
|
string
|
|
disabled
|
Disables the tag input. |
|
boolean
|
false
|
readonly
|
Makes the tag input readonly. Tags are visible but cannot be added or removed. |
|
boolean
|
false
|
required
|
Makes the tag input required. |
|
boolean
|
false
|
appearance
|
The visual appearance of the tag input. |
|
'normal'
|
'normal'
|
size
|
The size of the tag input. |
|
'xs'
|
'md'
|
pill
|
Draws the tag input in a pill shape. |
|
boolean
|
false
|
min
|
The minimum number of tags required for validation. Set to 0 for no minimum. |
|
number
|
0
|
max
|
The maximum number of tags allowed. Set to 0 for no limit. When the limit is reached, no more tags can be added. |
|
number
|
0
|
delimiter
|
One or more characters that will create a tag when typed. For example, set
delimiter="," so typing a comma adds a tag. Each character in the string is
treated as a separate delimiter. Set to an empty string to disable delimiter-based tag creation.
|
|
string
|
','
|
form
|
The form to associate with. |
|
string
|
|
allowDuplicates
allow-duplicates
|
Allows duplicate tag values. By default, duplicate values are silently rejected. |
|
boolean
|
false
|
withClear
with-clear
|
Adds a clear button when not blank. |
|
boolean
|
false
|
inputmode
|
Provides the browser with a hint about the type of data that might be entered by the user, allowing the appropriate virtual keyboard to be displayed on supported devices. |
|
'none'
|
|
autocapitalize
|
Turns autocapitalize on or off in supported browsers. |
|
'off'
|
|
autocorrect
|
Turns autocorrect on or off in supported browsers. |
|
boolean
|
|
enterkeyhint
|
Sets the enter key label on virtual keyboards. |
|
'enter'
|
|
spellcheck
|
Turns spell checking on or off in supported browsers. |
|
boolean
|
Methods Jump to heading
Tag Input supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods
| Name | Description | Arguments |
|---|---|---|
addTag() |
Adds a tag with the given text. Returns true if the tag was added,
false otherwise.
|
text: string
|
removeTag() |
Removes a tag by its value. Removes the first occurrence if duplicates exist. Returns
true if removed.
|
value: string
|
removeTagByIndex() |
Removes a tag by its index. Returns true if removed, false if the index is
out of bounds or readonly.
|
index: number
|
hasTag() |
Returns true if a tag with the given value exists. |
value: string
|
clear() |
Removes all tags. | |
getTagValue() |
Returns the value stored for a tag given the user's typed text. Override this method to customize how typed text is transformed into a stored value (e.g., lowercasing or converting to slug). |
query: string
|
getTagContent() |
Returns the display content for a tag. Override this method to customize how tags are rendered. By default, returns the tag's value as plain text. |
value: string
|
focus() |
Sets focus to the tag input. | |
blur() |
Removes focus from the tag input. | |
checkValidity() |
Checks if the form control has any restraints and whether it satisfies them. If invalid,
false will be returned and the invalid event will be dispatched. If valid,
true will be returned.
|
|
reportValidity() |
Checks if the form control has any restraints and whether it satisfies them. If invalid,
false will be returned and the invalid event will be dispatched. In
addition, the problem will be reported to the user. If valid, true will be returned.
|
|
setCustomValidity()
|
Sets a custom validation message for the form control. If this message is not an empty string, then the form control is considered invalid and the specified message will be displayed to the user when reporting validity. Setting an empty string clears the custom validity state. | message: string |
Events Jump to heading
Tag Input dispatches the following custom events. You can listen to them the same way was native events. Learn more about custom events
| Name | Description |
|---|---|
quiet-blur |
Emitted when the tag input loses focus. |
quiet-change |
Emitted when a tag is added, removed, or cleared. |
quiet-focus |
Emitted when the tag input receives focus. |
quiet-input |
Emitted when the tag input receives input. |
quiet-create |
Emitted when a new tag is about to be created. Call event.preventDefault() to reject
the tag. The event detail contains value and
label properties.
|
CSS custom properties Jump to heading
Tag Input supports the following CSS custom properties. You can style them like any other CSS property. Learn more about CSS custom properties
| Name | Description | Default |
|---|---|---|
--text-box-min-width |
The minimum width of the input field when shown next to tags. |
12ch
|
CSS parts Jump to heading
Tag Input exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts
| Name | Description | CSS selector |
|---|---|---|
label |
The element that contains the tag input's label. |
::part(label)
|
description |
The element that contains the tag input's description. |
::part(description)
|
visual-box |
The element that wraps the internal text box. |
::part(visual-box)
|
input-area |
The wrapper surrounding tags and the internal text box. |
::part(input-area)
|
tag |
Individual tag elements. |
::part(tag)
|
tag-label |
The text label inside a tag. |
::part(tag-label)
|
tag-remove |
The remove button for tags. |
::part(tag-remove)
|
text-box |
The internal text box, an <input> element. |
::part(text-box)
|
clear-button |
The clear button. |
::part(clear-button)
|
Custom States Jump to heading
Tag Input has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states
| Name | Description | CSS selector |
|---|---|---|
disabled |
Applied when the tag input is disabled. |
:state(disabled)
|
focused |
Applied when the tag input has focus. |
:state(focused)
|
blank |
Applied when the tag input has no value. |
:state(blank)
|
user-valid |
Applied when valid after user interaction. |
:state(user-valid)
|
user-invalid |
Applied when invalid after user interaction. |
:state(user-invalid)
|
Dependencies Jump to heading
Tag Input automatically imports the following elements. Sub-dependencies are also included in this list.