feat(app): float composer trackers as pills over the transcript (#3482)

The subagents track and the task list were stacked cards above the
composer. Each one pushed the composer further down the pane and painted
an opaque band the timeline stopped at, and both spent a full row on a
count that fits in a pill.

Both are now pills that open a panel — a popover on wide screens, a sheet
on compact ones, from the existing menu engine rather than a fourth
floating-panel implementation. The row frame is shared, so a subagent row
and a task row sit on the same rail whatever their contents.

The bar mounts inside the transcript's animated container and pins itself
to the bottom edge, so scrolled content passes under the pills instead of
stopping above them. It stays a child of that container rather than a
sibling floating over the composer: on Android a view outside its parent's
bounds paints but takes no touches, and every pill is pressable. The
container carries the same keyboard transform the composer does, so the
pills track the composer's top edge when the keyboard moves.

The tracker state moves out of the composer with it. None of it was
composer state; it lived there because that is where it used to render.
This commit is contained in:
Mohamed Boudra
2026-08-17 12:36:28 +02:00
committed by GitHub
parent ac4331456c
commit 0eab0b7828
23 changed files with 672 additions and 442 deletions
+3 -2
View File
@@ -336,7 +336,6 @@ export const ar: TranslationResources = {
title: "المهام",
empty: "لا توجد مهام حتى الآن.",
tasksProgress: "{{completed}}/{{total}} مهام",
tasksProgressCurrent: "{{completed}}/{{total}} مهام · {{task}}",
activity: {
created: "تم إنشاء {{count}} مهام",
added: "أُضيفت",
@@ -1620,12 +1619,14 @@ export const ar: TranslationResources = {
backdrop: "خلفية القائمة",
},
subagents: {
title: "الوكلاء الفرعيون",
pillLabelOne: "وكيل فرعي واحد",
pillLabelMany: "{{count}} وكلاء فرعيين",
detachAction: "فصل {{label}}",
detachTooltip: "فصل الوكيل الفرعي",
archiveAction: "أرشيف{{label}}",
archiveTooltip: "أرشفة الوكيل الفرعي",
archiveFinishedAction: "أرشفة الوكلاء الفرعيين المكتملين",
archiveFinishedTooltip: "أرشفة المكتملين",
archiveFinishedRetry: "إعادة المحاولة ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -334,7 +334,6 @@ export const en = {
title: "Tasks",
empty: "No tasks yet.",
tasksProgress: "{{completed}}/{{total}} tasks",
tasksProgressCurrent: "{{completed}}/{{total}} tasks · {{task}}",
activity: {
created: "Created {{count}} tasks",
added: "Added",
@@ -1630,12 +1629,14 @@ export const en = {
backdrop: "Menu backdrop",
},
subagents: {
title: "Subagents",
pillLabelOne: "1 subagent",
pillLabelMany: "{{count}} subagents",
detachAction: "Detach {{label}}",
detachTooltip: "Detach subagent",
archiveAction: "Archive {{label}}",
archiveTooltip: "Archive subagent",
archiveFinishedAction: "Archive finished subagents",
archiveFinishedTooltip: "Archive finished",
archiveFinishedRetry: "Retry ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -339,7 +339,6 @@ export const es: TranslationResources = {
title: "Tareas",
empty: "Aún no hay tareas.",
tasksProgress: "{{completed}}/{{total}} tareas",
tasksProgressCurrent: "{{completed}}/{{total}} tareas · {{task}}",
activity: {
created: "Se crearon {{count}} tareas",
added: "Añadida",
@@ -1663,12 +1662,14 @@ export const es: TranslationResources = {
backdrop: "Fondo del menú",
},
subagents: {
title: "Subagentes",
pillLabelOne: "1 subagente",
pillLabelMany: "{{count}} subagentes",
detachAction: "Separar {{label}}",
detachTooltip: "Separar subagente",
archiveAction: "Archivo{{label}}",
archiveTooltip: "Subagente de archivo",
archiveFinishedAction: "Archivar subagentes finalizados",
archiveFinishedTooltip: "Archivar finalizados",
archiveFinishedRetry: "Reintentar ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -340,7 +340,6 @@ export const fr: TranslationResources = {
title: "Tâches",
empty: "Aucune tâche pour l'instant.",
tasksProgress: "{{completed}}/{{total}} tâches",
tasksProgressCurrent: "{{completed}}/{{total}} tâches · {{task}}",
activity: {
created: "{{count}} tâches créées",
added: "Ajoutée",
@@ -1667,12 +1666,14 @@ export const fr: TranslationResources = {
backdrop: "Toile de fond du menu",
},
subagents: {
title: "Sous-agents",
pillLabelOne: "1 sous-agent",
pillLabelMany: "{{count}} sous-agents",
detachAction: "Detacher {{label}}",
detachTooltip: "Detacher le sous-agent",
archiveAction: "Archiver{{label}}",
archiveTooltip: "Sous-agent d'archivage",
archiveFinishedAction: "Archiver les sous-agents terminés",
archiveFinishedTooltip: "Archiver les terminés",
archiveFinishedRetry: "Réessayer ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -339,7 +339,6 @@ export const ja: TranslationResources = {
title: "タスク",
empty: "タスクがまだありません。",
tasksProgress: "{{completed}}/{{total}}タスク",
tasksProgressCurrent: "{{completed}}/{{total}}タスク · {{task}}",
activity: {
created: "{{count}}件のタスクを作成",
added: "追加",
@@ -1636,12 +1635,14 @@ export const ja: TranslationResources = {
backdrop: "メニューの背景",
},
subagents: {
title: "サブエージェント",
pillLabelOne: "サブエージェント 1 件",
pillLabelMany: "サブエージェント {{count}} 件",
detachAction: "{{label}}を切り離す",
detachTooltip: "サブエージェントを切り離す",
archiveAction: "{{label}}をアーカイブ",
archiveTooltip: "サブエージェントをアーカイブ",
archiveFinishedAction: "完了したサブエージェントをアーカイブ",
archiveFinishedTooltip: "完了した項目をアーカイブ",
archiveFinishedRetry: "再試行 ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -337,7 +337,6 @@ export const ko: TranslationResources = {
title: "작업",
empty: "아직 작업이 없습니다.",
tasksProgress: "작업 {{completed}}/{{total}}개",
tasksProgressCurrent: "작업 {{completed}}/{{total}}개 · {{task}}",
activity: {
created: "작업 {{count}}개 생성",
added: "추가됨",
@@ -1630,12 +1629,14 @@ export const ko: TranslationResources = {
backdrop: "메뉴 배경",
},
subagents: {
title: "하위 에이전트",
pillLabelOne: "하위 에이전트 1개",
pillLabelMany: "하위 에이전트 {{count}}개",
detachAction: "{{label}} 분리",
detachTooltip: "하위 에이전트 분리",
archiveAction: "{{label}} 보관",
archiveTooltip: "서브에이전트 보관",
archiveFinishedAction: "완료된 하위 에이전트 보관",
archiveFinishedTooltip: "아카이브 완료",
archiveFinishedRetry: "다시 시도 ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -339,7 +339,6 @@ export const ptBR: TranslationResources = {
title: "Tarefas",
empty: "Nenhuma tarefa ainda.",
tasksProgress: "{{completed}}/{{total}} tarefas",
tasksProgressCurrent: "{{completed}}/{{total}} tarefas · {{task}}",
activity: {
created: "{{count}} tarefas criadas",
added: "Adicionada",
@@ -1649,12 +1648,14 @@ export const ptBR: TranslationResources = {
backdrop: "Fundo do menu",
},
subagents: {
title: "Subagentes",
pillLabelOne: "1 subagente",
pillLabelMany: "{{count}} subagentes",
detachAction: "Desanexar {{label}}",
detachTooltip: "Desanexar subagente",
archiveAction: "Arquivar {{label}}",
archiveTooltip: "Arquivar subagente",
archiveFinishedAction: "Arquivar subagentes concluídos",
archiveFinishedTooltip: "Arquivar concluídos",
archiveFinishedRetry: "Tentar novamente ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -338,7 +338,6 @@ export const ru: TranslationResources = {
title: "Задачи",
empty: "Заданий пока нет.",
tasksProgress: "{{completed}}/{{total}} задач",
tasksProgressCurrent: "{{completed}}/{{total}} задач · {{task}}",
activity: {
created: "Создано задач: {{count}}",
added: "Добавлена",
@@ -1654,12 +1653,14 @@ export const ru: TranslationResources = {
backdrop: "Фон меню",
},
subagents: {
title: "Субагенты",
pillLabelOne: "1 субагент",
pillLabelMany: "{{count}} субагентов",
detachAction: "Отсоединить {{label}}",
detachTooltip: "Отсоединить субагент",
archiveAction: "Архив{{label}}",
archiveTooltip: "Архивный субагент",
archiveFinishedAction: "Архивировать завершенные субагенты",
archiveFinishedTooltip: "Архивировать завершенные",
archiveFinishedRetry: "Повторить ({{failed}}/{{total}})",
},
panels: {
+3 -2
View File
@@ -336,7 +336,6 @@ export const zhCN: TranslationResources = {
title: "任务",
empty: "还没有任务。",
tasksProgress: "{{completed}}/{{total}} 项任务",
tasksProgressCurrent: "{{completed}}/{{total}} 项任务 · {{task}}",
activity: {
created: "已创建 {{count}} 项任务",
added: "已添加",
@@ -1600,12 +1599,14 @@ export const zhCN: TranslationResources = {
backdrop: "菜单背景",
},
subagents: {
title: "Subagent",
pillLabelOne: "1 个 subagent",
pillLabelMany: "{{count}} 个 subagent",
detachAction: "分离 {{label}}",
detachTooltip: "分离 subagent",
archiveAction: "归档 {{label}}",
archiveTooltip: "归档 subagent",
archiveFinishedAction: "归档已完成的 subagent",
archiveFinishedTooltip: "归档已完成项",
archiveFinishedRetry: "重试 ({{failed}}/{{total}})",
},
panels: {