@workerdeck/ui 0.12.0 → 0.13.0

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.
@@ -28,8 +28,11 @@ export interface StatusBarProps {
28
28
  onOpenStatus?: () => void
29
29
  onOpenContext?: () => void
30
30
  onOpenUsage?: () => void
31
- /** Trailing slot — the session-actions menu, in the panel's top-right. */
31
+ /** Trailing slot — the session-actions menu, at the bar's trailing edge. */
32
32
  actions?: ReactNode
33
+ /** Which edge the bar sits on, so its separating rule goes on the other side.
34
+ * Placement is the panel's decision; this only styles it. */
35
+ placement?: 'top' | 'bottom'
33
36
  className?: string
34
37
  }
35
38
 
@@ -149,6 +152,7 @@ export function StatusBar({
149
152
  onOpenContext,
150
153
  onOpenUsage,
151
154
  actions,
155
+ placement = 'top',
152
156
  className,
153
157
  }: StatusBarProps) {
154
158
  const meta = STATUS_META[state.status]
@@ -160,7 +164,10 @@ export function StatusBar({
160
164
  <div
161
165
  data-slot='status-bar'
162
166
  className={cn(
163
- 'flex items-center gap-2 border-b border-border bg-surface px-3 py-1.5',
167
+ 'flex items-center gap-2 border-border bg-surface px-3 py-1.5',
168
+ // The rule goes between the bar and the content, so which edge it sits
169
+ // on follows the placement.
170
+ placement === 'bottom' ? 'border-t' : 'border-b',
164
171
  className,
165
172
  )}>
166
173
  {/* One slot, two meanings: connection trouble wins it, because a session
@@ -171,7 +171,7 @@ function RecapRow({ line, since }: { line: string; since?: number }) {
171
171
  if (lines) {
172
172
  return (
173
173
  <div data-slot='recap' className='flex items-baseline gap-2 py-0.5'>
174
- <LineGlyph className='text-accent'>※</LineGlyph>
174
+ <LineGlyph className='text-fg-3'>※</LineGlyph>
175
175
  <span className='min-w-0 flex-1 text-label leading-5 text-fg-3'>
176
176
  <span className='text-fg-2'>recap:</span> {text}
177
177
  </span>
@@ -260,9 +260,8 @@ function SentAttachments({
260
260
  attachments: MessageAttachment[]
261
261
  attachmentUrl?: (attachmentId: string) => string
262
262
  }) {
263
- const lines = useLines()
264
263
  return (
265
- <div className={cn('mb-1 flex flex-wrap gap-1.5', lines ? 'justify-start' : 'justify-end')}>
264
+ <div className='mb-1 flex flex-wrap justify-start gap-1.5'>
266
265
  {attachments.map((attachment) => {
267
266
  const href = attachmentUrl?.(attachment.id)
268
267
  return attachment.mediaType.startsWith('image/') && href ? (
@@ -128,7 +128,7 @@ export function LineOptionList({
128
128
  'flex w-full items-baseline gap-2 text-left outline-none',
129
129
  isFocused ? 'bg-surface-hover' : 'hover:bg-surface-hover/60',
130
130
  )}>
131
- <LineGlyph className={isFocused ? 'text-accent' : undefined}>
131
+ <LineGlyph className={isFocused ? 'text-fg-1' : undefined}>
132
132
  {isFocused ? '❯' : ' '}
133
133
  </LineGlyph>
134
134
  <span className='shrink-0 font-mono text-label leading-5 text-fg-4'>{index + 1}</span>
@@ -184,7 +184,7 @@ export function LineInput({
184
184
  }) {
185
185
  return (
186
186
  <div className='flex items-baseline gap-2'>
187
- <LineGlyph className='text-accent'>›</LineGlyph>
187
+ <LineGlyph className='text-fg-3'>›</LineGlyph>
188
188
  <input
189
189
  autoFocus
190
190
  value={value}
@@ -14,7 +14,7 @@ export const MenuContent: FunctionComponent<
14
14
  align={align}
15
15
  side={side}
16
16
  sideOffset={sideOffset}
17
- className='isolate z-60 outline-none'>
17
+ className='isolate z-80 outline-none'>
18
18
  <MenuPrimitive.Popup
19
19
  data-slot='menu-content'
20
20
  className={cn(
@@ -45,7 +45,7 @@ export const SelectContent: FunctionComponent<
45
45
  alignItemWithTrigger={alignItemWithTrigger}
46
46
  side={side}
47
47
  sideOffset={sideOffset}
48
- className='isolate z-60 outline-none'>
48
+ className='isolate z-80 outline-none'>
49
49
  <SelectPrimitive.Popup
50
50
  data-slot='select-content'
51
51
  className={cn(
@@ -8,7 +8,7 @@ export const TooltipContent: FunctionComponent<
8
8
  TooltipPrimitive.Popup.Props & Pick<TooltipPrimitive.Positioner.Props, 'side' | 'sideOffset'>
9
9
  > = ({ className, side = 'top', sideOffset = 6, ...props }) => (
10
10
  <TooltipPrimitive.Portal>
11
- <TooltipPrimitive.Positioner side={side} sideOffset={sideOffset} className='isolate z-60'>
11
+ <TooltipPrimitive.Positioner side={side} sideOffset={sideOffset} className='isolate z-90'>
12
12
  <TooltipPrimitive.Popup
13
13
  data-slot='tooltip-content'
14
14
  className={cn(
package/src/index.ts CHANGED
@@ -136,7 +136,15 @@ export {
136
136
  type SessionListItemProps,
137
137
  type SessionListProps,
138
138
  } from './components/agent/SessionList.tsx'
139
- export { SessionBrowser, type SessionBrowserProps } from './components/agent/SessionBrowser.tsx'
139
+ export {
140
+ SessionBrowser,
141
+ rowShapeClass,
142
+ type SessionBrowserProps,
143
+ } from './components/agent/SessionBrowser.tsx'
144
+ export { SessionStatusIcon } from './components/agent/SessionBrowser.tsx'
145
+ // Lifted out of the VS Code sidebar once the dashboard grew a collapsed rail
146
+ // that needs the same glyph — two copies of a trademark set is one too many.
147
+ export { EngineIcon } from './components/agent/EngineIcon.tsx'
140
148
  export {
141
149
  SessionEmptyState,
142
150
  type SessionEmptyStateProps,
@@ -24,6 +24,15 @@
24
24
  --bg-code: #f5f5f5;
25
25
  --bg-elevated: #ffffffcc;
26
26
 
27
+ /* A list row's hover and selected fills. **Alpha, not a flat colour**, because
28
+ a row sits on whatever its host paints — `bg-sidebar` in the dashboard,
29
+ `--vscode-sideBar-background` in the extension — and a flat value tuned for
30
+ one of those is invisible on the others. `--bg-surface-hover` was exactly
31
+ that mistake: on the dark sidebar (#131313) it lands on #141414, one step
32
+ of 255 away, so the hover state did not exist. */
33
+ --row-hover: rgb(0 0 0 / 0.05);
34
+ --row-active: rgb(0 0 0 / 0.08);
35
+
27
36
  /* ---------- Borders ---------- */
28
37
  --border: #ebebeb;
29
38
  --border-light: #e0e0e0;
@@ -36,12 +45,19 @@
36
45
  --fg-4: #a1a1a1;
37
46
  --fg-disabled: #c9c9c9;
38
47
 
39
- /* ---------- Accent = the inverse of the canvas ---------- */
40
- --accent: #171717;
41
- --accent-hover: #000000;
42
- --accent-dim: #737373;
43
- --accent-bg: #f2f2f2;
44
- --accent-ring: #17171733;
48
+ /* ---------- Accent ----------
49
+ * VS Code blue (`#0078d4`) — the product's primary. It is the *same* hue in
50
+ * both themes rather than the inverse of the canvas: a primary that flips
51
+ * from near-black to near-white is a contrast device, not a brand colour, and
52
+ * WorkerDeck now shares an editor's visual language.
53
+ *
54
+ * Not to be confused with the brand's live green (`docs/assets/BRAND.md`),
55
+ * which stays what it is — a *signal*, not a primary. */
56
+ --accent: #0078d4;
57
+ --accent-hover: #106ebe;
58
+ --accent-dim: #6ca9d8;
59
+ --accent-bg: #eff6fc;
60
+ --accent-ring: #0078d433;
45
61
 
46
62
  /* ---------- Semantic ---------- */
47
63
  --success: #0f7b4f;
@@ -72,7 +88,9 @@
72
88
  --accent-tint: var(--accent-bg);
73
89
  --accent-fg: #ffffff;
74
90
  --warn: var(--warning);
75
- --ring: var(--fg-1);
91
+ /* Focus ring is the accent, as in an editor — the comment below already said
92
+ * "accent-derived"; before the blue it was indistinguishable from fg-1. */
93
+ --ring: var(--accent);
76
94
  }
77
95
 
78
96
  [data-theme='dark'] {
@@ -83,6 +101,9 @@
83
101
  --bg-code: #141414;
84
102
  --bg-elevated: #0a0a0acc;
85
103
 
104
+ --row-hover: rgb(255 255 255 / 0.06);
105
+ --row-active: rgb(255 255 255 / 0.10);
106
+
86
107
  /* ---------- Borders ---------- */
87
108
  --border: #1f1f1f;
88
109
  --border-light: #292929;
@@ -95,12 +116,16 @@
95
116
  --fg-4: #6e6e6e;
96
117
  --fg-disabled: #454545;
97
118
 
98
- /* ---------- Accent = the inverse of the canvas ---------- */
99
- --accent: #ededed;
100
- --accent-hover: #ffffff;
101
- --accent-dim: #8f8f8f;
102
- --accent-bg: #1f1f1f;
103
- --accent-ring: #ffffff3d;
119
+ /* ---------- Accent ----------
120
+ * The same blue as light. `--accent` stays `#0078d4` because it is a *fill*
121
+ * carrying white text (4.6:1) — the brighter `#3794ff` would drop that to
122
+ * 2.9:1. The bright one is the hover and the ring, where nothing sits on top
123
+ * of it and the extra lift is what a dark canvas needs. */
124
+ --accent: #0078d4;
125
+ --accent-hover: #3794ff;
126
+ --accent-dim: #4a7ba0;
127
+ --accent-bg: #12283c;
128
+ --accent-ring: #3794ff4d;
104
129
 
105
130
  /* ---------- Semantic ---------- */
106
131
  --success: #3ecf8e;
@@ -131,9 +156,12 @@
131
156
  --text: var(--fg-1);
132
157
  --text-muted: var(--fg-3);
133
158
  --accent-tint: var(--accent-bg);
134
- --accent-fg: #0a0a0a;
159
+ /* White on the blue fill in both themes — the accent no longer inverts. */
160
+ --accent-fg: #ffffff;
135
161
  --warn: var(--warning);
136
- --ring: var(--fg-1);
162
+ /* Focus ring is the accent, as in an editor — the comment below already said
163
+ * "accent-derived"; before the blue it was indistinguishable from fg-1. */
164
+ --ring: var(--accent);
137
165
  }
138
166
 
139
167
  /* Theme-independent tokens — type tracking, easing, fonts.
@@ -188,6 +216,8 @@
188
216
  --color-ring: var(--ring);
189
217
 
190
218
  --color-surface-hover: var(--bg-surface-hover);
219
+ --color-row-hover: var(--row-hover);
220
+ --color-row-active: var(--row-active);
191
221
  /* Named code-bg (not code) so it can't shadow the --text-code font-size token:
192
222
  with a --color-code defined, `text-code` would resolve to the color namespace
193
223
  and paint text in the code *background* color — invisible in both themes. */