From 6113f2cef154eb37493670b39df3abefe3a3d936 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Sun, 18 Oct 2026 21:17:53 -0400 Subject: [PATCH] fix(app): align activity panel with capsule --- .../src/session/composer/activity-chips.css | 52 +++++++++++++++++++ .../composer/activity-chips.stories.tsx | 4 +- .../src/session/composer/activity-chips.tsx | 22 +++++--- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/packages/app/src/session/composer/activity-chips.css b/packages/app/src/session/composer/activity-chips.css index 79676d4412d..d4ab49a61e5 100644 --- a/packages/app/src/session/composer/activity-chips.css +++ b/packages/app/src/session/composer/activity-chips.css @@ -63,3 +63,55 @@ opacity: 0.16; } } + +/* + * The open panel grows out of the capsule, which stays as its bottom row. Everything sits on the capsule's grid: + * 1px border + 8px padding puts glyphs at x=9; a 15px glyph + 6px gap puts text at x=30. + */ +[data-component="menu-v2-content"][data-slot="session-activity-panel"] { + width: max-content; + min-width: max(var(--kb-popper-anchor-width, 0px), 240px); + max-width: min(360px, calc(100vw - 24px)); + padding: 4px 4px 32px; + border: 1px solid var(--v2-border-border-base); + border-radius: 14px; + background: var(--v2-background-bg-base); + /* Past the 6px gutter and the 28px capsule, so the panel's bottom edge is the capsule's. */ + translate: 0 34px; + + [data-component="menu-v2-item"] { + padding-inline: 4px 8px; + border-radius: 10px; + } + + [data-slot="menu-v2-item-content"] { + gap: 6px; + } + + [data-slot="menu-v2-item-content"] > svg:first-child { + flex: none; + width: 15px; + height: 15px; + } + + [data-slot="menu-v2-group-label"] { + height: 24px; + padding-inline: 4px; + } + + [data-slot="menu-v2-separator"] { + width: calc(100% + 8px); + margin: 4px -4px; + } + + @media (prefers-reduced-motion: reduce) { + animation: none; + } +} + +/* While open, the capsule is the panel's bottom row rather than a pill of its own. */ +[data-slot="session-activity-chip"][data-expanded] { + border-color: transparent; + background: transparent; + box-shadow: none; +} diff --git a/packages/app/src/session/composer/activity-chips.stories.tsx b/packages/app/src/session/composer/activity-chips.stories.tsx index 9d4ed68d4a4..70585ec81a8 100644 --- a/packages/app/src/session/composer/activity-chips.stories.tsx +++ b/packages/app/src/session/composer/activity-chips.stories.tsx @@ -17,8 +17,8 @@ import type { SessionActivityItem } from "./activity-chips" const timelineDetail = timelinePresets[2].value const subagents = [ + { id: "ses_child_scroll", agent: "general", description: "Investigate Linux scroll jacking" }, { id: "ses_child_audit", agent: "explore", description: "Audit the timeline projection" }, - { id: "ses_child_review", agent: "general", description: "Review the composer dock" }, { id: "ses_child_search", agent: "explore", description: "Search for shell metadata" }, ] @@ -233,7 +233,7 @@ export const TwoSubagents = { render: preview(2, 2, 0) } export const OneShell = { render: preview(7, 0, 1) } -export const SubagentsAndShells = { render: preview(3, 2, 1) } +export const SubagentsAndShells = { render: preview(4, 2, 2) } export const ManySubagents = { render: preview(4, 12, 2) } diff --git a/packages/app/src/session/composer/activity-chips.tsx b/packages/app/src/session/composer/activity-chips.tsx index 5138f6c824a..da7e87664a0 100644 --- a/packages/app/src/session/composer/activity-chips.tsx +++ b/packages/app/src/session/composer/activity-chips.tsx @@ -21,6 +21,9 @@ export function SessionActivityChips(props: { }) { const language = useLanguage() + // With one kind running, the capsule row already names it. + const both = () => props.subagents.length > 0 && props.shells.length > 0 + const label = () => language.activitySummary({ subagents: props.subagents.length, shells: props.shells.length }) return ( @@ -31,16 +34,18 @@ export function SessionActivityChips(props: { as="button" type="button" data-slot="session-activity-chip" - class="flex h-7 min-w-0 max-w-full items-center gap-1.5 rounded-full border border-v2-border-border-base bg-v2-background-bg-base ps-2 pe-2.5 text-[13px] font-[530] leading-text-compact tracking-[-0.04px] whitespace-nowrap tabular-nums text-v2-text-text-base shadow-[var(--v2-elevation-raised)] outline-none duration-150 ease-out animate-in fade-in motion-reduce:animate-none hover:bg-v2-background-bg-layer-01 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-v2-border-border-focus data-[expanded]:bg-v2-background-bg-layer-01" + class="flex h-7 min-w-0 max-w-full items-center gap-1.5 rounded-full border border-v2-border-border-base bg-v2-background-bg-base ps-2 pe-2.5 text-[13px] font-[530] leading-text-compact tracking-[-0.04px] whitespace-nowrap tabular-nums text-v2-text-text-base shadow-[var(--v2-elevation-raised)] outline-none duration-150 ease-out animate-in fade-in motion-reduce:animate-none hover:bg-v2-background-bg-layer-01 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-v2-border-border-focus" > {label()} - + 0}> - {language.t("session.activity.section.subagents")} + + {language.t("session.activity.section.subagents")} + {(item) => ( props.onOpen(item)}> @@ -58,17 +63,22 @@ export function SessionActivityChips(props: { - 0 && props.shells.length > 0}> + 0}> - {language.t("session.activity.section.shells")} + + {language.t("session.activity.section.shells")} + {(item) => ( props.onOpen(item)}> - + {item.label}