Tags Input

Production-ready tags input with extensive token integration, state management, and semantic HTML.

Overview

The Tags Input component is a core building block of the Byteion design system, providing a robust, accessibility-compliant interface for its specific UI capabilities.

Why this exists

Tags input lets users freely add custom values (not just select from a list) as discrete chips. It is the go-to pattern for labeling, keywords, and skill entries.

Mental model

A tags input converts free-text entry into discrete removable chips. Press Enter or comma to add a tag.

When to use

• Keywords or tags for blog posts or products • Skill entry in a profile • Email recipient fields • Any free-form multi-value entry

When not to use

• Do not use when values must come from a predefined list — use multi-select • Avoid for single-value entry — use a plain input

Basic example

The following example demonstrates standard usage, fully compliant with Byteion's token-first approach.

Variants

Each variant communicates a different meaning. Choose based on priority, not aesthetics.

Single default variant.

Sizes

Size should match the importance and context of the component.

  • md — md size.

States

This component reacts seamlessly to the following interaction and data states:

  • default — Resting appearance before interaction.
  • hover — Pointer is over the element — visual feedback via color or shadow.
  • focus — Keyboard or tab focus — shows ring indicator for accessibility.
  • active — Currently selected or in use.
  • disabled — Non-interactive — grayed out, cursor not-allowed.
  • loading — Action in progress — spinner replaces icon, button is disabled.
  • invalid — Input value does not match expected format.
  • error — Validation failed — red border and error message.
  • success — Validation passed — green indicator.

Anatomy

• Tag container — holds chip elements • Tag chip — removable pill • Inline input — for typing new tags • Validation message — duplicate or invalid tag warning

Usage guidelines

  • Accept Enter and comma as delimiters.
  • Prevent duplicate tags.
  • Validate format (e.g., no special characters).

Do and Don't

Do

  • Accept Enter/comma to add.
  • Prevent duplicates.
  • Validate tag format.

Don't

  • Do not allow empty tags.
  • Do not allow duplicates.
  • Do not use for predefined lists.

Accessibility

Each chip is focusable and removable. Input announces number of tags.

Role:combobox listbox

ARIA Attributes

  • aria-expanded
  • aria-activedescendant
  • role

Keyboard Navigation

  • Enter: Adds typed tag or selected suggestion
  • Comma: Adds typed tag when configured as separator
  • Backspace: Removes the last tag when input is empty
  • ArrowDown: Moves to next suggestion
  • ArrowUp: Moves to previous suggestion
  • Escape: Closes suggestions

Customization

Tag chips use badge/soft tokens.

Compose with React cva()

Use the exportedcva() +cn() utilities to compose your own variant on top of the Byteion tokens.

import { cva, cn, type VariantProps } from '@byteion/react';

const myTagsInput = cva('base classes…', {
 variants: {
  accent: { soft:'border-primary-200', loud:'border-primary-500' },
 },
 defaultVariants: { accent:'soft' },
});

type Props = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof myTagsInput>;

Compose with Vue cva()

Use the exportedcva() +cn() utilities inside standard Vue setup blocks.

<script setup lang="ts">
import { computed, useAttrs } from 'vue';
import { cva, type VariantProps } from '@byteion/vue';

interface Props { accent?:'soft' |'loud' }
const props = withDefaults(defineProps<Props>(), { accent:'soft' });
const attrs = useAttrs();

const myTagsInput = cva('base classes…', {
  variants: { accent: { soft:'border-primary-200', loud:'border-primary-500' } },
});

const cls = computed(() => myTagsInput({ accent: props.accent, class: attrs.class as string | undefined }));
</script>

Runtime events

Byteion keeps framework APIs idiomatic: HTML uses DOM custom events, React uses callback props, and Vue uses emitted events / v-model updates.

HTML / JS events

  • bi:tags-input:add
  • bi:tags-input:change
  • bi:tags-input:error
  • bi:tags-input:load
  • bi:tags-input:remove
  • bi:tags-input:search
  • bi:tags:add
  • bi:tags:change
  • bi:tags:remove

React callbacks

  • onValueChange(value: string[]) => void

Vue emits

  • update:modelValue[value: string[]]

Remote / AJAX

Remote tag suggestions

Add data-bi-source to fetch tag suggestions. When data-bi-allow-create is true, users may still create a tag that is not returned by the backend.

Attributes

  • data-bi-source
  • data-bi-search-param
  • data-bi-min-chars
  • data-bi-debounce
  • data-bi-value-field
  • data-bi-label-field
  • data-bi-allow-create
  • data-bi-name
  • data-bi-loading-text
  • data-bi-empty-text
  • data-bi-error-text

Runtime events

  • bi:tags-input:search
  • bi:tags-input:load
  • bi:tags-input:error
  • bi:tags-input:add
  • bi:tags-input:remove
  • bi:tags-input:change
Backend response: Remote endpoints must return JSON. Byteion accepts an array or an object with data, items, results, or options. Each item can be a string/number or an object; value resolves from value, id, or key, and label resolves from label, name, text, or the value. Override object fields with data-bi-value-field and data-bi-label-field.

Accessibility: loading sets aria-busy="true"; empty states use role="status"; error states use alert/status messaging where the runtime renders remote status rows.

API Reference

Requires JS for chip management.

HTML Data Attributes

No custom data attributes required.

React Props · TagsInputProps

Extracted directly fromreact/src/components/TagsInput.tsx.

export interface TagsInputProps
  extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'defaultValue' | 'onChange' | 'size'> {
  /** Controlled list of tags. */
  value?: string[];
  defaultValue?: string[];
  onValueChange?: (value: string[]) => void;
  /** Optional label rendered above the field. */
  label?: ReactNode;
  /** Helper / error / success text below the field. */
  helperText?: ReactNode;
  error?: ReactNode;
  success?: ReactNode;
  /** Render the field in a loading state (input disabled, spinner inline). */
  loading?: boolean;
  /** Keys that commit the current input. Default: Enter + comma. */
  commitKeys?: string[];
  /** Reject duplicate tags. Default true. */
  unique?: boolean;
  /** Max number of tags allowed. */
  max?: number;
  /** Transform a raw input string before committing (e.g. trim, slugify). */
  transform?: (raw: string) => string;
  /** Validate a tag before committing. Return false to reject. */
  validate?: (tag: string, existing: string[]) => boolean;
}

Vue Props · TagsInputProps

Extracted directly fromvue/src/components/TagsInput.vue.

export interface TagsInputProps {
  /** Controlled list of tags. */
  modelValue?: string[];
  /** Initial list of tags when uncontrolled. */
  defaultValue?: string[];
  /** Label rendered above the field. */
  label?: string;
  helperText?: string;
  error?: string;
  success?: string;
  loading?: boolean;
  /** Keys that commit the current input. Default: Enter + comma. */
  commitKeys?: string[];
  /** Reject duplicate tags. Default true. */
  unique?: boolean;
  /** Max number of tags allowed. */
  max?: number;
  /** Transform a raw input string before committing (e.g. trim, slugify). */
  transform?: (raw: string) => string;
  /** Validate a tag before committing. Return false to reject. */
  validate?: (tag: string, existing: string[]) => boolean;
  disabled?: boolean;
  placeholder?: string;
  id?: string;
}

Developer tips

• Edge case: handle paste — split comma-separated pasted text into individual tags.

Common mistakes

Avoid hardcoded neutral colors, placeholder-only labels, duplicated primary actions, and missing keyboard states. Keep this component on Byteion tokens so dashboard, admin, POS, ERP, ecommerce back-office, Laravel, React, and Vue starter-kit screens can be rebranded without rewriting markup.

Production usage tips

Use the canonical HTML as the source of truth, keep React and Vue wrappers aligned with the documented variants, test dark mode and branded themes before release, and wire interactive behavior through data-bi-* attributes instead of styling hooks.

Premium examples

Advanced patterns available in Byteion Pro:

• Autocomplete suggestions while typing tags • Drag-to-reorder tags

Unlock Premium Patterns

Get access to copy-paste ready Pro blocks, SaaS templates, and advanced data-tables built with this component.

Explore Pro Components