Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b7f6dec
fix(web): align input group control styling
t3-code[bot] Aug 12, 2026
2d800d3
ci: retry checks after runner timeout
t3-code[bot] Aug 12, 2026
de22137
refactor(web): move terminal chrome to tailwind
t3-code[bot] Aug 13, 2026
a44720b
refactor(web): simplify global stylesheet
t3-code[bot] Aug 13, 2026
8e3066e
fix(web): preserve dark composer pseudo-elements
t3-code[bot] Aug 13, 2026
8925f19
fix(web): preserve dropdown glass saturation
t3-code[bot] Aug 13, 2026
d471299
fix(web): preserve dropdown elevation overrides
t3-code[bot] Aug 13, 2026
578bf5b
test(web): format titlebar regression coverage
t3-code[bot] Aug 13, 2026
4fa9cce
refactor(web): centralize compact control styles
t3-code[bot] Aug 13, 2026
7ec3df9
fix(web): align pull request search controls
t3-code[bot] Aug 13, 2026
70fecd3
refactor(web): move one-off styles to components
t3-code[bot] Aug 13, 2026
56dfc6f
refactor(web): reuse shared compact controls
t3-code[bot] Aug 13, 2026
69ea104
refactor(web): finish shared control cleanup
t3-code[bot] Aug 13, 2026
583affc
merge main into fix/ui-control-consistency
t3-code[bot] Aug 13, 2026
f13684f
fix(web): preserve compact inline panel chrome
t3-code[bot] Aug 13, 2026
5f81f7a
refactor(web): finish shared control audit
t3-code[bot] Aug 13, 2026
0bdcee1
refactor(web): use theme css variants
t3-code[bot] Aug 14, 2026
e0cd878
Merge remote-tracking branch 'origin/main' into fix/ui-control-consis…
t3-code[bot] Aug 14, 2026
f387e17
refactor(web): complete stylesheet audit
t3-code[bot] Aug 14, 2026
1170852
merge main into fix/ui-control-consistency
t3-code[bot] Aug 14, 2026
b9937b7
merge latest main into fix/ui-control-consistency
t3-code[bot] Aug 14, 2026
3482c11
fix(web): preserve menu minimum width
t3-code[bot] Aug 14, 2026
ed080cc
refactor(web): remove final css duplicates
t3-code[bot] Aug 14, 2026
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
18 changes: 10 additions & 8 deletions apps/web/src/components/AgentsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { useEffect, useRef, useState } from "react";
import { cn } from "~/lib/utils";
import { orchestrationEnvironment } from "~/state/orchestration";
import { ScrollArea } from "~/components/ui/scroll-area";
import { Button } from "~/components/ui/button";

/**
* In-flight states all present as Working (one steady state, per the
Expand Down Expand Up @@ -282,14 +283,15 @@ function WorkflowScriptView({
<span className="truncate font-mono text-[.65rem] text-muted-foreground">
{scriptPath.split("/").at(-1)}
</span>
<button
type="button"
<Button
size="icon-micro"
variant="ghost-muted"
onClick={onClose}
aria-label="Close script"
className="ml-auto text-muted-foreground hover:text-foreground"
className="ml-auto"
>
<X aria-hidden className="size-3" />
</button>
</Button>
</div>
<div className="max-h-72 overflow-auto p-2">
{result._tag === "Success" ? (
Expand Down Expand Up @@ -417,14 +419,14 @@ function ExpandedWorkflowSection({
<span className="ml-auto font-mono normal-case text-muted-foreground/80">
{settled}/{members.length} settled
</span>
<button
type="button"
<Button
size="icon-micro"
variant="ghost-muted"
onClick={onCollapse}
aria-label="Collapse workflow"
className="text-muted-foreground hover:text-foreground"
>
<ChevronDown aria-hidden className="size-3" />
</button>
</Button>
</div>
<PhaseRail group={group} />
{scriptOpen && canShowScript ? (
Expand Down
9 changes: 6 additions & 3 deletions apps/web/src/components/BranchToolbarBranchSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
} from "./ThreadStatusIndicators";
import { Button } from "./ui/button";
import { Switch } from "./ui/switch";
import { getVirtualizedScrollFadeClassName } from "./ui/scroll-area";
import {
Combobox,
ComboboxEmpty,
Expand Down Expand Up @@ -814,9 +815,11 @@ export function BranchToolbarBranchSelector({
maybeFetchNextBranchPage();
}}
className={cn(
"scrollbar-gutter-stable overflow-x-hidden overscroll-y-contain ps-1 pe-0 pt-2 pb-1 [--fade-size:1.5rem]",
showTopBranchScrollFade && "mask-t-from-[calc(100%-var(--fade-size))]",
showBottomBranchScrollFade && "mask-b-from-[calc(100%-var(--fade-size))]",
"scrollbar-gutter-stable overflow-x-hidden overscroll-y-contain ps-1 pe-0 pt-2 pb-1",
getVirtualizedScrollFadeClassName({
top: showTopBranchScrollFade,
bottom: showBottomBranchScrollFade,
}),
)}
style={{ maxHeight: "14rem" }}
/>
Expand Down
23 changes: 13 additions & 10 deletions apps/web/src/components/ChatMarkdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) {
{children}
</table>
</ScrollArea>
<div className="chat-markdown-table-footer select-none">
<div className="mt-0.5 flex items-center justify-between select-none">
<Tooltip>
<TooltipTrigger
render={
Expand Down Expand Up @@ -642,12 +642,12 @@ function MarkdownCodeBlock({

return (
<div
className="chat-markdown-codeblock border border-border/70 bg-secondary leading-snug dark:border-transparent dark:bg-input/32"
className="chat-markdown-codeblock my-[0.65rem] overflow-hidden rounded-[var(--radius)] border border-border/70 bg-secondary leading-snug dark:border-transparent dark:bg-input/32"
data-language={language}
data-wrap={wrapped ? "true" : "false"}
>
<div className="chat-markdown-codeblock-header select-none">
<span className="chat-markdown-codeblock-title">
<div className="chat-markdown-codeblock-header flex items-center justify-between gap-2 pt-1.5 pr-1.5 pb-0 pl-3 select-none">
<span className="inline-flex min-w-0 items-center gap-[0.4rem] [font-family:var(--font-mono,ui-monospace,SFMono-Regular,monospace)] [font-size:0.6875rem]">
<MarkdownCodeBlockTitleContent
fenceTitle={fenceTitle}
language={language}
Expand Down Expand Up @@ -897,7 +897,10 @@ const failedFaviconHosts = new Set<string>();
const MarkdownLinkFavicon = memo(function MarkdownLinkFavicon({ host }: { host: string }) {
const [failedHost, setFailedHost] = useState<string | null>(null);
return (
<span className="chat-markdown-link-favicon" aria-hidden>
<span
className="ms-[0.25em] me-[0.2em] inline-flex size-[14px] [vertical-align:-0.125em]"
aria-hidden
>
{failedHost === host || failedFaviconHosts.has(host) ? (
<GlobeIcon className={MARKDOWN_LINK_FAVICON_CLASS_NAME} />
) : (
Expand Down Expand Up @@ -1044,7 +1047,7 @@ function MarkdownExternalLinkContent({
const leadingLength = leadingExternalLinkTextLength(plainText);
return (
<>
<span className="chat-markdown-link-leading">
<span className="whitespace-nowrap">
<MarkdownLinkFavicon host={host} />
{plainText.slice(0, leadingLength)}
</span>
Expand All @@ -1060,7 +1063,7 @@ function MarkdownExternalLinkContent({
const leadingLength = leadingExternalLinkTextLength(firstChild);
return (
<>
<span className="chat-markdown-link-leading">
<span className="whitespace-nowrap">
<MarkdownLinkFavicon host={host} />
{firstChild.slice(0, leadingLength)}
</span>
Expand All @@ -1072,7 +1075,7 @@ function MarkdownExternalLinkContent({

return (
<>
<span className="chat-markdown-link-leading">
<span className="whitespace-nowrap">
<MarkdownLinkFavicon host={host} />
{firstChild}
</span>
Expand Down Expand Up @@ -1289,7 +1292,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({
side="top"
className="max-w-[min(40rem,calc(100vw-2rem))] font-mono text-[11px] leading-tight"
>
<div className="markdown-file-link-tooltip-scroll overflow-x-auto whitespace-nowrap">
<div className="overflow-x-auto whitespace-nowrap [scrollbar-color:color-mix(in_srgb,var(--border)_78%,transparent)_transparent] [scrollbar-width:thin] [&::-webkit-scrollbar]:h-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-[color-mix(in_srgb,var(--border)_78%,transparent)] [&::-webkit-scrollbar-track]:bg-transparent">
{displayPath}
</div>
</TooltipPopup>
Expand Down Expand Up @@ -1699,7 +1702,7 @@ function ChatMarkdown({
return (
<div
className={cn(
"chat-markdown w-full min-w-0 text-sm leading-relaxed text-foreground/80",
"chat-markdown w-full min-w-0 text-sm leading-relaxed text-foreground/80 [overflow-wrap:anywhere] [word-break:break-word]",
className,
)}
onCopy={handleCopy}
Expand Down
18 changes: 10 additions & 8 deletions apps/web/src/components/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6023,8 +6023,9 @@ function ChatViewContent(props: ChatViewProps) {
// One inset in both states: the controls move between containers when
// the right panel opens, and a different right offset made them jump
// sideways on every toggle.
"workspace-titlebar-controls z-50 mr-px gap-1 [-webkit-app-region:no-drag]",
"absolute top-[var(--workspace-controls-top)] right-[var(--workspace-controls-right)] z-50 mr-px flex h-[var(--workspace-topbar-height)] items-center gap-1 [-webkit-app-region:no-drag]",
)}
data-workspace-titlebar-controls
>
{rightPanelOpen && !shouldUseRightPanelSheet ? (
<RightPanelMaximizeControl
Expand Down Expand Up @@ -6165,12 +6166,12 @@ function ChatViewContent(props: ChatViewProps) {
"bg-background transition-[padding-left] duration-200 ease-linear motion-reduce:transition-none",
isElectron
? cn(
"workspace-topbar drag-region relative px-3 sm:px-5",
"drag-region relative flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center px-3 sm:px-5",
reserveTitleBarControlInset &&
!inlineRightPanelOwnsTitleBar &&
"wco:pr-[var(--workspace-native-controls-inset)]",
)
: "workspace-topbar pl-[calc(env(safe-area-inset-left)+0.75rem)] pr-[calc(env(safe-area-inset-right)+0.75rem)] sm:pl-[calc(env(safe-area-inset-left)+1.25rem)] sm:pr-[calc(env(safe-area-inset-right)+1.25rem)]",
: "flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center pl-[calc(env(safe-area-inset-left)+0.75rem)] pr-[calc(env(safe-area-inset-right)+0.75rem)] sm:pl-[calc(env(safe-area-inset-left)+1.25rem)] sm:pr-[calc(env(safe-area-inset-right)+1.25rem)]",
COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,
)}
>
Expand Down Expand Up @@ -6273,16 +6274,17 @@ function ChatViewContent(props: ChatViewProps) {
className="pointer-events-none absolute left-1/2 z-30 flex -translate-x-1/2 justify-center py-1.5"
style={{ bottom: composerOverlayHeight + 4 }}
>
<button
type="button"
<Button
aria-label="Scroll to end"
title="Scroll to end"
onClick={() => scrollToEnd(true)}
className="chat-composer-glass pointer-events-auto flex items-center gap-1.5 rounded-full border border-border/60 px-3 py-1 text-muted-foreground text-xs shadow-sm transition-colors hover:border-border hover:text-foreground hover:cursor-pointer"
className="pointer-events-auto gap-1.5 rounded-full px-3 text-muted-foreground hover:text-foreground"
size="xs"
variant="glass"
>
<ChevronDownIcon className="size-3.5" />
Scroll to end
</button>
</Button>
</div>
)}
</div>
Expand All @@ -6299,7 +6301,7 @@ function ChatViewContent(props: ChatViewProps) {
>
<div
ref={attachDraftHeroTransitionGroupRef}
className="chat-composer-horizontal-inset w-full"
className="w-full ps-[calc(env(safe-area-inset-left)+0.75rem)] pe-[calc(env(safe-area-inset-right)+0.75rem)] sm:ps-[calc(env(safe-area-inset-left)+1.25rem)] sm:pe-[calc(env(safe-area-inset-right)+1.25rem)]"
>
<div className="pointer-events-auto relative z-10">
{isDraftHeroState ? (
Expand Down
12 changes: 6 additions & 6 deletions apps/web/src/components/ComposerPromptEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import {
import { cn, isMacPlatform } from "~/lib/utils";
import { basenameOfPath } from "~/pierre-icons";
import {
COMPOSER_INLINE_CHIP_DECORATOR_CLASS_NAME,
COMPOSER_INLINE_CHIP_ICON_CLASS_NAME,
COMPOSER_INLINE_SKILL_CHIP_CLASS_NAME,
COMPOSER_INLINE_SKILL_CHIP_LABEL_CLASS_NAME,
Expand Down Expand Up @@ -188,7 +189,7 @@ class ComposerMentionNode extends DecoratorNode<React.ReactElement> {

override createDOM(): HTMLElement {
const dom = document.createElement("span");
dom.className = "composer-inline-chip relative inline-flex align-[-0.125em] leading-none";
dom.className = COMPOSER_INLINE_CHIP_DECORATOR_CLASS_NAME;
return dom;
}

Expand Down Expand Up @@ -326,7 +327,7 @@ class ComposerSkillNode extends DecoratorNode<React.ReactElement> {

override createDOM(): HTMLElement {
const dom = document.createElement("span");
dom.className = "composer-inline-chip relative inline-flex align-[-0.125em] leading-none";
dom.className = COMPOSER_INLINE_CHIP_DECORATOR_CLASS_NAME;
return dom;
}

Expand Down Expand Up @@ -397,7 +398,7 @@ class ComposerTerminalContextNode extends DecoratorNode<React.ReactElement> {

override createDOM(): HTMLElement {
const dom = document.createElement("span");
dom.className = "composer-inline-chip relative inline-flex align-[-0.125em] leading-none";
dom.className = COMPOSER_INLINE_CHIP_DECORATOR_CLASS_NAME;
return dom;
}

Expand Down Expand Up @@ -1747,13 +1748,12 @@ function ComposerPromptEditorInner({

return (
<ComposerTerminalContextActionsContext value={terminalContextActions}>
<div className="composer-editor-surface relative">
<div className="relative [font-family:var(--font-composer,var(--font-sans))] [font-size:var(--font-size-prompt,0.875rem)] [@media(max-width:39.999rem)_and_(pointer:coarse)]:[font-size:max(var(--font-size-prompt,1rem),16px)]">
<PlainTextPlugin
contentEditable={
<ContentEditable
className={cn(
// The size comes from .composer-editor-surface so Settings -> Appearance
// can drive it; keep everything else here.
// The wrapper owns the appearance preference; keep everything else here.
"block max-h-50 min-h-17.5 w-full overflow-y-auto whitespace-pre-wrap wrap-break-word bg-transparent leading-relaxed text-foreground focus:outline-none",
className,
)}
Expand Down
9 changes: 5 additions & 4 deletions apps/web/src/components/DiffPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,7 @@ export default function DiffPanel({
</div>
) : (
<>
<div className="diff-panel-viewport flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background">
{isSelectedPatchTruncated && (
<p className="shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-[11px] text-muted-foreground">
This diff was truncated because it exceeded the preview limit. The changes shown are
Expand Down Expand Up @@ -907,10 +907,11 @@ export default function DiffPanel({
<Tooltip>
<TooltipTrigger
render={
<button
type="button"
<Button
size="icon-micro"
variant="ghost"
className={cn(
"-ms-0.5 inline-flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 transition-colors hover:bg-foreground/10 focus-visible:outline-hidden",
"-ms-0.5 [--control-icon-color:currentColor] bg-transparent hover:bg-foreground/10",
getDiffCollapseIconClassName(fileDiff),
)}
aria-label={collapsed ? `Expand ${filePath}` : `Collapse ${filePath}`}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/DiffPanelShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function getDiffPanelHeaderRowClassName(mode: DiffPanelMode) {
mode === "embedded" ? "px-2" : "px-4",
shouldUseDragRegion
? "drag-region h-[52px] border-b border-border wco:h-[env(titlebar-area-height)] wco:pr-[calc(100vw-env(titlebar-area-width)-env(titlebar-area-x)+1em)]"
: "surface-subheader",
: "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",
);
}

Expand Down
7 changes: 4 additions & 3 deletions apps/web/src/components/LegacySidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2925,11 +2925,12 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
<Tooltip>
<TooltipTrigger
render={
<button
type="button"
<Button
size="icon-xs"
variant="ghost-muted"
aria-label="Add project"
data-testid="sidebar-add-project-trigger"
className="inline-flex h-6 min-w-6 cursor-pointer items-center justify-center rounded-md px-[calc(--spacing(1)-1px)] text-icon-muted transition-colors hover:bg-accent hover:text-foreground"
className="size-6 [--control-icon-color:currentColor] text-icon-muted"
onClick={openAddProject}
/>
}
Expand Down
4 changes: 3 additions & 1 deletion apps/web/src/components/NoActiveThreadState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export function NoActiveThreadState() {
<header
className={cn(
"border-b border-border px-3 transition-[padding-left] duration-200 ease-linear motion-reduce:transition-none sm:px-5",
isElectron ? "workspace-topbar drag-region" : "workspace-topbar",
isElectron
? "drag-region flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center"
: "flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center",
COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS,
)}
>
Expand Down
13 changes: 10 additions & 3 deletions apps/web/src/components/RightPanelTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type { DesktopPreviewOverlay } from "~/previewStateStore";
import type { RightPanelSurface } from "~/rightPanelStore";
import { cn } from "~/lib/utils";
import { readLocalApi } from "~/localApi";
import { Button } from "~/components/ui/button";
import { Tooltip, TooltipPopup, TooltipTrigger } from "~/components/ui/tooltip";
import { Kbd } from "~/components/ui/kbd";
import { Menu, MenuItem, MenuPopup, MenuTrigger } from "~/components/ui/menu";
Expand Down Expand Up @@ -603,7 +604,7 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
>
<div
className={cn(
"workspace-topbar gap-1 pl-2",
"flex h-[var(--workspace-topbar-height)] min-h-[var(--workspace-topbar-height)] shrink-0 items-center gap-1 pl-2",
// The sheet overlays from the viewport top, so its tab bar keeps
// the titlebar's height: a compact row re-centers the layout
// controls a few pixels higher and the cluster jumps on open.
Expand Down Expand Up @@ -682,8 +683,14 @@ export function RightPanelTabs(props: RightPanelTabsProps) {
{props.surfaces.length > 0 ? (
<Menu>
<MenuTrigger
className="cursor-pointer relative inline-flex size-6 shrink-0 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
aria-label="Add panel surface"
render={
<Button
aria-label="Add panel surface"
className="size-6 shrink-0 text-muted-foreground hover:text-foreground"
size="icon-xs"
variant="ghost"
/>
}
>
<Plus className="size-3.5" />
</MenuTrigger>
Expand Down
Loading
Loading