Skip to content

Commit 6a7553c

Browse files
committed
Polish task center and autopilot transition
1 parent 0e8435f commit 6a7553c

23 files changed

Lines changed: 486 additions & 316 deletions

client/src/App.shell-layout.test.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,18 @@ describe("AppShell fixed sidebar layout", () => {
147147
expect(shell).toContain("--sidebar-width:0px");
148148
expect(shell).toContain("padding-left:0");
149149
});
150+
151+
it("does not keep the task sidebar offset when the home URL has query or hash state", () => {
152+
locationState.current = "/?from=tasks#autopilot";
153+
viewportState.isMobile = false;
154+
viewportState.isTablet = false;
155+
156+
const markup = renderToStaticMarkup(<AppShell />);
157+
const shell = markup.match(/<div class="min-h-screen[^>]*>/)?.[0] ?? "";
158+
159+
expect(markup).not.toContain('data-testid="app-sidebar"');
160+
expect(shell).toContain("--sidebar-width:0px");
161+
expect(shell).toContain("padding-left:0");
162+
expect(shell).not.toContain("transition-[padding-left]");
163+
});
150164
});

client/src/App.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ function RecoveryGuard() {
107107
);
108108
}
109109

110+
function isHomeLocation(location: string) {
111+
const [pathname] = location.trim().split(/[?#]/, 1);
112+
return pathname === "" || pathname === "/";
113+
}
114+
110115
export function AppShell() {
111116
const { isMobile, isTablet } = useViewportTier();
112117
const [location] = useLocation();
@@ -117,24 +122,29 @@ export function AppShell() {
117122
}, [isTablet]);
118123

119124
const sidebarWidth = isMobile ? 0 : sidebarCollapsed ? 64 : 248;
125+
const isHome = isHomeLocation(location);
120126

121127
return (
122128
<>
123129
<RecoveryGuard />
124130

125-
{!isMobile && location !== "/" && (
131+
{!isMobile && !isHome && (
126132
<AppSidebar
127133
collapsed={sidebarCollapsed}
128134
onToggleCollapse={() => setSidebarCollapsed(current => !current)}
129135
/>
130136
)}
131137

132138
<div
133-
className="min-h-screen transition-[padding-left] duration-[250ms] ease-in-out"
139+
className={
140+
isHome
141+
? "min-h-screen"
142+
: "min-h-screen transition-[padding-left] duration-[250ms] ease-in-out"
143+
}
134144
style={
135145
{
136-
"--sidebar-width": `${location === "/" ? 0 : sidebarWidth}px`,
137-
paddingLeft: location === "/" ? 0 : sidebarWidth,
146+
"--sidebar-width": `${isHome ? 0 : sidebarWidth}px`,
147+
paddingLeft: isHome ? 0 : sidebarWidth,
138148
} as React.CSSProperties
139149
}
140150
>

client/src/components/AppSidebar.tsx

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ type SidebarTone = "light" | "glass";
2020
function SidebarHeader({
2121
collapsed,
2222
tone,
23+
locale,
2324
}: {
2425
collapsed: boolean;
2526
tone: SidebarTone;
27+
locale: string;
2628
}) {
2729
const glass = tone === "glass";
30+
const subtitle =
31+
locale === "zh-CN"
32+
? "办公空间协同决策智能体平台"
33+
: "Collaborative agent office platform";
2834

2935
return (
3036
<div
@@ -44,7 +50,7 @@ function SidebarHeader({
4450
<span className="absolute inset-0 bg-[radial-gradient(circle_at_30%_20%,rgba(125,211,252,0.42),transparent_42%),linear-gradient(135deg,rgba(255,255,255,0.96),rgba(224,242,254,0.46))]" />
4551
<span className="relative">CP</span>
4652
</span>
47-
{!collapsed && (
53+
{!collapsed ? (
4854
<span className="min-w-0">
4955
<span
5056
className={cn(
@@ -55,10 +61,10 @@ function SidebarHeader({
5561
Cube Pets Office
5662
</span>
5763
<span className="mt-1.5 block truncate text-[11px] font-semibold leading-none text-slate-500">
58-
办公室已成为桌面运转的伙伴
64+
{subtitle}
5965
</span>
6066
</span>
61-
)}
67+
) : null}
6268
</div>
6369
);
6470
}
@@ -122,13 +128,13 @@ function SidebarNavItem({
122128
>
123129
<Icon className="size-[17px] shrink-0" />
124130
</span>
125-
{!collapsed && <span className="truncate">{label}</span>}
126-
{active && (
131+
{!collapsed ? <span className="truncate">{label}</span> : null}
132+
{active ? (
127133
<>
128134
<span className="absolute left-0 top-1/2 h-7 w-1 -translate-y-1/2 rounded-r-full bg-sky-400 shadow-[0_0_18px_rgba(56,189,248,0.68)]" />
129135
<span className="pointer-events-none absolute inset-y-2 right-2 w-12 rounded-full bg-[radial-gradient(circle,rgba(125,211,252,0.22),transparent_68%)]" />
130136
</>
131-
)}
137+
) : null}
132138
</button>
133139
);
134140

@@ -139,11 +145,11 @@ function SidebarNavItem({
139145
<TooltipTrigger asChild>{content}</TooltipTrigger>
140146
<TooltipContent side="right" sideOffset={8}>
141147
{label}
142-
{isDisabled && (
148+
{isDisabled ? (
143149
<span className="ml-1 text-xs opacity-60">
144150
({comingSoonLabel})
145151
</span>
146-
)}
152+
) : null}
147153
</TooltipContent>
148154
</Tooltip>
149155
</li>
@@ -156,11 +162,14 @@ function SidebarNavItem({
156162
function SidebarUserBlock({
157163
collapsed,
158164
tone,
165+
locale,
159166
}: {
160167
collapsed: boolean;
161168
tone: SidebarTone;
169+
locale: string;
162170
}) {
163171
const glass = tone === "glass";
172+
const modeLabel = locale === "zh-CN" ? "高级模式" : "Advanced mode";
164173

165174
return (
166175
<div
@@ -185,16 +194,16 @@ function SidebarUserBlock({
185194
>
186195
MC
187196
</div>
188-
{!collapsed && (
197+
{!collapsed ? (
189198
<span className="min-w-0">
190199
<span className="block truncate text-sm font-bold text-slate-800">
191200
Mission Control
192201
</span>
193202
<span className="mt-0.5 block truncate text-[11px] font-medium text-slate-500">
194-
高级模式
203+
{modeLabel}
195204
</span>
196205
</span>
197-
)}
206+
) : null}
198207
</div>
199208
);
200209
}
@@ -233,21 +242,22 @@ export function AppSidebar({
233242
embedded = false,
234243
}: AppSidebarProps) {
235244
const [location, setLocation] = useLocation();
236-
const { copy } = useI18n();
245+
const { locale, copy } = useI18n();
237246
const activeId = getActiveSidebarId(location);
238-
const sidebarCopy = copy.sidebar;
239247
const sidebarTone: SidebarTone = embedded ? "glass" : "light";
248+
const isZh = locale === "zh-CN";
249+
const sidebarCopy = copy.sidebar;
240250

241251
const labelMap: Record<string, string> = {
242-
autopilot: sidebarCopy.autopilot,
243-
tasks: sidebarCopy.tasks,
244-
projects: sidebarCopy.projects,
245-
knowledge: sidebarCopy.knowledge,
246-
datasource: sidebarCopy.datasource,
247-
dashboard: sidebarCopy.dashboard,
248-
marketplace: sidebarCopy.marketplace,
249-
notifications: sidebarCopy.notifications,
250-
settings: sidebarCopy.settings,
252+
autopilot: isZh ? "自动驾驶" : sidebarCopy.autopilot,
253+
tasks: isZh ? "任务中心" : sidebarCopy.tasks,
254+
projects: isZh ? "项目空间" : sidebarCopy.projects,
255+
knowledge: isZh ? "知识库" : sidebarCopy.knowledge,
256+
datasource: isZh ? "数据源" : sidebarCopy.datasource,
257+
dashboard: isZh ? "数据看板" : sidebarCopy.dashboard,
258+
marketplace: isZh ? "智能体市场" : sidebarCopy.marketplace,
259+
notifications: isZh ? "通知中心" : sidebarCopy.notifications,
260+
settings: isZh ? "设置与集成" : sidebarCopy.settings,
251261
};
252262

253263
return (
@@ -272,7 +282,11 @@ export function AppSidebar({
272282
color: "#1e293b",
273283
}}
274284
>
275-
<SidebarHeader collapsed={collapsed} tone={sidebarTone} />
285+
<SidebarHeader
286+
collapsed={collapsed}
287+
tone={sidebarTone}
288+
locale={locale}
289+
/>
276290

277291
<nav
278292
className={cn(
@@ -281,9 +295,9 @@ export function AppSidebar({
281295
)}
282296
aria-label="Main navigation"
283297
>
284-
{!collapsed && (
298+
{!collapsed ? (
285299
<span className="pointer-events-none absolute bottom-8 left-[31px] top-5 w-px bg-gradient-to-b from-transparent via-sky-100/80 to-transparent" />
286-
)}
300+
) : null}
287301
<ul role="list" className="relative flex flex-col gap-2.5">
288302
{SIDEBAR_NAV_ITEMS.map(item => (
289303
<SidebarNavItem
@@ -319,9 +333,13 @@ export function AppSidebar({
319333

320334
<SidebarStatusBlock collapsed={collapsed} tone={sidebarTone} />
321335

322-
<SidebarUserBlock collapsed={collapsed} tone={sidebarTone} />
336+
<SidebarUserBlock
337+
collapsed={collapsed}
338+
tone={sidebarTone}
339+
locale={locale}
340+
/>
323341

324-
{!collapsed && <SidebarTaskStats tone={sidebarTone} />}
342+
{!collapsed ? <SidebarTaskStats tone={sidebarTone} /> : null}
325343
</aside>
326344
);
327345
}

client/src/components/Scene3D.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ export function Scene3D({
163163
return (
164164
<div
165165
ref={containerRef}
166-
className="absolute inset-0 z-0 h-full w-full touch-pan-y"
166+
className="absolute inset-0 z-0 h-full w-full touch-pan-y bg-[linear-gradient(180deg,#eef6fb_0%,#f7fbfd_48%,#e5f1f4_100%)]"
167167
style={{ visibility: hidden ? "hidden" : "visible" }}
168168
>
169169
<Canvas

client/src/components/launch/LaunchRuntimeMeta.tsx

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type { ReactNode } from "react";
2-
import { Loader2, Monitor, Paperclip, Send, Server } from "lucide-react";
2+
import { Loader2, Monitor, Paperclip, Server } from "lucide-react";
33

4-
import { GlowButton } from "@/components/ui/GlowButton";
54
import { Button } from "@/components/ui/button";
65
import type { RuntimeMode } from "@/lib/store";
76
import { cn } from "@/lib/utils";
@@ -35,9 +34,6 @@ export function LaunchRuntimeMeta({
3534
maxAttachments,
3635
onPickFiles,
3736
operatorActionRail,
38-
onSubmit,
39-
submitLabel,
40-
submitDisabled = false,
4137
}: {
4238
locale: string;
4339
runtimeMode: RuntimeMode;
@@ -46,16 +42,13 @@ export function LaunchRuntimeMeta({
4642
maxAttachments?: number;
4743
onPickFiles?: () => void;
4844
operatorActionRail?: ReactNode;
49-
onSubmit?: () => void;
50-
submitLabel?: string;
51-
submitDisabled?: boolean;
5245
}) {
5346
const hasSharedActionRail = Boolean(operatorActionRail);
5447

5548
return (
5649
<div
5750
className={cn(
58-
"mt-1.5 flex gap-1.5 text-xs text-stone-500",
51+
"mt-3 flex gap-2 text-xs text-slate-500",
5952
hasSharedActionRail
6053
? "flex-wrap items-end"
6154
: "overflow-x-auto whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden"
@@ -71,7 +64,7 @@ export function LaunchRuntimeMeta({
7164
<Button
7265
type="button"
7366
variant="outline"
74-
className="h-7 rounded-full px-2.5 text-[11px] whitespace-nowrap"
67+
className="h-8 rounded-full border-slate-200/80 bg-white/74 px-3 text-[11px] font-semibold text-slate-600 shadow-none whitespace-nowrap hover:bg-white hover:text-slate-900"
7568
disabled={
7669
isPreparingFiles ||
7770
(typeof maxAttachments === "number" &&
@@ -88,7 +81,7 @@ export function LaunchRuntimeMeta({
8881
</Button>
8982
) : null}
9083

91-
<span className="inline-flex items-center gap-1 rounded-full border border-stone-200/80 bg-stone-50 px-2 py-0.75 whitespace-nowrap">
84+
<span className="inline-flex h-8 items-center gap-1.5 rounded-full border border-slate-200/80 bg-white/62 px-3 text-[11px] font-semibold text-slate-600 whitespace-nowrap">
9285
{runtimeMode === "advanced" ? (
9386
<Server className="size-3.5" />
9487
) : (
@@ -98,7 +91,7 @@ export function LaunchRuntimeMeta({
9891
</span>
9992

10093
{attachmentCount > 0 ? (
101-
<span className="inline-flex items-center gap-1 rounded-full border border-stone-200/80 bg-stone-50 px-2 py-0.75 whitespace-nowrap">
94+
<span className="inline-flex h-8 items-center gap-1 rounded-full border border-slate-200/80 bg-white/62 px-3 text-[11px] font-semibold text-slate-600 whitespace-nowrap">
10295
{getLaunchAttachmentCountLabel(locale, attachmentCount)}
10396
</span>
10497
) : null}
@@ -113,18 +106,6 @@ export function LaunchRuntimeMeta({
113106
)}
114107
>
115108
{operatorActionRail}
116-
117-
{!hasSharedActionRail && onSubmit && submitLabel ? (
118-
<GlowButton
119-
type="button"
120-
disabled={submitDisabled}
121-
className="h-7 shrink-0 rounded-full px-2.5 text-[11px] font-semibold shadow-[0_10px_24px_rgba(94,139,114,0.18)]"
122-
onClick={onSubmit}
123-
>
124-
<Send className="size-3.5" />
125-
{submitLabel}
126-
</GlowButton>
127-
) : null}
128109
</div>
129110
</div>
130111
);

0 commit comments

Comments
 (0)