# Migration Guide

This guide helps you migrate from existing tagging libraries to taga11y. It covers API mapping, DOM structure differences, and accessibility improvements.

## From Tagify

### Initialization

**Tagify:**
```js
const tagify = new Tagify(inputEl, {
  whitelist: ['JavaScript', 'TypeScript', 'Rust'],
  maxTags: 10,
});
```

**taga11y:**
```js
const widget = new Taga11y(inputEl, {
  suggestions: ['JavaScript', 'TypeScript', 'Rust'],
  maxTags: 10,
});
```

### Adding a tag

**Tagify:**
```js
tagify.add({ label: 'Rust', value: 'rust' });
```

**taga11y:**
```js
widget.addTag('rust');
```

### Getting tags

**Tagify:**
```js
console.log(tagify.value); // Array of tag objects
```

**taga11y:**
```js
console.log(widget.tags);  // [{ id, label, value }, ...]
console.log(widget.getTags()); // Same as .tags
```

### Removing a tag

**Tagify:**
```js
tagify.removeTags('rust');
```

**taga11y:**
```js
widget.removeTag('rust');
```

### Clearing all tags

**Tagify:**
```js
tagify.clear();
```

**taga11y:**
```js
widget.clearTags();
```

### Destroying the instance

**Tagify:**
```js
tagify.destroy();
```

**taga11y:**
```js
widget.destroy();
```

### Listening for events

**Tagify:**
```js
tagify.on('add', (e) => console.log(e.detail.value));
tagify.on('remove', (e) => console.log(e.detail.value));
```

**taga11y:**
```js
widget.on('taga11y:add', (e) => console.log(e.detail.tag));
widget.on('taga11y:remove', (e) => console.log(e.detail.tag));
widget.on('taga11y:clear', (e) => console.log(e.detail.tags));
widget.on('taga11y:change', (e) => console.log(e.detail.tags));
widget.on('taga11y:paste', (e) => console.log(e.detail.added, e.detail.skipped));
widget.on('taga11y:destroy', (e) => console.log(e.detail));
```

### Key differences

| Feature | Tagify | taga11y |
|---|---|---|
| ARIA pattern | Partial implementation | Full WAI-ARIA APG combobox |
| Screen reader support | Inconsistent across ATs | Designed for all major ATs |
| Focus management | Moves focus into listbox | Keeps focus on input (aria-activedescendant) |
| Event names | `add`, `remove`, `clear` | `taga11y:add`, `taga11y:remove`, `taga11y:clear` |
| Dynamic suggestions | Built-in `fetch` | User-provided callback (full control) |
| Whitelist mode | `enforceUsers` / `mode` | `enforceSuggestions: true` |
| Delimiters | `delimiters` option | `delimiter` option (single char or array) |
| Theming | CSS classes | CSS custom properties |
| Progressive enhancement | Wraps input | Wraps input (same approach) |

## From Choices.js

### Initialization

**Choices.js:**
```js
const choices = new Choices(inputEl, {
  items: [{ value: 'js', label: 'JavaScript' }],
  renderChoiceLimit: 10,
});
```

**taga11y:**
```js
const widget = new Taga11y(inputEl, {
  suggestions: [{ label: 'JavaScript', value: 'js' }],
  // 10-item limit is always enforced (no option needed)
});
```

### Adding items

**Choices.js:**
```js
choices.addItems(['js', 'ts']);
```

**taga11y:**
```js
widget.addTags([{ label: 'JavaScript', value: 'js' }, { label: 'TypeScript', value: 'ts' }]);
```

### Getting items

**Choices.js:**
```js
console.log(choices.getValue()); // Array of selected values
```

**taga11y:**
```js
console.log(widget.tags);  // [{ id, label, value }, ...]
```

### Destroying

**Choices.js:**
```js
choices.destroy();
```

**taga11y:**
```js
widget.destroy();
```

### Key differences

| Feature | Choices.js | taga11y |
|---|---|---|
| ARIA pattern | Select-like with listbox | WAI-ARIA APG combobox |
| Input behavior | Replaces input with custom element | Wraps input, keeps it as real `<input>` |
| Keyboard navigation | Limited | Full (Arrow keys, Home, End, Enter, Escape) |
| Screen reader | Inconsistent | Designed for all major ATs |
| Free text | Limited support | Full free-text mode |
| Delimiters | Not supported | Supported (comma, Enter, custom) |
| Bundle size | Larger | Smaller (focused scope) |

## DOM Structure Differences

taga11y wraps the original input in a `<div class="taga11y">` and updates the input's attributes in place. On destroy, the input is restored to its original state and position.

**taga11y DOM structure:**
```html
<div class="taga11y">
  <label class="taga11y__label" for="tags">Tags</label>
  <div class="taga11y__tags">
    <ul class="taga11y__tag-list" aria-label="Selected tags">
      <li class="taga11y__tag" role="listitem">
        <span class="taga11y__tag-label">JavaScript</span>
        <button class="taga11y__tag-remove" type="button" aria-label="Remove JavaScript">&times;</button>
      </li>
    </ul>
    <input type="text" class="taga11y__input" id="tags"
           role="combobox" aria-autocomplete="list"
           aria-haspopup="listbox" aria-expanded="false"
           aria-controls="taga11y-tags-listbox" aria-activedescendant="">
  </div>
  <ul class="taga11y__listbox" id="taga11y-tags-listbox" role="listbox" hidden>
    <li class="taga11y__option" role="option" id="taga11y-tags-option-0">Go</li>
  </ul>
  <div class="taga11y__loading" aria-hidden="true" hidden>
    <span class="taga11y__loading-spinner"></span>
    <span class="taga11y__loading-text">Loading suggestions…</span>
  </div>
  <div class="taga11y__error" role="alert" hidden></div>
  <div class="taga11y__announcer" aria-live="polite" aria-atomic="true"></div>
  <input type="hidden" class="taga11y__hidden" name="tags" value="javascript">
</div>
```

## Accessibility Improvements

Compared to Tagify and Choices.js, taga11y provides:

1. **Correct ARIA combobox implementation** — Uses `aria-activedescendant` to keep focus on the input while navigating suggestions, matching the WAI-ARIA APG canonical pattern.
2. **Dual announcement channels** — Polite `aria-live` region for routine changes, assertive `role="alert"` region for errors. Both never fire simultaneously.
3. **Complete keyboard navigation** — ArrowDown/Up, Home/End, Enter, Escape, Tab, Backspace all work as expected.
4. **No focus traps** — Tab and Shift+Tab move focus naturally in and out of the component.
5. **Reduced motion support** — All animations disabled when `prefers-reduced-motion: reduce` is active.
6. **Voice control compatible** — Descriptive `aria-label` on chip remove buttons for voice targeting.
7. **WCAG 2.1 AA conformance** — Color contrast, focus indicators, and keyboard operability meet WCAG AA thresholds.
