diff --git a/apps/microbridge-ui/src/assets/integrations/README.md b/apps/microbridge-ui/src/assets/integrations/README.md new file mode 100644 index 0000000..6ac9b5e --- /dev/null +++ b/apps/microbridge-ui/src/assets/integrations/README.md @@ -0,0 +1,7 @@ +# Integration icons + +PNG marks used in Settings → Integrations. Extracted from each host’s installed +macOS app icon for identification in the Microbridge UI. + +All trademarks and logos remain the property of their respective owners. +Microbridge does not claim ownership of these marks. diff --git a/apps/microbridge-ui/src/assets/integrations/chatgpt.png b/apps/microbridge-ui/src/assets/integrations/chatgpt.png new file mode 100644 index 0000000..6e5c3d8 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/chatgpt.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/claude.png b/apps/microbridge-ui/src/assets/integrations/claude.png new file mode 100644 index 0000000..cf471a9 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/claude.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/cnvs.png b/apps/microbridge-ui/src/assets/integrations/cnvs.png new file mode 100644 index 0000000..73319da Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/cnvs.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/codex.png b/apps/microbridge-ui/src/assets/integrations/codex.png new file mode 100644 index 0000000..fbdd19c Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/codex.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/conductor.png b/apps/microbridge-ui/src/assets/integrations/conductor.png new file mode 100644 index 0000000..2616699 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/conductor.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/cursor.png b/apps/microbridge-ui/src/assets/integrations/cursor.png new file mode 100644 index 0000000..7cfaae1 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/cursor.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/factory.png b/apps/microbridge-ui/src/assets/integrations/factory.png new file mode 100644 index 0000000..cc107ad Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/factory.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/opencode.png b/apps/microbridge-ui/src/assets/integrations/opencode.png new file mode 100644 index 0000000..fc5d094 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/opencode.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/synara.png b/apps/microbridge-ui/src/assets/integrations/synara.png new file mode 100644 index 0000000..55f4a84 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/synara.png differ diff --git a/apps/microbridge-ui/src/assets/integrations/t3code.png b/apps/microbridge-ui/src/assets/integrations/t3code.png new file mode 100644 index 0000000..d9fa222 Binary files /dev/null and b/apps/microbridge-ui/src/assets/integrations/t3code.png differ diff --git a/apps/microbridge-ui/src/components/IntegrationCard.tsx b/apps/microbridge-ui/src/components/IntegrationCard.tsx index fe928f3..56c0742 100644 --- a/apps/microbridge-ui/src/components/IntegrationCard.tsx +++ b/apps/microbridge-ui/src/components/IntegrationCard.tsx @@ -7,12 +7,14 @@ import { function TileFace({ name, + iconSrc, diagnostic, light, label, theme, }: { name: string; + iconSrc?: string; diagnostic: string; light: TrafficLight; label: string; @@ -21,17 +23,37 @@ function TileFace({ const colors = TRAFFIC_COLORS[light]; return ( <> - +
+ {iconSrc ? ( + + ) : ( + + {name.slice(0, 1)} + + )} + +
-
+
{name}
{label} @@ -39,7 +61,7 @@ function TileFace({
); + const className = + "group relative flex h-[72px] w-full flex-col items-stretch justify-between rounded-xl px-2 py-1.5 text-left transition-colors"; + return (
  • {onSelect ? ( @@ -98,7 +126,7 @@ export function IntegrationCard({ title={diagnostic} aria-label={`${name}: ${label}. ${diagnostic}`} aria-expanded={expandable ? expanded : undefined} - className="group relative flex aspect-square w-full flex-col items-start justify-between rounded-2xl p-3 text-left transition-colors" + className={className} style={shellStyle} > {face} @@ -107,7 +135,7 @@ export function IntegrationCard({
    {face} @@ -119,11 +147,13 @@ export function IntegrationCard({ export function IntegrationDetail({ name, + iconSrc, diagnostic, theme, children, }: { name: string; + iconSrc?: string; diagnostic: string; theme: ThemeTokens; children?: ReactNode; @@ -136,7 +166,19 @@ export function IntegrationDetail({ border: `1px solid ${theme.hairline}`, }} > -
    {name}
    +
    + {iconSrc ? ( + + ) : null} +
    {name}
    +
    {diagnostic}
    diff --git a/apps/microbridge-ui/src/lib/integrationIcons.ts b/apps/microbridge-ui/src/lib/integrationIcons.ts new file mode 100644 index 0000000..a0c4576 --- /dev/null +++ b/apps/microbridge-ui/src/lib/integrationIcons.ts @@ -0,0 +1,29 @@ +import chatgpt from "../assets/integrations/chatgpt.png"; +import claude from "../assets/integrations/claude.png"; +import cnvs from "../assets/integrations/cnvs.png"; +import codex from "../assets/integrations/codex.png"; +import conductor from "../assets/integrations/conductor.png"; +import cursor from "../assets/integrations/cursor.png"; +import factory from "../assets/integrations/factory.png"; +import opencode from "../assets/integrations/opencode.png"; +import synara from "../assets/integrations/synara.png"; +import t3code from "../assets/integrations/t3code.png"; + +/** App icons keyed by daemon adapter id. */ +export const INTEGRATION_ICONS: Record = { + chatgpt, + claude, + claude_desktop: claude, + cnvs, + codex, + conductor, + cursor, + factory, + opencode, + synara, + t3code, +}; + +export function integrationIcon(adapterId: string): string | undefined { + return INTEGRATION_ICONS[adapterId]; +} diff --git a/apps/microbridge-ui/src/surfaces/Settings.tsx b/apps/microbridge-ui/src/surfaces/Settings.tsx index 6ca5feb..1a13a4a 100644 --- a/apps/microbridge-ui/src/surfaces/Settings.tsx +++ b/apps/microbridge-ui/src/surfaces/Settings.tsx @@ -35,6 +35,7 @@ import { integrationView, isHostAttributed, } from "../lib/hosts"; +import { integrationIcon } from "../lib/integrationIcons"; const LIGHTING_STATES: { id: keyof StateColors; label: string }[] = [ { id: "idle", label: "Idle" }, @@ -641,9 +642,9 @@ export function Settings({

    Integrations

    - Each app is a tile. Green / yellow / red is always visible; hover - for detail. Click Cursor, Factory, T3 Code, or OpenCode to enable - or repair. + Compact tiles with each app's icon. Status color is always + visible; hover for detail. Click Cursor, Factory, T3 Code, or + OpenCode to enable or repair.

    Synara and the desktop apps share Claude/Codex journals — no @@ -661,11 +662,12 @@ export function Settings({ {group.label} · {group.items.length}

    -
      +
        {group.items.map(({ adapter, view, actionable }) => ( diff --git a/apps/microbridge-ui/src/surfaces/surfaces.test.tsx b/apps/microbridge-ui/src/surfaces/surfaces.test.tsx index e07f51a..071e7e9 100644 --- a/apps/microbridge-ui/src/surfaces/surfaces.test.tsx +++ b/apps/microbridge-ui/src/surfaces/surfaces.test.tsx @@ -133,7 +133,8 @@ describe("Settings", () => { expect(html).toContain("Lifecycle is connected"); expect(html).toContain("Live state"); expect(html).toContain("Integrations"); - expect(html).toContain("grid-cols-2"); + expect(html).toContain("grid-cols-3"); + expect(html).toContain("integrations/"); // Synara waits (yellow) with no sessions; CNVS stays connected. expect(html).toContain("Connected · 1"); expect(html).toContain("Not connected · 2"); @@ -147,6 +148,7 @@ describe("Settings", () => { // Cursor is auto-selected as the first actionable not-connected tile. expect(html).toContain("Repair bundled integration"); expect(html).toContain("hover for detail"); + expect(html).toContain('width="28"'); expect(html).not.toContain("Install managed plugin"); expect(html).not.toContain("scaffold only"); expect(html).not.toContain("not production"); diff --git a/docs/design/README.md b/docs/design/README.md index fb73810..a951aff 100644 --- a/docs/design/README.md +++ b/docs/design/README.md @@ -131,11 +131,12 @@ Keyboard setup. Four sections in a left rail: - **Agent Keys** — live "six keys, six threads" view, key source, deck focus mode (auto/pinned), app priority order, approvals-interrupt toggle (policy only — no live approve UI) -- **Integrations** — compact square tile grid (2–3 columns), grouped by - connected / not connected. Each tile always shows name + traffic-light status; - hover reveals the diagnostic. Click Cursor / Factory / T3 / OpenCode to open a - detail strip for enable / repair / pair. Host-attributed apps (Synara, - ChatGPT, Claude Desktop, Conductor) are status + hover only +- **Integrations** — dense icon tile grid (3–5 columns, ~72px tall), grouped by + connected / not connected. Each tile shows the host app icon, name, and + traffic-light status; hover reveals the diagnostic. Click Cursor / Factory / + T3 / OpenCode to open a detail strip for enable / repair / pair. + Host-attributed apps (Synara, ChatGPT, Claude Desktop, Conductor) are status + + hover only - **Device** — Appearance (System/Light/Dark), Lighting (Codex defaults + Phosphor preset + reset), brightness, LED test, sleep timer (default 3 min), firmware, zero-network note