From 1b912a75736b973f9950a9efdd28054446c112cd Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 22:01:51 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Limit=20visible=20tas?= =?UTF-8?q?ks=20in=20MissionControl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added truncation and limit to MissionControl tasks list to prevent sidebar layout breakage when there are many or long active tasks. --- .jules/palette.md | 4 ++ .../ui/components/sidebar/MissionControl.tsx | 49 ++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index 559dc665..03a717da 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -1,3 +1,7 @@ ## 2026-08-29 - Truncation Awareness **Learning:** When displaying dynamic lists in terminal UIs (such as those using `ink`), if the list is truncated to fit constraints (e.g., a `maxVisible` limit), it is important to include an explicit visual indicator to preserve user situational awareness. **Action:** Always add an explicit UI element indicating truncation and count, rather than silently hiding items. + +## 2026-09-04 - Text Wrapping in Ink Sidebar +**Learning:** In terminal UIs with constrained sidebar width, long strings break layout and formatting if not handled properly. Text elements need `wrap="truncate"` within a `Box` that uses `flexGrow=1` in a `flexDirection="row"` layout to behave well. +**Action:** When adding task lists or freeform text to sidebars, always use `Box` with `flexGrow` and `Text` with `wrap="truncate"`. diff --git a/src/cli/ui/components/sidebar/MissionControl.tsx b/src/cli/ui/components/sidebar/MissionControl.tsx index fd68624e..46f99bf8 100644 --- a/src/cli/ui/components/sidebar/MissionControl.tsx +++ b/src/cli/ui/components/sidebar/MissionControl.tsx @@ -6,6 +6,9 @@ import { useUIStore } from '../../store/context.js'; export const MissionControl: React.FC = () => { const { state } = useUIStore(); + const maxVisible = 5; + const visibleTasks = state.missionTasks.slice(0, Math.max(0, maxVisible)); + return ( @@ -17,19 +20,39 @@ export const MissionControl: React.FC = () => { No active tasks. ) : ( - state.missionTasks.map((task) => ( - - - {task.status === 'completed' ? '[x] ' : '[ ] '} - - - {task.content} - - - )) + <> + {visibleTasks.map((task) => ( + + + + {task.status === 'completed' ? '[x] ' : '[ ] '} + + + + + {task.content} + + + + ))} + {state.missionTasks.length > maxVisible && ( + + + + + + + ... and {state.missionTasks.length - maxVisible} more task + {state.missionTasks.length - maxVisible === 1 ? '' : 's'} + + + + )} + )}