Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/browser/components/ChatMetaSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const ChatMetaSidebarComponent: React.FC<ChatMetaSidebarProps> = ({ workspaceId,
return (
<div
className={cn(
"bg-separator border-l border-border-light flex flex-col overflow-hidden transition-[width] duration-200 flex-shrink-0",
"bg-sidebar border-l border-border-light flex flex-col overflow-hidden transition-[width] duration-200 flex-shrink-0",
showCollapsed ? "w-5 sticky right-0 z-10 shadow-[-2px_0_4px_rgba(0,0,0,0.2)]" : "w-80"
)}
role="complementary"
Expand Down
4 changes: 2 additions & 2 deletions src/browser/components/LeftSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function LeftSidebar(props: LeftSidebarProps) {
aria-label="Open sidebar menu"
className={cn(
"hidden mobile-menu-btn fixed top-3 left-3 z-[998]",
"w-10 h-10 bg-separator border border-border-light rounded-md cursor-pointer",
"w-10 h-10 bg-sidebar border border-border-light rounded-md cursor-pointer",
"items-center justify-center text-foreground text-xl transition-all duration-200",
"shadow-[0_2px_4px_rgba(0,0,0,0.3)]",
"hover:bg-hover hover:border-bg-light",
Expand All @@ -49,7 +49,7 @@ export function LeftSidebar(props: LeftSidebarProps) {
{/* Sidebar */}
<div
className={cn(
"h-screen bg-separator border-r border-dark flex flex-col shrink-0",
"h-screen bg-sidebar border-r border-border flex flex-col shrink-0",
"transition-all duration-200 overflow-hidden relative z-[100]",
collapsed ? "w-8" : "w-72",
"mobile-sidebar",
Expand Down
77 changes: 41 additions & 36 deletions src/browser/components/ProjectSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ const DraggableProjectItemBase: React.FC<DraggableProjectItemProps> = ({
<div
ref={(node) => drag(drop(node))}
className={cn(
"py-2 px-3 flex items-center border-l-transparent transition-all duration-150 bg-separator",
"py-2 px-3 flex items-center border-l-transparent transition-all duration-150 bg-sidebar",
isDragging ? "cursor-grabbing opacity-40 [&_*]:!cursor-grabbing" : "cursor-grab",
isOver && "bg-accent/[0.08]",
selected && "bg-hover border-l-accent",
"hover:bg-hover hover:[&_button]:opacity-100 hover:[&_[data-drag-handle]]:opacity-100"
"hover:[&_button]:opacity-100 hover:[&_[data-drag-handle]]:opacity-100"
)}
{...rest}
>
Expand Down Expand Up @@ -465,19 +465,19 @@ const ProjectSidebarInner: React.FC<ProjectSidebarProps> = ({
<DndProvider backend={HTML5Backend}>
<ProjectDragLayer />
<div
className="font-primary bg-dark border-border-light flex flex-1 flex-col overflow-hidden border-r"
className="font-primary bg-sidebar border-border-light flex flex-1 flex-col overflow-hidden border-r"
role="navigation"
aria-label="Projects"
>
{!collapsed && (
<>
<div className="border-dark flex items-center justify-between border-b p-4">
<h2 className="text-foreground text-md m-0 font-semibold">Agents</h2>
<h2 className="text-foreground m-0 text-lg font-medium">Projects</h2>
<TooltipWrapper inline>
<button
onClick={onAddProject}
aria-label="Add project"
className="text-foreground hover:bg-hover hover:border-border-light flex h-6 w-6 cursor-pointer items-center justify-center rounded border border-transparent bg-transparent p-0 text-lg transition-all duration-200"
className="text-secondary hover:bg-hover hover:border-border-light flex h-6 w-6 cursor-pointer items-center justify-center rounded border border-transparent bg-transparent p-0 text-2xl transition-all duration-200"
>
+
</button>
Expand Down Expand Up @@ -513,42 +513,47 @@ const ProjectSidebarInner: React.FC<ProjectSidebarProps> = ({
projectPath={projectPath}
onReorder={handleReorder}
selected={false}
onClick={() => toggleProject(projectPath)}
onClick={() => handleAddWorkspace(projectPath)}
onKeyDown={(e: React.KeyboardEvent) => {
// Ignore key events from child buttons
if (e.target instanceof HTMLElement && e.target !== e.currentTarget) {
return;
}
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
toggleProject(projectPath);
handleAddWorkspace(projectPath);
}
}}
role="button"
tabIndex={0}
aria-expanded={isExpanded}
aria-controls={workspaceListId}
aria-label={`${isExpanded ? "Collapse" : "Expand"} project ${projectName}`}
aria-label={`Create workspace in ${projectName}`}
data-project-path={projectPath}
>
<span
<button
onClick={(event) => {
event.stopPropagation();
toggleProject(projectPath);
}}
aria-label={`${isExpanded ? "Collapse" : "Expand"} project ${projectName}`}
data-project-path={projectPath}
aria-hidden="true"
className="text-muted mr-2 shrink-0 text-xs transition-transform duration-200"
style={{ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)" }}
className="text-secondary hover:bg-hover hover:border-border-light mr-2 flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded border border-transparent bg-transparent p-0 transition-all duration-200"
>
<ChevronRight size={12} />
</span>
<ChevronRight
size={12}
className="transition-transform duration-200"
style={{ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)" }}
/>
</button>
<div className="flex min-w-0 flex-1 items-center pr-2">
<TooltipWrapper inline>
<div className="text-muted-dark truncate text-sm">
<div className="text-muted-dark flex gap-2 truncate text-sm">
{(() => {
const abbrevPath = PlatformPaths.abbreviate(projectPath);
const { dirPath, basename } =
PlatformPaths.splitAbbreviated(abbrevPath);
const { basename } = PlatformPaths.splitAbbreviated(abbrevPath);
return (
<>
<span>{dirPath}</span>
<span className="text-foreground font-medium">
{basename}
</span>
</>
<span className="text-foreground font-medium">{basename}</span>
);
})()}
</div>
Expand Down Expand Up @@ -582,34 +587,34 @@ const ProjectSidebarInner: React.FC<ProjectSidebarProps> = ({
title="Remove project"
aria-label={`Remove project ${projectName}`}
data-project-path={projectPath}
className="text-muted-dark hover:text-danger-light hover:bg-danger-light/10 flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-[3px] border-none bg-transparent text-base opacity-0 transition-all duration-200"
className="text-muted-dark hover:text-danger-light hover:bg-danger-light/10 mr-1 flex h-5 w-5 shrink-0 cursor-pointer items-center justify-center rounded-[3px] border-none bg-transparent text-base opacity-0 transition-all duration-200"
>
×
</button>
<Tooltip className="tooltip" align="right">
Remove project
</Tooltip>
</TooltipWrapper>
<button
onClick={(event) => {
event.stopPropagation();
handleAddWorkspace(projectPath);
}}
aria-label={`New chat in ${projectName}`}
data-project-path={projectPath}
className="text-secondary hover:bg-hover hover:border-border-light shrink-0 cursor-pointer rounded border border-transparent bg-transparent px-1.5 py-0.5 text-[11px] transition-all duration-200"
>
+ New Chat
</button>
</DraggableProjectItem>

{isExpanded && (
<div
id={workspaceListId}
role="region"
aria-label={`Workspaces for ${projectName}`}
className="pt-1"
>
<div className="border-hover border-b px-3 py-2">
<button
onClick={() => handleAddWorkspace(projectPath)}
data-project-path={projectPath}
aria-label={`Add workspace to ${projectName}`}
className="text-muted border-border-medium hover:bg-hover hover:border-border-darker hover:text-foreground w-full cursor-pointer rounded border border-dashed bg-transparent px-3 py-1.5 text-left text-[13px] transition-all duration-200"
>
+ New Workspace
{selectedWorkspace?.projectPath === projectPath &&
` (${formatKeybind(KEYBINDS.NEW_WORKSPACE)})`}
</button>
</div>
{(() => {
const allWorkspaces =
sortedWorkspacesByProject.get(projectPath) ?? [];
Expand Down
4 changes: 2 additions & 2 deletions src/browser/components/RightSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const SidebarContainer: React.FC<SidebarContainerProps> = ({
return (
<div
className={cn(
"bg-separator border-l border-border-light flex flex-col overflow-hidden flex-shrink-0",
"bg-sidebar border-l border-border-light flex flex-col overflow-hidden flex-shrink-0",
customWidth ? "" : "transition-[width] duration-200",
collapsed && "sticky right-0 z-10 shadow-[-2px_0_4px_rgba(0,0,0,0.2)]",
// Mobile: Show vertical meter when collapsed (20px), full width when expanded
Expand Down Expand Up @@ -215,7 +215,7 @@ const RightSidebarComponent: React.FC<RightSidebarProps> = ({
<div className={cn("flex-row h-full", !showCollapsed ? "flex" : "hidden")}>
{/* Render meter when Review tab is active */}
{selectedTab === "review" && (
<div className="bg-separator border-border-light flex w-5 shrink-0 flex-col border-r">
<div className="bg-sidebar border-border-light flex w-5 shrink-0 flex-col border-r">
{verticalMeter}
</div>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/browser/components/RightSidebar/VerticalTokenMeter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const VerticalTokenMeterComponent: React.FC<VerticalTokenMeterProps> = ({

return (
<div
className="bg-separator border-border-light flex h-full w-5 flex-col items-center border-l py-3"
className="bg-sidebar border-border-light flex h-full w-5 flex-col items-center border-l py-3"
data-component="vertical-token-meter"
>
{/* Percentage label at top */}
Expand Down
2 changes: 1 addition & 1 deletion src/browser/components/TitleBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ export function TitleBar() {
const showUpdateIndicator = true;

return (
<div className="bg-separator border-border-light font-primary text-muted flex h-8 shrink-0 items-center justify-between border-b px-4 text-[11px] select-none">
<div className="bg-sidebar border-border-light font-primary text-muted flex h-8 shrink-0 items-center justify-between border-b px-4 text-[11px] select-none">
<div className="mr-4 flex min-w-0 items-center gap-2">
{showUpdateIndicator && (
<TooltipWrapper>
Expand Down
2 changes: 1 addition & 1 deletion src/browser/components/VimTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export const VimTextArea = React.forwardRef<HTMLTextAreaElement, VimTextAreaProp
...(trailingAction ? { scrollbarGutter: "stable both-edges" } : {}),
}}
className={cn(
"w-full border text-light py-1.5 px-2 rounded font-mono text-[13px] resize-none min-h-8 max-h-[50vh] overflow-y-auto",
"w-full border text-light py-1.5 px-2 rounded font-sans text-[13px] resize-none min-h-8 max-h-[50vh] overflow-y-auto",
"placeholder:text-placeholder",
"focus:outline-none",
trailingAction && "pr-10",
Expand Down
2 changes: 1 addition & 1 deletion src/browser/components/WorkspaceHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const WorkspaceHeader: React.FC<WorkspaceHeaderProps> = ({
}, [startTutorial, isSequenceCompleted]);

return (
<div className="bg-separator border-border-light flex h-8 items-center justify-between border-b px-[15px] [@media(max-width:768px)]:h-auto [@media(max-width:768px)]:flex-wrap [@media(max-width:768px)]:gap-2 [@media(max-width:768px)]:py-2 [@media(max-width:768px)]:pl-[60px]">
<div className="bg-sidebar border-border-light flex h-8 items-center justify-between border-b px-[15px] [@media(max-width:768px)]:h-auto [@media(max-width:768px)]:flex-wrap [@media(max-width:768px)]:gap-2 [@media(max-width:768px)]:py-2 [@media(max-width:768px)]:pl-[60px]">
<div className="text-foreground flex min-w-0 items-center gap-2 overflow-hidden font-semibold">
<RuntimeBadge runtimeConfig={runtimeConfig} isWorking={canInterrupt} />
<GitStatusIndicator
Expand Down
45 changes: 25 additions & 20 deletions src/browser/components/WorkspaceListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,26 +160,31 @@ const WorkspaceListItemInner: React.FC<WorkspaceListItemProps> = ({
data-workspace-id={workspaceId}
/>
) : (
<span
className={cn(
"text-foreground -mx-1 min-w-0 flex-1 truncate rounded-sm px-1 text-left text-[14px] transition-colors duration-200",
!isDisabled && "cursor-pointer hover:bg-white/5"
)}
onDoubleClick={(e) => {
if (isDisabled) return;
e.stopPropagation();
startRenaming();
}}
title={isDisabled ? undefined : "Double-click to rename"}
>
{canInterrupt || isCreating ? (
<Shimmer className="w-full truncate" colorClass="var(--color-foreground)">
{displayName}
</Shimmer>
) : (
displayName
)}
</span>
<TooltipWrapper inline>
<span
className={cn(
"text-foreground -mx-1 min-w-0 flex-1 truncate rounded-sm px-1 text-left text-[14px] transition-colors duration-200",
!isDisabled && "cursor-pointer"
)}
onDoubleClick={(e) => {
if (isDisabled) return;
e.stopPropagation();
startRenaming();
}}
title={isDisabled ? undefined : "Double-click to rename"}
>
{canInterrupt || isCreating ? (
<Shimmer className="w-full truncate" colorClass="var(--color-foreground)">
{displayName}
</Shimmer>
) : (
displayName
)}
</span>
<Tooltip className="tooltip" align="left">
Double-click to rename
</Tooltip>
</TooltipWrapper>
)}

<div className="ml-auto flex items-center gap-1">
Expand Down
16 changes: 10 additions & 6 deletions src/browser/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
/* Background & Layout */
--color-background: hsl(0 0% 12%);
--color-background-secondary: hsl(60 1% 15%);
--color-border: hsl(240 2% 25%);
--color-border: #262626; /* neutral-800 */
--color-foreground: hsl(0 0% 83%);
--color-text: hsl(0 0% 83%);
--color-text-light: hsl(0 0% 73%);
Expand Down Expand Up @@ -189,20 +189,21 @@
--color-gray: hsl(0 0% 48%); /* #7a7a7a - gray */
--color-medium: hsl(0 0% 59%); /* #969696 - medium */

--color-border-light: hsl(240 3% 25%); /* #3e3e42 - lighter borders */
--color-border-light: #262626; /* neutral-800 - borders */
--color-border-medium: hsl(0 0% 27%); /* #444 - medium borders */
--color-border-darker: hsl(0 0% 33%); /* #555 - darker borders */
--color-border-subtle: hsl(0 0% 40%); /* #666 - subtle border */
--color-border-gray: hsl(240 1% 31%); /* #4e4e52 - gray border */

--color-dark: hsl(0 0% 11.5%); /* #1e1e1e - dark backgrounds */
--color-dark: #1D1D1D; /* dark backgrounds */
--color-darker: hsl(0 0% 8.6%); /* #161616 - darker backgrounds */
--color-hover: hsl(0 0% 16.5%); /* #2a2a2b - hover states */
--color-bg-medium: hsl(0 0% 27%); /* #454545 - medium bg */
--color-bg-light: hsl(0 0% 30%); /* #4c4c4c - light bg */
--color-bg-subtle: hsl(240 3% 22%); /* #37373d - subtle bg */

--color-separator: hsl(0 0% 15%); /* #252526 - separators */
--color-sidebar: #171717; /* neutral-900 - sidebar background */
--color-separator: #262626; /* neutral-800 - dividers/separators */
--color-separator-light: hsl(0 0% 27%); /* #464647 - lighter separator */
--color-modal-bg: hsl(0 0% 18%); /* #2d2d30 - modal backgrounds */

Expand Down Expand Up @@ -434,6 +435,7 @@
--color-bg-light: hsl(210 24% 84%);
--color-bg-subtle: hsl(210 32% 92%);

--color-sidebar: hsl(0 0% 96%); /* light theme sidebar */
--color-separator: hsl(0 0% 91%);
--color-separator-light: hsl(0 0% 96%);
--color-modal-bg: hsl(210 35% 96%);
Expand Down Expand Up @@ -662,7 +664,8 @@
--color-bg-light: #d5ceb8;
--color-bg-subtle: #eee8d5;

--color-separator: #eee8d5; /* base2 - sidebar background */
--color-sidebar: #eee8d5; /* base2 - sidebar background */
--color-separator: #d5ceb8;
--color-separator-light: #f5efdc;
--color-modal-bg: #fdf6e3;

Expand Down Expand Up @@ -881,7 +884,8 @@
--color-bg-light: #106577;
--color-bg-subtle: #073642;

--color-separator: #073642; /* base02 - sidebar background */
--color-sidebar: #073642; /* base02 - sidebar background */
--color-separator: #0a4555;
--color-separator-light: #094555; /* slightly lighter for hover states */
--color-modal-bg: #073642;

Expand Down
4 changes: 3 additions & 1 deletion tests/e2e/utils/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ export function createWorkspaceUI(page: Page, context: DemoProjectConfig): Works
const workspaceItem = workspaceItems.first();
const isVisible = await workspaceItem.isVisible().catch(() => false);
if (!isVisible) {
await projectItem.click();
// Click the expand/collapse button within the project item
const expandButton = projectItem.getByRole("button", { name: /expand project/i });
await expandButton.click();
await workspaceItem.waitFor({ state: "visible" });
}

Expand Down