RelayCTX Creative briefsSPEC.app-components.md
RelayCTX Creative · Document

SPEC — App Components (cross-surface inventory)

1,279 words · 6 min View raw Source History

SPEC — App Components (cross-surface inventory)

Companion to SPEC.design-v35.md (visual tokens) and mcp/response-cards.html (the MCP card reference). This spec is about interaction components and where each one is allowed to live — not colors/type, which stay owned by brand/relay-tokens-v35.css.

Why this exists

Mobile, Wearable, Slack, Chat, and Relay Agent (concepts/app-*.html) each got built as one-off concept files. That's fine for a first cut, but three of them (Slack, Chat, Relay Agent) already needed the same three things — a way to reach Graph/Streams/Explore, a profile + security surface, and a notification entry point — and without a shared reference each concept was about to reinvent them slightly differently. This doc is the single place that says what each component is, which surfaces get it, which surfaces deliberately don't, and which file is the canonical example to copy from.

This is a planning document for static concept prototypes, not a shipped component library — relay-app has no shared component package yet (see relay-app CLAUDE.md: the web app is vanilla TypeScript, no component abstraction). Treat "canonical file" below as the concept to copy markup/CSS from, not an import path.

Component inventory

ComponentWhat it isCanonical conceptNotes
Card — designed (.acard family)Relay's own fully-designed card: avatar, title, meta, working Approve/Deny buttons, resolved stateapp-mobile-v2.html (.card), app-relay-agent.html (.acard)Used wherever Relay owns the pixels end to end. Buttons are real, not markdown.
Card — raw tool-call (.cm family)The MCP chat-tool block: glyph + bold title, <hr> framing, italic signal line, no interactive buttonsmcp/response-cards.html, reused verbatim in app-slack.html (Slack attachment chrome) and app-chat.html (host chat chrome)Used wherever a third-party host is rendering the reply — Relay doesn't control the pixels, so the card degrades to what that host's markdown/attachment format allows.
Tools panelA sheet that reveals feature shortcuts (Graph, Streams, Explore) without leaving the current surfaceapp-relay-agent.html (.agentwin-tools, opens above the input bar), app-mobile-v2.html (.tools-sheet, opens from Home's "Jump to a feature" row)Explore is tier-gated (Horizon) — the panel must show it as reachable-but-locked, never hide it outright (fail-closed-visible, not fail-silent).
Slide-up sheetAn overlay that slides up from the bottom over the current screen (and the tab bar, on Mobile), collapsing back down on a second trigger, the backdrop, an explicit close, or navigating elsewhere. Never a route change.app-mobile-v2.html (.tools-sheet, .menu-sheet)The general mechanic behind both the Tools panel and the Menu (see below). Transform-only animation (translateY), never height/max-height, to avoid layout thrash.
Notification bellPersistent header entry point for pending/resurfacing items, separate from the main feed/transcript; opens a small dropdown, not a sheetapp-relay-agent.html (#bellBtn + .head-panel), app-mobile-v2.html (#bellBtn in the persistent .topbar, on every screen)Badge count is the same number as the Activity tab badge on Mobile — the bell is a shortcut into Activity, not a second inbox. See "Activity is the unified space" below.
Menu (was: You tab)Identity, this-week stats, the tools/Explore entry, Security, and Settings — now a slide-up sheet triggered from the tab bar, not a persistent 5th screenapp-mobile-v2.html (.menu-sheet, toggleMenu())Deliberately not a screen: opening it never loses your place. The old "You" tab and Relay Agent's profile dropdown both feed from the same content described below.
Profile & security panelIdentity (name/handle/org/tier) + security (passkey status, active sessions, sign-out-other-sessions) + a link out to full account settingsapp-relay-agent.html (#profileBtn + .head-panel profile variant, a small dropdown), app-mobile-v2.html (folded into the Menu sheet, a full section since there's more room)Same content, different container: a compact dropdown where the surface is small/transient (Relay Agent), a full sheet section where it's the primary account entry point (Mobile). "Manage account" hands off to a fuller settings surface either way.
Capture input barText/voice entry with a + affordance that opens the tools panelapp-relay-agent.html (.agentwin-input)Mobile's equivalent is the Capture tab's Send/Claim segmented control (app-mobile-v2.html) — different chrome, same job.
Approve/Deny action patternPrimary = Approve, single tap. Deny = 5s undo toast before it finalizes. Never symmetric-weight buttons.app-mobile-v2.html (resolve() + .toast)Canonical behavior contract — every surface that can approve/deny (Mobile, Slack, Relay Agent) follows this timing, even where the visual chrome differs.
Segmented controlTwo-way switch (Send/Claim, host picker, Graph/Catalog/Journey)app-mobile-v2.html (.segbar)Same .segbar CSS reused verbatim in app-chat.html's host picker.

Surface capability matrix

SurfaceCardTools panel (Graph/Streams/Explore)NotificationsProfile + securityCaptureApprove/Deny
Mobile (app-mobile-v2.html)Designed✅ built — Home's "Jump to a feature" row opens a bottom sheet✅ built — persistent bell in a top bar on every screen, badge synced to Activity✅ built — folded into the Menu sheet (replaces the old You tab)✅ Send/Claim segmented✅ canonical behavior
Wearable (app-wearable-v1.html)Designed (minimal)intentionally — no Search/You/tools drawer, 3 faces only❌ Glance face covers this at a glance-level, no bell/listintentionally — no account surface on a 40mm screenVoice-only✅ (haptic-timed undo)
Slack (app-slack.html)Raw tool-call (Slack attachment chrome)Not applicable — Slack's own app-home / shortcuts would carry this, out of scope for the conceptNative Slack notifications carry this alreadyNot applicable — Slack owns identity/relay capture, forward, react✅ canonical behavior
Chat (app-chat.html)Raw tool-call (host chat chrome)Not applicable — host's own UI, Relay has no chrome to add it toNot applicable — host owns notificationsNot applicable — host owns identityNatural language❌ deliberately fenced off (see concept notes)
Relay Agent (app-relay-agent.html)Designed✅ built✅ built✅ built✅ text/voice + + tools✅ canonical behavior

Reading the matrix: Slack and Chat get an "N/A" on tools/notifications/profile because Relay is a guest inside someone else's chrome there — those jobs are the host's to do, and Relay shouldn't try to rebuild a mini-app inside another app's window. Mobile and Relay Agent are Relay's own chrome, so they both owe the user the full set. Wearable is the one surface that opts out on purpose, not because it's unfinished — see its own concept notes.

Rule: Activity is the one unified space for notifications and activity, not two competing inboxes. The Mobile bell and Relay Agent's bell both open a quick-glance dropdown of the same "Needs you" + resurfacing items that lead the Activity feed, with a "View all in Activity" link out — they are shortcuts into Activity, never a separate feed with its own state. Don't add a second unread-count anywhere; Activity's badge is the single source of truth every bell reads from.

Open items


Source of truth for tokens: brand/relay-tokens-v35.css. Source of truth for the MCP card markup: mcp/response-cards.html. This file owns cross-surface component/behavior decisions only.