JaleelB/emblor

A fully-featured tag input component built with shadcn/ui

TypeScript

1,215

426 commits

updated Sep 23, 2026

See the code

README

Emblor

Emblor v2 is a headless tag-input primitive. It owns tag and draft state, keyboard behavior, validation, focus coordination, native forms, and accessible announcements. Consumers own markup and styling.

import {
  EmblorClear,
  EmblorInput,
  EmblorLabel,
  EmblorRoot,
  EmblorTag,
  EmblorTagList,
  EmblorTagRemove,
  EmblorTagText,
} from 'emblor';

<EmblorRoot defaultValue={['react']} name="skills">
  <EmblorLabel>Skills</EmblorLabel>
  <EmblorTagList>
    {(tag, index) => (
      <EmblorTag key={tag} index={index}>
        <EmblorTagText />
        <EmblorTagRemove />
      </EmblorTag>
    )}
  </EmblorTagList>
  <EmblorInput placeholder="Add a skill" />
  <EmblorClear>Clear</EmblorClear>
</EmblorRoot>;

Import all supported parts from the package root. The compound API requires exactly one EmblorInput; EmblorTagList is optional. Use value/onValueChange or defaultValue for string[] tags. Draft control, when needed, lives on Root through inputValue, defaultInputValue, and onInputValueChange.

Enter commits, literal delimiters default to [','], addOnTab opts into Tab commits, addOnPaste defaults to true, and blurBehavior defaults to 'noop'. transform runs before length, duplicate, capacity, and boolean validate checks. onReject receives structured rejection details; pasted values are evaluated left-to-right and accepted in one batch transition.

With name, committed tags submit as ordered repeated native form values. required means at least one committed tag. Labels associate automatically, actions remain accessible under as polymorphism, and every part forwards applicable DOM/ARIA/data/style/event props. Consumers own React keys and optional tag IDs. The example uses the value as its key because duplicates are disabled; consumers enabling duplicates should maintain stable occurrence IDs alongside their string[].

The package intentionally excludes autocomplete, cmdk, popovers, sorting, drag-and-drop, Tailwind, CVA, and styling runtimes. See packages/emblor/README.md for the full contract and packages/emblor/MIGRATION.md for v1 migration.

autocomplete
input
popover
radix
react-tag-input
shadcn-ui
tag-input

JaleelB/emblor

A fully-featured tag input component built with shadcn/ui

TypeScript

1,215

426 commits

updated Sep 23, 2026

See the code

README

Emblor

Emblor v2 is a headless tag-input primitive. It owns tag and draft state, keyboard behavior, validation, focus coordination, native forms, and accessible announcements. Consumers own markup and styling.

import {
  EmblorClear,
  EmblorInput,
  EmblorLabel,
  EmblorRoot,
  EmblorTag,
  EmblorTagList,
  EmblorTagRemove,
  EmblorTagText,
} from 'emblor';

<EmblorRoot defaultValue={['react']} name="skills">
  <EmblorLabel>Skills</EmblorLabel>
  <EmblorTagList>
    {(tag, index) => (
      <EmblorTag key={tag} index={index}>
        <EmblorTagText />
        <EmblorTagRemove />
      </EmblorTag>
    )}
  </EmblorTagList>
  <EmblorInput placeholder="Add a skill" />
  <EmblorClear>Clear</EmblorClear>
</EmblorRoot>;

Import all supported parts from the package root. The compound API requires exactly one EmblorInput; EmblorTagList is optional. Use value/onValueChange or defaultValue for string[] tags. Draft control, when needed, lives on Root through inputValue, defaultInputValue, and onInputValueChange.

Enter commits, literal delimiters default to [','], addOnTab opts into Tab commits, addOnPaste defaults to true, and blurBehavior defaults to 'noop'. transform runs before length, duplicate, capacity, and boolean validate checks. onReject receives structured rejection details; pasted values are evaluated left-to-right and accepted in one batch transition.

With name, committed tags submit as ordered repeated native form values. required means at least one committed tag. Labels associate automatically, actions remain accessible under as polymorphism, and every part forwards applicable DOM/ARIA/data/style/event props. Consumers own React keys and optional tag IDs. The example uses the value as its key because duplicates are disabled; consumers enabling duplicates should maintain stable occurrence IDs alongside their string[].

The package intentionally excludes autocomplete, cmdk, popovers, sorting, drag-and-drop, Tailwind, CVA, and styling runtimes. See packages/emblor/README.md for the full contract and packages/emblor/MIGRATION.md for v1 migration.

autocomplete
input
popover
radix
react-tag-input
shadcn-ui
tag-input

Project health

Latest release

1.4.8 · Mar 28, 2025

Releases this year

0

Significant stargazers

Renée

499 followers · starred Aug 2024

Steven Tey

6,153 followers · starred Nov 2024

Railly Hugo

414 followers · starred Mar 2024

Travis Van Nimwegen

426 followers · starred Sep 2024