From b7f6decde6c85ef7c6fc77e42fb43f940f2f6a6f Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Wed, 12 Aug 2026 21:31:02 +0000 Subject: [PATCH 01/22] fix(web): align input group control styling Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- .../src/components/files/FileBrowserPanel.tsx | 2 +- .../components/preview/PreviewChromeRow.tsx | 2 +- .../settings/ThemeSearchSection.tsx | 30 +++++++++++-------- apps/web/src/components/ui/input-group.tsx | 4 +-- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/apps/web/src/components/files/FileBrowserPanel.tsx b/apps/web/src/components/files/FileBrowserPanel.tsx index ff658693a70c..abc9969b47e4 100644 --- a/apps/web/src/components/files/FileBrowserPanel.tsx +++ b/apps/web/src/components/files/FileBrowserPanel.tsx @@ -78,7 +78,7 @@ function FileSearchField(props: { value: string; }) { return ( - + - + -
- - setQuery(event.currentTarget.value)} - placeholder="try dracula, nord, catppuccin..." - size="lg" - type="search" - value={query} - /> + + + + + + setQuery(event.currentTarget.value)} + placeholder="try dracula, nord, catppuccin..." + size="lg" + type="search" + value={query} + /> + + )} diff --git a/apps/web/src/components/RightPanelTabs.tsx b/apps/web/src/components/RightPanelTabs.tsx index 7f4ce8d8b0bc..3da8ff0ebbe8 100644 --- a/apps/web/src/components/RightPanelTabs.tsx +++ b/apps/web/src/components/RightPanelTabs.tsx @@ -25,6 +25,7 @@ import { isElectron } from "~/env"; 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"; @@ -668,8 +669,14 @@ export function RightPanelTabs(props: RightPanelTabsProps) { {props.surfaces.length > 0 ? ( + } > diff --git a/apps/web/src/components/chat/ProviderStatusBanner.tsx b/apps/web/src/components/chat/ProviderStatusBanner.tsx index f82c17b13ddd..1c7571b962f9 100644 --- a/apps/web/src/components/chat/ProviderStatusBanner.tsx +++ b/apps/web/src/components/chat/ProviderStatusBanner.tsx @@ -2,6 +2,7 @@ import { type ServerProvider } from "@t3tools/contracts"; import { memo } from "react"; import { InfoIcon, XIcon } from "lucide-react"; import { cn } from "~/lib/utils"; +import { Button } from "../ui/button"; import { formatProviderDriverKindLabel } from "../../providerModels"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; @@ -66,14 +67,15 @@ export const ProviderStatusBanner = memo(function ProviderStatusBanner({ - + ); diff --git a/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx b/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx index 3ad02f4316b3..2943679d3e30 100644 --- a/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx +++ b/apps/web/src/components/pullRequest/PullRequestCodeTab.tsx @@ -923,10 +923,11 @@ export function PullRequestCodeTab({ ) : ( // Bottom-right, clear of the vertical scrollbar the diff view keeps to its own right // edge. - + )} ); diff --git a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx index 71d7c65700df..68537a81c965 100644 --- a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx +++ b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx @@ -24,6 +24,7 @@ import type { ElementType } from "react"; import { cn } from "~/lib/utils"; import { getSourceControlPresentationForKind } from "~/sourceControlPresentation"; import { ProjectFavicon } from "../ProjectFavicon"; +import { InputGroup, InputGroupAddon, InputGroupInput } from "../ui/input-group"; import { Menu, @@ -79,29 +80,18 @@ export function PullRequestSearchInput({ onChange: (value: string) => void; }) { return ( -
- {busy ? ( - - ) : ( - - )} - + + {busy ? : } + + onChange(event.currentTarget.value)} placeholder="Search pull requests, or label:bug" aria-label="Search pull requests" - // Tracks the shared input's height at both widths, so it stays level with the icon - // button beside it rather than towering over it on wide screens. - className="h-9 w-full rounded-lg border border-input bg-background pr-3 pl-9 text-sm outline-none placeholder:text-muted-foreground/72 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/24 sm:h-8" /> -
+ ); } diff --git a/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx b/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx index 25c663794e97..8330c87a9294 100644 --- a/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx +++ b/apps/web/src/components/pullRequest/PullRequestReviewerPicker.tsx @@ -19,6 +19,7 @@ import { useAtomCommand } from "~/state/use-atom-command"; import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime"; import { Button } from "../ui/button"; +import { Input } from "../ui/input"; import { Menu, MenuPopup, MenuTrigger } from "../ui/menu"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; import { toastManager } from "../ui/toast"; @@ -131,13 +132,13 @@ export function PullRequestReviewerPicker({ />
- setQuery(event.currentTarget.value)} placeholder="Search people with access" aria-label="Search people with access" - className="h-7 w-full rounded-md border border-input bg-background px-2 text-xs outline-none placeholder:text-muted-foreground/72 focus-visible:border-ring" + size="compact" />
diff --git a/apps/web/src/components/settings/DiagnosticsSettings.tsx b/apps/web/src/components/settings/DiagnosticsSettings.tsx index 5bd4fdc08c4a..7122da25c1e3 100644 --- a/apps/web/src/components/settings/DiagnosticsSettings.tsx +++ b/apps/web/src/components/settings/DiagnosticsSettings.tsx @@ -793,9 +793,8 @@ function DiagnosticsRefreshButton({ onOpenChange(true)} aria-label="Search keybindings" > @@ -144,10 +143,10 @@ function ExpandableHeaderSearch({ return (
- onChange(event.currentTarget.value)} onBlur={() => { @@ -162,7 +161,8 @@ function ExpandableHeaderSearch({ }} placeholder="Search keybindings" aria-label="Search keybindings" - className="h-6 w-44 rounded-md border border-input bg-background pl-7 pr-2 text-[11px] text-foreground outline-none placeholder:text-muted-foreground/72 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/24" + className="w-44 [&_[data-slot=input]]:pl-7" + size="compact" />
); @@ -309,10 +309,7 @@ function WhenVariableSelect({ return ( setOperator(value as BooleanOperator)}> - + - - @@ -545,7 +536,7 @@ function WhenExpressionNodeEditor({ type="button" variant="ghost" size="icon-sm" - className="ml-auto size-7 sm:size-7" + className="ml-auto size-7" aria-label="Remove group" onClick={onRemove} > @@ -640,23 +631,11 @@ function WhenExpressionBuilder({
When
- - @@ -702,17 +681,11 @@ function WhenExpressionBuilder({ ) : (
- - @@ -864,8 +837,7 @@ function KeybindingTableRow({ )} {isDirty ? ( ); + const micro = renderToStaticMarkup( + , + ); + + expect(compact).toContain("h-7"); + expect(compact).toContain("rounded-md"); + expect(micro).toContain("size-5"); + expect(micro).toContain("rounded-sm"); + expect(micro).toContain("text-muted-foreground"); + }); }); diff --git a/apps/web/src/components/ui/button.tsx b/apps/web/src/components/ui/button.tsx index 778574ba0107..9f0b4d049eda 100644 --- a/apps/web/src/components/ui/button.tsx +++ b/apps/web/src/components/ui/button.tsx @@ -16,9 +16,13 @@ const buttonVariants = cva( }, variants: { size: { + compact: + "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-xs before:rounded-[calc(var(--radius-md)-1px)] [&_svg:not([class*='size-'])]:size-3.5", default: "h-9 px-[calc(--spacing(3)-1px)] sm:h-8", icon: "size-9 sm:size-8", "icon-lg": "size-10 sm:size-9", + "icon-micro": + "size-5 rounded-sm p-0 before:rounded-[calc(var(--radius-sm)-1px)] [&_svg:not([class*='size-'])]:size-3", "icon-sm": "size-8 sm:size-7", "icon-xl": "size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5", @@ -38,6 +42,10 @@ const buttonVariants = cva( "border-input bg-popover not-dark:bg-clip-padding text-destructive-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4", ghost: "[--control-icon-color:var(--muted-foreground)] border-transparent text-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent", + "ghost-muted": + "[--control-icon-color:var(--muted-foreground)] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground", + glass: + "surface-glass [--control-icon-color:var(--muted-foreground)] border-border/60 text-foreground shadow-sm [:hover,[data-pressed]]:border-border", link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline", outline: "[--control-icon-color:var(--muted-foreground)] border-input bg-popover not-dark:bg-clip-padding text-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64", diff --git a/apps/web/src/components/ui/input.tsx b/apps/web/src/components/ui/input.tsx index 6edc8d4a62fc..cae3dfe62852 100644 --- a/apps/web/src/components/ui/input.tsx +++ b/apps/web/src/components/ui/input.tsx @@ -6,7 +6,7 @@ import type * as React from "react"; import { cn } from "~/lib/utils"; type InputProps = Omit, "size"> & { - size?: "sm" | "default" | "lg" | number; + size?: "sm" | "compact" | "default" | "lg" | number; unstyled?: boolean; nativeInput?: boolean; }; @@ -20,6 +20,7 @@ function Input({ }: InputProps) { const inputClassName = cn( "h-8.5 w-full min-w-0 rounded-[inherit] px-[calc(--spacing(3)-1px)] leading-8.5 outline-none placeholder:text-placeholder sm:h-7.5 sm:leading-7.5 [transition:background-color_5000000s_ease-in-out_0s]", + size === "compact" && "h-7 px-[calc(--spacing(2.5)-1px)] text-xs leading-7 sm:h-7 sm:leading-7", size === "sm" && "h-7.5 px-[calc(--spacing(2.5)-1px)] leading-7.5 sm:h-6.5 sm:leading-6.5", size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5", props.type === "search" && @@ -59,6 +60,9 @@ function Input({ cn( !unstyled && "relative inline-flex w-full rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_1px_--theme(--color-black/4%)] has-focus-visible:has-aria-invalid:border-destructive/64 has-focus-visible:has-aria-invalid:ring-destructive/16 has-aria-invalid:border-destructive/36 has-focus-visible:border-ring has-autofill:bg-foreground/4 has-disabled:opacity-64 has-[:disabled,:focus-visible,[aria-invalid]]:shadow-none has-focus-visible:ring-[3px] sm:text-sm dark:bg-input/32 dark:has-autofill:bg-foreground/8 dark:has-aria-invalid:ring-destructive/24 dark:not-has-disabled:not-has-focus-visible:not-has-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)]", + !unstyled && + size === "compact" && + "rounded-md before:rounded-[calc(var(--radius-md)-1px)]", className, ) || undefined } diff --git a/apps/web/src/components/ui/select.tsx b/apps/web/src/components/ui/select.tsx index b58260190896..46b2c8eb1ba0 100644 --- a/apps/web/src/components/ui/select.tsx +++ b/apps/web/src/components/ui/select.tsx @@ -26,6 +26,8 @@ const selectTriggerVariants = cva( "border-transparent text-secondary-label focus-visible:ring-2 focus-visible:ring-ring data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground", }, size: { + compact: + "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-xs before:rounded-[calc(var(--radius-md)-1px)] [&_svg:not([class*='size-'])]:size-3.5", default: "min-h-9 px-[calc(--spacing(3)-1px)] sm:min-h-8", lg: "min-h-10 px-[calc(--spacing(3)-1px)] sm:min-h-9", sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7", diff --git a/apps/web/src/components/ui/toggle.tsx b/apps/web/src/components/ui/toggle.tsx index 936d4eecabbf..5bf04adf41a1 100644 --- a/apps/web/src/components/ui/toggle.tsx +++ b/apps/web/src/components/ui/toggle.tsx @@ -14,6 +14,8 @@ const toggleVariants = cva( }, variants: { size: { + compact: + "h-7 min-w-7 rounded-md px-[calc(--spacing(1)-1px)] text-xs before:rounded-[calc(var(--radius-md)-1px)] [&_svg:not([class*='size-'])]:size-3.5", default: "h-9 min-w-9 px-[calc(--spacing(2)-1px)] sm:h-8 sm:min-w-8", lg: "h-10 min-w-10 px-[calc(--spacing(2.5)-1px)] sm:h-9 sm:min-w-9", sm: "h-8 min-w-8 px-[calc(--spacing(1.5)-1px)] sm:h-7 sm:min-w-7", From 7ec3df9907d20b0c399f8e17805d1d269e60ff08 Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:39:29 +0000 Subject: [PATCH 10/22] fix(web): align pull request search controls Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- apps/web/src/components/pullRequest/PullRequestListFilters.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx index 68537a81c965..e26476cb2e94 100644 --- a/apps/web/src/components/pullRequest/PullRequestListFilters.tsx +++ b/apps/web/src/components/pullRequest/PullRequestListFilters.tsx @@ -80,7 +80,7 @@ export function PullRequestSearchInput({ onChange: (value: string) => void; }) { return ( - + {busy ? : } From 70fecd3686b04a85bf5f281748d98fa9151f2378 Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:48:18 +0000 Subject: [PATCH 11/22] refactor(web): move one-off styles to components Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- .../src/components/ComposerPromptEditor.tsx | 5 +-- .../components/chat/ModelPickerContent.tsx | 2 +- apps/web/src/index.css | 45 ------------------- 3 files changed, 3 insertions(+), 49 deletions(-) diff --git a/apps/web/src/components/ComposerPromptEditor.tsx b/apps/web/src/components/ComposerPromptEditor.tsx index 0489e8c79cdf..0a21f7ac019f 100644 --- a/apps/web/src/components/ComposerPromptEditor.tsx +++ b/apps/web/src/components/ComposerPromptEditor.tsx @@ -1747,13 +1747,12 @@ function ComposerPromptEditorInner({ return ( -
+
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, )} diff --git a/apps/web/src/components/chat/ModelPickerContent.tsx b/apps/web/src/components/chat/ModelPickerContent.tsx index 579032e4da51..ceb40fc12f90 100644 --- a/apps/web/src/components/chat/ModelPickerContent.tsx +++ b/apps/web/src/components/chat/ModelPickerContent.tsx @@ -781,7 +781,7 @@ export const ModelPickerContent = memo(function ModelPickerContent(props: { onLayout={updateModelListScrollFades} onScroll={updateModelListScrollFades} className={cn( - "model-picker-list scrollbar-gutter-stable h-full overflow-x-hidden overscroll-y-contain py-1.5 [--fade-size:1.5rem]", + "scrollbar-gutter-stable h-full overflow-x-hidden overscroll-y-contain py-1.5 [--fade-size:1.5rem] [&::-webkit-scrollbar-track]:my-2", showTopScrollFade && "model-picker-list-scroll-fade-top", showBottomScrollFade && "model-picker-list-scroll-fade-bottom", )} diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 2759336369eb..bbeedb11532b 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -1577,28 +1577,6 @@ code { background: var(--app-scrollbar-thumb-hover); } -/* Settings -> Appearance can point the composer at its own face (for example a - mono font); default follows the sans stack. Applied on the surface wrapper so - the editor and its placeholder inherit together. */ -.composer-editor-surface { - font-family: var(--font-composer, var(--font-sans)); - font-size: var(--font-size-prompt, 0.875rem); -} - -/* Touch browsers zoom the page when a focused field is under 16px, so keep - the floor there regardless of the preference. Gated on a coarse pointer: - the zoom quirk does not exist on desktop, where a narrow window must not - silently override a smaller chosen prompt size. */ -@media (max-width: 39.999rem) and (pointer: coarse) { - .composer-editor-surface { - font-size: max(var(--font-size-prompt, 1rem), 16px); - } -} - -.model-picker-list::-webkit-scrollbar-track { - margin-block: 0.5rem; -} - .model-picker-list-scroll-fade-top, .model-picker-list-scroll-fade-bottom { -webkit-mask-image: var(--model-picker-list-scroll-mask), linear-gradient(black, black); @@ -1637,29 +1615,6 @@ code { ); } -.turn-chip-strip { - scrollbar-width: none; - -ms-overflow-style: none; - overscroll-behavior-x: contain; -} - -.turn-chip-strip::-webkit-scrollbar { - display: none; -} - -/* Reasoning select -- clickable label surface */ -label:has(> select#reasoning-effort) { - position: relative; -} -label:has(> select#reasoning-effort) select { - position: absolute; - inset: 0; - opacity: 0; - cursor: pointer; - width: 100%; - height: 100%; -} - /* Chat markdown rendering */ .chat-markdown { min-width: 0; From 56dfc6f3f72ca889d48751be604974251a6bff07 Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:58:44 +0000 Subject: [PATCH 12/22] refactor(web): reuse shared compact controls Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- .../pullRequest/PullRequestDetailPanel.tsx | 10 ++++++++-- .../search/ProjectContentSearchDialog.tsx | 15 +++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx b/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx index 7237b4357481..2f4e84dc3fd2 100644 --- a/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx +++ b/apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx @@ -1137,8 +1137,14 @@ export function PullRequestDetailPanel({ <> + } > diff --git a/apps/web/src/components/search/ProjectContentSearchDialog.tsx b/apps/web/src/components/search/ProjectContentSearchDialog.tsx index 1890aab7fa79..d877d6537bda 100644 --- a/apps/web/src/components/search/ProjectContentSearchDialog.tsx +++ b/apps/web/src/components/search/ProjectContentSearchDialog.tsx @@ -11,6 +11,7 @@ import { useProjectContentSearch } from "~/state/queries"; import { PierreEntryIcon } from "../chat/PierreEntryIcon"; import { CommandPaletteContent } from "../CommandPaletteContent"; import { ScrollArea } from "../ui/scroll-area"; +import { Toggle } from "../ui/toggle"; import { HighlightedSearchLine } from "./HighlightedSearchLine"; interface ProjectContentSearchDialogProps { @@ -58,19 +59,17 @@ function SearchOptionButton(props: { readonly children: ReactNode; }) { return ( - + ); } From 69ea1040ac9a9b5d7af569c3f398e9315679e7ef Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 22:43:55 +0000 Subject: [PATCH 13/22] refactor(web): finish shared control cleanup Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- apps/web/src/components/AgentsPanel.tsx | 18 ++++--- apps/web/src/components/ChatMarkdown.tsx | 2 +- apps/web/src/components/DiffPanel.tsx | 2 +- apps/web/src/components/Sidebar.tsx | 4 +- .../src/components/ThreadTerminalDrawer.tsx | 9 ++-- .../settings/DiagnosticsSettings.tsx | 16 +++--- .../settings/ProviderInstanceCard.tsx | 9 ++-- .../settings/ProviderModelsSection.tsx | 4 +- .../settings/ResourceTelemetryDiagnostics.tsx | 14 +++--- .../settings/SettingsSidebarNav.tsx | 4 +- .../settings/SourceControlSettings.tsx | 40 +++++---------- .../components/settings/settingsLayout.tsx | 8 +-- apps/web/src/components/usage/UsagePage.tsx | 9 ++-- apps/web/src/index.css | 49 ------------------- 14 files changed, 58 insertions(+), 130 deletions(-) diff --git a/apps/web/src/components/AgentsPanel.tsx b/apps/web/src/components/AgentsPanel.tsx index 4eeff67ce5f7..62044a8659d7 100644 --- a/apps/web/src/components/AgentsPanel.tsx +++ b/apps/web/src/components/AgentsPanel.tsx @@ -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 @@ -282,14 +283,15 @@ function WorkflowScriptView({ {scriptPath.split("/").at(-1)} - +
{result._tag === "Success" ? ( @@ -417,14 +419,14 @@ function ExpandedWorkflowSection({ {settled}/{members.length} settled - +
{scriptOpen && canShowScript ? ( diff --git a/apps/web/src/components/ChatMarkdown.tsx b/apps/web/src/components/ChatMarkdown.tsx index e9390ed0a8aa..c6341871d58b 100644 --- a/apps/web/src/components/ChatMarkdown.tsx +++ b/apps/web/src/components/ChatMarkdown.tsx @@ -1289,7 +1289,7 @@ const MarkdownFileLink = memo(function MarkdownFileLink({ side="top" className="max-w-[min(40rem,calc(100vw-2rem))] font-mono text-[11px] leading-tight" > -
+
{displayPath}
diff --git a/apps/web/src/components/DiffPanel.tsx b/apps/web/src/components/DiffPanel.tsx index 385d67b6b701..1cd121d0c2c6 100644 --- a/apps/web/src/components/DiffPanel.tsx +++ b/apps/web/src/components/DiffPanel.tsx @@ -825,7 +825,7 @@ export default function DiffPanel({
) : ( <> -
+
{isSelectedPatchTruncated && (

This diff was truncated because it exceeded the preview limit. The changes shown are diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index 840e4918bfa7..59cecd2600a4 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -3263,9 +3263,9 @@ export default function Sidebar() { {isSearchingThreads ? ( +

); diff --git a/apps/web/src/components/settings/DiagnosticsSettings.tsx b/apps/web/src/components/settings/DiagnosticsSettings.tsx index 7122da25c1e3..a472c6a8d3d7 100644 --- a/apps/web/src/components/settings/DiagnosticsSettings.tsx +++ b/apps/web/src/components/settings/DiagnosticsSettings.tsx @@ -273,14 +273,14 @@ function TraceIdCell({ traceId }: { traceId: string }) { copyToClipboard(traceId)} > - + } /> {copied ? "Copied" : "Copy full trace ID"} @@ -322,14 +322,14 @@ function ProcessNameCell({ style={{ paddingLeft: `${Math.min(process.depth, 6) * 10}px` }} > {hasChildren ? ( - + ) : (
+ ) : ( )} @@ -975,9 +975,8 @@ export function ResourceTelemetryDiagnostics() { - } - /> - - {children} - - - ); -} - function optionLabel(value: Option.Option): string | null { return Option.getOrNull(value); } @@ -316,9 +301,8 @@ function DiscoveryItemRow({
{hasDetails ? ( + } /> diff --git a/apps/web/src/components/usage/UsagePage.tsx b/apps/web/src/components/usage/UsagePage.tsx index d40fe6599226..7a5cdd883db2 100644 --- a/apps/web/src/components/usage/UsagePage.tsx +++ b/apps/web/src/components/usage/UsagePage.tsx @@ -20,6 +20,7 @@ import { makeWindow, } from "@t3tools/shared/usageFormat"; import { ScrollArea } from "../ui/scroll-area"; +import { Button } from "../ui/button"; import { SidebarInset } from "../ui/sidebar"; import { WorkspaceBreadcrumb, WorkspaceBreadcrumbItem } from "../WorkspaceBreadcrumb"; import { COLLAPSED_SIDEBAR_TITLEBAR_INSET_CLASS } from "../../workspaceTitlebar"; @@ -156,14 +157,14 @@ export function UsagePage() { ))}
- +
diff --git a/apps/web/src/index.css b/apps/web/src/index.css index bbeedb11532b..3343b3ca4225 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -1837,24 +1837,6 @@ code { background: color-mix(in srgb, var(--border) 78%, transparent); } -.markdown-file-link-tooltip-scroll { - scrollbar-width: thin; - scrollbar-color: color-mix(in srgb, var(--border) 78%, transparent) transparent; -} - -.markdown-file-link-tooltip-scroll::-webkit-scrollbar { - height: 6px; -} - -.markdown-file-link-tooltip-scroll::-webkit-scrollbar-track { - background: transparent; -} - -.markdown-file-link-tooltip-scroll::-webkit-scrollbar-thumb { - border-radius: 999px; - background: color-mix(in srgb, var(--border) 78%, transparent); -} - .chat-markdown .chat-markdown-codeblock { margin: 0.65rem 0; overflow: hidden; @@ -2001,11 +1983,6 @@ code { animation: provider-update-pill-countdown var(--provider-update-pill-dismiss-ms) linear forwards; } -/* Diffs theme bridge (match diff surfaces to app palette) */ -.diff-panel-viewport { - background: var(--background); -} - /* Diffs live directly on the panel canvas. Normal chat code blocks may use a raised code surface, but carrying that fill into the diff creates a card-like rectangle that does not belong in the panel. */ @@ -2013,7 +1990,6 @@ code { --code-background: var(--background); } -.diff-render-file, .diff-render-surface diffs-container { border: 0; border-radius: 0; @@ -2095,31 +2071,6 @@ code { animation: ultrathink-chroma-shift 10s linear infinite; } -.ultrathink-pill { - background: - linear-gradient(var(--card), var(--card)) padding-box, - var(--ultrathink-spectrum) border-box; - background-size: - 100% 100%, - 220% 220%; - background-position: - 0 0, - 0% 50%; - animation: ultrathink-rainbow 10s linear infinite; - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--card) 82%, transparent); -} - -.ultrathink-word { - display: inline-block; - color: transparent; - background-image: var(--ultrathink-spectrum); - background-size: 220% 220%; - background-position: 0% 50%; - background-clip: text; - -webkit-background-clip: text; - animation: ultrathink-rainbow 10s linear infinite; -} - /* Composer chips are non-editable decorators, so the browser skips them when painting text selection; this overlay stands in for the native highlight. */ .composer-inline-chip[data-composer-chip-selected]::after { From f13684f48ed50a64a7b86c0125c6ce9bfacbe995 Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:00:16 +0000 Subject: [PATCH 14/22] fix(web): preserve compact inline panel chrome Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- apps/web/src/components/DiffPanelShell.tsx | 2 +- apps/web/src/components/files/FileBrowserPanel.tsx | 2 +- apps/web/src/components/files/FilePreviewPanel.tsx | 2 +- apps/web/src/components/preview/PreviewChromeRow.tsx | 2 +- apps/web/src/index.css | 7 ------- 5 files changed, 4 insertions(+), 11 deletions(-) diff --git a/apps/web/src/components/DiffPanelShell.tsx b/apps/web/src/components/DiffPanelShell.tsx index 4a7f68d18666..a9b7cf542e02 100644 --- a/apps/web/src/components/DiffPanelShell.tsx +++ b/apps/web/src/components/DiffPanelShell.tsx @@ -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)]" - : "flex h-10 min-h-10 shrink-0 items-center border-b border-border/60 bg-background", + : "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", ); } diff --git a/apps/web/src/components/files/FileBrowserPanel.tsx b/apps/web/src/components/files/FileBrowserPanel.tsx index e3aa88f06419..e3280c99caa3 100644 --- a/apps/web/src/components/files/FileBrowserPanel.tsx +++ b/apps/web/src/components/files/FileBrowserPanel.tsx @@ -351,7 +351,7 @@ export default function FileBrowserPanel({ data-file-browser-panel={`${environmentId}:${cwd}`} >
diff --git a/apps/web/src/components/files/FilePreviewPanel.tsx b/apps/web/src/components/files/FilePreviewPanel.tsx index cd20314f8c77..c4ca57b805fd 100644 --- a/apps/web/src/components/files/FilePreviewPanel.tsx +++ b/apps/web/src/components/files/FilePreviewPanel.tsx @@ -858,7 +858,7 @@ export default function FilePreviewPanel({
{relativePath ? (
diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 7a2141e62a64..6c7ff4d93fbd 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -668,13 +668,6 @@ html[data-mobile-composer-route-transition="true"]::view-transition-old(t3-mobil outline: none; } - [data-preview-panel-mode="inline"] [data-right-panel-surface-content] [data-surface-subheader] { - height: calc(var(--spacing) * 7); - min-height: calc(var(--spacing) * 7); - margin-bottom: calc(var(--spacing) * 3); - border-bottom-color: transparent; - } - .chat-composer-glass-shell { --chat-composer-glass-surface: var(--card); --chat-composer-outline: rgb(0 0 0 / 8%); From 5f81f7a1e663c522e4e5b22ad892fd914174cd8e Mon Sep 17 00:00:00 2001 From: "t3-code[bot]" <269035359+t3-code[bot]@users.noreply.github.com> Date: Thu, 13 Aug 2026 23:28:01 +0000 Subject: [PATCH 15/22] refactor(web): finish shared control audit Co-authored-by: Julius Marminge <51714798+juliusmarminge@users.noreply.github.com> --- apps/web/src/components/ChatMarkdown.tsx | 21 ++++--- apps/web/src/components/DiffPanel.tsx | 7 ++- apps/web/src/components/LegacySidebar.tsx | 7 ++- apps/web/src/components/Sidebar.tsx | 9 +-- .../ComposerPreviewAnnotationCards.test.tsx | 14 +++++ .../chat/ComposerPreviewAnnotationCards.tsx | 10 ++-- .../components/chat/ComposerStashBadge.tsx | 2 +- .../components/chat/ContextWindowMeter.tsx | 15 ++--- .../pullRequest/PullRequestCodeTab.tsx | 11 ++-- .../sidebar/SidebarProviderUpdatePill.tsx | 12 ++-- apps/web/src/components/ui/toast.tsx | 27 +++++---- apps/web/src/index.css | 55 ------------------- 12 files changed, 77 insertions(+), 113 deletions(-) diff --git a/apps/web/src/components/ChatMarkdown.tsx b/apps/web/src/components/ChatMarkdown.tsx index c6341871d58b..53b043f3a8ff 100644 --- a/apps/web/src/components/ChatMarkdown.tsx +++ b/apps/web/src/components/ChatMarkdown.tsx @@ -449,7 +449,7 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) { {children} -
+
-
- +
+ (); const MarkdownLinkFavicon = memo(function MarkdownLinkFavicon({ host }: { host: string }) { const [failedHost, setFailedHost] = useState(null); return ( - + {failedHost === host || failedFaviconHosts.has(host) ? ( ) : ( @@ -1044,7 +1047,7 @@ function MarkdownExternalLinkContent({ const leadingLength = leadingExternalLinkTextLength(plainText); return ( <> - + {plainText.slice(0, leadingLength)} @@ -1060,7 +1063,7 @@ function MarkdownExternalLinkContent({ const leadingLength = leadingExternalLinkTextLength(firstChild); return ( <> - + {firstChild.slice(0, leadingLength)} @@ -1072,7 +1075,7 @@ function MarkdownExternalLinkContent({ return ( <> - + {firstChild} @@ -1699,7 +1702,7 @@ function ChatMarkdown({ return (
} diff --git a/apps/web/src/components/Sidebar.tsx b/apps/web/src/components/Sidebar.tsx index c46cd10763a8..1db4d3d3047d 100644 --- a/apps/web/src/components/Sidebar.tsx +++ b/apps/web/src/components/Sidebar.tsx @@ -3384,18 +3384,19 @@ export default function Sidebar() { className="size-4 shrink-0" /> {project.displayName} - + ); })} diff --git a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.test.tsx b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.test.tsx index 5bb28054e7d7..46af299073c5 100644 --- a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.test.tsx +++ b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.test.tsx @@ -43,4 +43,18 @@ describe("ComposerPreviewAnnotationCards", () => { expect(markup).not.toContain("localhost:3000"); expect(markup).not.toContain("Preview annotation"); }); + + it("uses the shared button contract for removal", () => { + const markup = renderToStaticMarkup( + , + ); + + expect(markup).toContain('aria-label="Remove preview annotation"'); + expect(markup).toContain('data-slot="button"'); + }); }); diff --git a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx index 5e9e43dcf21e..19f6a5ca308e 100644 --- a/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx +++ b/apps/web/src/components/chat/ComposerPreviewAnnotationCards.tsx @@ -5,6 +5,7 @@ import type { ReactNode } from "react"; import type { ComposerImageAttachment } from "~/composerDraftStore"; import { formatElementContextLabel, normalizeElementContextSelection } from "~/lib/elementContext"; import { cn } from "~/lib/utils"; +import { Button } from "../ui/button"; interface ComposerPreviewAnnotationCardsProps { annotations: ReadonlyArray; @@ -128,14 +129,15 @@ export function ComposerPreviewAnnotationCards({
- + ); })} diff --git a/apps/web/src/components/chat/ComposerStashBadge.tsx b/apps/web/src/components/chat/ComposerStashBadge.tsx index 79ed301a5d56..a2599ebc9f9f 100644 --- a/apps/web/src/components/chat/ComposerStashBadge.tsx +++ b/apps/web/src/components/chat/ComposerStashBadge.tsx @@ -46,7 +46,7 @@ export const ComposerStashBadge = memo(function ComposerStashBadge(props: { className={cn( "rounded-full px-1.5 text-[10px] font-medium tabular-nums", props.pulsing - ? "prompt-stash-count-enter bg-primary text-primary-foreground" + ? "animate-[prompt-stash-count-enter_180ms_ease-out_both] bg-primary text-primary-foreground motion-reduce:animate-none" : "bg-muted text-muted-foreground", )} > diff --git a/apps/web/src/components/chat/ContextWindowMeter.tsx b/apps/web/src/components/chat/ContextWindowMeter.tsx index 752ec4013768..f377c893ae2c 100644 --- a/apps/web/src/components/chat/ContextWindowMeter.tsx +++ b/apps/web/src/components/chat/ContextWindowMeter.tsx @@ -1,4 +1,4 @@ -import { cn } from "~/lib/utils"; +import { Button } from "../ui/button"; import { type ContextWindowSnapshot, formatContextWindowTokens } from "~/lib/contextWindow"; import { Popover, PopoverPopup, PopoverTrigger } from "../ui/popover"; @@ -36,13 +36,10 @@ export function ContextWindowMeter(props: { delay={150} closeDelay={0} render={ - + } /> { event.stopPropagation(); toggleFile(item.id); @@ -685,7 +684,7 @@ export function PullRequestCodeTab({ ) : ( )} - + ); }, [toggleFile], diff --git a/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx b/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx index 421934b98a15..dcab7440aced 100644 --- a/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx +++ b/apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx @@ -10,6 +10,7 @@ import { type ProviderUpdateSidebarPillView, } from "../ProviderUpdateLaunchNotification.logic"; import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; +import { Button } from "../ui/button"; const PROVIDER_UPDATE_PILL_STYLES = { loading: @@ -151,7 +152,7 @@ export function SidebarProviderUpdatePill() {