Tag input โ
A multi-value tag entry with optional autocomplete suggestions, validation states, max-tags limit, and slot-overridable label/helper. Tags are added with Enter, , or Tab, and removed with ร or Backspace on an empty input. Toggle Vue / CSS to switch the live demo and source together.
Basic โ
Default tag input that accepts custom values.
Vue SFC
Sizes โ
Small, medium and large.
Vue SFC
Variants โ
outlined, filled and underlined.
underlined focuses with a soft glow under the line rather than a ring around the field โ tune it with --mono-tag-input-underline-glow (default 0 5px 6px -6px).
The tag chips follow the variant: outlined โ soft chips, filled โ solid chips (a soft chip would disappear into the tinted field), underlined โ outline chips. Pin a skin with chip.
Vue SFC
Colors โ
All built-in color variants. The tag chips are tinted with the same color โ pin them to a different one with chip.
Vue SFC
Chips โ
The tags are mono-chip markup, configured as one object so every chip prop is reachable:
vue
<mono-tag-input :chip.prop="{ size: 'md', shape: 'rounded', dot: true }" />chip takes size, color, variant, shape, dot, closeLabel and cssClass โ the same names and values as the chip component. Keys you leave out follow the control rather than a fixed default: color tracks the control's color (and any --mono-tag-input-focus-color override), and variant tracks the skin mapping above. Setting color pins the chips and stops that tracking, so a success field can carry neutral tags.
Static HTML can pass the same object as a JSON attribute: chip='{"size":"md","dot":true}'.
Vue SFC
States โ
Disabled, readonly and required.
Vue SFC
Validation โ
valid, invalid and warning states with messages.
Vue SFC
Suggestions โ
Autocomplete dropdown driven by an items array.
Vue SFC
Keyboard โ
Focusing the field opens the panel and highlights the first suggestion, so โ / โ move from there and Enter adds the highlighted one as a tag. The highlight scrolls into view on long lists, and is drawn as a leading bar on the item's left edge โ the background is reserved for a checked/selected suggestion, and the items already carry their own bottom dividers. Tune it with --mono-tag-input-cursor-width (default 3px) and --mono-tag-input-cursor-color.
open(), close(), toggle() and isOpen are public, mirroring <mono-select>, so the panel can be driven from outside (that's how the data grid opens it on Enter when a tag-input is an inline cell editor).
Max tags โ
Limit how many tags can be added.
Vue SFC
Slots โ
Custom label and helper content via named slots.
Vue SFC
Event log โ
Live log of mno-add, mno-remove, mno-clear and mno-change.
Vue SFC
Customized โ
Override per-element styling with cssClass (Vue) or utility classes (CSS).
Vue SFC
Custom keys โ
Use key-value and display-value to feed natural-shape items (for example { id, name }) without pre-mapping. key-value names the property stored in each tag of modelValue; omit it to store the whole item object. display-value is either a property name (string) or a (item) => string function โ when unset it falls back to item.label.
Without key-value each tag is the whole item, and tags are matched by identity โ that is what decides whether clicking an option selects or de-selects it. A reactive wrapper around an item is fine (the tag input compares raw targets), but an item rebuilt between renders โ a refetch, a structuredClone, a JSON round trip โ is a different object and would be added as a second tag. Pass key-value whenever items are re-created.
Vue SFC
DataSource (devextreme) โ
Bind a live devextreme DataSource with :data-source.prop. Suggestions come straight from the source, typing filters the loaded set client-side, and load-more="scroll" pages it one chunk at a time (here pageSize: 5). :immediate.prop="true" loads the first page on attach. This example builds the source with mono-utils' monoOdataFetch against a public OData endpoint (baseUrl, no configBaseUrl). Bind with .prop and use key-value / display-value to map the server fields.
Checkable + max โ
Add checkable for a checkbox multi-select: each suggestion row shows a checkbox (reusing mono-checkbox's styling), selected rows stay in the list checked instead of disappearing, and the dropdown stays open so you can tick several. Chips reuse mono-chip styling. The max prop caps how many chips show inline โ the rest collapse into a clickable "+N more" chip whose dropdown lists them. Works with a raw items array (shown here) and a bound DataSource alike.
Vue SFC
Search the server โ
Typing filters loaded suggestions; with a bound DataSource and search-value set, it queries the server (debounced) so you can tick matches from the whole dataset. A plain items array filters client-side.
Search expressions โ
search-value is not limited to top-level field names. It takes the same grammar the data grid uses, as an array or as a comma-separated string โ the two are equivalent, so plain HTML loses nothing:
html
search-value="Company.Name,Transaction.[*].Price,*.[*].*"ts
:search-value.prop="['Company.Name', 'Transaction.[1].Name', 'Transaction.[*].Price', '*']"An entry can be:
| Entry | Matches |
|---|---|
Nama | a top-level field |
Company.Name | a nested field |
Transaction.[1].Name | one array element |
Transaction.[*].Name | any element of the array |
* | every top-level field |
Company.* | every field of Company |
*.* | every field of every nested object |
*.[*].* | every field of every array element |
Patterns read literally, segment by segment โ '*' covers the top level only, so pair it with '*.*' / '*.[*].*' to reach deeper. A field named explicitly always wins over a pattern, in either order, and is searched exactly once.
In the array form an entry may also be a { field, custom } clause builder, for a column contains can't search โ a boolean, or a code the user never types. Return null to opt the column out of a given term:
ts
:search-value.prop="[
'*',
{ field: 'Active', custom: ({ field, value }) => `${field} eq ${value === 'yes'}` },
]"Setting search-value explicitly means it alone decides what is searched.
Leave it off and the default is '*' โ every top-level field of an option โ so searching works without naming anything. display-value (when it's a string) and key-value stay in the list beside it, and the rendered display text and each option's description are matched too.
Two caveats on a bound DataSource: a * pattern is resolved against the rows already loaded, so it can only see fields present in that sample; and it only emits clauses for string columns, because contains(Price,'x') is not valid OData. That is exactly why display-value / key-value remain alongside '*' โ they are explicit entries, so they still work before the first page arrives and a numeric key-value stays searchable. Give any other non-text column an explicit entry or a custom builder.
To offer no search at all, use searchable="false" rather than emptying search-value.
Vue SFC
Turning search off โ
The field is a text box by default, so searchable defaults to true. Pass searchable="false" to make it read-only: it can't be typed into, so it never filters, never queries the server, and no custom tag can be entered that way. Everything else is unchanged โ clicking opens the dropdown, arrows and Enter pick, Backspace removes the last chip.
Vue SFC
Grouped options โ
display-group is an array with one accessor per level (string field or function). Add the boolean group to bucket a paginated source client-side, or feed pre-grouped { key, items } data directly; group-sticky pins headers.
Two levels over a 1,200-row static array, load-more="scroll" revealing a chunk at a time.
Vue SFC
Pre-grouped data with custom group-key / group-items field names.
Vue SFC
Width & height โ
Set width, height, min-width, max-width, min-height or max-height โ each takes a CSS string ("320px", "80%") or a number (px). Fields are full width by default; set width to constrain.
Vue SFC
Placement โ
The suggestions panel keeps itself inside the viewport, so a field near the bottom of the page is never clipped:
flip(defaulttrue) opens the suggestions upward when there isn't room below.shift(defaulttrue) slides them horizontally so they don't overflow a screen edge.- When neither side fits the full list, it opens on the roomier side and shrinks to fit, scrolling internally. This caps
dropdownHeight/dropdownMaxHeightโ those stay the requested size whenever there is room for them.
Set :flip="false" / :shift="false" to pin the suggestions below the field.
CSS Variables โ
Vue SFC
Themed through --mono-tag-input-* custom properties (they inherit and pierce the shadow boundary); an explicit --mono-tag-input-focus-color override wins over the color prop. Re-skin globally via the --theme-* tokens.
| Variable | Default | Controls |
|---|---|---|
--mono-tag-input-focus-color | --theme-primary | Focus / hover border (set by color) |
--mono-tag-input-focus-rgb | primary rgb | Focus ring color (as r, g, b) |
--mono-tag-input-underline-glow | 0 5px 6px -6px | Underlined focus glow geometry |
--mono-tag-input-cursor-width | 3px | Keyboard-cursor bar on the highlighted suggestion |
--mono-tag-input-cursor-color | --mono-tag-input-focus-color | Colour of that bar |
--mono-tag-input-text | --theme-text | Field + label text color |
--mono-tag-input-border | --theme-border | Field border color |
--mono-tag-input-surface | --theme-surface | Dropdown surface |
--mono-tag-input-background | --theme-background | Field background base |
--mono-tag-input-success | --theme-success | Valid-state color |
--mono-tag-input-danger | --theme-danger | Invalid / required color |
--mono-tag-input-warning | --theme-warning | Warning-state color |
The tag chips are painted by chip's stylesheet, so --mono-tag-input-focus-color recolors them along with the field โ unless chip.color pins a hue, which opts them out. For finer control, set the matching --mono-chip-* variable on the field.
Types โ
Import
import { TagInputProps } from 'mono-helper'| Prop | Value | Default | Description |
|---|---|---|---|
modelValue | unknown[] | โ | Two-way bound array of selected tag values. |
value | unknown[] | โ | Selected tag values (kept in sync with modelValue). |
items | string | TagInputItem[] | โ | Suggestion items to choose from. |
dataSource | TagInputDataSource<TagInputItem> | โ | DataSource driving the suggestions; takes precedence over items. |
immediate | boolean | โ | DataSource-only: auto-load the source on attach when it has no items yet. |
loadMore | '' | 'button' | 'scroll' | boolean | โ | Incremental loading mode; enabling defaults to scroll, button opts into a button. |
pageSize | number | โ | Chunk size used when paging a plain items array (default 10). |
dropdownHeight | string | number | โ | Fixed height of the scrollable suggestions list. |
dropdownMaxHeight | string | number | โ | Max height of the scrollable suggestions list. |
stayOpen | boolean | โ | Exempt this tag-input from every automatic close โ clicking or focusing anything outside it, which includes opening another one. Not a lock: its own trigger, Escape and picking an item still close it. |
keyValue | string | โ | Property name on each item used as the stored tag value. |
displayValue | string | (item: TagInputItem) => string | โ | Property name or selector function deriving each item's display text. |
displayGroup | TagInputDisplayGroup | โ | Per-level accessors for grouped options (header label per group level). |
groupKey | string | โ | Field holding a group node's key (default 'key'). |
groupItems | string | โ | Field holding a group node's child array (default 'items'). |
group | boolean | โ | Group a plain, paginated DataSource (or flat array) client-side. |
groupSticky | boolean | โ | Keep group headers pinned to the top while their rows scroll. |
searchable | boolean | โ | Whether typing in the field searches (default `true`; `false` = read-only input). |
searchValue | string | MonoSearchExprEntry[] | โ | Field(s) the search matches (server query + client filter target). A comma string or an array; entries may be plain columns, paths (`Company.Name`, `Transaction.[*].Price`), `*` patterns (`'*'`, `'*.[*].*'`) or, in array form, `{ field, custom }` clause builders. |
searchOperation | string | โ | devextreme search operation for server search (default 'contains'). |
searchDebounce | number | โ | Debounce (ms) before a server search fires (default 300). |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl' | โ | Size of the tag input. |
color | 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | โ | Color theme of the tag input. |
variant | 'underlined' | 'outlined' | 'filled' | โ | Visual style of the tag input. |
chip | string | TagInputChipProps | โ | Tag chip configuration โ the `mono-chip` props to apply to every tag. Bind it as a real property (`:chip.prop="{ size: 'md' }"`); a plain `chip='{"size":"md"}'` JSON attribute also works for static HTML. |
label | string | โ | Text label shown above the field. |
placeholder | string | โ | Placeholder text shown when the input is empty. |
helperText | string | โ | Helper text shown below the field. |
validationState | 'warning' | 'default' | 'valid' | 'invalid' | โ | Validation state controlling field styling. |
validationMessage | string | โ | Message shown for the current validation state. |
errorMessage | string | โ | Error message that forces the invalid state. |
successMessage | string | โ | Success message that forces the valid state. |
name | string | โ | Form field name for the underlying input. |
disabled | boolean | โ | Disables interaction with the tag input. |
readonly | boolean | โ | Makes the tag input read-only. |
required | boolean | โ | Marks the field as required. |
clearable | boolean | โ | Shows a clear button to remove all tags. |
allowCustom | boolean | โ | Allows adding custom tags not present in the items. |
duplicate | boolean | โ | Allows duplicate tag values. |
maxTags | number | โ | Maximum number of tags that can be added. |
checkable | boolean | โ | Checkbox multi-select mode (selected rows stay checked, dropdown stays open). |
max | number | โ | Max chips shown inline; the rest collapse into a clickable "+N more" chip. |
ariaLabelText | string | โ | Accessible label for screen readers. |
ariaLabel | string | โ | โ |
width | string | number | โ | Explicit sizing of the field. Each accepts a CSS length string (`"320px"`, `"80%"`) or a number (interpreted as px). Use `width="100%"` for full width. (Distinct from `dropdownHeight`/`dropdownMaxHeight`, which size the popup.) |
height | string | number | โ | โ |
minWidth | string | number | โ | โ |
maxWidth | string | number | โ | โ |
minHeight | string | number | โ | โ |
maxHeight | string | number | โ | โ |
cssClass | TagInputCssClass | โ | Per-part class overrides for styling internal elements. |
visible | boolean | โ | Whether the control is shown. Defaults to `true`. |
visibleType | 'invisible' | 'none' | โ | How it hides when `visible` is `false`. Defaults to `'none'`. |