diff --git a/packages/dashboard/app/components/LeftSidebarNav.css b/packages/dashboard/app/components/LeftSidebarNav.css index f94d729273..389259e7ea 100644 --- a/packages/dashboard/app/components/LeftSidebarNav.css +++ b/packages/dashboard/app/components/LeftSidebarNav.css @@ -3,7 +3,7 @@ FNXC:Navigation 2026-06-19-00:00: The experimental sidebar is a persistent desktop/tablet navigation replacement for the Header view-toggle row. It uses the same tokenized visual rhythm as Header navigation so the flag can be toggled without changing dashboard information architecture. */ .left-sidebar-nav { - --left-sidebar-nav-width: calc(var(--space-2xl) * 8); + --left-sidebar-nav-width: calc(var(--space-2xl) * 7); --left-sidebar-nav-rail-width: calc(var(--space-2xl) * 2); position: relative; display: flex; diff --git a/packages/dashboard/app/components/LeftSidebarNav.tsx b/packages/dashboard/app/components/LeftSidebarNav.tsx index 691783a87c..a93a2a6379 100644 --- a/packages/dashboard/app/components/LeftSidebarNav.tsx +++ b/packages/dashboard/app/components/LeftSidebarNav.tsx @@ -56,7 +56,11 @@ interface SidebarNavEntry { onSelect: () => void; } -const LEFT_SIDEBAR_DEFAULT_WIDTH = 256; +/* +FNXC:Navigation 2026-06-20-00:00: +The experimental sidebar default is intentionally narrower than the original 256px layout so desktop/tablet navigation preserves more board content while keeping the existing resize clamps. +*/ +const LEFT_SIDEBAR_DEFAULT_WIDTH = 224; const LEFT_SIDEBAR_MIN_WIDTH = 192; const LEFT_SIDEBAR_MAX_WIDTH = 384; const LEFT_SIDEBAR_WIDTH_STORAGE_KEY = "fusion:left-sidebar-width"; @@ -144,6 +148,14 @@ function sortPluginViews(entries: PluginDashboardViewEntry[]): PluginDashboardVi return [...entries].sort((a, b) => (a.view.order ?? Number.MAX_SAFE_INTEGER) - (b.view.order ?? Number.MAX_SAFE_INTEGER)); } +/* +FNXC:Navigation 2026-06-20-00:00: +Experimental sidebar plugin labels must read as plain navigation nouns without an appended "view" suffix. The Compound Engineering plugin is intentionally shortened to "Compound" so its label fits the narrower sidebar. +*/ +function getSidebarPluginLabel(entry: PluginDashboardViewEntry): string { + return entry.pluginId === "fusion-plugin-compound-engineering" ? "Compound" : entry.view.label; +} + export function LeftSidebarNav({ view, onChangeView, @@ -234,7 +246,7 @@ export function LeftSidebarNav({ const primaryEntries: SidebarNavEntry[] = [ { id: "board", - label: t("header.boardView", "Board view"), + label: t("nav.board", "Board"), view: "board", isActive: view === "board", icon: LayoutGrid, @@ -243,7 +255,7 @@ export function LeftSidebarNav({ }, { id: "list", - label: t("header.listView", "List view"), + label: t("nav.list", "List"), view: "list", isActive: view === "list", icon: List, @@ -254,7 +266,7 @@ export function LeftSidebarNav({ ? [ { id: "agents", - label: t("header.agentsView", "Agents view"), + label: t("nav.agents", "Agents"), view: "agents" as TaskView, isActive: view === "agents", icon: Bot, @@ -265,7 +277,7 @@ export function LeftSidebarNav({ : []), { id: "command-center", - label: t("header.commandCenterView", "Command Center"), + label: t("nav.commandCenter", "Command Center"), view: "command-center", isActive: view === "command-center", icon: Gauge, @@ -274,7 +286,7 @@ export function LeftSidebarNav({ }, { id: "missions", - label: t("header.missionsView", "Missions view"), + label: t("nav.missions", "Missions"), view: "missions", isActive: view === "missions", icon: Target, @@ -283,7 +295,7 @@ export function LeftSidebarNav({ }, { id: "chat", - label: t("header.chatView", "Chat view"), + label: t("nav.chat", "Chat"), view: "chat", isActive: view === "chat", icon: MessageSquare, @@ -293,7 +305,7 @@ export function LeftSidebarNav({ }, { id: "documents", - label: t("header.documentsView", "Documents view"), + label: t("nav.documents", "Documents"), view: "documents", isActive: view === "documents", icon: FileText, @@ -302,7 +314,7 @@ export function LeftSidebarNav({ }, { id: "mailbox", - label: t("header.mailboxView", "Mailbox view"), + label: t("nav.mailbox", "Mailbox"), view: "mailbox", isActive: view === "mailbox", icon: Mail, @@ -316,7 +328,7 @@ export function LeftSidebarNav({ const targetView = getPluginEntryView(entry); return { id: `plugin-${entry.pluginId}-${entry.view.viewId}`, - label: `${entry.view.label} view`, + label: getSidebarPluginLabel(entry), view: targetView, isActive: isPluginEntryActive(view, entry), icon: PluginIcon, @@ -358,7 +370,7 @@ export function LeftSidebarNav({ const targetView = getPluginEntryView(entry); return { id: `plugin-${entry.pluginId}-${entry.view.viewId}`, - label: entry.view.label, + label: getSidebarPluginLabel(entry), view: targetView, isActive: isPluginEntryActive(view, entry), icon: PluginIcon, diff --git a/packages/dashboard/app/components/__tests__/LeftSidebarNav.test.tsx b/packages/dashboard/app/components/__tests__/LeftSidebarNav.test.tsx index 423bc2d835..2da7601c98 100644 --- a/packages/dashboard/app/components/__tests__/LeftSidebarNav.test.tsx +++ b/packages/dashboard/app/components/__tests__/LeftSidebarNav.test.tsx @@ -111,6 +111,17 @@ describe("LeftSidebarNav", () => { expect(screen.queryByTestId("sidebar-nav-plugin-fusion-plugin-primary-primary-view")).toBeNull(); }); + it("renders shortened primary labels and default width", () => { + renderSidebar(); + + expect(screen.getByTestId("left-sidebar-nav")).toHaveStyle({ width: "224px", minWidth: "224px" }); + expect(screen.getByTestId("sidebar-nav-board")).toHaveAccessibleName("Board"); + expect(screen.getByTestId("sidebar-nav-list")).toHaveAccessibleName("List"); + expect(screen.getByTestId("sidebar-nav-agents")).toHaveAccessibleName("Agents"); + expect(screen.getByTestId("sidebar-nav-missions")).toHaveAccessibleName("Missions"); + expect(screen.queryByRole("button", { name: /view$/i })).toBeNull(); + }); + it("renders mailbox and stash badges", () => { renderSidebar(); @@ -131,6 +142,35 @@ describe("LeftSidebarNav", () => { expect(screen.getByTestId("sidebar-nav-plugin-fusion-plugin-overflow-overflow-view")).toBeDefined(); }); + it("renders plugin labels without view suffix and shortens Compound Engineering", () => { + renderSidebar({ + pluginDashboardViews: [ + ...pluginViews, + { + pluginId: "fusion-plugin-compound-engineering", + view: { + viewId: "compound", + label: "Compound Engineering", + componentPath: "./CompoundEngineering", + placement: "primary", + order: 0, + }, + }, + ], + }); + + const primaryPlugin = screen.getByTestId("sidebar-nav-plugin-fusion-plugin-primary-primary-view"); + const compoundPlugin = screen.getByTestId("sidebar-nav-plugin-fusion-plugin-compound-engineering-compound"); + expect(primaryPlugin).toHaveAccessibleName("Primary Plugin"); + expect(primaryPlugin).toHaveAttribute("title", "Primary Plugin"); + expect(primaryPlugin).toHaveTextContent("Primary Plugin"); + expect(primaryPlugin).not.toHaveTextContent("view"); + expect(compoundPlugin).toHaveAccessibleName("Compound"); + expect(compoundPlugin).toHaveAttribute("title", "Compound"); + expect(compoundPlugin).toHaveTextContent("Compound"); + expect(compoundPlugin).not.toHaveTextContent("Compound Engineering"); + }); + it.each<[TaskView, string]>([ ["board", "sidebar-nav-board"], ["research", "sidebar-nav-research"], diff --git a/packages/i18n/locales/en/app.json b/packages/i18n/locales/en/app.json index c7fb632fdf..1561255b9b 100644 --- a/packages/i18n/locales/en/app.json +++ b/packages/i18n/locales/en/app.json @@ -3823,6 +3823,7 @@ "activityLog": "Activity Log", "agents": "Agents", "automation": "Automation", + "board": "Board", "chat": "Chat", "chatUnreadAriaLabel": "Unread chat response", "commandCenter": "Command Center", @@ -3834,6 +3835,7 @@ "goals": "Goals", "importFromGitHub": "Import from GitHub", "insights": "Insights", + "list": "List", "loadingScripts": "Loading scripts…", "mailbox": "Mailbox", "mailboxPendingAriaLabel": "Pending approvals", diff --git a/packages/i18n/locales/es/app.json b/packages/i18n/locales/es/app.json index 30d2cd4c11..07e24aa7ba 100644 --- a/packages/i18n/locales/es/app.json +++ b/packages/i18n/locales/es/app.json @@ -3823,6 +3823,7 @@ "activityLog": "Registro de actividad", "agents": "Agentes", "automation": "Automatización", + "board": "Tablero", "chat": "Chat", "chatUnreadAriaLabel": "Respuesta de chat no leída", "commandCenter": "", @@ -3834,6 +3835,7 @@ "goals": "Objetivos", "importFromGitHub": "Importar desde GitHub", "insights": "Perspectivas", + "list": "Lista", "loadingScripts": "Cargando scripts…", "mailbox": "Bandeja de entrada", "mailboxPendingAriaLabel": "Aprobaciones pendientes", diff --git a/packages/i18n/locales/fr/app.json b/packages/i18n/locales/fr/app.json index 6c564543a5..1ed48a43fa 100644 --- a/packages/i18n/locales/fr/app.json +++ b/packages/i18n/locales/fr/app.json @@ -3823,6 +3823,7 @@ "activityLog": "Journal d'activité", "agents": "Agents", "automation": "Automatisation", + "board": "Tableau", "chat": "Chat", "chatUnreadAriaLabel": "Réponse non lue", "commandCenter": "", @@ -3834,6 +3835,7 @@ "goals": "Objectifs", "importFromGitHub": "Importer depuis GitHub", "insights": "Insights", + "list": "Liste", "loadingScripts": "Chargement des scripts…", "mailbox": "Boîte de réception", "mailboxPendingAriaLabel": "Approbations en attente", diff --git a/packages/i18n/locales/ko/app.json b/packages/i18n/locales/ko/app.json index 252b0a2b99..9149e65ce8 100644 --- a/packages/i18n/locales/ko/app.json +++ b/packages/i18n/locales/ko/app.json @@ -3823,6 +3823,7 @@ "activityLog": "활동 로그", "agents": "에이전트", "automation": "자동화", + "board": "보드", "chat": "채팅", "chatUnreadAriaLabel": "읽지 않은 채팅 응답", "commandCenter": "", @@ -3834,6 +3835,7 @@ "goals": "목표", "importFromGitHub": "GitHub에서 가져오기", "insights": "인사이트", + "list": "목록", "loadingScripts": "스크립트 불러오는 중…", "mailbox": "메일함", "mailboxPendingAriaLabel": "승인 대기 중", diff --git a/packages/i18n/locales/zh-CN/app.json b/packages/i18n/locales/zh-CN/app.json index 0fd9f109c3..cf79840d67 100644 --- a/packages/i18n/locales/zh-CN/app.json +++ b/packages/i18n/locales/zh-CN/app.json @@ -3823,6 +3823,7 @@ "activityLog": "活动日志", "agents": "智能体", "automation": "自动化", + "board": "看板", "chat": "聊天", "chatUnreadAriaLabel": "未读聊天回复", "commandCenter": "", @@ -3834,6 +3835,7 @@ "goals": "目标", "importFromGitHub": "从 GitHub 导入", "insights": "洞察", + "list": "列表", "loadingScripts": "正在加载脚本…", "mailbox": "邮箱", "mailboxPendingAriaLabel": "待审批", diff --git a/packages/i18n/locales/zh-TW/app.json b/packages/i18n/locales/zh-TW/app.json index 89f23270e6..084960c08b 100644 --- a/packages/i18n/locales/zh-TW/app.json +++ b/packages/i18n/locales/zh-TW/app.json @@ -3823,6 +3823,7 @@ "activityLog": "活動紀錄", "agents": "代理", "automation": "自動化", + "board": "看板", "chat": "聊天", "chatUnreadAriaLabel": "未讀聊天回覆", "commandCenter": "", @@ -3834,6 +3835,7 @@ "goals": "目標", "importFromGitHub": "從 GitHub 匯入", "insights": "洞察", + "list": "清單", "loadingScripts": "正在載入腳本…", "mailbox": "收件匣", "mailboxPendingAriaLabel": "待審核",