anentrypoint-design 1.0.32 → 1.0.34
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/colors_and_type.css +1 -1
- package/dist/247420.css +149 -27
- package/dist/247420.js +25 -25
- package/package.json +1 -1
- package/src/community-app.js +1 -1
- package/src/components/chat/message.js +9 -1
- package/src/components/content/panel.js +1 -1
- package/src/components/shell/app-shell.js +2 -2
- package/src/components/shell/atoms.js +1 -1
- package/src/components/shell/workspace-shell.js +1 -1
- package/src/css/app-shell/base.css +9 -0
- package/src/css/app-shell/chat-polish.css +18 -1
- package/src/css/app-shell/files.css +10 -2
- package/src/css/app-shell/hero-content.css +16 -4
- package/src/css/app-shell/kits-appended.css +33 -16
- package/src/css/app-shell/primitives.css +33 -1
- package/src/css/app-shell/states-interactions.css +16 -0
- package/src/css/app-shell/topbar.css +14 -2
- package/src/kits/os/theme.css +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
package/src/community-app.js
CHANGED
|
@@ -256,7 +256,7 @@ export function mountCommunityApp(root, adapter = {}) {
|
|
|
256
256
|
// id + tabindex match AppShell()'s contract so the skip link
|
|
257
257
|
// above actually lands somewhere; this app builds its own shell
|
|
258
258
|
// and so inherited neither.
|
|
259
|
-
h('main', { class: 'app-main', id: 'app-main', tabindex: '0', onclick: () => { if (s.mobileMenuOpen && A.closeMobileMenu) A.closeMobileMenu(); } },
|
|
259
|
+
h('main', { class: 'app-main ds-app-surface', id: 'app-main', tabindex: '0', onclick: () => { if (s.mobileMenuOpen && A.closeMobileMenu) A.closeMobileMenu(); } },
|
|
260
260
|
// The channel name is the page title, but it lived only in
|
|
261
261
|
// the topbar brand span, leaving the document with no
|
|
262
262
|
// heading at all. sr-only because the topbar and chat-head
|
|
@@ -95,6 +95,12 @@ export function ChatMessage({ role, who = 'them', avatar, text, parts, time, typ
|
|
|
95
95
|
if (time) metaItems.push(h('span', { class: 't', key: 'ti' }, time));
|
|
96
96
|
if (tickNode) metaItems.push(tickNode);
|
|
97
97
|
const meta = metaItems.length ? h('div', { class: 'chat-meta' }, ...metaItems) : null;
|
|
98
|
+
// Incoming turns show the name above the bubble, level with the avatar's
|
|
99
|
+
// top edge, so the two read as one identity unit -- the way the 'you'
|
|
100
|
+
// side already pairs its avatar with its own bubble. Placing meta after
|
|
101
|
+
// the bubble (as for 'you', where only time/receipt trail below) left an
|
|
102
|
+
// incoming message's name floating above the PREVIOUS message's bubble
|
|
103
|
+
// instead of its own, with a bare avatar disc stranded beside its bubble.
|
|
98
104
|
// Per-message actions (copy / retry / edit) — a hover-revealed control row
|
|
99
105
|
// below the bubble, the way Claude-Desktop surfaces message-level actions.
|
|
100
106
|
// Each action is { label, icon, onClick, title }. Kept icon-only with an
|
|
@@ -132,7 +138,9 @@ export function ChatMessage({ role, who = 'them', avatar, text, parts, time, typ
|
|
|
132
138
|
const roleLabel = isFlat
|
|
133
139
|
? h('div', { class: 'chat-role', key: '_role' }, resolvedWho === 'you' ? t('chat.roleYou', 'You') : (name || t('chat.roleAssistant', 'Assistant')))
|
|
134
140
|
: null;
|
|
135
|
-
const stack =
|
|
141
|
+
const stack = resolvedWho === 'them'
|
|
142
|
+
? h('div', { class: 'chat-stack' }, roleLabel, meta, ...bodyNodes, reactionRow, actionRow)
|
|
143
|
+
: h('div', { class: 'chat-stack' }, roleLabel, ...bodyNodes, reactionRow, actionRow, meta);
|
|
136
144
|
// Centered roles (system/tool/thinking) skip the avatar column entirely so
|
|
137
145
|
// the bubble owns the full row — the chrome reads as out-of-band signal,
|
|
138
146
|
// not a participant turn.
|
|
@@ -14,7 +14,7 @@ export function Panel({ title, count, right, style = '', class: className = '',
|
|
|
14
14
|
// a screen-reader heading-jump can actually find each section, not just
|
|
15
15
|
// the page's single top-level h1.
|
|
16
16
|
const headingTag = 'h' + headingLevel;
|
|
17
|
-
return h('div', { class: cls, style, ...(id ? { id } : {}) },
|
|
17
|
+
return h('div', { class: cls, style: style || null, ...(id ? { id } : {}) },
|
|
18
18
|
title != null ? h('div', { class: 'panel-head' },
|
|
19
19
|
h(headingTag, { class: 'panel-title' }, title),
|
|
20
20
|
right != null ? right : (count != null ? h('span', { class: 'ds-badge' }, String(count)) : null)
|
|
@@ -164,7 +164,7 @@ function isStatusCollapsed() {
|
|
|
164
164
|
try { return localStorage.getItem(STATUS_COLLAPSE_KEY) === '1'; } catch (_) { return false; }
|
|
165
165
|
}
|
|
166
166
|
function toggleStatusCollapsed(fromEl) {
|
|
167
|
-
const app = fromEl && fromEl.closest && fromEl.closest('.app');
|
|
167
|
+
const app = fromEl && fromEl.closest && fromEl.closest('.app, .ws-shell');
|
|
168
168
|
const bar = app && app.querySelector('.app-status');
|
|
169
169
|
if (!bar) return;
|
|
170
170
|
const next = !bar.classList.contains('is-collapsed');
|
|
@@ -185,7 +185,7 @@ export function Status({ left = [], right = [] } = {}) {
|
|
|
185
185
|
// ref runs on mount, before paint, so there's no expanded-then-collapse flash.
|
|
186
186
|
const syncLiveVar = (el) => {
|
|
187
187
|
if (!el) return;
|
|
188
|
-
const app = el.closest('.app');
|
|
188
|
+
const app = el.closest('.app, .ws-shell');
|
|
189
189
|
if (app) app.style.setProperty('--app-status-h-live', collapsed ? 'var(--space-4)' : 'var(--app-status-h)');
|
|
190
190
|
};
|
|
191
191
|
return h('footer', { class: 'app-status' + (collapsed ? ' is-collapsed' : ''), role: 'contentinfo', ref: syncLiveVar },
|
|
@@ -145,7 +145,7 @@ export function Glyph({ children, color, size = 'base', label } = {}) {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
export function Heading({ level = 1, children, style = '', class: className = '', 'aria-level': ariaLevel }) {
|
|
148
|
-
return h('h' + level, { class: className || null, style, 'aria-level': ariaLevel != null ? String(ariaLevel) : null }, children);
|
|
148
|
+
return h('h' + level, { class: className || null, style: style || null, 'aria-level': ariaLevel != null ? String(ariaLevel) : null }, children);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
export function Lede({ children }) {
|
|
@@ -120,7 +120,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
120
120
|
onclick: (e) => toggleWsDrawer('pane', null, e.currentTarget),
|
|
121
121
|
}, Icon('page')) : null)
|
|
122
122
|
: null,
|
|
123
|
-
h('main', { class: 'ws-main' + (narrow ? ' narrow' : '') + (mainFlush ? ' ws-main--flush' : ''), id: 'ws-main', tabindex: '-1' },
|
|
123
|
+
h('main', { class: 'ws-main ds-app-surface' + (narrow ? ' narrow' : '') + (mainFlush ? ' ws-main--flush' : ''), id: 'ws-main', tabindex: '-1' },
|
|
124
124
|
...(Array.isArray(main) ? main : [main])),
|
|
125
125
|
status || null),
|
|
126
126
|
// Optional right context pane. Its desktop collapse toggle now lives in
|
|
@@ -143,6 +143,15 @@ h3 + .lede, h3 + .t-lede,
|
|
|
143
143
|
margin-top: var(--space-2);
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
/* .app-main.narrow widens well past prose measure on wide no-sidebar
|
|
147
|
+
viewports on purpose (topbar.css) so full-width siblings like .post-meta/
|
|
148
|
+
h1/.post-index use the room. .lede/.ds-prose keep their reading-measure
|
|
149
|
+
caps (38ch/--measure) but stayed left edge-anchored inside that wider
|
|
150
|
+
column, turning the freed width into one-sided dead whitespace on the
|
|
151
|
+
right of the article body instead of being absorbed as margin. */
|
|
152
|
+
.app-main.narrow > .lede, .app-main.narrow > .t-lede,
|
|
153
|
+
.app-main.narrow > .ds-prose { margin-left: auto; margin-right: auto; }
|
|
154
|
+
|
|
146
155
|
.lede + .post-body, .t-lede + .post-body,
|
|
147
156
|
.lede + .ds-prose, .t-lede + .ds-prose {
|
|
148
157
|
margin-top: var(--space-4);
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
.chat-empty-title { font-size: var(--fs-sm); margin: 0 0 var(--space-1); }
|
|
47
47
|
.chat-empty-sub { font-size: var(--fs-tiny); margin: 0; opacity: .82; } /* WCAG-verified 2026 restyle: .7 blended --fg-3 to 3.72:1 on dark --bg (#1a1a1a); .82 clears 4.53:1 */
|
|
48
48
|
|
|
49
|
-
.chat-msg { display: flex; gap: var(--space-2-75); align-items: flex-start; padding: var(--space-1-75) 0; position: relative; min-width: 0; }
|
|
49
|
+
.chat-msg { display: flex; flex-shrink: 0; gap: var(--space-2-75); align-items: flex-start; padding: var(--space-1-75) 0; position: relative; min-width: 0; }
|
|
50
50
|
.chat-msg.you { flex-direction: row-reverse; }
|
|
51
51
|
.chat-msg.you .chat-stack { align-items: flex-end; }
|
|
52
52
|
.chat-msg:hover { background: color-mix(in oklab, var(--fg) 4%, transparent); padding: var(--space-1-75) 0; margin: 0; border-radius: var(--r-0); transition: background var(--dur-base) var(--ease); }
|
|
@@ -613,6 +613,23 @@
|
|
|
613
613
|
text-align: center;
|
|
614
614
|
margin: 0;
|
|
615
615
|
}
|
|
616
|
+
/* Reference's Projects/General sidebar switcher: a two-pill row sitting
|
|
617
|
+
above the tree, spaced off the tree below it like a real section header,
|
|
618
|
+
not flush against it. Tighter side padding than --pad-x (round 4 widened
|
|
619
|
+
that to 48px) -- two pills at natural width need more of the 256px rail
|
|
620
|
+
than a 48px-each-side gutter leaves, so this row alone uses --space-3 to
|
|
621
|
+
stay a single non-wrapping row like the reference, without touching the
|
|
622
|
+
shared --pad-x token every other sidebar section still uses. */
|
|
623
|
+
.aicat-side-tabs {
|
|
624
|
+
padding: var(--space-3) var(--space-3) var(--space-2);
|
|
625
|
+
flex-wrap: nowrap;
|
|
626
|
+
}
|
|
627
|
+
.ds-side-empty-note {
|
|
628
|
+
padding: var(--space-2) var(--pad-x);
|
|
629
|
+
color: var(--fg-3);
|
|
630
|
+
font-size: var(--fs-sm);
|
|
631
|
+
margin: 0;
|
|
632
|
+
}
|
|
616
633
|
|
|
617
634
|
/* ============================================================
|
|
618
635
|
Composer attachment-detected badge, context line, hint, toolbar,
|
|
@@ -51,7 +51,10 @@
|
|
|
51
51
|
.ds-skel::after {
|
|
52
52
|
content: ''; position: absolute; inset: 0;
|
|
53
53
|
background: linear-gradient(90deg, transparent, var(--bg-3), transparent);
|
|
54
|
-
transform: translateX(-100%);
|
|
54
|
+
transform: translateX(-100%);
|
|
55
|
+
}
|
|
56
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
57
|
+
.ds-skel::after { animation: ds-skel-shimmer 1.2s infinite; }
|
|
55
58
|
}
|
|
56
59
|
.ds-skel-icon { width: 22px; height: 22px; }
|
|
57
60
|
.ds-skel-title { height: 12px; width: 60%; }
|
|
@@ -375,6 +378,7 @@
|
|
|
375
378
|
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
|
376
379
|
}
|
|
377
380
|
.ds-crumb-seg:hover { background: var(--bg-2); color: var(--fg); }
|
|
381
|
+
.ds-crumb-seg:focus-visible { outline: none; box-shadow: var(--focus-ring-inset); }
|
|
378
382
|
.ds-crumb-seg.leaf { color: var(--fg); font-weight: 600; }
|
|
379
383
|
.ds-crumb-sep { color: var(--fg-3); opacity: 0.6; user-select: none; }
|
|
380
384
|
|
|
@@ -546,7 +550,11 @@
|
|
|
546
550
|
progress) — a sliding marquee bar reads as "working", not stuck at 0%. */
|
|
547
551
|
.ds-upload-bar.indeterminate .ds-upload-fill {
|
|
548
552
|
width: 40%; transition: none;
|
|
549
|
-
|
|
553
|
+
}
|
|
554
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
555
|
+
.ds-upload-bar.indeterminate .ds-upload-fill {
|
|
556
|
+
animation: ds-upload-marquee 1.1s ease-in-out infinite;
|
|
557
|
+
}
|
|
550
558
|
}
|
|
551
559
|
@keyframes ds-upload-marquee {
|
|
552
560
|
0% { transform: translateX(-100%); }
|
|
@@ -100,6 +100,16 @@
|
|
|
100
100
|
@container (max-width: 900px) {
|
|
101
101
|
.ds-hero { padding: var(--space-7) 0 var(--space-6); }
|
|
102
102
|
}
|
|
103
|
+
/* .ds-hero already supplies its own --space-8 (96px) trailing padding, same
|
|
104
|
+
"gap owned by one side only" pattern as * + .ds-section below. A .panel
|
|
105
|
+
right after it still added its own --space-6-scaled top margin PLUS its
|
|
106
|
+
panel-head top padding on top of that -- measured live, the stat block sat
|
|
107
|
+
~138px from "currently shipping" (96 hero pad + panel's own lead) versus
|
|
108
|
+
the ~42px any other block gets ahead of a .panel, and well past the 96px
|
|
109
|
+
.ds-section itself uses for its "more space above than below" lead. Zero
|
|
110
|
+
the panel's own top margin here so the hero's trailing padding is the only
|
|
111
|
+
contributor, matching every other panel/section transition on the page. */
|
|
112
|
+
.ds-hero + .panel { margin-top: 0; }
|
|
103
113
|
.ds-chat-title { margin: 0; font-size: inherit; }
|
|
104
114
|
|
|
105
115
|
/* ============================================================
|
|
@@ -172,14 +182,16 @@
|
|
|
172
182
|
.ds-marquee-track {
|
|
173
183
|
display: inline-flex; gap: var(--space-5);
|
|
174
184
|
white-space: nowrap; will-change: transform;
|
|
175
|
-
|
|
185
|
+
}
|
|
186
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
187
|
+
.ds-marquee-track { animation: ds-marquee-run 28s linear infinite; }
|
|
188
|
+
.ds-marquee:hover .ds-marquee-track,
|
|
189
|
+
.ds-marquee:focus-within .ds-marquee-track,
|
|
190
|
+
.ds-marquee:active .ds-marquee-track { animation-play-state: paused; }
|
|
176
191
|
}
|
|
177
192
|
.ds-marquee-run { display: inline-flex; align-items: center; gap: var(--space-5); }
|
|
178
193
|
.ds-marquee-item { display: inline-flex; align-items: center; gap: var(--space-5); }
|
|
179
194
|
.ds-marquee-sep { color: var(--accent-ink); }
|
|
180
|
-
.ds-marquee:hover .ds-marquee-track,
|
|
181
|
-
.ds-marquee:focus-within .ds-marquee-track,
|
|
182
|
-
.ds-marquee:active .ds-marquee-track { animation-play-state: paused; }
|
|
183
195
|
@keyframes ds-marquee-run {
|
|
184
196
|
from { transform: translateX(0); }
|
|
185
197
|
to { transform: translateX(-50%); }
|
|
@@ -388,7 +388,18 @@
|
|
|
388
388
|
}
|
|
389
389
|
.ds-prim-panel { padding: clamp(10px, 2.5vw, 14px) clamp(10px, 3vw, 18px); display: flex; flex-direction: column; gap: 18px; }
|
|
390
390
|
.ds-prim-row { display: flex; gap: var(--space-2-5); flex-wrap: wrap; align-items: center; }
|
|
391
|
+
/* collab overlay specimens (LiveCursorOverlay/RemoteSelectionRings/
|
|
392
|
+
RecentEditHighlightFlash) are `position:absolute; inset:0`, meant to
|
|
393
|
+
overlay their own demo row -- without a positioned ancestor closer than
|
|
394
|
+
the ancestor `.panel` (panel-row.css), they escape to cover the whole
|
|
395
|
+
panel including its title. Scope them to this row. */
|
|
396
|
+
.ds-prim-row-collab { position: relative; min-height: 64px; }
|
|
391
397
|
.ds-prim-label { flex: 0 0 64px; font-family: var(--ff-mono); font-size: var(--fs-nano); color: var(--fg-3); }
|
|
398
|
+
/* Trailing status readouts (e.g. "none pressed yet") share .ds-prim-label's
|
|
399
|
+
type/color but are free-length prose, not the fixed-width leading row
|
|
400
|
+
label -- the shared 64px flex-basis wrapped them into a cramped 3-line
|
|
401
|
+
stack. Give status text room to sit on one line instead. */
|
|
402
|
+
.ds-prim-label-status { flex: 0 1 auto; white-space: nowrap; }
|
|
392
403
|
|
|
393
404
|
/* == appended: content-site == */
|
|
394
405
|
/* Home landing wrappers (site/theme.mjs) — replace banned inline styles. */
|
|
@@ -475,8 +486,8 @@
|
|
|
475
486
|
need a clearly larger interval between them than within them, or the whole
|
|
476
487
|
form reads as one undifferentiated column. Margin-collapse-free (flow root
|
|
477
488
|
siblings) — first/last are zeroed so the panel body sets the outer edge. */
|
|
478
|
-
.ds-field-block { display: flex; flex-direction: column; gap: var(--space-1-75); margin: calc(var(--space-4) * var(--density)) 0 0; }
|
|
479
|
-
.ds-settings-body > .ds-field-block:first-child { margin-top: 0; }
|
|
489
|
+
.ds-field-block, .ds-field-wrap { display: flex; flex-direction: column; gap: var(--space-1-75); margin: calc(var(--space-4) * var(--density)) 0 0; }
|
|
490
|
+
.ds-settings-body > .ds-field-block:first-child, .ds-settings-body > .ds-field-wrap:first-child { margin-top: 0; }
|
|
480
491
|
/* Field width is a hint about expected input length. A name or handle stretched
|
|
481
492
|
across a 1000px desktop column tells the user to type a paragraph and leaves
|
|
482
493
|
the eye no left-to-right anchor; capping the control (not the row) keeps the
|
|
@@ -555,7 +566,7 @@
|
|
|
555
566
|
then has to scroll. `auto` collapses when the pane is short, centres when tall. */
|
|
556
567
|
.ds-auth-col { width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: var(--space-2); margin: auto 0; min-width: 0; }
|
|
557
568
|
/* 18px ceiling: no tier between --space-3 (16) and --space-3-5 (20). */
|
|
558
|
-
.ds-auth-form {
|
|
569
|
+
.ds-auth-form { display: flex; flex-direction: column; gap: var(--space-2-5); }
|
|
559
570
|
.ds-auth-sent { align-items: center; text-align: center; }
|
|
560
571
|
/* 32px is an ICON size, not a type size: this is the confirmation mark above
|
|
561
572
|
the "check your mail" copy, sized to the 440px auth column, and the --fs-*
|
|
@@ -762,18 +773,19 @@
|
|
|
762
773
|
/* min-height is a floor, not the intended size — .chat-kit-page's flex-column
|
|
763
774
|
splits leftover height between this (flex:1 1 0%, "leftover") and the
|
|
764
775
|
pattern-notes panel below it (flex:0 1 auto, i.e. sized to its own content
|
|
765
|
-
first).
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
has room
|
|
776
|
-
|
|
776
|
+
first). A hard px floor here (this used to read max(30vh, 420px)) can
|
|
777
|
+
exceed .chat-kit-page's own available height on a short/laptop viewport —
|
|
778
|
+
420px plus the panel's natural content height overflows the column
|
|
779
|
+
instead of yielding to it, so .chat-thread's internal overflow-y:auto
|
|
780
|
+
never engages and the last couple of messages are stranded below the
|
|
781
|
+
fold with no reachable scroll region (the thread is never empty, it is
|
|
782
|
+
invisible). min-height:0 here — same as .chat/.chat-thread already use —
|
|
783
|
+
lets flex:1 actually shrink this to whatever .chat-kit-page has left,
|
|
784
|
+
so .chat-thread (flex:1, min-height:0, overflow-y:auto) is the thing that
|
|
785
|
+
scrolls, not the page. It still grows past 0 via flex:1 whenever the
|
|
786
|
+
column has room, and 30vh remains the width->grid breakpoint's intent via
|
|
787
|
+
plain flex growth, not a floor that can outgrow its container. */
|
|
788
|
+
.ds-chat-layout { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: var(--space-3); }
|
|
777
789
|
.ds-chat-layout > .chat { min-width: 0; }
|
|
778
790
|
.ds-chat-detail { display: none; }
|
|
779
791
|
@media (min-width: 1100px) {
|
|
@@ -962,9 +974,14 @@
|
|
|
962
974
|
color: var(--fg-3);
|
|
963
975
|
line-height: 1.3;
|
|
964
976
|
}
|
|
965
|
-
/* Message body claims the full second line of the wrapping body row.
|
|
977
|
+
/* Message body claims the full second line of the wrapping body row. Capped
|
|
978
|
+
to a readable measure -- unlike .chat-bubble this is a flat list row, not
|
|
979
|
+
a two-sided bubble, but an uncapped prose line stretches the full pane
|
|
980
|
+
width (~970px), which reads as dead paper beside every short message
|
|
981
|
+
rather than an intentionally spacious flat list. */
|
|
966
982
|
.ds-community-msg-text {
|
|
967
983
|
flex: 1 0 100%;
|
|
984
|
+
max-width: 70ch;
|
|
968
985
|
margin: 0;
|
|
969
986
|
min-width: 0;
|
|
970
987
|
color: var(--fg-2);
|
|
@@ -188,7 +188,11 @@
|
|
|
188
188
|
border-radius: 50%;
|
|
189
189
|
background: var(--sky);
|
|
190
190
|
transform: translateY(-50%);
|
|
191
|
-
|
|
191
|
+
}
|
|
192
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
193
|
+
.chip.tone-live::before {
|
|
194
|
+
animation: chip-live-pulse 1.6s ease-in-out infinite;
|
|
195
|
+
}
|
|
192
196
|
}
|
|
193
197
|
@keyframes chip-live-pulse {
|
|
194
198
|
0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in oklab, var(--sky) 50%, transparent); }
|
|
@@ -317,3 +321,31 @@
|
|
|
317
321
|
.ds-tooltip { transition: none; }
|
|
318
322
|
}
|
|
319
323
|
|
|
324
|
+
/* -- Menubar -------------------------------------------------------------
|
|
325
|
+
Row of closed triggers (mirrors .ds-dp-trigger's affordance); without
|
|
326
|
+
this the wrapper and its item divs fall back to block-level UA defaults,
|
|
327
|
+
stacking the triggers vertically and rendering them as filled buttons
|
|
328
|
+
abutting any adjacent status text. */
|
|
329
|
+
.ds-menubar { display: inline-flex; align-items: center; gap: var(--space-1); }
|
|
330
|
+
.ds-menubar-item { display: inline-flex; }
|
|
331
|
+
.ds-menubar-trigger {
|
|
332
|
+
display: inline-flex;
|
|
333
|
+
align-items: center;
|
|
334
|
+
min-height: 32px;
|
|
335
|
+
padding: var(--space-1-5) var(--space-2-5);
|
|
336
|
+
border: 0;
|
|
337
|
+
border-radius: var(--r-2);
|
|
338
|
+
background: var(--bg-2);
|
|
339
|
+
color: var(--fg);
|
|
340
|
+
font-family: inherit;
|
|
341
|
+
font-size: var(--fs-sm);
|
|
342
|
+
cursor: pointer;
|
|
343
|
+
transition: background-color var(--dur-snap) var(--ease), color var(--dur-snap) var(--ease);
|
|
344
|
+
}
|
|
345
|
+
.ds-menubar-trigger:hover { background: var(--bg-3); }
|
|
346
|
+
.ds-menubar-trigger:focus-visible { box-shadow: var(--focus-ring-inset); outline: none; }
|
|
347
|
+
.ds-menubar-trigger.is-open { background: var(--bg-3); }
|
|
348
|
+
@media (prefers-reduced-motion: reduce) {
|
|
349
|
+
.ds-menubar-trigger { transition: none; }
|
|
350
|
+
}
|
|
351
|
+
|
|
@@ -77,6 +77,9 @@ button:not(:disabled):hover,
|
|
|
77
77
|
border-radius: 50%;
|
|
78
78
|
animation: spinner-rotate 0.8s linear infinite;
|
|
79
79
|
}
|
|
80
|
+
@media (prefers-reduced-motion: reduce) {
|
|
81
|
+
.loading::after { animation: none; }
|
|
82
|
+
}
|
|
80
83
|
|
|
81
84
|
/* Error state.
|
|
82
85
|
No !important: the only rule in the kit that also resets a matching element's
|
|
@@ -208,6 +211,16 @@ input[type="checkbox"], input[type="radio"] {
|
|
|
208
211
|
.list-item.drag-after::after { animation: pulse-line 0.6s ease-in-out infinite; }
|
|
209
212
|
}
|
|
210
213
|
|
|
214
|
+
/* ------------------------------------------------------------
|
|
215
|
+
Focus-visible for controls with no other component sheet
|
|
216
|
+
-------------------------------------------------------------- */
|
|
217
|
+
|
|
218
|
+
.ds-session-new:focus-visible,
|
|
219
|
+
.agentchat-cwd-btn:focus-visible {
|
|
220
|
+
outline: none;
|
|
221
|
+
box-shadow: var(--focus-ring-inset);
|
|
222
|
+
}
|
|
223
|
+
|
|
211
224
|
/* ------------------------------------------------------------
|
|
212
225
|
Context Menu Styles
|
|
213
226
|
-------------------------------------------------------------- */
|
|
@@ -775,6 +788,9 @@ input[type="password"]:not(:placeholder-shown) + .input-clear {
|
|
|
775
788
|
animation: skeleton-load 1.5s infinite;
|
|
776
789
|
border-radius: var(--r-2);
|
|
777
790
|
}
|
|
791
|
+
@media (prefers-reduced-motion: reduce) {
|
|
792
|
+
.skeleton { animation: none; }
|
|
793
|
+
}
|
|
778
794
|
|
|
779
795
|
@keyframes skeleton-load {
|
|
780
796
|
0% { background-position: 200% 0; }
|
|
@@ -72,8 +72,19 @@ body.canvas-host { background: transparent !important; }
|
|
|
72
72
|
-webkit-backdrop-filter: none; padding: 0; min-height: 0;
|
|
73
73
|
flex: 1 1 auto;
|
|
74
74
|
}
|
|
75
|
-
.app-chrome > .app-crumb { order: 1; flex: 1 1 auto; }
|
|
76
|
-
|
|
75
|
+
.app-chrome > .app-crumb { order: 1; flex: 1 1 auto; min-width: 0; }
|
|
76
|
+
/* flex:1 1 auto + min-width:0 (not the previous 0 0 auto): a merged
|
|
77
|
+
* chrome's topbar carries the search input, which has its own shrink
|
|
78
|
+
* basis (.ds-topbar-search, kits-appended.css) meant to yield space before
|
|
79
|
+
* the row wraps -- but a `0 0 auto` topbar box never shrinks itself, so the
|
|
80
|
+
* search input's flexibility was inert and the whole topbar instead
|
|
81
|
+
* dropped to a second line as one unit once combined crumb+topbar content
|
|
82
|
+
* exceeded the row (witnessed live on the search kit at 1280px: crumb
|
|
83
|
+
* 564px + topbar 596px overflowed a 1184px content box, wrapping the
|
|
84
|
+
* topbar under the crumb and reading as a broken sticky header). Letting
|
|
85
|
+
* the topbar itself shrink means the search input actually compresses
|
|
86
|
+
* first, keeping both bars on one line at realistic content widths. */
|
|
87
|
+
.app-chrome > .app-topbar { order: 2; flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
|
|
77
88
|
.app-chrome > .app-topbar > .brand { display: none; }
|
|
78
89
|
.app-chrome > .app-topbar > nav { margin-left: 0; }
|
|
79
90
|
.app-chrome > .app-crumb > .crumb-right { margin-left: auto; }
|
|
@@ -369,6 +380,7 @@ body.canvas-host { background: transparent !important; }
|
|
|
369
380
|
/* Full-height route children fill the region instead of scrolling the page. */
|
|
370
381
|
.app-main > .chat,
|
|
371
382
|
.app-main > .chat-area,
|
|
383
|
+
.app-main > .chat-kit-page,
|
|
372
384
|
.app-main > .ds-file-stage,
|
|
373
385
|
.app-main > .ds-files-stack,
|
|
374
386
|
.app-main > .grow { flex: 1 1 auto; min-height: 0; }
|
package/src/kits/os/theme.css
CHANGED
|
@@ -361,6 +361,7 @@ html, body {
|
|
|
361
361
|
* independent — replacing the `!important` wall that previously did the same
|
|
362
362
|
* job by force. Do not un-scope these; the scope IS the override mechanism. */
|
|
363
363
|
.ds-247420 .wm-win {
|
|
364
|
+
position: absolute;
|
|
364
365
|
background: var(--os-bg-1);
|
|
365
366
|
border: 1px solid color-mix(in oklab, var(--os-fg) 14%, transparent);
|
|
366
367
|
border-radius: var(--radius-lg, var(--r-3));
|