Skip to content

Add reactive plugin appearance and built-in palette contracts - #2243

Open
ymichael wants to merge 9 commits into
mainfrom
bb/add-reactive-plugin-appearance-api-thr_3rvv9swj6u
Open

Add reactive plugin appearance and built-in palette contracts#2243
ymichael wants to merge 9 commits into
mainfrom
bb/add-reactive-plugin-appearance-api-thr_3rvv9swj6u

Conversation

@ymichael

@ymichael ymichael commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

What was wrong

Plugin JavaScript consumers had no supported semantic contract for BB's client light/dark appearance even though the app already owns reactive mode and preference stores. Monaco 0.1.0 consequently observes BB's private root dark class to choose vs / vs-dark, while Theme Toggle 0.2.1 reads the private bb.theme storage key, dispatches a synthetic storage event, calls matchMedia, and mutates that root class from a content-script menu. Appearance access is a client-wide capability; coupling it separately to footer-action and content-script contexts would make the API depend on where code happened to run rather than what it needed.

The live marketplace audit also showed that mode must stay separate from palettes: Ayu 0.2.2 and Tokyo Night 0.1.0 already use bb.themes / bb.sdk.theme; Fonts 0.1.0 is only partially covered because it additionally needs a future palette-change notification, not speculative palette values or CSS tokens here.

Separately, bb.sdk.theme.catalog() omitted BB's own bundled palettes. Theme Toggle therefore copies the six built-in ids, names, and descriptions into its server code before appending the catalog's custom and plugin palettes; that copy can silently drift from BB's canonical list and ordering.

What changed

  • Added one typed semantic client-appearance contract: resolved colorMode, client-local colorModePreference, and setColorModePreference(...).
  • Exported one app-wide experimental_appearance external store from @get-bb/plugin-sdk/app:
    • getSnapshot() supports point-of-use reads from any plugin module, callback, content script, or setup code.
    • subscribe(listener) supports non-React reactivity and returns its cleanup function.
    • experimental_useAppearance() is the React convenience wrapper over the same store for Monaco-style consumers.
  • Kept surface contexts focused: sidebarFooterAction.run still receives only openSettings, and PluginContentScriptContext still contains lifecycle plus its existing optional thread-row status API. There are no appearance-specific footer/content-script adapters.
  • Migrated the development-only Plugin API Tester as the in-repo consumer. Its panel uses the hook and presents Light, Dark, and System as responsive, descriptive choices with explicit pressed and focus states. It no longer registers a sidebar footer action.
  • Added representative external contract fixtures: a Theme Toggle-style content script imports the same store, the Monaco fixture verifies reactive vs / vs-dark mapping, and a palette-switcher fixture builds its choices from the SDK theme catalog.
  • Extended bb.sdk.theme.catalog() with required experimental_builtIn metadata sourced from BB's canonical builtInThemes list. Built-in ids retain their exact string union; the field contains only id, name, description, and canonical display order.
  • Migrated bb theme list to consume catalog.experimental_builtIn while preserving its existing builtInThemes JSON output key.
  • Kept AppToaster on BB's internal theme hook; first-party app chrome does not consume the plugin facade.
  • Documented both experimental contracts in docs/api_to_audit.md, updated the canonical bb-plugin-authoring skill and SDK test harness, and bumped the plugin SDK from 0.4.13 to 0.4.14 (Plugin API Tester requires it).
  • Kept palette CSS, code-theme assets, typography tokens, DOM classes, and storage keys out of the contracts. There is no server/host-daemon wire change, so HOST_DAEMON_PROTOCOL_VERSION is unchanged.

Measured from the branch base (0e12ccca7) with clean Turbo builds:

  • App entry: 537,289 → 537,289 raw bytes (+0); 166,891 → 166,897 gzip (+6).
  • Full boot closure: 1,617,883 → 1,618,069 raw (+186); 520,415 → 520,470 gzip (+55).
  • Existing lazy plugin-frontend chunk: 132,213 → 132,916 raw (+703); 39,508 → 39,758 gzip (+250).
  • SDK app facade: 1,976 → 2,165 raw (+189); 476 → 502 gzip (+26).
  • Optional testing harness: 57,964 → 61,276 raw (+3,312); 11,585 → 12,145 gzip (+560).
  • The catalog addition itself contributes 77 raw / 14 gzip / 32 brotli bytes to the existing preloaded query-helper chunk and zero plugin SDK runtime JavaScript.
  • The final Plugin API Tester panel refinement, measured against 4bc815bf2, adds 688 raw / 220 gzip bytes of optional plugin JavaScript and 9,279 raw / 955 gzip bytes of scoped plugin CSS. It adds no dependency and does not affect app boot.
  • Chunk counts are unchanged (72 boot / 559 total). There is no new dependency or lazy chunk; Plugin API Tester remains a separately built development plugin.

How you verified

  • pnpm exec turbo run typecheck --filter=@bb/server --filter=@bb/cli --filter=@bb/sdk --filter=@bb/server-contract --filter=@get-bb/plugin-sdk — 9/9 tasks passed.
  • pnpm exec turbo run build --filter=@bb/server --filter=@bb/cli --filter=@bb/sdk --filter=@bb/server-contract --filter=@get-bb/plugin-sdk --filter=@bb/app — 9/9 tasks passed.
  • pnpm exec turbo run test --filter=@bb/server --force -- test/system/appearance.test.ts — 14 tests passed, including canonical catalog mapping.
  • pnpm exec turbo run test --filter=@get-bb/plugin-sdk --force -- src/testing/__tests__/fake-plugin-host.test.ts — 44 tests passed, including the palette-switcher contract fixture.
  • pnpm exec turbo run test --filter=@bb/sdk --force -- test/public-types.test.ts — 9 tests passed, including the exact built-in id union.
  • pnpm exec turbo run test --filter=@bb/server --force -- test/services/plugins/plugin-authoring-docs.test.ts — 14 tests passed.
  • pnpm exec turbo run typecheck --filter=bb-plugin-plugin-api-tester — 4/4 tasks passed.
  • pnpm exec turbo run test --filter=bb-plugin-plugin-api-tester --force — 1 focused behavior test passed, covering panel writes, external reactivity, pressed state, and absence of a footer contribution.
  • pnpm exec turbo run build --filter=bb-app — 11/11 tasks passed; the packaged plugin contains no footer-action registration.
  • Earlier appearance-slice validation remains green: plugin SDK suites, focused app behavior tests, app lint, and clean app/SDK builds.
  • git diff --check — passed.

Fixes: no linked issue.

AGENT GENERATED: by GPT-5

@ymichael
ymichael force-pushed the bb/add-reactive-plugin-appearance-api-thr_3rvv9swj6u branch 2 times, most recently from edba98e to a3c9b6c Compare August 21, 2026 22:18
@ymichael ymichael changed the title Add a reactive appearance contract for plugins Add reactive plugin appearance and built-in palette contracts Aug 21, 2026
@ymichael
ymichael force-pushed the bb/add-reactive-plugin-appearance-api-thr_3rvv9swj6u branch from b0baa2c to 0eb160c Compare August 22, 2026 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant