taga11y - v0.1.0
    Preparing search index...

    taga11y - v0.1.0

    taga11y

    Accessibility-first tagging / multi-select input library for the web.

    taga11y provides an accessible combobox component with inline chips, keyboard navigation, screen reader announcements, and native form integration. It follows the WAI-ARIA APG combobox pattern exactly, with aria-activedescendant keeping focus on the input during dropdown navigation.

    • Accessible by default — full WAI-ARIA APG combobox pattern, screen reader announcements, keyboard and switch device support
    • Progressive enhancement — the original <input> is enhanced in place and works as a form control without JavaScript
    • Three suggestion modes — static arrays, pre-fetched async, and dynamic per-keystroke callbacks
    • Whitelist mode — restrict to predefined suggestions with enforceSuggestions: true
    • Configurable — delimiters, max tags, debounce, theming, custom serializers
    • Dark mode — automatic (prefers-color-scheme) or forced (data-theme)
    • CSS custom properties — retheme from ~6 base tokens; 9 derived tokens cascade automatically (per-token opt-out preserved)
    • Native form integration — hidden input with serialised values, form reset support
    • Zero dependencies — bundles to a single ESM/CJS/IIFE file via Vite
    npm install taga11y
    
    import Taga11y from 'taga11y';
    import 'taga11y/dist/taga11y.css';

    const widget = new Taga11y(inputEl, {
    suggestions: ['JavaScript', 'TypeScript', 'Rust'],
    maxTags: 10,
    });
    <script src="https://unpkg.com/taga11y/dist/taga11y.iife.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/taga11y/dist/taga11y.css">

    <script>
    const widget = new Taga11y(inputEl, {
    suggestions: ['JavaScript', 'TypeScript'],
    });
    </script>
    <label for="tags">Select tags:</label>
    <input id="tags" type="text">
    import Taga11y from 'taga11y';
    import 'taga11y/dist/taga11y.css';

    const input = document.querySelector('#tags');
    const widget = new Taga11y(input, {
    suggestions: [
    'JavaScript',
    'TypeScript',
    'Rust',
    'Go',
    'Python',
    ],
    maxTags: 10,
    delimiter: [',', 'Enter'],
    });

    All options are optional.

    Option Type Default Description
    suggestions SuggestionItem[] | { once } | { query } Suggestion source: static array, pre-fetched async ({ once: () => Promise<SuggestionItem[]> }), or dynamic per-keystroke ({ query: (input, signal) => Promise<SuggestionItem[]> }). Omit for free-text mode.
    maxTags number Maximum number of tags. No limit when omitted.
    delimiter string | string[] [',', 'Enter'] Character(s) that commit the current input as a tag. 'Tab' is a valid value.
    enforceSuggestions boolean false When true, only suggestions from the source can be committed. Free-text is rejected.
    name string inherited from input.name name on the hidden form input. The original input's name is removed on init (prevents double submission) and restored on destroy(). Override only when you need a different name.
    label string Injects a <label> inside the widget wrapper. Only use when no page-level <label for="…"> exists — existing page labels work automatically via the preserved id. Do not combine both.
    disabled boolean false Renders the component in a disabled state.
    theme 'dark' | 'light' | null null Forces a colour scheme. null follows prefers-color-scheme.
    serialize (tags: TagData[]) => string comma-join values Custom serializer for the hidden input value.
    deserialize (raw: string) => SuggestionItem[] split on ,, trim, drop empties Custom parser for the original input's value on init and on form reset. Pair with serialize to round-trip a non-comma format (e.g. JSON). String items resolve labels from loaded suggestions; { label, value } items are used as-is.
    debounceMs number 200 Debounce delay (ms) for dynamic suggestion requests. Negative values are clamped to 0.
    i18n { locale: string; dir?: 'ltr' | 'rtl'; strings?: Partial<I18nStrings> } Internationalisation. locale is a BCP 47 tag; dir (optional) stamps direction on the wrapper, otherwise it cascades; strings partially overrides the built-in English map (missing keys fall back to English with a dev console.warn). Init-only — ignored by settings(); switch locale via destroy() + new Taga11y(). See the i18n guide.

    The widget dispatches custom events on the original <input> element. All events bubble, are non-cancelable, and carry a detail payload. Use widget.on(name, handler) or inputEl.addEventListener(name, handler).

    Event Detail When fired
    taga11y:add { tag: TagData } After a single tag is added (typing, suggestion select, addTag, addTags, or each chunk of a delimited paste).
    taga11y:remove { tag: TagData } After a tag is removed (chip button, Backspace on empty input, or removeTag).
    taga11y:clear { tags: TagData[] } After all tags are cleared via clearTags or setTags (fired before the new tags are added).
    taga11y:change { tags: TagData[] } After any mutation, with the final tag set. Fired once per addTags / setTags / delimited paste, after all per-chunk taga11y:add events.
    taga11y:paste { added: TagData[], skipped: string[] } Once after a paste gesture that contained a configured single-character delimiter. skipped lists chunks rejected (not in suggestion list in whitelist mode, already selected, or maxTags reached). Not fired for paste without a delimiter.
    taga11y:destroy {} After destroy() tears down the widget.

    See docs/guides/events.md for full per-event reference and examples.

    Full API documentation with all classes, methods, types, and options is generated by TypeDoc and available at /docs/api.

    • Taga11y class — constructor, methods, computed getters
    • TypesTagData, Taga11yOptions, SuggestionsSource, SuggestionItem

    Guides for contributors verifying and extending taga11y:

    See the examples/ directory for runnable demos:

    Run the examples locally:

    npm run dev
    

    MIT