@silo-code/sdk 0.31.0 → 0.33.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.
Files changed (55) hide show
  1. package/dist/ActivityGlyph.d.ts +25 -0
  2. package/dist/ActivityGlyph.d.ts.map +1 -0
  3. package/dist/ActivityGlyph.js +25 -0
  4. package/dist/ActivityGlyph.js.map +1 -0
  5. package/dist/IconButton.d.ts +23 -6
  6. package/dist/IconButton.d.ts.map +1 -1
  7. package/dist/IconButton.js +14 -5
  8. package/dist/IconButton.js.map +1 -1
  9. package/dist/activity.d.ts +36 -0
  10. package/dist/activity.d.ts.map +1 -0
  11. package/dist/activity.js +33 -0
  12. package/dist/activity.js.map +1 -0
  13. package/dist/editor-service.d.ts +5 -1
  14. package/dist/editor-service.d.ts.map +1 -1
  15. package/dist/icon-button-classes.d.ts +10 -2
  16. package/dist/icon-button-classes.d.ts.map +1 -1
  17. package/dist/icon-button-classes.js +9 -5
  18. package/dist/icon-button-classes.js.map +1 -1
  19. package/dist/index.d.ts +7 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/phosphor-icon.d.ts +15 -0
  24. package/dist/phosphor-icon.d.ts.map +1 -0
  25. package/dist/phosphor-icon.js +2 -0
  26. package/dist/phosphor-icon.js.map +1 -0
  27. package/dist/tab-adornment.d.ts +242 -0
  28. package/dist/tab-adornment.d.ts.map +1 -0
  29. package/dist/tab-adornment.js +2 -0
  30. package/dist/tab-adornment.js.map +1 -0
  31. package/dist/terminal-service.d.ts +18 -35
  32. package/dist/terminal-service.d.ts.map +1 -1
  33. package/dist/toolbar-items.d.ts +171 -0
  34. package/dist/toolbar-items.d.ts.map +1 -0
  35. package/dist/toolbar-items.js +2 -0
  36. package/dist/toolbar-items.js.map +1 -0
  37. package/dist/types.d.ts +15 -0
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/workspace-service.d.ts +66 -45
  40. package/dist/workspace-service.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/ActivityGlyph.tsx +43 -0
  43. package/src/IconButton.tsx +28 -6
  44. package/src/activity.test.ts +35 -0
  45. package/src/activity.ts +57 -0
  46. package/src/editor-service.ts +5 -1
  47. package/src/icon-button-classes.test.ts +10 -0
  48. package/src/icon-button-classes.ts +18 -5
  49. package/src/index.ts +35 -1
  50. package/src/phosphor-icon.ts +14 -0
  51. package/src/tab-adornment.ts +261 -0
  52. package/src/terminal-service.ts +21 -35
  53. package/src/toolbar-items.ts +190 -0
  54. package/src/types.ts +17 -0
  55. package/src/workspace-service.ts +72 -45
@@ -1,5 +1,6 @@
1
1
  import type { Disposable } from "./types.js";
2
2
  import type { Workspace } from "./domain-types.js";
3
+ import type { Activity } from "./activity.js";
3
4
  export type { Workspace, TerminalRecord } from "./domain-types.js";
4
5
  /**
5
6
  * A single status row contributed by a {@link WorkspaceStatusProvider}.
@@ -11,8 +12,11 @@ export type { Workspace, TerminalRecord } from "./domain-types.js";
11
12
  export interface WorkspaceStatusRow {
12
13
  /** Stable key unique within this provider's results; used for reconciliation. */
13
14
  id: string;
14
- /** Semantic status dot shown to the left of the label. */
15
- status?: "ok" | "warn" | "busy" | "error";
15
+ /**
16
+ * Host-owned {@link Activity} glyph to the left of the label. Omit for the
17
+ * neutral gray fallback (same as today’s omitted `status`). See ADR 0030.
18
+ */
19
+ activity?: Activity;
16
20
  /** Short label — the host truncates with an ellipsis when space is tight. */
17
21
  label: string;
18
22
  /**
@@ -66,21 +70,22 @@ export interface WorkspaceBadge {
66
70
  /** Short text rendered inside the badge. */
67
71
  text: string;
68
72
  /**
69
- * CSS color applied to both the badge border and text. Falls back to the
70
- * muted text color (`--silo-color-text-lo`) when omitted.
73
+ * Solid chip fill color. Text paints white on top for contrast. Falls back
74
+ * to a muted solid background + hi text when omitted.
71
75
  */
72
76
  color?: string;
73
77
  }
74
78
  /**
75
- * A badge provider that contributes {@link WorkspaceBadge}s next to the
76
- * workspace name in the Workspaces side panel. Register via
77
- * {@link WorkspaceService.registerBadge}.
79
+ * A badge binder that contributes {@link WorkspaceBadge}s next to the
80
+ * workspace name in the Workspaces side panel. Prefer
81
+ * {@link WorkspaceService.bindBadge}; {@link WorkspaceService.registerBadge}
82
+ * remains as a deprecated alias.
78
83
  *
79
84
  * @category Consumer Services
80
85
  * @public
81
86
  */
82
87
  export interface WorkspaceBadgeProvider {
83
- /** Unique id for this provider — conventionally `"<extension-id>.badges"`. */
88
+ /** Unique id for this binder — conventionally `"<extension-id>.badges"`. */
84
89
  id: string;
85
90
  /**
86
91
  * Called synchronously for each workspace during render. Return an empty
@@ -89,15 +94,19 @@ export interface WorkspaceBadgeProvider {
89
94
  provide(workspaceId: string): WorkspaceBadge[];
90
95
  }
91
96
  /**
92
- * A status provider that contributes {@link WorkspaceStatusRow}s to
93
- * workspace rows in the Workspaces side panel. Register via
94
- * {@link WorkspaceService.registerStatus}.
97
+ * A status binder that contributes {@link WorkspaceStatusRow}s to
98
+ * workspace rows in the Workspaces side panel. Prefer
99
+ * {@link WorkspaceService.bindStatus}; {@link WorkspaceService.registerStatus}
100
+ * remains as a deprecated alias.
101
+ *
102
+ * Unlike CenterDock tab `bindIndicator` (single adornment | null), status
103
+ * and badge binders return an **array** — one projection may emit many rows.
95
104
  *
96
105
  * @category Consumer Services
97
106
  * @public
98
107
  */
99
108
  export interface WorkspaceStatusProvider {
100
- /** Unique id for this provider — conventionally `"<extension-id>.status"`. */
109
+ /** Unique id for this binder — conventionally `"<extension-id>.status"`. */
101
110
  id: string;
102
111
  /**
103
112
  * Called synchronously for each workspace during render. Return an empty
@@ -246,47 +255,56 @@ export interface WorkspaceService {
246
255
  */
247
256
  delete(id: string): Promise<void>;
248
257
  /**
249
- * Register a status provider that contributes status rows to workspace
250
- * rows in the Workspaces side panel. Multiple providers may be registered;
251
- * their rows are concatenated in registration order. Returns a
252
- * {@link Disposable} that unregisters the provider.
258
+ * Imperatively adorn a workspace row with a status line. `row.id` is the
259
+ * adornment key for {@link WorkspaceService.clearStatus}.
260
+ */
261
+ setStatus(workspaceId: string, row: WorkspaceStatusRow): void;
262
+ /** Remove an imperative status row previously set via {@link WorkspaceService.setStatus}. */
263
+ clearStatus(workspaceId: string, rowId: string): void;
264
+ /**
265
+ * Keep a status projection in sync for every workspace. `provide` returns
266
+ * an array of rows (may be empty). Prefer this over repeatedly calling
267
+ * {@link WorkspaceService.setStatus}.
253
268
  *
254
269
  * @example
255
270
  * ```ts
256
271
  * ctx.subscriptions.push(
257
- * ctx.workspaces.registerStatus({
272
+ * ctx.workspaces.bindStatus({
258
273
  * id: "my-ext.status",
259
274
  * provide(workspaceId) {
260
275
  * const running = getRunningTasks(workspaceId);
261
- * return running.map(t => ({ id: t.id, status: "busy", label: t.name, startedAt: t.startedAt }));
276
+ * return running.map(t => ({ id: t.id, activity: "working", label: t.name, startedAt: t.startedAt }));
262
277
  * },
263
278
  * }),
264
- * ctx.workspaces.subscribeStatus(() => ctx.workspaces.invalidateStatus()),
265
279
  * );
266
280
  * ```
267
281
  */
282
+ bindStatus(binder: WorkspaceStatusProvider): Disposable;
283
+ /**
284
+ * @deprecated Prefer {@link WorkspaceService.bindStatus}.
285
+ */
268
286
  registerStatus(provider: WorkspaceStatusProvider): Disposable;
269
287
  /**
270
- * Concatenate all registered providers' rows for one workspace (in
271
- * registration order). Called synchronously during panel render — providers
272
- * must be fast and side-effect-free.
288
+ * Concatenate imperative rows and all binders' rows for one workspace (in
289
+ * binder registration order). Called synchronously during panel render —
290
+ * binders must be fast and side-effect-free.
273
291
  */
274
292
  getStatus(workspaceId: string): WorkspaceStatusRow[];
275
293
  /**
276
- * Signal that status data has changed. Fires all listeners registered
294
+ * Signal that binder data has changed. Fires all listeners registered
277
295
  * via {@link WorkspaceService.subscribeStatus}, causing the Workspaces
278
- * panel to re-query providers and re-render the status rows.
296
+ * panel to re-query binders and re-render the status rows.
279
297
  *
280
298
  * Call this after any mutation to the state your `provide` function reads.
299
+ * Imperative {@link WorkspaceService.setStatus} / {@link WorkspaceService.clearStatus}
300
+ * already notify listeners.
281
301
  */
282
302
  invalidateStatus(): void;
283
303
  /**
284
304
  * Subscribe to status invalidations. The listener is called whenever
285
- * {@link WorkspaceService.invalidateStatus} is invoked. Returns a
286
- * {@link Disposable} that cancels the subscription.
287
- *
288
- * The Workspaces panel subscribes internally; extensions may also subscribe
289
- * to observe invalidations.
305
+ * {@link WorkspaceService.invalidateStatus} is invoked (or imperative
306
+ * set/clear runs). Returns a {@link Disposable} that cancels the
307
+ * subscription.
290
308
  */
291
309
  subscribeStatus(listener: () => void): Disposable;
292
310
  /**
@@ -353,15 +371,20 @@ export interface WorkspaceService {
353
371
  */
354
372
  registerPropertyPage(page: WorkspacePropertyPage): Disposable;
355
373
  /**
356
- * Register a badge provider that contributes {@link WorkspaceBadge}s next to
357
- * the workspace name in the Workspaces side panel. Multiple providers may be
358
- * registered; their badges are concatenated in registration order. Returns a
359
- * {@link Disposable} that unregisters the provider.
374
+ * Imperatively adorn a workspace name with a badge. `badge.id` is the
375
+ * adornment key for {@link WorkspaceService.clearBadge}.
376
+ */
377
+ setBadge(workspaceId: string, badge: WorkspaceBadge): void;
378
+ /** Remove an imperative badge previously set via {@link WorkspaceService.setBadge}. */
379
+ clearBadge(workspaceId: string, badgeId: string): void;
380
+ /**
381
+ * Keep a badge projection in sync for every workspace. `provide` returns
382
+ * an array of badges (may be empty).
360
383
  *
361
384
  * @example
362
385
  * ```ts
363
386
  * ctx.subscriptions.push(
364
- * ctx.workspaces.registerBadge({
387
+ * ctx.workspaces.bindBadge({
365
388
  * id: "my-ext.badges",
366
389
  * provide(workspaceId) {
367
390
  * const status = getStatus(workspaceId);
@@ -372,25 +395,23 @@ export interface WorkspaceService {
372
395
  * );
373
396
  * ```
374
397
  */
398
+ bindBadge(binder: WorkspaceBadgeProvider): Disposable;
399
+ /**
400
+ * @deprecated Prefer {@link WorkspaceService.bindBadge}.
401
+ */
375
402
  registerBadge(provider: WorkspaceBadgeProvider): Disposable;
376
403
  /**
377
- * Concatenate all registered providers' badges for one workspace (in
378
- * registration order). Called synchronously during panel render — providers
379
- * must be fast and side-effect-free.
404
+ * Concatenate imperative badges and all binders' badges for one workspace
405
+ * (in binder registration order).
380
406
  */
381
407
  getBadges(workspaceId: string): WorkspaceBadge[];
382
408
  /**
383
- * Signal that badge data has changed. Fires all listeners registered via
384
- * {@link WorkspaceService.subscribeBadges}, causing the Workspaces panel to
385
- * re-query providers and re-render the name row.
386
- *
387
- * Call this after any mutation to the state your `provide` function reads.
409
+ * Signal that badge binder data has changed. Imperative set/clear already
410
+ * notify listeners.
388
411
  */
389
412
  invalidateBadges(): void;
390
413
  /**
391
- * Subscribe to badge invalidations. The listener is called whenever
392
- * {@link WorkspaceService.invalidateBadges} is invoked. Returns a
393
- * {@link Disposable} that cancels the subscription.
414
+ * Subscribe to badge invalidations.
394
415
  */
395
416
  subscribeBadges(listener: () => void): Disposable;
396
417
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-service.d.ts","sourceRoot":"","sources":["../src/workspace-service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workspace-service.d.ts","sourceRoot":"","sources":["../src/workspace-service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silo-code/sdk",
3
- "version": "0.31.0",
3
+ "version": "0.33.0",
4
4
  "description": "The public, types-first SDK for building Silo extensions — the only surface third-party extensions import.",
5
5
  "license": "MIT",
6
6
  "author": "Dave Weaver",
@@ -0,0 +1,43 @@
1
+ import type { HTMLAttributes } from "react";
2
+ import {
3
+ activityClass,
4
+ type Activity as ActivityKind,
5
+ type ActivitySize,
6
+ } from "./activity";
7
+
8
+ /**
9
+ * Host-painted activity glyph — same look on workspace rows, CenterDock tabs,
10
+ * and extension UI. Pick an {@link Activity}; the host owns color and motion
11
+ * (ADR 0030). Omit `activity` only for the workspace-row neutral gray fallback.
12
+ *
13
+ * Styled purely via host-provided `.silo-activity*` classes — no stylesheet
14
+ * import is needed in the extension.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * <ActivityGlyph activity="working" size="md" />
19
+ * <ActivityGlyph activity="ready" />
20
+ * <ActivityGlyph size="sm" /> // workspace neutral (omit)
21
+ * ```
22
+ *
23
+ * @category Consumer Services
24
+ * @public
25
+ */
26
+ export function ActivityGlyph({
27
+ activity,
28
+ size = "sm",
29
+ className,
30
+ ...rest
31
+ }: {
32
+ activity?: ActivityKind;
33
+ size?: ActivitySize;
34
+ } & Omit<HTMLAttributes<HTMLSpanElement>, "children">) {
35
+ const classes = activityClass(activity, size);
36
+ return (
37
+ <span
38
+ className={className ? `${classes} ${className}` : classes}
39
+ aria-hidden={rest["aria-label"] == null ? true : undefined}
40
+ {...rest}
41
+ />
42
+ );
43
+ }
@@ -1,7 +1,11 @@
1
1
  import type { ButtonHTMLAttributes, ReactNode } from "react";
2
- import { iconButtonClass, type IconButtonSize } from "./icon-button-classes";
2
+ import {
3
+ iconButtonClass,
4
+ type IconButtonSize,
5
+ type IconButtonVariant,
6
+ } from "./icon-button-classes";
3
7
 
4
- export type { IconButtonSize };
8
+ export type { IconButtonSize, IconButtonVariant };
5
9
 
6
10
  /**
7
11
  * A square icon-only button — the kit's one answer for ✕, ⋮, ↻, ✏️, and
@@ -9,18 +13,27 @@ export type { IconButtonSize };
9
13
  * label is the accessible name. Pair with {@link Tooltip} so sighted users
10
14
  * get the same label on hover.
11
15
  *
16
+ * Sized in terms of `--silo-font-size-base` so the hit target and child SVGs
17
+ * scale with Silo's UI zoom (`uiFontSize`). Prefer Phosphor `size="1em"`
18
+ * (or omit a fixed px size) so the glyph tracks the button.
19
+ *
12
20
  * Styled purely via host-provided `.silo-icon-button*` classes — no
13
21
  * stylesheet import is needed in the extension.
14
22
  *
15
23
  * @example
16
24
  * ```tsx
17
25
  * <IconButton aria-label="Refresh" onClick={refresh}>
18
- * <RefreshIcon />
26
+ * <RefreshIcon size="1em" />
19
27
  * </IconButton>
20
28
  *
21
29
  * // compact — e.g. in a ListRow's trailing slot
22
30
  * <IconButton size="sm" aria-label="Pin" onClick={pin}>
23
- * <PinIcon />
31
+ * <PinIcon size="1em" />
32
+ * </IconButton>
33
+ *
34
+ * // panel / breadcrumb toolbar (local-web-viewer tone)
35
+ * <IconButton size="sm" variant="toolbar" aria-label="Mark">
36
+ * <FlagIcon size="1em" weight="bold" />
24
37
  * </IconButton>
25
38
  * ```
26
39
  *
@@ -29,19 +42,28 @@ export type { IconButtonSize };
29
42
  */
30
43
  export function IconButton({
31
44
  size = "normal",
45
+ variant = "normal",
32
46
  className,
33
47
  type = "button",
34
48
  children,
35
49
  "aria-label": ariaLabel,
36
50
  ...rest
37
51
  }: {
38
- /** 32px standalone / 26px for tight or inline contexts. */
52
+ /**
53
+ * Hit-target size in `em` of `--silo-font-size-base` (tracks Zoom In/Out).
54
+ * `normal` = 2.5em, `sm` = 2em (local-web-viewer toolbar buttons).
55
+ */
39
56
  size?: IconButtonSize;
57
+ /**
58
+ * `"toolbar"` — black/white toolbar-text icons, hover fill only, no
59
+ * press-scale. Use on editor/terminal breadcrumb clusters and panel bars.
60
+ */
61
+ variant?: IconButtonVariant;
40
62
  /** Required — the icon is the only visual. */
41
63
  "aria-label": string;
42
64
  children?: ReactNode;
43
65
  } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "aria-label">) {
44
- const classes = iconButtonClass(size);
66
+ const classes = iconButtonClass(size, variant);
45
67
  return (
46
68
  <button
47
69
  type={type}
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { activityClass, activityFromAgent } from "./activity";
3
+
4
+ describe("activityClass", () => {
5
+ it("maps kinds and sizes", () => {
6
+ expect(activityClass("working", "md")).toBe(
7
+ "silo-activity silo-activity-working silo-activity-md",
8
+ );
9
+ expect(activityClass("ready")).toBe(
10
+ "silo-activity silo-activity-ready silo-activity-sm",
11
+ );
12
+ expect(activityClass("warn", "sm")).toBe(
13
+ "silo-activity silo-activity-warn silo-activity-sm",
14
+ );
15
+ expect(activityClass("error")).toBe(
16
+ "silo-activity silo-activity-error silo-activity-sm",
17
+ );
18
+ });
19
+
20
+ it("uses none fallback when activity is omitted", () => {
21
+ expect(activityClass(undefined)).toBe(
22
+ "silo-activity silo-activity-none silo-activity-sm",
23
+ );
24
+ });
25
+ });
26
+
27
+ describe("activityFromAgent", () => {
28
+ it("maps overlapping agent states", () => {
29
+ expect(activityFromAgent("working")).toBe("working");
30
+ expect(activityFromAgent("idle")).toBe("ready");
31
+ expect(activityFromAgent("error")).toBe("error");
32
+ expect(activityFromAgent("none")).toBeNull();
33
+ expect(activityFromAgent("dead")).toBeNull();
34
+ });
35
+ });
@@ -0,0 +1,57 @@
1
+ import type { AgentActivity } from "./agents-service";
2
+
3
+ /**
4
+ * Host-owned activity state for chrome (workspace rows, CenterDock tabs,
5
+ * SideDock tabs, and the public {@link Activity} glyph). Extensions pick a
6
+ * kind only — never an icon, color, or motion. See ADR 0030.
7
+ *
8
+ * @category Core Types
9
+ * @public
10
+ */
11
+ export type Activity = "working" | "ready" | "warn" | "error";
12
+
13
+ /**
14
+ * Glyph size for {@link Activity}. `"sm"` matches workspace status rows (~6px);
15
+ * `"md"` is slightly larger for CenterDock / SideDock tabs.
16
+ *
17
+ * @category Core Types
18
+ * @public
19
+ */
20
+ export type ActivitySize = "sm" | "md";
21
+
22
+ /**
23
+ * Map {@link AgentActivity} onto UI {@link Activity}. Returns `null` when there
24
+ * is nothing to paint (`none` / `dead` — callers may map `dead` → `"error"`
25
+ * themselves if they want chrome).
26
+ *
27
+ * @category Core Types
28
+ * @public
29
+ */
30
+ export function activityFromAgent(a: AgentActivity): Activity | null {
31
+ switch (a) {
32
+ case "working":
33
+ return "working";
34
+ case "idle":
35
+ return "ready";
36
+ case "error":
37
+ return "error";
38
+ case "none":
39
+ case "dead":
40
+ return null;
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Resolve the host `.silo-activity*` class string. Pinned by unit tests
46
+ * (RFC 0016 class-contract pattern). When `activity` is omitted, uses the
47
+ * neutral workspace fallback (gray “none” look).
48
+ *
49
+ * @internal
50
+ */
51
+ export function activityClass(
52
+ activity: Activity | undefined,
53
+ size: ActivitySize = "sm",
54
+ ): string {
55
+ const kind = activity ?? "none";
56
+ return `silo-activity silo-activity-${kind} silo-activity-${size}`;
57
+ }
@@ -1,6 +1,7 @@
1
1
  import type { Disposable } from "./types";
2
2
  import type { Event } from "./event";
3
3
  import type { EditorMode } from "./domain-types";
4
+ import type { TabAdornmentMethods } from "./tab-adornment";
4
5
 
5
6
  // `ctx.editors` — the editor & document domain (public contract). Opening files
6
7
  // into editor tabs, the active-editor save/close commands, the diff-content
@@ -225,10 +226,13 @@ export interface EditorSaveEvent {
225
226
  * editors register save handlers. The single entry point for opening editors —
226
227
  * prefer it over reaching into workspace/editor state.
227
228
  *
229
+ * Tab chrome adornments (`setIcon` / `setIndicator` / …) take an **editor id**
230
+ * as the target — see {@link TabAdornmentMethods}.
231
+ *
228
232
  * @category Consumer Services
229
233
  * @public
230
234
  */
231
- export interface EditorService {
235
+ export interface EditorService extends TabAdornmentMethods {
232
236
  /**
233
237
  * Open a file in an editor tab. Promotes an existing preview, focuses an
234
238
  * already-open tab, or opens a new one.
@@ -5,9 +5,19 @@ describe("iconButtonClass", () => {
5
5
  it("defaults to silo-icon-button", () => {
6
6
  expect(iconButtonClass()).toBe("silo-icon-button");
7
7
  expect(iconButtonClass("normal")).toBe("silo-icon-button");
8
+ expect(iconButtonClass("normal", "normal")).toBe("silo-icon-button");
8
9
  });
9
10
 
10
11
  it("adds the sm modifier", () => {
11
12
  expect(iconButtonClass("sm")).toBe("silo-icon-button silo-icon-button-sm");
12
13
  });
14
+
15
+ it("adds the toolbar variant", () => {
16
+ expect(iconButtonClass("normal", "toolbar")).toBe(
17
+ "silo-icon-button silo-icon-button-toolbar",
18
+ );
19
+ expect(iconButtonClass("sm", "toolbar")).toBe(
20
+ "silo-icon-button silo-icon-button-sm silo-icon-button-toolbar",
21
+ );
22
+ });
13
23
  });
@@ -6,14 +6,27 @@
6
6
  */
7
7
  export type IconButtonSize = "normal" | "sm";
8
8
 
9
+ /**
10
+ * Visual tone for {@link IconButton}. `"toolbar"` matches the local-web-viewer
11
+ * bar buttons (toolbar-text icons, hover fill only, no press-scale).
12
+ *
13
+ * @internal
14
+ */
15
+ export type IconButtonVariant = "normal" | "toolbar";
16
+
9
17
  /**
10
18
  * Resolve the host `.silo-icon-button*` class string for an IconButton's
11
- * `size`. Default is the 32px standalone size; `sm` adds the 26px modifier.
19
+ * `size` + `variant`. Default is the standalone size; `sm` adds the compact
20
+ * modifier; `toolbar` swaps in the breadcrumb/panel-toolbar tone.
12
21
  *
13
22
  * @internal
14
23
  */
15
- export function iconButtonClass(size: IconButtonSize = "normal"): string {
16
- return size === "sm"
17
- ? "silo-icon-button silo-icon-button-sm"
18
- : "silo-icon-button";
24
+ export function iconButtonClass(
25
+ size: IconButtonSize = "normal",
26
+ variant: IconButtonVariant = "normal",
27
+ ): string {
28
+ const parts = ["silo-icon-button"];
29
+ if (size === "sm") parts.push("silo-icon-button-sm");
30
+ if (variant === "toolbar") parts.push("silo-icon-button-toolbar");
31
+ return parts.join(" ");
19
32
  }
package/src/index.ts CHANGED
@@ -110,6 +110,40 @@ export type {
110
110
  TerminalTabDecorationProvider,
111
111
  OscEvent,
112
112
  } from "./terminal-service";
113
+ export type {
114
+ TabAdornmentColor,
115
+ TabIconAdornment,
116
+ TabHighlightAdornment,
117
+ TabIndicatorAdornment,
118
+ TabIndicatorFlash,
119
+ TabActivityAdornment,
120
+ TabActivityFlash,
121
+ TabIconContribution,
122
+ TabHighlightContribution,
123
+ TabIndicatorContribution,
124
+ TabActivityContribution,
125
+ TabIconBinder,
126
+ TabHighlightBinder,
127
+ TabIndicatorBinder,
128
+ TabActivityBinder,
129
+ TabAdornmentMethods,
130
+ } from "./tab-adornment";
131
+ export type { Activity, ActivitySize } from "./activity";
132
+ export { activityFromAgent } from "./activity";
133
+ export { ActivityGlyph } from "./ActivityGlyph";
134
+ export type { PhosphorIconName } from "./phosphor-icon";
135
+ export type {
136
+ ToolbarSurface,
137
+ ToolbarItemContext,
138
+ ToolbarItemFields,
139
+ ToolbarCommandItemContribution,
140
+ ToolbarMenuItemContribution,
141
+ ToolbarChromeFields,
142
+ ToolbarSeparatorContribution,
143
+ ToolbarSpacerSize,
144
+ ToolbarSpacerContribution,
145
+ ToolbarItemContribution,
146
+ } from "./toolbar-items";
113
147
  export type {
114
148
  FileService,
115
149
  FileMeta,
@@ -226,7 +260,7 @@ export { Tooltip } from "./Tooltip";
226
260
  export { Button } from "./Button";
227
261
  export type { ButtonVariant, ButtonSize } from "./Button";
228
262
  export { IconButton } from "./IconButton";
229
- export type { IconButtonSize } from "./IconButton";
263
+ export type { IconButtonSize, IconButtonVariant } from "./IconButton";
230
264
  export { Input } from "./Input";
231
265
  export { Textarea } from "./Textarea";
232
266
  export { SearchInput } from "./SearchInput";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Export name of an icon from `@phosphor-icons/react` — e.g. `"Flag"`,
3
+ * `"ArrowClockwise"`, `"PushPin"`. The host resolves the name and paints it:
4
+ * toolbar chrome uses `weight="bold"`; tab decorations use `weight="regular"`
5
+ * by default (`filled: true` → `weight="fill"`); both use `size="1em"` so
6
+ * glyphs track UI zoom.
7
+ *
8
+ * Use the PascalCase component name from
9
+ * [Phosphor](https://phosphoricons.com), not a kebab-case path.
10
+ *
11
+ * @category Registration
12
+ * @public
13
+ */
14
+ export type PhosphorIconName = string;