@adia-ai/web-components 0.0.26 → 0.0.28
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.
- package/components/agent-artifact/agent-artifact.a2ui.json +1 -1
- package/components/agent-artifact/agent-artifact.css +11 -0
- package/components/agent-artifact/agent-artifact.js +23 -2
- package/components/agent-artifact/agent-artifact.yaml +1 -1
- package/components/agent-questions/agent-questions.css +20 -1
- package/components/agent-reasoning/agent-reasoning.css +11 -0
- package/components/agent-reasoning/agent-reasoning.js +16 -0
- package/components/agent-trace/agent-trace.css +36 -12
- package/components/alert/alert.a2ui.json +10 -4
- package/components/alert/alert.css +13 -0
- package/components/alert/alert.js +1 -1
- package/components/alert/alert.yaml +21 -4
- package/components/badge/badge.a2ui.json +0 -2
- package/components/badge/badge.css +20 -0
- package/components/badge/badge.js +10 -2
- package/components/badge/badge.yaml +0 -2
- package/components/breadcrumb/breadcrumb.a2ui.json +16 -1
- package/components/breadcrumb/breadcrumb.css +27 -0
- package/components/breadcrumb/breadcrumb.js +95 -17
- package/components/breadcrumb/breadcrumb.yaml +15 -1
- package/components/calendar-picker/calendar-picker.css +17 -0
- package/components/chart/chart.css +20 -13
- package/components/chart/chart.js +49 -17
- package/components/chart-legend/chart-legend.css +30 -54
- package/components/chart-legend/chart-legend.js +48 -30
- package/components/code/code.css +41 -0
- package/components/code/code.js +44 -3
- package/components/command/command.js +52 -1
- package/components/empty-state/empty-state.js +32 -21
- package/components/feed/feed-item.yaml +50 -0
- package/components/feed/feed.a2ui.json +59 -0
- package/components/feed/feed.css +141 -0
- package/components/feed/feed.js +276 -0
- package/components/feed/feed.yaml +33 -0
- package/components/index.js +2 -0
- package/components/list/list.js +20 -16
- package/components/menu/menu.css +18 -0
- package/components/menu/menu.js +24 -10
- package/components/pane/pane.css +5 -0
- package/components/pipeline-status/pipeline-status.css +15 -1
- package/components/popover/popover.css +17 -0
- package/components/select/select.css +18 -0
- package/components/swatch/swatch.a2ui.json +116 -0
- package/components/swatch/swatch.css +141 -0
- package/components/swatch/swatch.js +121 -0
- package/components/swatch/swatch.yaml +101 -0
- package/components/swiper/swiper.css +9 -0
- package/components/table/table.css +5 -0
- package/components/table/table.js +45 -1
- package/components/table-toolbar/table-toolbar.css +13 -0
- package/components/tag/tag.css +10 -0
- package/components/timeline/timeline.css +15 -4
- package/components/toast/toast.css +93 -48
- package/components/toast/toast.js +101 -22
- package/components/toolbar/toolbar.css +13 -0
- package/components/tooltip/tooltip.css +11 -3
- package/core/provider.js +1 -0
- package/package.json +1 -1
- package/styles/colors/semantics.css +1 -1
- package/styles/components.css +1 -0
|
@@ -29,6 +29,7 @@ class AdiaCommand extends AdiaElement {
|
|
|
29
29
|
static template = () => null;
|
|
30
30
|
|
|
31
31
|
#items = [];
|
|
32
|
+
#recents = [];
|
|
32
33
|
#activeIdx = -1;
|
|
33
34
|
#inputEl = null;
|
|
34
35
|
#listEl = null;
|
|
@@ -37,6 +38,8 @@ class AdiaCommand extends AdiaElement {
|
|
|
37
38
|
#bound = false;
|
|
38
39
|
#itemByEl = new WeakMap();
|
|
39
40
|
|
|
41
|
+
static #RECENTS_MAX = 3;
|
|
42
|
+
|
|
40
43
|
#onListClick = (e) => {
|
|
41
44
|
const el = e.target instanceof Element ? e.target.closest('[role="option"]:not([aria-disabled])') : null;
|
|
42
45
|
if (!el) return;
|
|
@@ -99,7 +102,15 @@ class AdiaCommand extends AdiaElement {
|
|
|
99
102
|
// ── Public API ──
|
|
100
103
|
|
|
101
104
|
get value() { return this.#inputEl?.value || ''; }
|
|
102
|
-
set value(v) {
|
|
105
|
+
set value(v) {
|
|
106
|
+
if (!this.#inputEl) return;
|
|
107
|
+
const next = v ?? '';
|
|
108
|
+
this.#inputEl.value = next;
|
|
109
|
+
// Keep the rendered list in sync with the visible input — the host
|
|
110
|
+
// commonly clears value on (re)open, and consumers expect to see the
|
|
111
|
+
// full list (plus recents) rather than the previous filter's residue.
|
|
112
|
+
this.#renderItems(next);
|
|
113
|
+
}
|
|
103
114
|
|
|
104
115
|
focus() { this.#inputEl?.focus(); }
|
|
105
116
|
|
|
@@ -148,6 +159,26 @@ class AdiaCommand extends AdiaElement {
|
|
|
148
159
|
const flat = this.#items;
|
|
149
160
|
let visibleCount = 0;
|
|
150
161
|
|
|
162
|
+
// Recents — only when no filter is applied. Resolved against the
|
|
163
|
+
// current item set so a stale recent (item removed via setItems)
|
|
164
|
+
// is silently dropped.
|
|
165
|
+
if (!q && this.#recents.length) {
|
|
166
|
+
const resolved = this.#recents
|
|
167
|
+
.map(v => this.#findItem(v))
|
|
168
|
+
.filter(it => it && !it.disabled);
|
|
169
|
+
if (resolved.length) {
|
|
170
|
+
const groupEl = document.createElement('div');
|
|
171
|
+
groupEl.setAttribute('data-group', '');
|
|
172
|
+
groupEl.setAttribute('data-recent', '');
|
|
173
|
+
groupEl.innerHTML = `<div data-group-label>Recent</div>`;
|
|
174
|
+
for (const item of resolved) {
|
|
175
|
+
groupEl.appendChild(this.#createItemEl(item, visibleCount));
|
|
176
|
+
visibleCount++;
|
|
177
|
+
}
|
|
178
|
+
this.#listEl.appendChild(groupEl);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
151
182
|
for (const entry of flat) {
|
|
152
183
|
if (entry.items) {
|
|
153
184
|
// Group
|
|
@@ -182,6 +213,24 @@ class AdiaCommand extends AdiaElement {
|
|
|
182
213
|
if (visibleCount > 0) this.#activate(0);
|
|
183
214
|
}
|
|
184
215
|
|
|
216
|
+
#findItem(value) {
|
|
217
|
+
for (const entry of this.#items) {
|
|
218
|
+
if (entry.items) {
|
|
219
|
+
const hit = entry.items.find(i => i.value === value);
|
|
220
|
+
if (hit) return hit;
|
|
221
|
+
} else if (entry.value === value) {
|
|
222
|
+
return entry;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#pushRecent(value) {
|
|
229
|
+
if (!value) return;
|
|
230
|
+
this.#recents = [value, ...this.#recents.filter(v => v !== value)]
|
|
231
|
+
.slice(0, AdiaCommand.#RECENTS_MAX);
|
|
232
|
+
}
|
|
233
|
+
|
|
185
234
|
#createItemEl(item, idx) {
|
|
186
235
|
const el = document.createElement('div');
|
|
187
236
|
el.setAttribute('role', 'option');
|
|
@@ -235,6 +284,7 @@ class AdiaCommand extends AdiaElement {
|
|
|
235
284
|
}
|
|
236
285
|
|
|
237
286
|
#select(item) {
|
|
287
|
+
this.#pushRecent(item.value);
|
|
238
288
|
this.dispatchEvent(new CustomEvent('select', {
|
|
239
289
|
bubbles: true,
|
|
240
290
|
detail: { value: item.value, label: item.label },
|
|
@@ -246,6 +296,7 @@ class AdiaCommand extends AdiaElement {
|
|
|
246
296
|
if (!active) return;
|
|
247
297
|
const value = active.dataset.value;
|
|
248
298
|
const label = active.querySelector('[data-text]')?.textContent || '';
|
|
299
|
+
this.#pushRecent(value);
|
|
249
300
|
this.dispatchEvent(new CustomEvent('select', {
|
|
250
301
|
bubbles: true,
|
|
251
302
|
detail: { value, label },
|
|
@@ -24,10 +24,15 @@ class AdiaEmptyState extends AdiaElement {
|
|
|
24
24
|
#headingEl = null;
|
|
25
25
|
#descEl = null;
|
|
26
26
|
|
|
27
|
+
// Mark slot elements we create so render() never overrides consumer-provided ones.
|
|
28
|
+
// See ADR-0010 (slot content is source of truth).
|
|
29
|
+
#stampMark(el) { el.dataset.emptyStateStamped = '1'; return el; }
|
|
30
|
+
#wasStamped(el) { return el?.dataset?.emptyStateStamped === '1'; }
|
|
31
|
+
|
|
27
32
|
connected() {
|
|
28
33
|
this.#iconEl = this.querySelector(':scope > [slot="icon"]');
|
|
29
34
|
if (!this.#iconEl) {
|
|
30
|
-
this.#iconEl = document.createElement('icon-ui');
|
|
35
|
+
this.#iconEl = this.#stampMark(document.createElement('icon-ui'));
|
|
31
36
|
this.#iconEl.setAttribute('slot', 'icon');
|
|
32
37
|
this.#iconEl.setAttribute('size', 'lg');
|
|
33
38
|
this.insertBefore(this.#iconEl, this.firstChild);
|
|
@@ -35,14 +40,14 @@ class AdiaEmptyState extends AdiaElement {
|
|
|
35
40
|
|
|
36
41
|
this.#headingEl = this.querySelector(':scope > [slot="heading"]');
|
|
37
42
|
if (!this.#headingEl) {
|
|
38
|
-
this.#headingEl = document.createElement('span');
|
|
43
|
+
this.#headingEl = this.#stampMark(document.createElement('span'));
|
|
39
44
|
this.#headingEl.setAttribute('slot', 'heading');
|
|
40
45
|
this.insertBefore(this.#headingEl, this.querySelector('[slot="action"]'));
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
this.#descEl = this.querySelector(':scope > [slot="description"]');
|
|
44
49
|
if (!this.#descEl) {
|
|
45
|
-
this.#descEl = document.createElement('span');
|
|
50
|
+
this.#descEl = this.#stampMark(document.createElement('span'));
|
|
46
51
|
this.#descEl.setAttribute('slot', 'description');
|
|
47
52
|
this.insertBefore(this.#descEl, this.querySelector('[slot="action"]'));
|
|
48
53
|
}
|
|
@@ -51,28 +56,34 @@ class AdiaEmptyState extends AdiaElement {
|
|
|
51
56
|
render() {
|
|
52
57
|
if (!this.#iconEl) return;
|
|
53
58
|
|
|
54
|
-
// Icon
|
|
55
|
-
if (this
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
// Icon — only mutate stamped elements; visibility follows the source of truth.
|
|
60
|
+
if (this.#wasStamped(this.#iconEl)) {
|
|
61
|
+
if (this.icon) {
|
|
62
|
+
this.#iconEl.setAttribute('name', this.icon);
|
|
63
|
+
this.#iconEl.hidden = false;
|
|
64
|
+
} else {
|
|
65
|
+
this.#iconEl.hidden = true;
|
|
66
|
+
}
|
|
60
67
|
}
|
|
61
68
|
|
|
62
|
-
// Heading
|
|
63
|
-
if (this
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
// Heading — same policy.
|
|
70
|
+
if (this.#wasStamped(this.#headingEl)) {
|
|
71
|
+
if (this.heading) {
|
|
72
|
+
this.#headingEl.textContent = this.heading;
|
|
73
|
+
this.#headingEl.hidden = false;
|
|
74
|
+
} else {
|
|
75
|
+
this.#headingEl.hidden = true;
|
|
76
|
+
}
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
// Description
|
|
71
|
-
if (this
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
// Description — same policy.
|
|
80
|
+
if (this.#wasStamped(this.#descEl)) {
|
|
81
|
+
if (this.description) {
|
|
82
|
+
this.#descEl.textContent = this.description;
|
|
83
|
+
this.#descEl.hidden = false;
|
|
84
|
+
} else {
|
|
85
|
+
this.#descEl.hidden = true;
|
|
86
|
+
}
|
|
76
87
|
}
|
|
77
88
|
}
|
|
78
89
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
2
|
+
name: AdiaFeedItem
|
|
3
|
+
tag: feed-item-ui
|
|
4
|
+
component: FeedItem
|
|
5
|
+
category: feedback
|
|
6
|
+
version: 1
|
|
7
|
+
description: >-
|
|
8
|
+
Atomic feed entry inside a `<feed-ui>` lane. Three dismiss policies
|
|
9
|
+
are inferred from the prop shape — auto-fade (duration > 0 + no
|
|
10
|
+
action), sticky-dismissible (duration null/0), action-required
|
|
11
|
+
(duration null/0 + action; future phase). Posted via
|
|
12
|
+
`AdiaFeed.post()` rather than authored directly.
|
|
13
|
+
props:
|
|
14
|
+
text:
|
|
15
|
+
description: Body copy
|
|
16
|
+
type: string
|
|
17
|
+
default: ""
|
|
18
|
+
heading:
|
|
19
|
+
description: Optional emphasis line above text
|
|
20
|
+
type: string
|
|
21
|
+
default: ""
|
|
22
|
+
icon:
|
|
23
|
+
description: Optional leading icon name
|
|
24
|
+
type: string
|
|
25
|
+
default: ""
|
|
26
|
+
variant:
|
|
27
|
+
description: Semantic variant
|
|
28
|
+
type: string
|
|
29
|
+
default: default
|
|
30
|
+
enum:
|
|
31
|
+
- default
|
|
32
|
+
- info
|
|
33
|
+
- success
|
|
34
|
+
- warning
|
|
35
|
+
- danger
|
|
36
|
+
duration:
|
|
37
|
+
description: Auto-fade timer in ms; null/0 = sticky (requires user input)
|
|
38
|
+
type: number
|
|
39
|
+
default: 4000
|
|
40
|
+
dismissible:
|
|
41
|
+
description: Render an x close button (default true for sticky, false for auto-fade)
|
|
42
|
+
type: boolean
|
|
43
|
+
default: false
|
|
44
|
+
events:
|
|
45
|
+
close:
|
|
46
|
+
description: Fired after the item finishes its exit animation
|
|
47
|
+
slots:
|
|
48
|
+
body:
|
|
49
|
+
description: Default content slot (also accepts the `text` / `heading` props)
|
|
50
|
+
states: {}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/Feed.json",
|
|
4
|
+
"title": "Feed",
|
|
5
|
+
"description": "Shared top-layer feed channel. Per docs/specs/feed-channel.md (SPEC-FEED-CHANNEL-001). Per-position singletons mounted lazily into document.body via Popover API; consumers post via the static API (`AdiaFeed.post()`) or the global 'feed' CustomEvent.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "Feed"
|
|
18
|
+
},
|
|
19
|
+
"max": {
|
|
20
|
+
"description": "Cap on simultaneously visible items per lane",
|
|
21
|
+
"type": "number",
|
|
22
|
+
"default": 5
|
|
23
|
+
},
|
|
24
|
+
"position": {
|
|
25
|
+
"description": "Lane the feed renders into",
|
|
26
|
+
"type": "string",
|
|
27
|
+
"enum": [
|
|
28
|
+
"top-left",
|
|
29
|
+
"top-center",
|
|
30
|
+
"top-right",
|
|
31
|
+
"bottom-left",
|
|
32
|
+
"bottom-center",
|
|
33
|
+
"bottom-right",
|
|
34
|
+
"inline"
|
|
35
|
+
],
|
|
36
|
+
"default": "bottom-right"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"required": [
|
|
40
|
+
"component"
|
|
41
|
+
],
|
|
42
|
+
"unevaluatedProperties": false,
|
|
43
|
+
"x-adiaui": {
|
|
44
|
+
"anti_patterns": [],
|
|
45
|
+
"category": "container",
|
|
46
|
+
"events": {},
|
|
47
|
+
"examples": [],
|
|
48
|
+
"keywords": [],
|
|
49
|
+
"name": "AdiaFeedContainer",
|
|
50
|
+
"related": [],
|
|
51
|
+
"slots": {},
|
|
52
|
+
"states": {},
|
|
53
|
+
"synonyms": {},
|
|
54
|
+
"tag": "feed-ui",
|
|
55
|
+
"tokens": {},
|
|
56
|
+
"traits": [],
|
|
57
|
+
"version": 1
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
+
FEED-UI — Shared top-layer feed channel.
|
|
3
|
+
Per docs/specs/feed-channel.md (SPEC-FEED-CHANNEL-001).
|
|
4
|
+
═══════════════════════════════════════════════════════════════ */
|
|
5
|
+
|
|
6
|
+
/* Safari 17.x bug — same as toast: `:scope[data-open]` flavor B
|
|
7
|
+
doesn't reliably restyle on attribute toggling inside @scope.
|
|
8
|
+
Selectors moved out as plain feed-item-ui[data-…] rules. */
|
|
9
|
+
feed-item-ui[data-open] {
|
|
10
|
+
transition: transform var(--feed-item-duration) var(--feed-item-easing),
|
|
11
|
+
opacity var(--feed-item-duration) var(--feed-item-easing);
|
|
12
|
+
transform: translateY(0);
|
|
13
|
+
opacity: 1;
|
|
14
|
+
}
|
|
15
|
+
feed-item-ui[data-closing] {
|
|
16
|
+
transition: transform var(--feed-item-duration) var(--feed-item-easing),
|
|
17
|
+
opacity var(--feed-item-duration) var(--feed-item-easing);
|
|
18
|
+
opacity: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Container — per-position lane, mounted into document.body via
|
|
22
|
+
Popover API for top-layer placement. */
|
|
23
|
+
@scope (feed-ui) {
|
|
24
|
+
:where(:scope) {
|
|
25
|
+
--feed-gap: var(--a-space-2);
|
|
26
|
+
--feed-padding: var(--a-space-3);
|
|
27
|
+
--feed-max-width: 22rem;
|
|
28
|
+
--feed-offset: var(--a-space-4);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
:scope {
|
|
32
|
+
position: fixed;
|
|
33
|
+
z-index: 9999;
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: column;
|
|
36
|
+
gap: var(--feed-gap);
|
|
37
|
+
padding: 0;
|
|
38
|
+
background: transparent;
|
|
39
|
+
border: 0;
|
|
40
|
+
pointer-events: none; /* Items re-enable pointer-events. */
|
|
41
|
+
width: max-content;
|
|
42
|
+
max-width: var(--feed-max-width);
|
|
43
|
+
}
|
|
44
|
+
/* Reset native popover defaults so the lane is invisible until
|
|
45
|
+
items render. */
|
|
46
|
+
:scope[popover] { background: none; color: inherit; }
|
|
47
|
+
|
|
48
|
+
/* Position variants. Default = bottom-right. */
|
|
49
|
+
:scope,
|
|
50
|
+
:scope[position="bottom-right"] {
|
|
51
|
+
bottom: var(--feed-offset); right: var(--feed-offset);
|
|
52
|
+
}
|
|
53
|
+
:scope[position="bottom-left"] {
|
|
54
|
+
bottom: var(--feed-offset); left: var(--feed-offset); right: auto;
|
|
55
|
+
}
|
|
56
|
+
:scope[position="bottom-center"] {
|
|
57
|
+
bottom: var(--feed-offset);
|
|
58
|
+
left: 50%; right: auto;
|
|
59
|
+
transform: translateX(-50%);
|
|
60
|
+
}
|
|
61
|
+
:scope[position="top-right"] {
|
|
62
|
+
top: var(--feed-offset); right: var(--feed-offset); bottom: auto;
|
|
63
|
+
flex-direction: column-reverse;
|
|
64
|
+
}
|
|
65
|
+
:scope[position="top-left"] {
|
|
66
|
+
top: var(--feed-offset); left: var(--feed-offset); right: auto; bottom: auto;
|
|
67
|
+
flex-direction: column-reverse;
|
|
68
|
+
}
|
|
69
|
+
:scope[position="top-center"] {
|
|
70
|
+
top: var(--feed-offset); bottom: auto;
|
|
71
|
+
left: 50%; right: auto;
|
|
72
|
+
transform: translateX(-50%);
|
|
73
|
+
flex-direction: column-reverse;
|
|
74
|
+
}
|
|
75
|
+
:scope[position="inline"] {
|
|
76
|
+
position: relative;
|
|
77
|
+
inset: auto;
|
|
78
|
+
z-index: 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Item — atomic feed entry. */
|
|
83
|
+
@scope (feed-item-ui) {
|
|
84
|
+
:where(:scope) {
|
|
85
|
+
--feed-item-bg: var(--a-bg);
|
|
86
|
+
--feed-item-fg: var(--a-fg);
|
|
87
|
+
--feed-item-border: var(--a-border-subtle);
|
|
88
|
+
--feed-item-radius: var(--a-radius-md);
|
|
89
|
+
--feed-item-px: var(--a-space-3);
|
|
90
|
+
--feed-item-py: var(--a-space-2-5);
|
|
91
|
+
--feed-item-shadow: var(--a-shadow-md);
|
|
92
|
+
--feed-item-icon-size: var(--a-icon-size);
|
|
93
|
+
--feed-item-duration: var(--a-duration);
|
|
94
|
+
--feed-item-easing: var(--a-easing-out);
|
|
95
|
+
--feed-item-gap: var(--a-space-3);
|
|
96
|
+
--feed-item-max-width: var(--a-feed-max-width, 22rem);
|
|
97
|
+
}
|
|
98
|
+
:scope[variant="info"] { --feed-item-fg: var(--a-info-fg); --feed-item-bg: var(--a-info-muted); }
|
|
99
|
+
:scope[variant="success"] { --feed-item-fg: var(--a-success-fg); --feed-item-bg: var(--a-success-muted); }
|
|
100
|
+
:scope[variant="warning"] { --feed-item-fg: var(--a-warning-fg); --feed-item-bg: var(--a-warning-muted); }
|
|
101
|
+
:scope[variant="danger"] { --feed-item-fg: var(--a-danger-fg); --feed-item-bg: var(--a-danger-muted); }
|
|
102
|
+
|
|
103
|
+
:scope {
|
|
104
|
+
box-sizing: border-box;
|
|
105
|
+
display: flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
gap: var(--feed-item-gap);
|
|
108
|
+
max-width: var(--feed-item-max-width);
|
|
109
|
+
padding: var(--feed-item-py) var(--feed-item-px);
|
|
110
|
+
background: var(--feed-item-bg);
|
|
111
|
+
color: var(--feed-item-fg);
|
|
112
|
+
border: 1px solid var(--feed-item-border);
|
|
113
|
+
border-radius: var(--feed-item-radius);
|
|
114
|
+
box-shadow: var(--feed-item-shadow);
|
|
115
|
+
opacity: 0;
|
|
116
|
+
transform: translateY(0.5rem);
|
|
117
|
+
pointer-events: auto;
|
|
118
|
+
}
|
|
119
|
+
:scope > [slot="body"] {
|
|
120
|
+
flex: 1;
|
|
121
|
+
min-width: 0;
|
|
122
|
+
display: flex;
|
|
123
|
+
flex-direction: column;
|
|
124
|
+
gap: 0.125rem;
|
|
125
|
+
}
|
|
126
|
+
:scope > [slot="body"] strong {
|
|
127
|
+
font-weight: var(--a-font-weight-strong, 600);
|
|
128
|
+
}
|
|
129
|
+
:scope > [data-feed-close] {
|
|
130
|
+
flex-shrink: 0;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Reduced-motion: skip slide-in/out, keep opacity. */
|
|
135
|
+
@media (prefers-reduced-motion: reduce) {
|
|
136
|
+
feed-item-ui[data-open],
|
|
137
|
+
feed-item-ui[data-closing] {
|
|
138
|
+
transition: opacity var(--feed-item-duration) var(--feed-item-easing);
|
|
139
|
+
transform: none !important;
|
|
140
|
+
}
|
|
141
|
+
}
|