Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

Commit 7144efd

Browse files
feat: add 10 missing icon SVG paths, fix demo ESM imports, Lighthouse audit fixes
- Add SVG paths for: alt_route, animation, confirmation_number, devices, filter_center_focus, image, login, repeat, timer, verified - Fix ISSUE-6: use ESM import from dist bundle instead of window.AgentUI - Fix CLS on dividers, color contrast, ARIA labels, robots.txt SEO - Add new structural directive components (au-if, au-repeat, au-show, au-portal, au-intersection, au-media, au-transition, au-timer) - All paths sourced from official Google Material Design Icons repo - Lighthouse: Performance 91, Accessibility 100, CLS 0 v0.1.151
1 parent eb464b7 commit 7144efd

134 files changed

Lines changed: 6212 additions & 906 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
> For practical build recipes and templates, see [SKILL.md](./SKILL.md).
55
> To develop new components or extend the framework, see [AGENTS_DEV.md](./AGENTS_DEV.md).
66
7-
> **AI-friendly web components framework.** 50 components, zero Shadow DOM.
7+
> **AI-friendly web components framework.** 57 components, zero Shadow DOM.
88
99
---
1010

@@ -324,7 +324,7 @@ Wait for all components to be registered before manipulating them:
324324
// Wait for AgentUI to be ready
325325
document.addEventListener('au-ready', (e) => {
326326
console.log('AgentUI ready!', e.detail);
327-
// { version: '0.1.23', components: 50, timestamp: ... }
327+
// { version: '0.1.150', components: 57, timestamp: ... }
328328

329329
// Now safe to manipulate components
330330
const input = document.querySelector('au-input');

AGENTS_DEV.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ npx serve app-dist
418418
```
419419
AgentUI/
420420
├── src/ # Framework source
421-
│ └── components/ # 50 components
421+
│ └── components/ # 57 components
422422
423423
├── dist/ # Framework build
424424
│ ├── agentui.esm.js # Full ESM bundle (177 KB)
@@ -530,4 +530,4 @@ The `server.js` is optimized for **high Lighthouse** scores:
530530

531531
*This document is for framework developers. For building apps with AgentUI, see [AGENTS.md](./AGENTS.md).*
532532

533-
*Last updated: v0.1.65 - 2026-02-09*
533+
*Last updated: v0.1.150 - 2026-02-17*

AGENTS_REFERENCE.md

Lines changed: 184 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77

88
## Quick Reference
99

10-
### All Components (50)
10+
### All Components (57)
1111

1212
| Category | Components | Common Attributes |
1313
|----------|------------|-------------------|
1414
| **Layout** | `au-container`, `au-stack`, `au-grid`, `au-navbar`, `au-sidebar`, `au-divider` | `gap="xs\|sm\|md\|lg"`, `direction="row\|column"` |
1515
| **Form** | `au-button`, `au-input`, `au-textarea`, `au-checkbox`, `au-switch`, `au-radio`, `au-radio-group`, `au-dropdown`, `au-option`, `au-chip`, `au-form` | `variant`, `disabled`, `required`, `value` |
16-
| **Display** | `au-card`, `au-tabs`, `au-tab`, `au-table`, `au-avatar`, `au-badge`, `au-progress`, `au-skeleton`, `au-alert`, `au-icon` | `variant="elevated\|outlined\|filled"` |
16+
| **Display** | `au-card`, `au-tabs`, `au-tab`, `au-table`, `au-avatar`, `au-badge`, `au-callout`, `au-progress`, `au-skeleton`, `au-alert`, `au-icon` | `variant="elevated\|outlined\|filled"` |
1717
| **Feedback** | `au-modal`, `au-toast`, `au-toast-container`, `au-tooltip`, `au-spinner`, `au-confirm` | `duration`, `position` |
18-
| **Performance** | `au-virtual-list`, `au-lazy`, `au-repeat` | `items`, `renderItem` |
18+
| **Structural** | `au-if`, `au-show`, `au-repeat`, `au-portal`, `au-intersection`, `au-media`, `au-transition`, `au-timer` | `condition`, `threshold`, `active` |
19+
| **Performance** | `au-virtual-list`, `au-lazy` | `items`, `renderItem` |
1920
| **Data** | `au-fetch` | `url`, `auto`, `interval` |
2021
| **Enterprise** | `au-error-boundary` | `fallback` |
2122
| **Utility** | `au-theme-toggle` | - |
@@ -1744,7 +1745,7 @@ npx serve app-dist
17441745
```
17451746
AgentUI/
17461747
├── src/ # Framework source
1747-
│ └── components/ # 51 components
1748+
│ └── components/ # 57 components
17481749
17491750
├── dist/ # Framework build
17501751
│ ├── agentui.esm.js # Full bundle
@@ -1986,6 +1987,177 @@ list.addEventListener('click', (e) => {
19861987
</script>
19871988
```
19881989
1990+
### au-show (Show/Hide with State Preservation)
1991+
```html
1992+
<au-show id="panel" condition>
1993+
<form>
1994+
<!-- Form values, scroll position, timers all survive toggle -->
1995+
<au-input label="Name" value="Alice"></au-input>
1996+
</form>
1997+
</au-show>
1998+
1999+
<script type="module">
2000+
const panel = document.getElementById('panel');
2001+
panel.condition = false; // hidden via display:none, stays in DOM
2002+
panel.condition = true; // visible again, all state intact
2003+
2004+
panel.addEventListener('au-show', () => console.log('Visible'));
2005+
panel.addEventListener('au-hide', () => console.log('Hidden'));
2006+
</script>
2007+
```
2008+
2009+
**Key points:**
2010+
- Children hidden with `display: none` — **not removed** from DOM
2011+
- Internal state (form values, event listeners, timers) **preserved**
2012+
- Use `au-if` when you want true DOM removal; `au-show` when toggling frequently
2013+
- `display: contents` — zero layout impact
2014+
2015+
### au-portal (DOM Teleportation)
2016+
```html
2017+
<!-- Source: portal lives here but children render elsewhere -->
2018+
<div style="overflow: hidden;">
2019+
<au-portal target="#modal-container">
2020+
<au-modal open title="Escaped!">
2021+
<p>This modal is not clipped by overflow:hidden</p>
2022+
</au-modal>
2023+
</au-portal>
2024+
</div>
2025+
2026+
<!-- Target: teleported content appears here -->
2027+
<div id="modal-container"></div>
2028+
2029+
<script type="module">
2030+
const portal = document.querySelector('au-portal');
2031+
portal.addEventListener('au-teleport', () => console.log('Moved'));
2032+
portal.addEventListener('au-return', () => console.log('Returned'));
2033+
// Children auto-return on disconnect (cleanup)
2034+
</script>
2035+
```
2036+
2037+
**Key points:**
2038+
- Children are **moved** (not cloned) — DOM identity preserved
2039+
- Solves `overflow: hidden` and z-index stacking context issues
2040+
- Auto-cleanup: children return to source on disconnect
2041+
- `target` defaults to `document.body` when absent
2042+
2043+
### au-intersection (Viewport Observer)
2044+
```html
2045+
<!-- Lazy-load pattern -->
2046+
<au-intersection once threshold="0.1">
2047+
<img data-src="hero.webp" alt="Hero" />
2048+
</au-intersection>
2049+
2050+
<script type="module">
2051+
document.querySelectorAll('au-intersection').forEach(el => {
2052+
el.addEventListener('au-visible', (e) => {
2053+
console.log('Ratio:', e.detail.ratio);
2054+
const img = el.querySelector('img[data-src]');
2055+
if (img) { img.src = img.dataset.src; }
2056+
});
2057+
el.addEventListener('au-hidden', () => {
2058+
console.log('Left viewport');
2059+
});
2060+
});
2061+
</script>
2062+
```
2063+
2064+
**Key points:**
2065+
- Declarative `IntersectionObserver` — no manual setup/cleanup
2066+
- `once` mode disconnects after first intersection (lazy-load)
2067+
- `threshold` (0–1) controls visibility ratio trigger
2068+
- `root-margin` extends the viewport bounds (e.g. `"200px"` for preloading)
2069+
- Read `el.isVisible` for current state
2070+
2071+
### au-media (Responsive Rendering)
2072+
```html
2073+
<!-- Desktop-only sidebar -->
2074+
<au-media query="(min-width: 768px)">
2075+
<aside class="sidebar"><nav>...</nav></aside>
2076+
</au-media>
2077+
2078+
<!-- Mobile-only bottom nav -->
2079+
<au-media query="(max-width: 767px)">
2080+
<au-bottom-nav>
2081+
<au-nav-item icon="home">Home</au-nav-item>
2082+
</au-bottom-nav>
2083+
</au-media>
2084+
2085+
<script type="module">
2086+
const media = document.querySelector('au-media');
2087+
console.log(media.matches); // true/false
2088+
media.addEventListener('au-match', () => console.log('Query matches'));
2089+
media.addEventListener('au-unmatch', () => console.log('Query no longer matches'));
2090+
</script>
2091+
```
2092+
2093+
**Key points:**
2094+
- Children **truly removed** from DOM when query doesn't match (like `au-if`)
2095+
- Same DOM nodes restored on match (identity preserved)
2096+
- More efficient than CSS `display: none` for heavy components
2097+
- Read `el.matches` for current state
2098+
2099+
### au-transition (Enter/Leave Animations)
2100+
```html
2101+
<style>
2102+
.fade-enter-active, .fade-leave-active { transition: opacity 0.3s ease; }
2103+
.fade-enter-from, .fade-leave-active { opacity: 0; }
2104+
</style>
2105+
2106+
<au-transition name="fade" active>
2107+
<div>I animate in and out!</div>
2108+
</au-transition>
2109+
2110+
<script type="module">
2111+
const transition = document.querySelector('au-transition');
2112+
transition.active = true; // applies fade-enter-from → fade-enter-active
2113+
transition.active = false; // applies fade-leave-from → fade-leave-active
2114+
2115+
transition.addEventListener('au-enter', () => console.log('Enter started'));
2116+
transition.addEventListener('au-leave', () => console.log('Leave started'));
2117+
</script>
2118+
```
2119+
2120+
**Key points:**
2121+
- Vue-inspired class naming: `{name}-enter-from`, `{name}-enter-active`, `{name}-leave-from`, `{name}-leave-active`
2122+
- Does **not** define visual CSS — you provide the transition styles
2123+
- `name` attribute sets the class prefix (default: `au`)
2124+
- `display: contents` — zero layout impact
2125+
2126+
### au-timer (Declarative Timer)
2127+
```html
2128+
<!-- Count-up timer -->
2129+
<au-timer id="stopwatch" interval="1000" autostart></au-timer>
2130+
2131+
<!-- Countdown timer (30 seconds) -->
2132+
<au-timer id="countdown" interval="1000" countdown="30"></au-timer>
2133+
2134+
<script type="module">
2135+
const timer = document.getElementById('stopwatch');
2136+
timer.addEventListener('au-tick', (e) => {
2137+
display.textContent = e.detail.count; // 1, 2, 3...
2138+
});
2139+
timer.start();
2140+
timer.stop();
2141+
timer.reset();
2142+
2143+
const countdown = document.getElementById('countdown');
2144+
countdown.addEventListener('au-tick', (e) => {
2145+
display.textContent = e.detail.count; // 30, 29, 28...
2146+
});
2147+
countdown.addEventListener('au-complete', () => {
2148+
showToast('Time is up!', { severity: 'warning' });
2149+
});
2150+
countdown.start();
2151+
</script>
2152+
```
2153+
2154+
**Key points:**
2155+
- Automatic `clearInterval` on disconnect — no memory leaks
2156+
- `countdown` attribute enables count-down mode (fires `au-complete` at 0)
2157+
- `autostart` starts timer on connect
2158+
- Interval clamped to ≥100ms for safety
2159+
- Read `el.count` and `el.running` for current state
2160+
19892161
### au-table (Data Tables with Sorting)
19902162
```html
19912163
<au-table id="data-table"></au-table>
@@ -2153,7 +2325,7 @@ export async function render(container) {
21532325
21542326
## 📦 Component Quick Reference
21552327
2156-
> **All 51 AgentUI components at a glance.** Key attributes and copy-paste examples.
2328+
> **All 57 AgentUI components at a glance.** Key attributes and copy-paste examples.
21572329
21582330
### Buttons & Actions
21592331
@@ -2238,6 +2410,12 @@ export async function render(container) {
22382410
| `au-fetch` | `url`, `method` | `<au-fetch url="/api/data"></au-fetch>` |
22392411
| `au-repeat` | `items`, `template` | `<au-repeat items="...">...</au-repeat>` |
22402412
| `au-if` | `condition`, `else` | `<au-if condition>Visible</au-if>` |
2413+
| `au-show` | `condition` | `<au-show condition>Hidden with display:none</au-show>` |
2414+
| `au-portal` | `target` | `<au-portal target="#container">Teleported</au-portal>` |
2415+
| `au-intersection` | `threshold`, `root-margin`, `once` | `<au-intersection once>Lazy load</au-intersection>` |
2416+
| `au-media` | `query` | `<au-media query="(min-width: 768px)">Desktop only</au-media>` |
2417+
| `au-transition` | `name`, `active` | `<au-transition name="fade" active>Animated</au-transition>` |
2418+
| `au-timer` | `interval`, `countdown`, `autostart` | `<au-timer interval="1000" autostart></au-timer>` |
22412419
| `au-virtual-list` | `items`, `item-height` | `<au-virtual-list items="..." item-height="50"></au-virtual-list>` |
22422420
| `au-error-boundary` | `fallback` | `<au-error-boundary fallback="Error">...</au-error-boundary>` |
22432421

@@ -2277,4 +2455,4 @@ export async function render(container) {
22772455

22782456
---
22792457

2280-
*Last updated: v0.1.117 - 2026-02-11*
2458+
*Last updated: v0.1.150 - 2026-02-17*

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ bun run build:framework
6060
```
6161
AgentUI/
6262
├── src/
63-
│ ├── components/ # 50 components (MD3 application + dev tools)
63+
│ ├── components/ # 57 components (MD3 application + dev tools)
6464
│ ├── core/ # AuElement base, utils, scheduler
6565
│ └── styles/ # CSS design tokens (MD3)
6666
├── tests/

PHILOSOPHY.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Framework version upgrades are a real cost: dependency breakage, migration effor
5858

5959
- Built on **W3C Web Components** — a standard, not a framework
6060
- **Zero external dependencies** — no transitive version conflicts
61-
- **50 components** included — no dependency matrix to manage
61+
- **57 components** included — no dependency matrix to manage
6262

6363
**Trade-off acknowledged:** Standards evolve too (Web Components v0 → v1 was a breaking change). "Standards-based" reduces churn but doesn't eliminate it.
6464

@@ -191,7 +191,7 @@ this.innerHTML = html`
191191
## 5. Smart Bundle Architecture (61KB Critical Path)
192192

193193
**The tree-shaking argument:**
194-
"I only use 3 components, why download all 50?"
194+
"I only use 3 components, why download all 57?"
195195

196196
**AgentUI's response:**
197197

@@ -235,7 +235,7 @@ async function loadRoute(name) {
235235
item.addEventListener('mouseenter', () => loadRoute(pageId));
236236
```
237237

238-
**Result:** 100/100 Lighthouse Performance with all 50 components available.
238+
**Result:** 100/100 Lighthouse Performance with all 57 components available.
239239
[**→ Verify it yourself on PageSpeed Insights**](https://pagespeed.web.dev/analysis?url=https://giuseppescottolavina.github.io/AgentUI/demo/)
240240

241241
**Trade-off acknowledged:** The initial 61KB is larger than a minimal tree-shaken app. But the lazy loading architecture means subsequent pages load only what they need, and the developer experience is zero-config.
@@ -359,7 +359,7 @@ See [SECURITY.md](./SECURITY.md) for full audit details.
359359

360360
**Honest answer:** AgentUI doesn't have a large ecosystem, because:
361361

362-
1. **50 components built-in** — Buttons, cards, forms, modals, tables, tabs, tooltips, data tables, schema forms, virtual lists. Most apps need nothing else.
362+
1. **57 components built-in** — Buttons, cards, forms, modals, tables, tabs, tooltips, data tables, schema forms, virtual lists. Most apps need nothing else.
363363

364364
2. **Built-in EventBus** — Lightweight event bus (LightBus) for inter-component messaging is included, not a separate package.
365365

@@ -383,7 +383,7 @@ To stay focused, some things are explicitly **out of scope**:
383383
| Virtual DOM | Goes against core philosophy — direct DOM is the point |
384384
| JSX support | Use template literals; no transpilation required |
385385
| Shadow DOM by default | Light DOM enables AI inspection and global styling |
386-
| Plugin ecosystem | 50 components built-in; use vanilla JS libraries for the rest |
386+
| Plugin ecosystem | 57 components built-in; use vanilla JS libraries for the rest |
387387

388388
This isn't stubbornness — it's focus. Every feature has a maintenance cost, and saying "no" to the wrong features is what keeps AgentUI lean.
389389

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<h1 align="center">AgentUI</h1>
66

77
<p align="center">
8-
<strong>51 production-ready web components. Zero dependencies. One script tag.</strong>
8+
<strong>57 production-ready web components. Zero dependencies. One script tag.</strong>
99
</p>
1010

1111
<p align="center">
@@ -26,7 +26,7 @@
2626
<a href="./SECURITY.md"><img src="https://img.shields.io/badge/XSS-Safe-2ea44f?logo=shieldsdotio&logoColor=white" alt="XSS Safe"></a>
2727
<img src="https://img.shields.io/badge/CSP-Compatible-2ea44f?logo=shieldsdotio&logoColor=white" alt="CSP Compatible">
2828
<img src="https://img.shields.io/badge/eval()-None-2ea44f" alt="No eval()">
29-
<img src="https://img.shields.io/badge/tests-1949-blue" alt="1949 Tests">
29+
<img src="https://img.shields.io/badge/tests-2436-blue" alt="2436 Tests">
3030
</p>
3131

3232
---
@@ -44,24 +44,25 @@
4444

4545
## What's Included
4646

47-
51 components covering everything you need:
47+
57 components covering everything you need:
4848

4949
| Category | Components |
5050
|----------|------------|
51-
| **Layout** | `au-stack`, `au-grid`, `au-container`, `au-layout`, `au-page`, `au-navbar`, `au-sidebar`, `au-drawer`, `au-bottom-nav`, `au-divider` |
51+
| **Layout** | `au-stack`, `au-grid`, `au-container`, `au-layout`, `au-page`, `au-navbar`, `au-sidebar`, `au-drawer`, `au-drawer-item`, `au-bottom-nav`, `au-divider` |
5252
| **Form** | `au-button`, `au-input`, `au-textarea`, `au-form`, `au-dropdown`, `au-checkbox`, `au-switch`, `au-radio`, `au-chip`, `au-prompt-input` |
5353
| **Display** | `au-card`, `au-tabs`, `au-alert`, `au-badge`, `au-callout`, `au-progress`, `au-table`, `au-datatable`, `au-avatar`, `au-skeleton`, `au-code`, `au-message-bubble` |
5454
| **Feedback** | `au-spinner`, `au-modal`, `au-confirm`, `au-toast`, `au-tooltip`, `au-error-boundary`, `au-splash` |
55-
| **Structural** | `au-if`, `au-repeat`, `au-lazy`, `au-virtual-list`, `au-fetch`, `au-router` |
55+
| **Structural** | `au-if`, `au-show`, `au-repeat`, `au-lazy`, `au-virtual-list`, `au-fetch`, `au-router`, `au-portal`, `au-intersection`, `au-media`, `au-transition`, `au-timer` |
5656
| **Utility** | `au-icon`, `au-theme-toggle`, `au-schema-form` |
57+
| **Dev Tools** | `au-api-table`, `au-doc-page`, `au-example` |
5758

5859
---
5960

6061
## ⚡ Performance by Default
6162

6263
No Virtual DOM. No runtime framework overhead. Just native Custom Elements.
6364

64-
- **61KB total** — All 51 components, JS + CSS, gzipped. Smaller than most frameworks' "hello world".
65+
- **61KB total** — All 57 components, JS + CSS, gzipped. Smaller than most frameworks' "hello world".
6566
- **Lighthouse 100/100/100/100**[Verify it yourself →](https://pagespeed.web.dev/analysis?url=https://giuseppescottolavina.github.io/AgentUI/demo/)
6667
- **DOM Speed** — 500 instantiations <8ms, 500 updates <3ms.
6768
- **Zero Config** — One `<script>` tag. No bundler, no build step, no npm required.
@@ -88,7 +89,7 @@ Built on W3C Web Components — native browser APIs with zero abstraction tax.
8889

8990
| Decision | AgentUI Approach | Trade-off |
9091
|---|---|---|
91-
| **Bundle** | All 51 components in 61KB gzipped | No tree-shaking — you load everything |
92+
| **Bundle** | All 57 components in 61KB gzipped | No tree-shaking — you load everything |
9293
| **XSS** | Auto-escape `html` tagged template | Custom template syntax, not JSX |
9394
| **Dependencies** | Zero | No ecosystem — you build what you need |
9495
| **DOM** | Light DOM (no Shadow DOM) | Full access, but no style encapsulation |
@@ -124,7 +125,7 @@ Built on W3C Web Components — native browser APIs with zero abstraction tax.
124125

125126
| Metric | Value |
126127
|--------|-------|
127-
| **Tests** | 1949 (unit + E2E), 0 failures, 103 isolated test files |
128+
| **Tests** | 2436 (unit + E2E), 0 failures, 141 isolated test files |
128129
| **Security** | XSS-audited, CSP-compatible, no `eval()`, [full policy →](./SECURITY.md) |
129130
| **Memory** | Managed listeners (AbortController), zero leaks verified |
130131
| **DOM Speed** | 500 instantiations <8ms, 500 updates <3ms |
@@ -156,7 +157,7 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) to get started, or [open a discussion](
156157

157158
## Status
158159

159-
AgentUI is an **experimental** library (v0.1.x) — 51 components, 1949 tests, built by a single developer. Functional and tested, but still a work in progress.
160+
AgentUI is an **experimental** library (v0.1.x) — 57 components, 2436 tests, built by a single developer. Functional and tested, but still a work in progress.
160161

161162
Feedback, criticism, and stress-testing are welcome — [open a discussion](https://github.com/GiuseppeScottoLavina/AgentUI/discussions).
162163

0 commit comments

Comments
 (0)