anentrypoint-design 0.0.228 → 0.0.230
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/app-shell.css +18 -0
- package/chat.css +3 -0
- package/dist/247420.css +21 -0
- package/dist/247420.js +13 -13
- package/package.json +1 -1
- package/src/components/agent-chat.js +14 -3
- package/src/components/chat.js +31 -14
- package/src/components/context-pane.js +23 -8
- package/src/components/files-modals.js +21 -10
- package/src/components/files.js +3 -6
- package/src/components/overlay-primitives.js +47 -9
- package/src/components/sessions.js +15 -6
- package/src/components/shell.js +38 -16
- package/src/kits/os/theme.css +4 -0
package/src/components/shell.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// webjsx vnode out. CSS in app-shell.css uses these class names.
|
|
4
4
|
|
|
5
5
|
import * as webjsx from '../../vendor/webjsx/index.js';
|
|
6
|
+
import { trapTab } from './overlay-primitives.js';
|
|
6
7
|
const h = webjsx.createElement;
|
|
7
8
|
|
|
8
9
|
export function Brand({ name = '247420', leaf } = {}) {
|
|
@@ -324,8 +325,12 @@ function toggleWs(which) {
|
|
|
324
325
|
: which === 'sessions' ? 'ws-sessions-collapsed'
|
|
325
326
|
: 'ws-rail-collapsed';
|
|
326
327
|
const nowCollapsed = shell.classList.toggle(cls);
|
|
327
|
-
document.querySelectorAll('.ws-' + which + '-toggle').forEach((btn) =>
|
|
328
|
-
btn.setAttribute('aria-expanded', nowCollapsed ? 'false' : 'true')
|
|
328
|
+
document.querySelectorAll('.ws-' + which + '-toggle').forEach((btn) => {
|
|
329
|
+
btn.setAttribute('aria-expanded', nowCollapsed ? 'false' : 'true');
|
|
330
|
+
const nextLabel = nowCollapsed ? 'expand ' + which : 'collapse ' + which;
|
|
331
|
+
btn.setAttribute('aria-label', nextLabel);
|
|
332
|
+
btn.setAttribute('title', nextLabel);
|
|
333
|
+
});
|
|
329
334
|
try {
|
|
330
335
|
localStorage.setItem('ds.ws.' + which, nowCollapsed ? 'collapsed' : 'open');
|
|
331
336
|
} catch (_) {}
|
|
@@ -416,12 +421,18 @@ function toggleWsDrawer(which, open) {
|
|
|
416
421
|
if (next) shell.classList.remove(other);
|
|
417
422
|
const btn = document.querySelector('.ws-' + which + '-drawer-toggle');
|
|
418
423
|
if (btn) btn.setAttribute('aria-expanded', next ? 'true' : 'false');
|
|
419
|
-
// When opening, move focus into the drawer
|
|
424
|
+
// When opening, move focus into the drawer, arm an Esc-to-close, and trap
|
|
425
|
+
// Tab/Shift+Tab inside the drawer (a real focus trap, matching the kit's
|
|
426
|
+
// own dialogs - Tab from inside an open drawer previously walked focus out
|
|
427
|
+
// into the scrim/background content behind it).
|
|
420
428
|
if (next) {
|
|
421
429
|
const drawer = shell.querySelector(which === 'pane' ? '.ws-pane' : '.ws-sessions');
|
|
422
430
|
const focusable = drawer && drawer.querySelector('button, a, input, [tabindex]');
|
|
423
431
|
if (focusable) try { focusable.focus(); } catch (_) {}
|
|
424
|
-
const onKey = (e) => {
|
|
432
|
+
const onKey = (e) => {
|
|
433
|
+
if (e.key === 'Escape') { toggleWsDrawer(which, false); document.removeEventListener('keydown', onKey); if (btn) try { btn.focus(); } catch (_) {} return; }
|
|
434
|
+
if (drawer) trapTab(drawer, e);
|
|
435
|
+
};
|
|
425
436
|
shell._wsEscHandler = onKey;
|
|
426
437
|
document.addEventListener('keydown', onKey);
|
|
427
438
|
}
|
|
@@ -474,16 +485,20 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
474
485
|
// pane, so the shell does not re-flow its column count (4/3/2) on every tab
|
|
475
486
|
// switch - the loudest "separate pages" tell. The track collapses to width 0
|
|
476
487
|
// (ws-pane-collapsed) instead of being removed (ws-no-pane), so chat/history/
|
|
477
|
-
// files/live/settings all keep the same column geometry.
|
|
488
|
+
// files/live/settings all keep the same column geometry. The sessions column
|
|
489
|
+
// gets the identical treatment (ws-sessions-collapsed instead of ws-no-sessions)
|
|
490
|
+
// so files/live/settings do not shift the main column when sessions is null.
|
|
478
491
|
const keepPaneTrack = stableFrame && !hasPane;
|
|
492
|
+
const keepSessionsTrack = stableFrame && !hasSessions;
|
|
479
493
|
const railIsCollapsed = wsCollapsed('rail', railCollapsed);
|
|
480
494
|
const paneIsCollapsed = hasPane ? wsCollapsed('pane', paneCollapsed) : true;
|
|
481
|
-
const sessionsIsCollapsed = wsCollapsed('sessions', false);
|
|
495
|
+
const sessionsIsCollapsed = hasSessions ? wsCollapsed('sessions', false) : true;
|
|
482
496
|
const shellCls = 'ws-shell'
|
|
483
497
|
+ (railIsCollapsed ? ' ws-rail-collapsed' : '')
|
|
484
498
|
+ ((hasPane || keepPaneTrack) ? '' : ' ws-no-pane')
|
|
485
499
|
+ (((hasPane && paneIsCollapsed) || keepPaneTrack) ? ' ws-pane-collapsed' : '')
|
|
486
|
-
+ (hasSessions ? '' : ' ws-no-sessions')
|
|
500
|
+
+ ((hasSessions || keepSessionsTrack) ? '' : ' ws-no-sessions')
|
|
501
|
+
+ (((hasSessions && sessionsIsCollapsed) || keepSessionsTrack) ? ' ws-sessions-collapsed' : '')
|
|
487
502
|
+ (narrow ? ' narrow' : '');
|
|
488
503
|
return h('div', { class: shellCls, ref: seedWsWidths },
|
|
489
504
|
h('a', { href: '#ws-main', class: 'skip-link' }, 'skip to main content'),
|
|
@@ -506,7 +521,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
506
521
|
// Optional sessions column. On mobile it is a drawer; selecting a row
|
|
507
522
|
// (any button click inside) auto-closes it, mirroring AppShell.
|
|
508
523
|
hasSessions
|
|
509
|
-
? h('div', { class: 'ws-sessions', role: 'complementary', 'aria-label': 'conversations',
|
|
524
|
+
? h('div', { id: 'ws-sessions-col', class: 'ws-sessions', role: 'complementary', 'aria-label': 'conversations',
|
|
510
525
|
onclick: (e) => { if (window.innerWidth <= 1100 && e.target.closest('button, a, [role="button"]')) closeWsDrawers(); } }, sessions)
|
|
511
526
|
: null,
|
|
512
527
|
// Primary content column, with an optional thin crumb bar on top. On
|
|
@@ -519,6 +534,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
519
534
|
hasSessions ? h('button', {
|
|
520
535
|
class: 'ws-drawer-toggle ws-sessions-drawer-toggle', type: 'button',
|
|
521
536
|
'aria-label': 'toggle conversations', 'aria-expanded': 'false',
|
|
537
|
+
'aria-controls': 'ws-sessions-col',
|
|
522
538
|
onclick: () => toggleWsDrawer('sessions'),
|
|
523
539
|
}, Icon('thread')) : null,
|
|
524
540
|
// Desktop-only sessions collapse (reclaims its width for a
|
|
@@ -528,7 +544,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
528
544
|
'aria-label': sessionsIsCollapsed ? 'expand conversations' : 'collapse conversations',
|
|
529
545
|
title: sessionsIsCollapsed ? 'expand conversations' : 'collapse conversations',
|
|
530
546
|
'aria-expanded': sessionsIsCollapsed ? 'false' : 'true', onclick: () => toggleWs('sessions'),
|
|
531
|
-
}, Icon('chevron-left')) : null,
|
|
547
|
+
}, Icon(sessionsIsCollapsed ? 'chevron-right' : 'chevron-left')) : null,
|
|
532
548
|
h('div', { class: 'ws-crumb-main' }, crumb),
|
|
533
549
|
// Desktop-only context-pane collapse, on the same crumb-level
|
|
534
550
|
// chrome idiom as the sessions toggle. Hidden on mobile via CSS.
|
|
@@ -542,6 +558,7 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
542
558
|
hasPane ? h('button', {
|
|
543
559
|
class: 'ws-drawer-toggle ws-pane-drawer-toggle', type: 'button',
|
|
544
560
|
'aria-label': 'toggle context pane', 'aria-expanded': 'false',
|
|
561
|
+
'aria-controls': 'ws-pane-col',
|
|
545
562
|
onclick: () => toggleWsDrawer('pane'),
|
|
546
563
|
}, Icon('page')) : null)
|
|
547
564
|
: null,
|
|
@@ -551,13 +568,13 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
551
568
|
// Optional right context pane. Its desktop collapse toggle now lives in
|
|
552
569
|
// the crumb cluster, alongside the sessions toggle.
|
|
553
570
|
hasPane
|
|
554
|
-
? h('aside', { class: 'ws-pane', role: 'complementary', 'aria-label': paneLabel },
|
|
571
|
+
? h('aside', { id: 'ws-pane-col', class: 'ws-pane', role: 'complementary', 'aria-label': paneLabel },
|
|
555
572
|
pane)
|
|
556
573
|
: null,
|
|
557
574
|
// Keyboard/pointer column resize handles (desktop only).
|
|
558
575
|
(!narrow && !railIsCollapsed) ? WsResizer('rail') : null,
|
|
559
|
-
(!narrow && hasSessions) ? WsResizer('sessions') : null,
|
|
560
|
-
(!narrow && hasPane && !paneIsCollapsed) ? WsResizer('pane') : null,
|
|
576
|
+
(!narrow && (hasSessions || keepSessionsTrack) && !sessionsIsCollapsed) ? WsResizer('sessions') : null,
|
|
577
|
+
(!narrow && (hasPane || keepPaneTrack) && !paneIsCollapsed) ? WsResizer('pane') : null,
|
|
561
578
|
);
|
|
562
579
|
}
|
|
563
580
|
|
|
@@ -568,7 +585,11 @@ export function WorkspaceShell({ rail, sessions, main, pane, crumb, status, narr
|
|
|
568
585
|
//
|
|
569
586
|
// brand : short product name shown in the rail header.
|
|
570
587
|
// action : { label, icon, onClick } a prominent primary button (New chat).
|
|
571
|
-
// items : [{ key, label, icon, active, count, onClick }] nav entries.
|
|
588
|
+
// items : [{ key, label, icon, active, count, rail, onClick }] nav entries.
|
|
589
|
+
// `rail` (optional tone e.g. 'flame') paints an attention dot on the
|
|
590
|
+
// item — used when something in that surface needs the user's eyes
|
|
591
|
+
// even though they are looking at a different tab (e.g. a live
|
|
592
|
+
// session in error while the user is in Chat).
|
|
572
593
|
// footer : optional vnode pinned to the rail bottom (e.g. settings/theme).
|
|
573
594
|
export function WorkspaceRail({ brand = '247420', action, items = [], footer } = {}) {
|
|
574
595
|
return h('div', { class: 'ws-rail-inner' },
|
|
@@ -585,9 +606,9 @@ export function WorkspaceRail({ brand = '247420', action, items = [], footer } =
|
|
|
585
606
|
...items.map((it) => h('li', { key: it.key || it.label, role: 'listitem' },
|
|
586
607
|
h('button', {
|
|
587
608
|
type: 'button',
|
|
588
|
-
class: 'ws-rail-item' + (it.active ? ' active' : ''),
|
|
609
|
+
class: 'ws-rail-item' + (it.active ? ' active' : '') + (it.rail ? ' has-rail-flag' : ''),
|
|
589
610
|
'aria-current': it.active ? 'page' : null,
|
|
590
|
-
'aria-label': it.label + (it.count ? ' (' + it.count + ')' : ''),
|
|
611
|
+
'aria-label': it.label + (it.count ? ' (' + it.count + ')' : '') + (it.rail === 'flame' ? ', needs attention' : ''),
|
|
591
612
|
title: it.label,
|
|
592
613
|
onclick: it.onClick || null,
|
|
593
614
|
},
|
|
@@ -595,7 +616,8 @@ export function WorkspaceRail({ brand = '247420', action, items = [], footer } =
|
|
|
595
616
|
h('span', { class: 'ws-rail-item-label' }, it.label),
|
|
596
617
|
(it.count != null && it.count !== 0 && it.count !== '0')
|
|
597
618
|
? h('span', { class: 'ws-rail-item-count', 'aria-hidden': 'true' }, String(it.count))
|
|
598
|
-
: null
|
|
619
|
+
: null,
|
|
620
|
+
it.rail ? h('span', { class: 'ws-rail-item-flag tone-' + it.rail, 'aria-hidden': 'true' }) : null)))),
|
|
599
621
|
footer ? h('div', { class: 'ws-rail-foot' }, footer) : null,
|
|
600
622
|
);
|
|
601
623
|
}
|
package/src/kits/os/theme.css
CHANGED
|
@@ -1299,6 +1299,10 @@ html.ds-247420 { touch-action: pan-x pan-y; overscroll-behavior: none; -webkit-t
|
|
|
1299
1299
|
cursor: not-allowed;
|
|
1300
1300
|
background: color-mix(in oklab, var(--fg) 25%, transparent);
|
|
1301
1301
|
}
|
|
1302
|
+
.ds-247420 .chat-composer.is-disabled {
|
|
1303
|
+
opacity: .55;
|
|
1304
|
+
pointer-events: none;
|
|
1305
|
+
}
|
|
1302
1306
|
|
|
1303
1307
|
.ds-247420 .ds-icon { --ds-icon-stroke: 1.7; }
|
|
1304
1308
|
|