@adia-ai/web-components 0.0.19 → 0.0.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/components/accordion/accordion.css +101 -102
  2. package/components/agent-feedback-bar/agent-feedback-bar.js +8 -8
  3. package/components/agent-questions/agent-questions.css +2 -1
  4. package/components/agent-questions/agent-questions.js +6 -6
  5. package/components/agent-reasoning/agent-reasoning.js +20 -5
  6. package/components/agent-trace/agent-trace.a2ui.json +5 -5
  7. package/components/agent-trace/agent-trace.js +7 -5
  8. package/components/agent-trace/agent-trace.yaml +2 -2
  9. package/components/alert/alert.a2ui.json +1 -2
  10. package/components/alert/alert.css +4 -4
  11. package/components/alert/alert.yaml +1 -2
  12. package/components/avatar/avatar.a2ui.json +3 -3
  13. package/components/avatar/avatar.js +10 -0
  14. package/components/avatar/avatar.yaml +6 -6
  15. package/components/button/button.a2ui.json +14 -2
  16. package/components/button/button.css +19 -2
  17. package/components/button/button.js +1 -0
  18. package/components/button/button.yaml +20 -2
  19. package/components/calendar-picker/calendar-picker.css +2 -1
  20. package/components/calendar-picker/calendar-picker.js +12 -1
  21. package/components/chart/chart.css +11 -11
  22. package/components/chart/chart.js +26 -18
  23. package/components/chart-legend/chart-legend.a2ui.json +2 -2
  24. package/components/chart-legend/chart-legend.js +4 -1
  25. package/components/chart-legend/chart-legend.yaml +2 -2
  26. package/components/chat/chat-input.js +13 -5
  27. package/components/chat/chat.a2ui.json +2 -2
  28. package/components/chat/chat.js +14 -3
  29. package/components/chat/chat.yaml +2 -2
  30. package/components/code/code.css +16 -6
  31. package/components/command/command.js +9 -1
  32. package/components/field/field.a2ui.json +0 -5
  33. package/components/field/field.css +2 -2
  34. package/components/field/field.js +53 -5
  35. package/components/field/field.yaml +5 -8
  36. package/components/heatmap/heatmap.css +32 -23
  37. package/components/input/input.js +30 -1
  38. package/components/kbd/kbd.a2ui.json +5 -1
  39. package/components/kbd/kbd.yaml +5 -1
  40. package/components/menu/menu.css +20 -8
  41. package/components/menu/menu.js +9 -1
  42. package/components/modal/modal.css +101 -108
  43. package/components/noodles/noodles.js +25 -8
  44. package/components/pipeline-status/pipeline-status.css +4 -4
  45. package/components/pipeline-status/pipeline-status.js +6 -4
  46. package/components/popover/popover.js +4 -0
  47. package/components/progress-row/progress-row.a2ui.json +3 -2
  48. package/components/progress-row/progress-row.yaml +2 -1
  49. package/components/range/range.js +7 -0
  50. package/components/richtext/richtext.css +2 -2
  51. package/components/richtext/richtext.js +4 -1
  52. package/components/segment/segment.css +1 -1
  53. package/components/segmented/segmented.js +7 -1
  54. package/components/select/select.css +7 -4
  55. package/components/slider/slider.js +15 -8
  56. package/components/stepper/stepper.css +181 -144
  57. package/components/stepper/stepper.js +5 -2
  58. package/components/swiper/swiper.a2ui.json +3 -3
  59. package/components/swiper/swiper.css +11 -77
  60. package/components/swiper/swiper.js +6 -5
  61. package/components/swiper/swiper.yaml +3 -3
  62. package/components/switch/switch.a2ui.json +8 -1
  63. package/components/switch/switch.yaml +8 -1
  64. package/components/table/table.js +9 -1
  65. package/components/table-toolbar/table-toolbar.a2ui.json +20 -20
  66. package/components/table-toolbar/table-toolbar.css +15 -7
  67. package/components/table-toolbar/table-toolbar.js +24 -11
  68. package/components/table-toolbar/table-toolbar.yaml +16 -12
  69. package/components/tabs/tabs.css +3 -2
  70. package/components/tabs/tabs.js +7 -1
  71. package/components/tag/tag.a2ui.json +2 -2
  72. package/components/tag/tag.yaml +2 -2
  73. package/components/timeline/timeline.css +244 -204
  74. package/components/timeline/timeline.js +1 -3
  75. package/components/toast/toast.a2ui.json +2 -3
  76. package/components/toast/toast.yaml +5 -3
  77. package/components/toolbar/toolbar.css +6 -1
  78. package/components/toolbar/toolbar.js +10 -2
  79. package/components/tooltip/tooltip.css +8 -2
  80. package/components/tooltip/tooltip.js +12 -14
  81. package/components/tree/tree.css +21 -0
  82. package/core/icons.js +14 -0
  83. package/core/polyfills.js +17 -7
  84. package/package.json +1 -1
  85. package/patterns/a2ui-root/a2ui-root.js +21 -14
  86. package/patterns/app-shell/css/app-shell.main.css +30 -1
  87. package/patterns/app-shell/css/app-shell.tokens.css +1 -0
  88. package/patterns/gen-ui/gen-ui.js +1 -1
  89. package/styles/colors/semantics.css +59 -2
  90. package/styles/tokens.css +16 -12
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://adiaui.dev/a2ui/v0_9/components/Swiper.json",
4
4
  "title": "Swiper",
5
- "description": "CSS-first carousel with scroll-snap. Supports autoplay, loop, peek, and native scroll markers.",
5
+ "description": "CSS-first carousel with scroll-snap. Supports autoplay, loop, and peek; JS-stamped pagination dots and paddles.",
6
6
  "type": "object",
7
7
  "allOf": [
8
8
  {
@@ -77,8 +77,8 @@
77
77
  "autoplay-resume": {
78
78
  "description": "Fired on autoplay-resume."
79
79
  },
80
- "slide-change": {
81
- "description": "Fired on slide-change."
80
+ "change": {
81
+ "description": "Fired when the active slide changes. Detail: { index, slide }."
82
82
  }
83
83
  },
84
84
  "examples": [
@@ -1,7 +1,7 @@
1
1
  /* ═══════════════════════════════════════════════════════════════
2
2
  SWIPER-N — CSS-first carousel
3
- Scroll-snap positioning, native ::scroll-marker dots,
4
- ::scroll-button prev/next, container-query responsive.
3
+ Scroll-snap positioning, container-query responsive,
4
+ JS-stamped pagination dots + prev/next paddles.
5
5
 
6
6
  Structure (JS-stamped):
7
7
  swiper-ui ← flex column wrapper
@@ -10,6 +10,12 @@
10
10
  [data-swiper-dots] ← pagination dots (below track)
11
11
  [data-swiper-btn prev] ← absolute left paddle
12
12
  [data-swiper-btn next] ← absolute right paddle
13
+
14
+ Native ::scroll-marker / ::scroll-button is Chrome-135-only and
15
+ not yet on Safari/Firefox roadmaps. Until cross-engine, JS-stamped
16
+ dots are the single source of pagination UI; re-introduce native
17
+ paths gated on CSS.supports('selector(::scroll-marker)') when both
18
+ other engines ship.
13
19
  ═══════════════════════════════════════════════════════════════ */
14
20
 
15
21
  @scope (swiper-ui) {
@@ -31,9 +37,6 @@
31
37
  /* ── Host vertical rhythm ── */
32
38
  --swiper-gap-vertical: var(--a-space-3);
33
39
 
34
- /* ── Native scroll-marker group padding ── */
35
- --swiper-marker-group-py: var(--a-space-3);
36
-
37
40
  /* ── Paddle bottom offset ── */
38
41
  --swiper-btn-bottom: var(--a-space-3);
39
42
 
@@ -127,80 +130,11 @@
127
130
  :scope:not([slides-per-view]) { --swiper-columns: 3; }
128
131
  }
129
132
 
130
- /* ── Native scroll markers (Chrome 135+) ── */
131
-
132
- :scope > [data-swiper-track]::scroll-marker-group {
133
- display: flex;
134
- gap: var(--swiper-dot-gap);
135
- justify-content: center;
136
- padding-block: var(--swiper-marker-group-py);
137
- position: sticky;
138
- bottom: 0;
139
- align-self: end;
140
- grid-column: 1 / -1;
141
- }
142
-
143
- :scope > [data-swiper-track] > *::scroll-marker {
144
- content: '';
145
- width: var(--swiper-dot-size);
146
- height: var(--swiper-dot-size);
147
- border-radius: var(--swiper-dot-radius);
148
- background: var(--swiper-dot-bg);
149
- border: none;
150
- cursor: pointer;
151
- transition: background var(--swiper-duration) var(--swiper-easing),
152
- transform var(--swiper-duration) var(--swiper-easing);
153
- }
154
-
155
- :scope > [data-swiper-track] > *::scroll-marker:target-current {
156
- background: var(--swiper-dot-bg-active);
157
- }
158
-
159
- /* ── Native scroll buttons (Chrome 135+) ──
160
- Disabled — we always stamp JS paddles for consistent
161
- cross-browser appearance. Uncomment to use native instead. */
162
-
163
- /*
164
- :scope > [data-swiper-track]::scroll-button(inline-start),
165
- :scope > [data-swiper-track]::scroll-button(inline-end) {
166
- position: absolute;
167
- top: 50%;
168
- transform: translateY(-50%);
169
- width: var(--swiper-btn-size);
170
- height: var(--swiper-btn-size);
171
- display: flex;
172
- align-items: center;
173
- justify-content: center;
174
- border-radius: var(--swiper-btn-radius);
175
- background: var(--swiper-btn-bg);
176
- color: var(--swiper-btn-fg);
177
- border: none;
178
- box-shadow: var(--swiper-btn-shadow);
179
- cursor: pointer;
180
- z-index: 2;
181
- font-size: 1.25em;
182
- transition: background var(--swiper-duration) var(--swiper-easing),
183
- opacity var(--swiper-duration) var(--swiper-easing);
184
- }
185
-
186
- :scope > [data-swiper-track]::scroll-button(inline-start) { content: '\2039'; left: var(--swiper-btn-offset); }
187
- :scope > [data-swiper-track]::scroll-button(inline-end) { content: '\203A'; right: var(--swiper-btn-offset); }
188
-
189
- :scope > [data-swiper-track]::scroll-button(inline-start):hover,
190
- :scope > [data-swiper-track]::scroll-button(inline-end):hover {
191
- background: var(--swiper-btn-bg-hover);
192
- }
193
-
194
- :scope > [data-swiper-track]::scroll-button(inline-start):disabled,
195
- :scope > [data-swiper-track]::scroll-button(inline-end):disabled {
196
- opacity: 0;
197
- pointer-events: none;
198
- }
199
- */
200
-
201
133
  /* ══════════════════════════════════════════════════════════
202
- JS-stamped fallback paddles
134
+ JS-stamped paddles
203
135
  Centered vertically on the track area only.
136
+ Native ::scroll-button is Chrome-135-only — re-introduce
137
+ when cross-engine.
204
138
  ══════════════════════════════════════════════════════════ */
205
139
 
206
140
  :scope > [data-swiper-btn] {
@@ -6,16 +6,17 @@
6
6
  * </swiper-ui>
7
7
  *
8
8
  * CSS-first carousel. Scroll-snap does all positioning.
9
- * JS handles: auto-advance, programmatic API, ARIA, fallback nav.
9
+ * JS handles: auto-advance, programmatic API, ARIA, paddles + dots.
10
10
  *
11
11
  * On connect, wraps user children into a [data-swiper-track] scroll
12
12
  * container so pagination dots can sit below (outside overflow).
13
13
  *
14
- * Native ::scroll-marker / ::scroll-button in Chrome 135+.
15
- * JS-stamped button-ui fallback + dots in other browsers.
14
+ * Pagination dots and prev/next paddles are JS-stamped on every
15
+ * engine. Native ::scroll-marker / ::scroll-button are Chrome-135-only
16
+ * with no Safari / Firefox roadmap; re-evaluate when cross-engine.
16
17
  *
17
18
  * Events:
18
- * slide-change — { detail: { index, slide } }
19
+ * change — { detail: { index, slide } }
19
20
  * autoplay-pause — { detail: { reason } }
20
21
  * autoplay-resume
21
22
  */
@@ -180,7 +181,7 @@ class AdiaSwiper extends AdiaElement {
180
181
  if (index !== -1 && index !== this.#activeIndex) {
181
182
  this.#activeIndex = index;
182
183
  this.#updateFallbackDots();
183
- this.dispatchEvent(new CustomEvent('slide-change', {
184
+ this.dispatchEvent(new CustomEvent('change', {
184
185
  bubbles: true,
185
186
  detail: { index, slide: entry.target },
186
187
  }));
@@ -6,7 +6,7 @@ tag: swiper-ui
6
6
  component: Swiper
7
7
  category: layout
8
8
  version: 1
9
- description: CSS-first carousel with scroll-snap. Supports autoplay, loop, peek, and native scroll markers.
9
+ description: CSS-first carousel with scroll-snap. Supports autoplay, loop, and peek; JS-stamped pagination dots and paddles.
10
10
  props:
11
11
  autoplay:
12
12
  description: Enable auto-advance
@@ -49,8 +49,8 @@ events:
49
49
  description: "Fired on autoplay-pause."
50
50
  autoplay-resume:
51
51
  description: "Fired on autoplay-resume."
52
- slide-change:
53
- description: "Fired on slide-change."
52
+ change:
53
+ description: "Fired when the active slide changes. Detail: { index, slide }."
54
54
  slots:
55
55
  default:
56
56
  description: "Default slot — primary child content."
@@ -47,8 +47,15 @@
47
47
  "default": ""
48
48
  },
49
49
  "size": {
50
- "description": "Sizing scale (xs/sm/md/lg/xl).",
50
+ "description": "Sizing scale (full tier — xs / sm / md / lg / xl).",
51
51
  "type": "string",
52
+ "enum": [
53
+ "xs",
54
+ "sm",
55
+ "md",
56
+ "lg",
57
+ "xl"
58
+ ],
52
59
  "default": ""
53
60
  },
54
61
  "value": {
@@ -36,9 +36,16 @@ props:
36
36
  type: string
37
37
  default: ""
38
38
  size:
39
- description: "Sizing scale (xs/sm/md/lg/xl)."
39
+ description: Sizing scale (full tier — xs / sm / md / lg / xl).
40
40
  type: string
41
41
  default: ""
42
+ enum:
43
+ - xs
44
+ - sm
45
+ - md
46
+ - lg
47
+ - xl
48
+ reflect: true
42
49
  value:
43
50
  description: Form value (submitted as 'on' when checked)
44
51
  type: string
@@ -107,6 +107,7 @@ class AdiaTable extends AdiaElement {
107
107
  #bound = false;
108
108
  #lastSelectedIndex = -1; // for shift-click range select
109
109
  #openFilter = null; // column key of open filter dropdown
110
+ #filterFocusRaf = null;
110
111
 
111
112
  // ── Public API: columns ──
112
113
 
@@ -264,6 +265,10 @@ class AdiaTable extends AdiaElement {
264
265
  cancelAnimationFrame(this.#renderRaf);
265
266
  this.#renderRaf = null;
266
267
  }
268
+ if (this.#filterFocusRaf != null) {
269
+ cancelAnimationFrame(this.#filterFocusRaf);
270
+ this.#filterFocusRaf = null;
271
+ }
267
272
  }
268
273
 
269
274
  // ── <col-def> Parsing ──────────────────────────────────────────────────────
@@ -989,7 +994,10 @@ class AdiaTable extends AdiaElement {
989
994
  }
990
995
 
991
996
  // Auto-focus input
992
- requestAnimationFrame(() => {
997
+ if (this.#filterFocusRaf != null) cancelAnimationFrame(this.#filterFocusRaf);
998
+ this.#filterFocusRaf = requestAnimationFrame(() => {
999
+ this.#filterFocusRaf = null;
1000
+ if (!this.isConnected) return;
993
1001
  const input = dropdown.querySelector('input');
994
1002
  if (input) input.focus();
995
1003
  });
@@ -13,11 +13,6 @@
13
13
  }
14
14
  ],
15
15
  "properties": {
16
- "columns": {
17
- "description": "Show the Columns visibility popover button.",
18
- "type": "boolean",
19
- "default": true
20
- },
21
16
  "component": {
22
17
  "const": "TableToolbar"
23
18
  },
@@ -26,30 +21,35 @@
26
21
  "type": "string",
27
22
  "default": ""
28
23
  },
29
- "filterable": {
30
- "description": "Show the Filter popover button.",
31
- "type": "boolean",
32
- "default": true
33
- },
34
24
  "for": {
35
25
  "description": "id-ref of the table-ui to control. Falls back to the first sibling table-ui within the same parent when omitted.",
36
26
  "type": "string",
37
27
  "default": ""
38
28
  },
39
- "placeholder": {
40
- "description": "Placeholder text for the search input.",
41
- "type": "string",
42
- "default": "Search..."
29
+ "noColumns": {
30
+ "description": "Hide the Columns visibility popover button. Columns control is shown by default; set to opt out.",
31
+ "type": "boolean",
32
+ "default": false
33
+ },
34
+ "noFilter": {
35
+ "description": "Hide the Filter popover button. Filter is shown by default; set to opt out.",
36
+ "type": "boolean",
37
+ "default": false
43
38
  },
44
- "searchable": {
45
- "description": "Show the search input.",
39
+ "noSearch": {
40
+ "description": "Hide the search input. Search is shown by default; set to opt out.",
46
41
  "type": "boolean",
47
- "default": true
42
+ "default": false
48
43
  },
49
- "sortable": {
50
- "description": "Show the Sort popover button.",
44
+ "noSort": {
45
+ "description": "Hide the Sort popover button. Sort is shown by default; set to opt out.",
51
46
  "type": "boolean",
52
- "default": true
47
+ "default": false
48
+ },
49
+ "placeholder": {
50
+ "description": "Placeholder text for the search input.",
51
+ "type": "string",
52
+ "default": "Search..."
53
53
  },
54
54
  "text": {
55
55
  "description": "Title text shown on the left. Alternative to slotted heading content.",
@@ -9,6 +9,7 @@
9
9
  /* ── Surface ── */
10
10
  --table-toolbar-bg: transparent;
11
11
  --table-toolbar-border: transparent;
12
+ --table-toolbar-border-width: 0;
12
13
  --table-toolbar-radius: var(--a-radius-lg);
13
14
 
14
15
  /* ── Title ── */
@@ -60,16 +61,23 @@
60
61
  align-items: center;
61
62
  gap: var(--table-toolbar-gap);
62
63
  padding: var(--table-toolbar-py) var(--table-toolbar-px);
64
+ background: var(--table-toolbar-bg);
65
+ border: var(--table-toolbar-border-width) solid var(--table-toolbar-border);
66
+ border-radius: var(--table-toolbar-radius);
63
67
  min-width: 0;
64
68
  }
65
69
 
66
- /* ═══════ Variant: card ═══════ */
67
-
68
- :scope[variant="card"] [data-toolbar] {
69
- background: var(--table-toolbar-bg);
70
- border: 1px solid var(--table-toolbar-border);
71
- border-radius: var(--table-toolbar-radius);
72
- padding: var(--a-space-3) var(--a-space-4);
70
+ /* ═══════ Variant: card ═══════
71
+ Variant only re-assigns surface tokens; base layout above consumes
72
+ them unchanged. Matches contract §"Variants override TOKENS, never
73
+ base styles". */
74
+
75
+ :scope[variant="card"] {
76
+ --table-toolbar-bg: var(--a-bg);
77
+ --table-toolbar-border: var(--a-border-subtle);
78
+ --table-toolbar-border-width: 1px;
79
+ --table-toolbar-py: var(--a-space-3);
80
+ --table-toolbar-px: var(--a-space-4);
73
81
  }
74
82
 
75
83
  /* ═══════ Title cluster ═══════ */
@@ -31,10 +31,10 @@ class AdiaTableToolbar extends AdiaElement {
31
31
  for: { type: String, default: '', reflect: true },
32
32
  text: { type: String, default: '', reflect: false },
33
33
  count: { type: String, default: '', reflect: false },
34
- filterable: { type: Boolean, default: true, reflect: true },
35
- sortable: { type: Boolean, default: true, reflect: true },
36
- columns: { type: Boolean, default: true, reflect: true },
37
- searchable: { type: Boolean, default: true, reflect: true },
34
+ noFilter: { type: Boolean, default: false, reflect: true, attribute: 'no-filter' },
35
+ noSort: { type: Boolean, default: false, reflect: true, attribute: 'no-sort' },
36
+ noColumns: { type: Boolean, default: false, reflect: true, attribute: 'no-columns' },
37
+ noSearch: { type: Boolean, default: false, reflect: true, attribute: 'no-search' },
38
38
  placeholder: { type: String, default: 'Search...', reflect: false },
39
39
  variant: { type: String, default: 'default', reflect: true },
40
40
  };
@@ -45,6 +45,8 @@ class AdiaTableToolbar extends AdiaElement {
45
45
  #targetListeners = [];
46
46
  #activePopover = null; // { btn, panel, cleanup }
47
47
  #docListenersBound = false;
48
+ #docListenerRaf = null;
49
+ #sortIndicatorRafs = new Set();
48
50
 
49
51
  // ── Lifecycle ────────────────────────────────────────────────────────────
50
52
 
@@ -56,6 +58,12 @@ class AdiaTableToolbar extends AdiaElement {
56
58
  }
57
59
 
58
60
  disconnected() {
61
+ if (this.#docListenerRaf != null) {
62
+ cancelAnimationFrame(this.#docListenerRaf);
63
+ this.#docListenerRaf = null;
64
+ }
65
+ for (const id of this.#sortIndicatorRafs) cancelAnimationFrame(id);
66
+ this.#sortIndicatorRafs.clear();
59
67
  this.#closePopover();
60
68
  this.#detachTarget();
61
69
  }
@@ -227,15 +235,15 @@ class AdiaTableToolbar extends AdiaElement {
227
235
  if (el) el.hidden = hidden;
228
236
  };
229
237
 
230
- setHidden('[data-toolbar-btn="filter"]', !this.filterable);
231
- setHidden('[data-toolbar-btn="sort"]', !this.sortable);
232
- setHidden('[data-toolbar-btn="columns"]', !this.columns);
233
- setHidden('[data-search]', !this.searchable);
238
+ setHidden('[data-toolbar-btn="filter"]', this.noFilter);
239
+ setHidden('[data-toolbar-btn="sort"]', this.noSort);
240
+ setHidden('[data-toolbar-btn="columns"]', this.noColumns);
241
+ setHidden('[data-search]', this.noSearch);
234
242
  }
235
243
 
236
244
  // Re-run on attribute changes for boolean flags.
237
245
  attributeChanged(name) {
238
- if (['filterable', 'sortable', 'columns', 'searchable'].includes(name)) {
246
+ if (['no-filter', 'no-sort', 'no-columns', 'no-search'].includes(name)) {
239
247
  this.#updateControlVisibility();
240
248
  }
241
249
  if (name === 'placeholder') {
@@ -293,7 +301,9 @@ class AdiaTableToolbar extends AdiaElement {
293
301
 
294
302
  if (!this.#docListenersBound) {
295
303
  this.#docListenersBound = true;
296
- requestAnimationFrame(() => {
304
+ this.#docListenerRaf = requestAnimationFrame(() => {
305
+ this.#docListenerRaf = null;
306
+ if (!this.isConnected || !this.#docListenersBound) return;
297
307
  document.addEventListener('pointerdown', this.#onDocDown, true);
298
308
  document.addEventListener('keydown', this.#onDocKey, true);
299
309
  });
@@ -472,13 +482,16 @@ class AdiaTableToolbar extends AdiaElement {
472
482
 
473
483
  // Trailing direction indicator — append AFTER menu-item-ui's connected()
474
484
  // has run its #stamp() (defers via rAF so the [slot="text"] span exists).
475
- requestAnimationFrame(() => {
485
+ const rafId = requestAnimationFrame(() => {
486
+ this.#sortIndicatorRafs.delete(rafId);
487
+ if (!this.isConnected) return;
476
488
  const indicator = document.createElement('icon-ui');
477
489
  indicator.setAttribute('data-sort-indicator', '');
478
490
  indicator.setAttribute('size', 'xs');
479
491
  indicator.setAttribute('name', dir === 'asc' ? 'arrow-up' : dir === 'desc' ? 'arrow-down' : 'caret-up-down');
480
492
  row.appendChild(indicator);
481
493
  });
494
+ this.#sortIndicatorRafs.add(rafId);
482
495
 
483
496
  row.addEventListener('click', (e) => {
484
497
  // Forward to the bound table by simulating a header click — the table
@@ -29,26 +29,30 @@ props:
29
29
  description: Optional count badge value shown next to the title. When unset, falls back to the row count of the bound table.
30
30
  type: string
31
31
  default: ""
32
- filterable:
33
- description: Show the Filter popover button.
32
+ noFilter:
33
+ description: Hide the Filter popover button. Filter is shown by default; set to opt out.
34
34
  type: boolean
35
- default: true
35
+ default: false
36
36
  reflect: true
37
- sortable:
38
- description: Show the Sort popover button.
37
+ attribute: no-filter
38
+ noSort:
39
+ description: Hide the Sort popover button. Sort is shown by default; set to opt out.
39
40
  type: boolean
40
- default: true
41
+ default: false
41
42
  reflect: true
42
- columns:
43
- description: Show the Columns visibility popover button.
43
+ attribute: no-sort
44
+ noColumns:
45
+ description: Hide the Columns visibility popover button. Columns control is shown by default; set to opt out.
44
46
  type: boolean
45
- default: true
47
+ default: false
46
48
  reflect: true
47
- searchable:
48
- description: Show the search input.
49
+ attribute: no-columns
50
+ noSearch:
51
+ description: Hide the search input. Search is shown by default; set to opt out.
49
52
  type: boolean
50
- default: true
53
+ default: false
51
54
  reflect: true
55
+ attribute: no-search
52
56
  placeholder:
53
57
  description: Placeholder text for the search input.
54
58
  type: string
@@ -30,8 +30,9 @@
30
30
  --tabs-focus-radius: var(--a-radius-sm);
31
31
 
32
32
  /* ── Vertical strip min-width ── */
33
- /* Component-intrinsic visual constant; no --a-space-* equivalent */
34
- --tabs-vertical-strip-min-width: 140px;
33
+ /* Component-intrinsic visual constant; no --a-space-* equivalent
34
+ (8.75rem 140px at 1rem=16px). */
35
+ --tabs-vertical-strip-min-width: 8.75rem;
35
36
  }
36
37
 
37
38
  :scope {
@@ -27,6 +27,7 @@ class AdiaTabs extends AdiaElement {
27
27
 
28
28
  #strip = null;
29
29
  #indicator = null;
30
+ #transitionRaf = null;
30
31
 
31
32
  connected() {
32
33
  this.setAttribute('role', 'tablist');
@@ -42,6 +43,10 @@ class AdiaTabs extends AdiaElement {
42
43
  }
43
44
 
44
45
  disconnected() {
46
+ if (this.#transitionRaf != null) {
47
+ cancelAnimationFrame(this.#transitionRaf);
48
+ this.#transitionRaf = null;
49
+ }
45
50
  this.removeEventListener('click', this.#handleClick);
46
51
  this.removeEventListener('keydown', this.#handleKeydown);
47
52
  this.#strip = null;
@@ -175,7 +180,8 @@ class AdiaTabs extends AdiaElement {
175
180
  if (isNew) {
176
181
  this.#indicator.style.transition = 'none';
177
182
  apply();
178
- requestAnimationFrame(() => {
183
+ this.#transitionRaf = requestAnimationFrame(() => {
184
+ this.#transitionRaf = null;
179
185
  if (this.#indicator) this.#indicator.style.transition = '';
180
186
  });
181
187
  } else {
@@ -41,14 +41,14 @@
41
41
  "default": ""
42
42
  },
43
43
  "variant": {
44
- "description": "Visual style variant with semantic colors.",
44
+ "description": "Semantic variant `default | info | success | warning | danger`.",
45
45
  "type": "string",
46
46
  "enum": [
47
47
  "default",
48
48
  "info",
49
49
  "success",
50
50
  "warning",
51
- "error"
51
+ "danger"
52
52
  ],
53
53
  "default": "default"
54
54
  }
@@ -29,7 +29,7 @@ props:
29
29
  type: string
30
30
  default: ""
31
31
  variant:
32
- description: Visual style variant with semantic colors.
32
+ description: Semantic variant `default | info | success | warning | danger`.
33
33
  type: string
34
34
  default: default
35
35
  enum:
@@ -37,7 +37,7 @@ props:
37
37
  - info
38
38
  - success
39
39
  - warning
40
- - error
40
+ - danger
41
41
  events:
42
42
  remove:
43
43
  description: Fired when the dismiss button is activated.