# @bjjnarola/components — Component & Testing Matrix

This directory contains the Lit Web Components for the **Enetworks Design System (EDS)**. All components are built as standard Web Components (Custom Elements) with native form integration (`ElementInternals`), accessibility compliance (WCAG 2.2 AA / W3C APG patterns), and full design token integration.

---

## 📋 Component Specification & Testing Matrix

Below is the complete inventory of all 35 components in the EDS package, detailing their features to implement and the exact testing requirements (Unit, Accessibility, and Keyboard/Interaction).

### 1. Form Components

| Component | Tag | Features to Implement | What to Test |
|---|---|---|---|
| **Button** | `<eds-button>` | • Variants: `primary`, `secondary`, `outline`, `ghost`, `danger`, `link`<br>• Sizes: `s`, `m`, `l`<br>• States: `disabled`, `loading` (`aria-busy` + spinner)<br>• Anchor mode (`href` & `target` renders `<a>`) <br>• Slots: `start`, `end`, default | • Renders `<button>` or `<a>` based on `href`<br>• Click event disabled when `disabled` or `loading`<br>• `aria-busy="true"` in loading state<br>• Enter / Space key triggers click<br>• Focus outline visible on `:focus-visible` |
| **Icon Button** | `<eds-icon-button>` | • Mandatory `label` attribute (maps to `aria-label`)<br>• Variants: `primary`, `secondary`, `outline`, `ghost`, `danger`<br>• Sizes: `s`, `m`, `l`<br>• Disabled & loading states<br>• Min target size ≥24px (36-40px touch) | • Dev warning / lint if `label` is missing<br>• `aria-label` set on internal button<br>• Click event emitted when enabled<br>• Target size meets minimum hit area requirements |
| **Button Group** | `<eds-button-group>` | • Joined borders & collapsed inner radii<br>• Group-level size (`s`, `m`, `l`) cascaded to children<br>• Orientations: `horizontal`, `vertical`<br>• ARIA `role="group"` / `role="toolbar"`<br>• Roving tabindex in toolbar mode | • Cascades size prop to nested `eds-button` elements<br>• Correct radii collapse on first/last child<br>• Arrow key navigation in toolbar mode<br>• `role="group"` / `role="toolbar"` attribute presence |
| **Input** | `<eds-input>` | • Form-associated (`ElementInternals.setFormValue`)<br>• Types: `text`, `email`, `password`, `tel`, `url`, `search`, `number`<br>• Description & error slot wiring (`aria-describedby`)<br>• Invalid state (`aria-invalid`) & required mark | • Form value submission & reset via `ElementInternals`<br>• `aria-invalid="true"` set on error<br>• Linkage of `aria-describedby` to hint/error IDs<br>• Emission of `input` and `change` events |
| **Textarea** | `<eds-textarea>` | • Form-associated (`ElementInternals`)<br>• Autogrow option (auto-expands with content)<br>• `rows`, `cols`, `maxlength` properties<br>• Description & error slot integration | • Height recalculation when autogrow is true<br>• Form value collection on submission<br>• `aria-describedby` & `aria-invalid` wiring<br>• Maxlength character constraint enforcement |
| **Input Group** | `<eds-input-group>` | • Prepend / append slots for text, icons, buttons<br>• Presentations: `segmented` (joined borders) & `seamless`<br>• Auto-calculation of border radii for children<br>• Validation border rendering across whole group | • Radii adjustment on child slot change<br>• Segmented vs. seamless CSS class application<br>• Focus ring encircles group or control properly<br>• Event bubbling from internal controls |
| **Checkbox** | `<eds-checkbox>` | • States: `checked`, `indeterminate`, `disabled`<br>• Label slot & custom value<br>• Form-associated (`ElementInternals`) | • Toggle state on click & Space key<br>• Indeterminate rendering & `aria-checked="mixed"`<br>• `eds-change` custom event dispatch<br>• Form data inclusion when checked |
| **Checkbox Group** | `<eds-checkbox-group>` | • Array value binding (`value[]`)<br>• Cascades `disabled` & `name` to child checkboxes<br>• Orientations: `horizontal`, `vertical`<br>• Form-associated multi-value FormData emission | • Child checkbox selection updates group value array<br>• Form value syncs FormData with multiple entries<br>• `eds-change` fired with updated array<br>• Orientation layout classes |
| **Radio** | `<eds-radio>` | • Single radio option with value & label<br>• States: `checked`, `disabled`<br>• Button appearance support (`appearance="button"`) | • Selection toggle triggers `eds-change`<br>• Button appearance styling & border collapse<br>• Tabindex management (`0` when checked, `-1` otherwise) |
| **Radio Group** | `<eds-radio-group>` | • APG Radio Group pattern (roving tabindex + Arrow keys)<br>• `appearance="button"` renders as joined button group<br>• Single selected value<br>• Orientations: `horizontal`, `vertical` | • Arrow keys (Up/Down/Left/Right) move selection & focus<br>• Only one radio option is selected at a time<br>• `role="radiogroup"` attribute presence<br>• Form submission sends active value |
| **Switch** | `<eds-switch>` | • `role="switch"` semantics<br>• States: `checked`, `disabled`<br>• Animated toggle thumb<br>• Label slot integration | • `role="switch"` & `aria-checked` reflection<br>• Space and Enter key toggle state<br>• Click event toggles `checked` property<br>• Disabled state prevents toggle |
| **Select** | `<eds-select>` | • APG Combobox + Listbox pattern<br>• Single & multi-select modes<br>• Popover API listbox overlay<br>• Typeahead search filtering<br>• `aria-activedescendant` on highlighted option | • Arrow Up/Down navigation through options<br>• Enter selects option; Escape closes listbox<br>• Multi-select renders checkmarks & chip summary<br>• `aria-expanded` reflects open/closed state |
| **Autocomplete** | `<eds-autocomplete>` | • APG Editable Combobox pattern<br>• Asynchronous option loading with debounce<br>• Active descendant highlighting<br>• Clear button option | • Debounced input event triggers option fetch<br>• Arrow keys navigate filtered suggestions<br>• Selection populates input & emits `eds-select`<br>• Escape closes options overlay |
| **Field** | `<eds-field>` | • Composition wrapper for controls<br>• Renders label, required asterisk (`*`), hint, & error<br>• Auto-generates IDs & wires `for`, `aria-describedby`, `aria-invalid` | • Automatic linking of `<label for="...">` to control ID<br>• Correct concatenation of `aria-describedby` IDs<br>• Mutates `aria-invalid` and `required` on slotted control<br>• Slot change listener re-wires control |
| **File Upload** | `<eds-file-upload>` | • Drag & drop dropzone + file browser trigger<br>• Multiple files & `accept` MIME filtering<br>• Per-file progress & error display<br>• Keyboard accessible dropzone | • Dragover / dragleave visual class toggles<br>• File drop event validates size & type<br>• Space/Enter opens native file picker<br>• Delete button removes file & updates list |
| **Date Picker** | `<eds-datepicker>` | • Intl-based date parsing & formatting<br>• APG Date Picker dialog grid pattern<br>• Fast month/year dropdown selectors<br>• Precision modes: `day`, `month`, `year` | • Arrow keys navigate days/weeks in grid<br>• Month/Year header selects re-render grid directly<br>• Manual text entry validates date string<br>• Emits formatted `YYYY-MM-DD` string |
| **Date Range** | `<eds-date-range>` | • Dual-month calendar grid<br>• First click selects start date, second sets end date<br>• Endpoint highlighting & range span background tint | • First click sets start date; second sets end date<br>• Hover highlights prospective range span<br>• Selection emits `{ start, end }` object<br>• Keyboard navigation spans both month grids |
| **Time Picker** | `<eds-timepicker>` | • Hour:Minute input with scrollable time slot listbox<br>• Custom step intervals (e.g. 15m, 30m)<br>• Format 12h / 24h support | • Clicking trigger opens scrollable time listbox<br>• Manual input parses and formats valid time<br>• Arrow keys navigate time slot listbox<br>• Emits `HH:mm` format string |
| **Date Time Picker**| `<eds-datetime-picker>`| • Combined date calendar grid & time slot listbox<br>• Emits ISO 8601 string (`YYYY-MM-DDTHH:mm`) | • Synchronized date pick & time pick<br>• ISO 8601 value emission on selection<br>• Keyboard focus moves between grid & time list |

---

### 2. Data Display & Typography

| Component | Tag | Features to Implement | What to Test |
|---|---|---|---|
| **Table** | `<eds-table>` | • Semantic `<table>` rendering<br>• Sortable column headers with `aria-sort`<br>• Sticky header option<br>• Selection column with tri-state header checkbox | • `aria-sort` toggles (`ascending`, `descending`, `none`)<br>• Header checkbox toggles all row selections<br>• Sort button click fires `eds-sort` event<br>• Responsive horizontal scrolling on overflow |
| **Pagination** | `<eds-pagination>` | • `<nav aria-label="Pagination">`<br>• Page size selector dropdown<br>• Ellipsis calculation for large page counts<br>• Prev / Next navigation buttons | • Page calculation & ellipsis insertion<br>• Click on page number fires `eds-page-change`<br>• `aria-current="page"` applied to active page button<br>• Prev disabled on page 1, Next on last page |
| **Badge** | `<eds-badge>` | • Appearances: `text`, `count`, `dot`<br>• Variants: `default`, `neutral`, `info`, `success`, `warning`, `danger`<br>• Non-interactive base (not focusable)<br>• Optional dismiss button with `aria-label` | • Non-focusable by default (removed from tab order)<br>• Dismiss button click fires `eds-dismiss`<br>• Text, count, and dot appearance styles<br>• Status color token mapping |
| **Chip** | `<eds-chip>` | • Variants: `selectable`, `dismissible`<br>• Color variants & icon slot<br>• Keyboard operable dismiss button | • Selectable chip toggles selected state & fires `eds-change`<br>• Dismissible chip button fires `eds-dismiss`<br>• Keyboard Enter/Space on dismiss button<br>• Focus ring on focusable element |
| **Card** | `<eds-card>` | • Slot structure: `header`, `media`, default (body), `footer`<br>• Interactive mode (renders clickable card)<br>• Card Select (`eds-card-select`) with `aria-pressed` | • Slot content distribution<br>• Interactive card click fires `eds-click`<br>• `eds-card-select` toggles `aria-pressed`<br>• `href` prop renders as clickable `<a>` |
| **Avatar** | `<eds-avatar>` | • Image source with initials fallback<br>• Sizes: `xs`, `s`, `m`, `l`, `xl`<br>• Status dot indicator (online, offline, busy) | • Image load error falls back to initials<br>• Initials derived from `name` prop (e.g. "John Doe" → "JD")<br>• Status dot color rendering<br>• Custom fallback icon when no name provided |
| **Icon** | `<eds-icon>` | • SVG icon registry rendering<br>• Decorative (`aria-hidden="true"`) by default<br>• Informational when `label` provided (`role="img"` + `aria-label`) | • Renders correct SVG element for valid name<br>• Sets `aria-hidden="true"` when no label<br>• Sets `role="img"` & `aria-label` when label given<br>• Graceful fallback for missing icon name |

---

### 3. Navigation & Layout

| Component | Tag | Features to Implement | What to Test |
|---|---|---|---|
| **Header** | `<eds-header>` | • Landmark `<header>` element<br>• Slots: `logo`, `nav`, `search`, `actions`<br>• Responsive container queries | • Renders semantic `<header>` landmark<br>• Slots position correctly<br>• Responsive sticky / fixed positioning |
| **Sidebar** | `<eds-sidebar>` | • Multi-level navigation tree<br>• Collapsible rail mode with toggle<br>• `aria-current="page"` on active item<br>• Sub-menu disclosure expansion | • Expand / collapse toggle updates rail mode<br>• Sub-menu click toggles disclosure panel<br>• `aria-current="page"` set on active link<br>• Keyboard navigation through menu items |
| **Breadcrumb** | `<eds-breadcrumb>` | • `<nav aria-label="breadcrumb">`<br>• Ordered list (`<ol>`) of items<br>• Custom separator slot<br>• `aria-current="page"` on current (last) item | • Nav landmark & `aria-label` presence<br>• Last item has `aria-current="page"`<br>• Separators rendered between items<br>• Link target redirection |
| **Tabs** | `<eds-tabs>` | • APG Tabs pattern (roving tabindex)<br>• Left / Right / Home / End key navigation<br>• `role="tablist"`, `role="tab"`, `role="tabpanel"`<br>• Automatic vs. manual tab activation | • Arrow keys switch active tab & focus<br>• Home / End key jumps to first / last tab<br>• `aria-selected="true"` updated on active tab<br>• Corresponding tabpanel displayed, others hidden |
| **Stepper** | `<eds-stepper>` | • Ordered list (`<ol>`) of steps<br>• States: `completed` (check icon), `current` (`aria-current="step"`), `upcoming`<br>• Connector lines between step nodes<br>• Optional button navigation for completed steps | • Render correct state icon & label styling<br>• `aria-current="step"` set on active step<br>• Clicking completed step emits `eds-step-click`<br>• Connector line highlight up to active step |

---

### 4. Feedback & Overlays

| Component | Tag | Features to Implement | What to Test |
|---|---|---|---|
| **Alert** | `<eds-alert>` | • Severities: `info`, `success`, `warning`, `danger`<br>• Title & message slots<br>• Severity icon mapping<br>• Dismissible button with `aria-label` | • Severity icon & border color mapping<br>• Dismiss button click fires `eds-dismiss`<br>• Dynamically inserted alert sets `role="alert"`<br>• Title and content slot rendering |
| **Toast** | `<eds-toast>` | • Managed by `ToastController` singleton<br>• Severities & auto-dismiss duration<br>• Pause timer on hover / focus<br>• Live region announcement (`polite` / `assertive`) | • Auto-dismiss timer closes toast after duration<br>• Hover / focus pauses dismissal timer<br>• `aria-live` attribute set (`polite` vs `assertive`)<br>• Deduplication key prevents duplicate toasts |
| **Modal / Dialog** | `<eds-modal>` | • Native `<dialog>` element<br>• Focus trap inside dialog<br>• Escape key & backdrop click close<br>• Returns focus to trigger element on close | • `showModal()` opens modal with backdrop<br>• Tab key stays trapped inside modal<br>• Escape key closes modal & restores focus<br>• Header, body, & footer slots render |
| **Drawer** | `<eds-drawer>` | • Side panel overlay using native `<dialog>`<br>• Positions: `start` (left), `end` (right)<br>• Focus trap & Escape key dismissal<br>• Returns focus to trigger element | • Slide-in animation & position class<br>• Focus trap active while open<br>• Escape key & scrim click close drawer<br>• Restores focus to trigger button |
| **Tooltip** | `<eds-tooltip>` | • Trigger on hover & focus<br>• Positions: `top`, `bottom`, `left`, `right`<br>• `aria-describedby` linking trigger to tooltip<br>• Escape key dismissible | • Mouseenter & focusin show bubble<br>• Mouseleave & focusout hide bubble<br>• Escape key hides active tooltip<br>• `aria-describedby` set on trigger slot |
| **Popover** | `<eds-popover>` | • Native Popover API integration<br>• Trigger button toggle<br>• Light dismiss (click outside / Escape)<br>• `aria-expanded` state on trigger | • Trigger click toggles popover visibility<br>• Click outside closes popover<br>• `aria-expanded` synced with open state<br>• Focus management inside popover |
| **Accordion** | `<eds-accordion>` | • Disclosure pattern (native `<details>`/`<summary>` or APG)<br>• Expand / collapse toggle<br>• `aria-expanded` state<br>• Single-expand accordion group mode | • Header click / Enter / Space toggles content<br>• `aria-expanded` reflects open state<br>• Accordion group closes siblings in single-expand mode<br>• Smooth height animation |
| **Spinner** | `<eds-spinner>` | • `role="status"` live region<br>• Loading label for screen readers<br>• Minimum display time (500ms) to prevent flicker<br>• Respects `prefers-reduced-motion` | • `role="status"` & `aria-label="Loading"` present<br>• 500ms minimum display debounce time<br>• Motion paused when `prefers-reduced-motion` active<br>• Size variants (`s`, `m`, `l`) |
| **Progress** | `<eds-progress>` | • `role="progressbar"`<br>• `value` & `max` properties<br>• Indeterminate progress animation state<br>• `aria-valuenow`, `aria-valuemin`, `aria-valuemax` | • `role="progressbar"` attribute present<br>• `aria-valuenow` updates with `value` prop<br>• Indeterminate state removes `aria-valuenow`<br>• Accessible percentage text calculation |

---

## 🧪 Testing Methodology & Commands

### 1. Unit & Component Testing (Vitest)
Unit tests verify component state, prop reflection, event emission, shadow DOM ARIA wiring, and slot rendering using Vitest in a JSDOM environment.

#### 📌 Running Tests from Monorepo Root (`d:\LIVE_PROJECTS\EDS`)
```bash
# Run unit tests for all components
pnpm --filter @bjjnarola/components test

# Run unit tests for a specific component (e.g. Tooltip)
pnpm --filter @bjjnarola/components exec vitest run src/components/tooltip/tooltip.test.ts

# Run in Watch Mode (auto-re-runs on save)
pnpm --filter @bjjnarola/components exec vitest src/components/tooltip/tooltip.test.ts
```

#### 📌 Running Tests inside Components Package (`packages/components`)
```bash
cd packages/components

# Run all component tests
pnpm test

# Run a specific component test file once
pnpm exec vitest run src/components/tooltip/tooltip.test.ts

# Run in watch mode
pnpm exec vitest src/components/tooltip/tooltip.test.ts
```

---

### 2. Accessibility Testing (Storybook & axe-core)
Every component must meet **WCAG 2.2 AA / AAA** criteria:
- **WCAG 1.4.13 (Hoverable & Persistent Content)**: Hoverable tooltip bubbles with Esc key dismissal.
- **Focus Indicators**: 2px accent outline + 2px offset on `:focus-visible`.
- **Target Size**: Minimum hit area of 24×24 px (36–40 px for icon buttons).
- **Color Contrast**: Minimum 4.5:1 for body text (AAA 15.8:1 achieved for tooltips), 3:1 for graphical UI elements & focus rings.
- **ARIA & Roles**: Built-in APG patterns cross-checked using Storybook's `addon-a11y` (axe-core).

```bash
# Start Storybook dev server
pnpm run storybook

# Run story tests headlessly via Vitest CLI
pnpm --filter @bjjnarola/storybook exec vitest --config vitest.config.ts
```

---

### 3. Interactive Component Playground
Test components live with real-time property controls and theme switching:

```bash
cd apps/playground
pnpm run dev
# Opens playground at http://localhost:4200
```
