Skip to content
Closed
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
10 changes: 8 additions & 2 deletions apps/web/src/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2779,11 +2779,17 @@ function OpenCommandPaletteDialog(props: {
/>
) : null}
{browseAccessError ? (
<div role="alert" className="px-4 py-3 text-sm text-muted-foreground">
<div
role="alert"
className="px-4 py-3 text-sm text-muted-foreground redesign:mx-2 redesign:mb-2 redesign:rounded-lg redesign:bg-foreground/[0.035] redesign:text-secondary-label"
>
{browseAccessError}
</div>
) : isBrowsePending && browseResult === null ? (
<div role="status" className="px-4 py-3 text-sm text-muted-foreground">
<div
role="status"
className="px-4 py-3 text-sm text-muted-foreground redesign:py-8 redesign:text-center redesign:text-secondary-label"
>
Loading folders...
</div>
) : null}
Expand Down
20 changes: 13 additions & 7 deletions apps/web/src/components/CommandPaletteAddProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,15 +129,15 @@ export function NewProjectSummary(props: {
}) {
return (
<div className="p-2 pb-0">
<div className="flex min-h-8 items-center gap-2 rounded-sm px-2 py-1.5">
<div className="flex min-h-8 items-center gap-2 rounded-sm px-2 py-1.5 redesign:gap-3 redesign:rounded-lg redesign:bg-foreground/[0.035] redesign:px-3">
<CommandPaletteTitleIcon>
<FolderGit2Icon className={ITEM_ICON_CLASS} />
</CommandPaletteTitleIcon>
<span className="flex min-w-0 flex-1 flex-col">
<span className="truncate text-foreground text-sm">
<span className="truncate text-foreground text-sm redesign:font-medium">
{props.name.length > 0 ? props.name : "New project"}
</span>
<span className="truncate text-muted-foreground/85 text-xs">
<span className="truncate text-muted-foreground/85 text-xs redesign:text-secondary-label">
{props.name.length > 0
? `Creates ${props.pathPreview}`
: `Goes in ${props.projectsRoot}`}
Expand All @@ -156,14 +156,20 @@ export function RemoteRepositorySummary(props: {
}) {
return (
<div className="shrink-0 p-2 pb-0">
<div className="px-2 py-1.5 font-medium text-muted-foreground text-xs">Repository</div>
<div className="flex min-h-8 items-center gap-2 rounded-sm px-2 py-1.5">
<div className="px-2 py-1.5 font-medium text-muted-foreground text-xs redesign:font-semibold redesign:text-secondary-label">
Repository
</div>
<div className="flex min-h-8 items-center gap-2 rounded-sm px-2 py-1.5 redesign:gap-3 redesign:rounded-lg redesign:bg-foreground/[0.035] redesign:px-3">
<CommandPaletteTitleIcon>
{remoteProjectSourceIcon(props.source, ITEM_ICON_CLASS)}
</CommandPaletteTitleIcon>
<span className="flex min-w-0 flex-1 flex-col">
<span className="truncate text-foreground text-sm">{props.title}</span>
<span className="truncate text-muted-foreground/85 text-xs">{props.description}</span>
<span className="truncate text-foreground text-sm redesign:font-medium">
{props.title}
</span>
<span className="truncate text-muted-foreground/85 text-xs redesign:text-secondary-label">
{props.description}
</span>
</span>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/CommandPaletteContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function CommandPaletteContent({
{children}
</CommandPanel>
<CommandFooter className="max-sm:flex-col max-sm:items-start">
<div className="flex items-center gap-3">
<div className="flex items-center gap-3 redesign:min-w-0 redesign:flex-wrap redesign:gap-y-2">
<KbdGroup>
<Kbd>
<ArrowUpIcon />
Expand Down
36 changes: 27 additions & 9 deletions apps/web/src/components/CommandPaletteResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ interface CommandPaletteResultsProps {

function CommandPaletteEmptyState(props: { emptyStateMessage?: string; isActionsOnly: boolean }) {
return (
<div className="py-10 text-center text-sm text-muted-foreground">
<div className="py-10 text-center text-sm text-muted-foreground redesign:px-8 redesign:text-secondary-label redesign:text-balance">
{props.emptyStateMessage ??
(props.isActionsOnly
? "No matching actions."
Expand All @@ -53,7 +53,13 @@ export function CommandPaletteResults(props: CommandPaletteResultsProps) {
<CommandList>
{props.groups.map((group) => (
<CommandGroup items={group.items} key={group.value}>
{group.label ? <CommandGroupLabel>{group.label}</CommandGroupLabel> : null}
{group.label ? (
<CommandGroupLabel>
<span className="redesign:font-semibold redesign:text-secondary-label">
{group.label}
</span>
</CommandGroupLabel>
) : null}
<CommandCollection>
{(item) =>
item.disabled ? (
Expand Down Expand Up @@ -120,7 +126,11 @@ export function CommandPaletteVirtualizedResults(props: CommandPaletteVirtualize
renderItem={({ item: row }) =>
row.kind === "label" ? (
<div className={row.first ? undefined : "pt-1.5"}>
<CommandListHeading>{row.label}</CommandListHeading>
<CommandListHeading>
<span className="redesign:font-semibold redesign:text-secondary-label">
{row.label}
</span>
</CommandListHeading>
</div>
) : row.itemIndex === null ? (
<DisabledCommandPaletteResultRow item={row.item} />
Expand Down Expand Up @@ -149,7 +159,11 @@ export function CommandPaletteVirtualizedResults(props: CommandPaletteVirtualize
}

export function CommandPaletteTitleIcon(props: { children: ReactNode }) {
return <span className="flex h-5 shrink-0 items-center self-start pt-0.5">{props.children}</span>;
return (
<span className="flex h-5 shrink-0 items-center self-start pt-0.5 redesign:opacity-60 redesign:grayscale redesign:group-hover/palette-row:opacity-100 redesign:group-hover/palette-row:grayscale-0 redesign:group-data-active/palette-row:opacity-100 redesign:group-data-active/palette-row:grayscale-0">
{props.children}
</span>
);
}

function CommandPaletteTitle({
Expand All @@ -159,7 +173,10 @@ function CommandPaletteTitle({
}) {
const { title } = item;
return (
<span className="truncate" dir={typeof title === "string" ? textDirection(title) : undefined}>
<span
className="truncate redesign:text-foreground/75 redesign:group-hover/palette-row:text-foreground redesign:group-data-active/palette-row:text-foreground"
dir={typeof title === "string" ? textDirection(title) : undefined}
>
{title}
</span>
);
Expand All @@ -180,7 +197,7 @@ function ThreadRowContext({
.filter((part) => part && part !== item.matchHint?.text)
.join(" · ");
return context ? (
<span className="max-w-[45%] shrink-0 truncate text-muted-foreground/70 text-xs">
<span className="max-w-[45%] shrink-0 truncate text-muted-foreground/70 text-xs redesign:text-secondary-label">
{context}
</span>
) : null;
Expand All @@ -204,7 +221,7 @@ function DisabledCommandPaletteResultRow(props: {
) : props.item.matchHint ? (
<SearchMatchHintLine hint={props.item.matchHint} />
) : props.item.description ? (
<span className="min-w-0 text-muted-foreground/70 text-xs">
<span className="min-w-0 text-muted-foreground/70 text-xs redesign:text-secondary-label redesign:grayscale redesign:group-hover/palette-row:grayscale-0 redesign:group-data-active/palette-row:grayscale-0 redesign:[&_svg]:opacity-60 redesign:group-hover/palette-row:[&_svg]:opacity-100 redesign:group-data-active/palette-row:[&_svg]:opacity-100">
{props.item.description}
</span>
) : null}
Expand Down Expand Up @@ -234,6 +251,7 @@ function CommandPaletteResultRow(props: {
return (
<CommandItem
{...(props.index === undefined ? {} : { index: props.index })}
className="group/palette-row"
value={props.item.value}
active={props.isActive}
onMouseDown={(event) => {
Expand All @@ -256,7 +274,7 @@ function CommandPaletteResultRow(props: {
) : props.item.matchHint ? (
<SearchMatchHintLine hint={props.item.matchHint} />
) : props.item.description ? (
<span className="min-w-0 text-muted-foreground/70 text-xs">
<span className="min-w-0 text-muted-foreground/70 text-xs redesign:text-secondary-label redesign:grayscale redesign:group-hover/palette-row:grayscale-0 redesign:group-data-active/palette-row:grayscale-0 redesign:[&_svg]:opacity-60 redesign:group-hover/palette-row:[&_svg]:opacity-100 redesign:group-data-active/palette-row:[&_svg]:opacity-100">
{props.item.description}
</span>
) : null}
Expand All @@ -269,7 +287,7 @@ function CommandPaletteResultRow(props: {
)}
{props.item.titleTrailingContent}
{props.item.timestamp ? (
<span className="min-w-12 shrink-0 text-right text-xs tabular-nums text-muted-foreground/70">
<span className="min-w-12 shrink-0 text-right text-xs tabular-nums text-muted-foreground/70 redesign:self-start redesign:leading-5 redesign:text-secondary-label">
{props.item.timestamp}
</span>
) : null}
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/CommandPaletteThreadItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export function useCommandPaletteThreadItems(input: {
null;
return (
<ThreadCommandSubtitle
className="redesign:text-secondary-label"
project={projectByKey.get(`${thread.environmentId}:${thread.projectId}`) ?? null}
projectTitle={projectTitle ?? null}
environmentLabel={
Expand Down
49 changes: 32 additions & 17 deletions apps/web/src/components/DiffPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ import { useProject, useThreadCheckpointSummaries, useQuietThreadShell } from ".
import { useClientSettings, updateClientSettings } from "../hooks/useSettings";
import { formatShortTimestamp } from "../timestampFormat";
import { DiffFilePathCopyButton } from "./DiffFilePathCopyButton";
import { DiffPanelLoadingState, DiffPanelShell, type DiffPanelMode } from "./DiffPanelShell";
import {
DiffPanelEmptyState,
DiffPanelLoadingState,
DiffPanelShell,
type DiffPanelMode,
} from "./DiffPanelShell";
import { DiffStatLabel } from "./chat/DiffStatLabel";
import { AnnotatableCodeView, type AnnotatableCodeViewHandle } from "./diffs/AnnotatableCodeView";
import { DiffFileTree } from "./diffs/DiffFileTree";
Expand Down Expand Up @@ -200,6 +205,7 @@ export default function DiffPanel({
}: DiffPanelProps) {
const resolvedTheme = useRenderedAppearance();
const settings = useClientSettings((settings) => ({
redesignEnabled: settings.redesignEnabled,
diffFilesCollapsed: settings.diffFilesCollapsed,
diffIgnoreWhitespace: settings.diffIgnoreWhitespace,
diffLayout: settings.diffLayout,
Expand Down Expand Up @@ -666,7 +672,7 @@ export default function DiffPanel({
<div className="@container/diff-refs flex min-w-0 flex-1 items-center gap-3 [-webkit-app-region:no-drag]">
<DropdownMenu>
<DropdownMenuTrigger
render={<Button size="xs" variant="secondary" />}
render={<Button size="xs" variant={settings.redesignEnabled ? "ghost" : "secondary"} />}
className="max-w-full"
aria-label={`Diff scope: ${selectedScopeLabel}`}
>
Expand Down Expand Up @@ -713,7 +719,7 @@ export default function DiffPanel({
</DropdownMenu>
{selectedRunId === null && selectedGitScope === "branch" && selectedGitSource?.baseRef && (
<div
className="flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-xs text-muted-foreground"
className="flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-xs text-muted-foreground redesign:text-secondary-label"
aria-label={`Comparing ${selectedGitSource.headRef ?? "HEAD"} against ${selectedGitSource.baseRef}`}
>
<Tooltip>
Expand Down Expand Up @@ -985,37 +991,39 @@ export default function DiffPanel({
return (
<DiffPanelShell mode={mode} header={headerRow}>
{!activeThread ? (
<div className="flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70">
<DiffPanelEmptyState title="Select a thread">
Select a thread to inspect turn diffs.
</div>
</DiffPanelEmptyState>
) : !isGitRepo ? (
<div className="flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70">
<DiffPanelEmptyState title="Diffs unavailable">
Turn diffs are unavailable because this project is not a git repository.
</div>
</DiffPanelEmptyState>
) : selectedRunId !== null && orderedTurnDiffSummaries.length === 0 ? (
<div className="flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70">
<DiffPanelEmptyState title="No completed turns">
No completed turns yet.
</div>
</DiffPanelEmptyState>
) : selectedRunId === null && !canReadFiles ? (
fileAccess.isPending ? (
<DiffPanelLoadingState label="Checking file access..." />
) : (
<div className="flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70">
<DiffPanelEmptyState title="File access unavailable">
{fileAccess.error ?? "This connection cannot read local diffs."}
</div>
</DiffPanelEmptyState>
)
) : (
<>
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background">
{isSelectedPatchTruncated && !lazySource && (
<p className="shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-2xs text-muted-foreground">
<p className="shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-2xs text-muted-foreground redesign:mx-3 redesign:my-2 redesign:rounded-lg redesign:border-transparent redesign:px-3 redesign:py-2 redesign:text-xs">
This preview exceeds the size limit. Changes shown are incomplete.
{selectedGitSource?.files ? " Totals include all changes." : ""}
</p>
)}
{selectedPatchError && !renderablePatch && (
<div className="px-3">
<p className="mb-2 text-2xs text-error/80">{selectedPatchError}</p>
<div className="px-3 redesign:py-2">
<p className="mb-2 text-2xs text-error/80 redesign:rounded-lg redesign:bg-muted/40 redesign:p-3 redesign:text-xs">
{selectedPatchError}
</p>
</div>
)}
{!renderablePatch && !lazySource ? (
Expand All @@ -1030,13 +1038,16 @@ export default function DiffPanel({
}
/>
) : (
<div className="flex h-full items-center justify-center px-3 py-2 text-xs text-muted-foreground/70">
<DiffPanelEmptyState
title={hasNoNetChanges ? "No changes" : "Diff unavailable"}
className="flex h-full items-center justify-center px-3 py-2 text-xs text-muted-foreground/70"
>
<p>
{hasNoNetChanges
? "No net changes in this selection."
: "No patch available for this selection."}
</p>
</div>
</DiffPanelEmptyState>
)
) : lazySource || renderablePatch?.kind === "files" ? (
<div className="flex min-h-0 flex-1 overflow-hidden">
Expand Down Expand Up @@ -1139,7 +1150,11 @@ export default function DiffPanel({
fileKey={fileKey}
collapsed={unavailable || collapsedDiffFileKeys.has(fileKey)}
unavailable={unavailable}
iconClassName={getDiffCollapseIconClassName(fileDiff)}
iconClassName={
settings.redesignEnabled
? "text-muted-foreground"
: getDiffCollapseIconClassName(fileDiff)
}
onToggle={toggleDiffFileCollapsed}
/>
);
Expand Down
32 changes: 30 additions & 2 deletions apps/web/src/components/DiffPanelShell.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { ReactNode } from "react";
import { FileDiffIcon } from "lucide-react";

import { isElectron } from "~/env";
import { useClientSettings } from "~/hooks/useSettings";
import { cn } from "~/lib/utils";

import { Skeleton } from "./ui/skeleton";
Expand All @@ -15,6 +17,7 @@ function getDiffPanelHeaderRowClassName(mode: DiffPanelMode) {
shouldUseDragRegion
? "drag-region h-[var(--workspace-topbar-height)] border-b border-border wco:pr-(--workspace-native-controls-inset)"
: "flex h-10 min-h-10 shrink-0 items-center border-b border-border/60 bg-background in-data-[preview-panel-mode=inline]:mb-3 in-data-[preview-panel-mode=inline]:h-7 in-data-[preview-panel-mode=inline]:min-h-7 in-data-[preview-panel-mode=inline]:border-b-transparent",
"redesign:border-b-transparent redesign:px-3 redesign:in-data-[preview-panel-mode=inline]:mb-0",
);
}

Expand Down Expand Up @@ -52,7 +55,7 @@ export function DiffFileHeaderSkeleton({
titleWidth: "short" | "medium" | "long";
}) {
return (
<div className="flex h-8 items-center gap-2 px-2 pr-3">
<div className="flex h-8 items-center gap-2 px-2 pr-3 redesign:px-3">
<div className="flex size-5 shrink-0 items-center justify-center">
<Skeleton className="size-2.5" />
</div>
Expand Down Expand Up @@ -92,11 +95,12 @@ function DiffCodeLineSkeleton({ width }: { width: "short" | "medium" | "long" })
export function DiffPanelLoadingState(props: { label: string }) {
return (
<div
className="min-h-0 flex-1 overflow-hidden bg-background"
className="min-h-0 flex-1 overflow-hidden bg-background redesign:px-1 redesign:pt-2"
role="status"
aria-live="polite"
aria-label={props.label}
>
<p className="hidden px-3 pb-2 text-xs text-secondary-label redesign:block">{props.label}</p>
<DiffFileHeaderSkeleton titleWidth="medium" />
<div className="flex h-6 items-center gap-2 px-2 pr-3">
<div className="h-px flex-1 bg-border/40" />
Expand All @@ -114,3 +118,27 @@ export function DiffPanelLoadingState(props: { label: string }) {
</div>
);
}

export function DiffPanelEmptyState({
title,
children,
className = "flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70",
}: {
title: string;
children: ReactNode;
className?: string;
}) {
const redesignEnabled = useClientSettings((settings) => settings.redesignEnabled);
if (!redesignEnabled) return <div className={className}>{children}</div>;
return (
<div className="flex min-h-0 flex-1 items-center justify-center p-6 text-center">
<div className="flex max-w-72 flex-col items-center gap-2">
<div className="mb-2 flex size-10 items-center justify-center rounded-xl bg-muted/50 text-muted-foreground">
<FileDiffIcon className="size-5" aria-hidden />
</div>
<h3 className="text-base font-semibold text-foreground">{title}</h3>
<div className="text-sm leading-5 text-balance text-secondary-label">{children}</div>
</div>
</div>
);
}
Loading
Loading