authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-22 21:33:02-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-22 21:33:02-07:00
log71c9b693137c070b4887b365c68659f1a2fb7aed
treedec1bc67aab13caf78a8a3b757aeb262401aa4bf
parentf46522777372be1705e3b7a1ab08756f236db5d2
signature Signed by PGP key B5690EEEBB952194

refactor(web): Button consumers outside the composer stop restyling it (#13208)

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

38 files changed, 156 insertions(+), 220 deletions(-)

apps/web/src/browser/BrowserDeviceToolbar.tsx+18-23
...@@ -242,10 +242,7 @@ export function BrowserDeviceToolbar({...@@ -242,10 +242,7 @@ export function BrowserDeviceToolbar({
242 onChange={(event) => updateCustomDimension("width", event.target.value)}242 onChange={(event) => updateCustomDimension("width", event.target.value)}
243 aria-label="Viewport width"243 aria-label="Viewport width"
244 aria-invalid={!customValid}244 aria-invalid={!customValid}
245 className={cn(245 className={width >= 360 ? "w-14" : "w-13"}
246 "text-center [&_[data-slot=input]::-webkit-inner-spin-button]:appearance-none [&_[data-slot=input]]:[appearance:textfield]",
247 width >= 360 ? "w-14" : "w-13",
248 )}
249 />246 />
250 <span className="text-xs text-muted-foreground">×</span>247 <span className="text-xs text-muted-foreground">×</span>
251 <Input248 <Input
...@@ -270,10 +267,7 @@ export function BrowserDeviceToolbar({...@@ -270,10 +267,7 @@ export function BrowserDeviceToolbar({
270 onChange={(event) => updateCustomDimension("height", event.target.value)}267 onChange={(event) => updateCustomDimension("height", event.target.value)}
271 aria-label="Viewport height"268 aria-label="Viewport height"
272 aria-invalid={!customValid}269 aria-invalid={!customValid}
273 className={cn(270 className={width >= 360 ? "w-14" : "w-13"}
274 "text-center [&_[data-slot=input]::-webkit-inner-spin-button]:appearance-none [&_[data-slot=input]]:[appearance:textfield]",
275 width >= 360 ? "w-14" : "w-13",
276 )}
277 />271 />
278 </form>272 </form>
279273
...@@ -281,14 +275,13 @@ export function BrowserDeviceToolbar({...@@ -281,14 +275,13 @@ export function BrowserDeviceToolbar({
281 <TooltipTrigger275 <TooltipTrigger
282 render={276 render={
283 <Button277 <Button
284 variant="ghost"278 variant={aspectRatio === null ? "ghost" : "secondary"}
285 size="icon-xs"279 size="icon-xs"
286 type="button"280 type="button"
287 aria-label={281 aria-label={
288 aspectRatio === null ? "Lock viewport aspect ratio" : "Unlock viewport aspect ratio"282 aspectRatio === null ? "Lock viewport aspect ratio" : "Unlock viewport aspect ratio"
289 }283 }
290 aria-pressed={aspectRatio !== null}284 aria-pressed={aspectRatio !== null}
291 className={cn(aspectRatio !== null && "bg-accent text-foreground")}
292 disabled={pending || !customValid}285 disabled={pending || !customValid}
293 onPointerDown={(event) => event.preventDefault()}286 onPointerDown={(event) => event.preventDefault()}
294 onClick={toggleAspectRatio}287 onClick={toggleAspectRatio}
...@@ -315,19 +308,21 @@ export function BrowserDeviceToolbar({...@@ -315,19 +308,21 @@ export function BrowserDeviceToolbar({
315 >308 >
316 <ScreenRotationIcon />309 <ScreenRotationIcon />
317 </Button>310 </Button>
318 <Button311 {/* Sticky backing so scrolled controls do not show through the close action. */}
319 variant="ghost"312 <span className="sticky right-0 ml-auto flex bg-background/95">
320 size="icon-xs"313 <Button
321 type="button"314 variant="ghost"
322 aria-label="Close device toolbar"315 size="icon-xs"
323 className="sticky right-0 ml-auto bg-background/95"316 type="button"
324 disabled={pending}317 aria-label="Close device toolbar"
325 onClick={() => {318 disabled={pending}
326 apply({ _tag: "fill" }, null);319 onClick={() => {
327 }}320 apply({ _tag: "fill" }, null);
328 >321 }}
329 <X />322 >
330 </Button>323 <X />
324 </Button>
325 </span>
331 </div>326 </div>
332 );327 );
333}328}
apps/web/src/components/ChatMarkdown.tsx+4-8
...@@ -784,9 +784,8 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) {...@@ -784,9 +784,8 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) {
784 render={784 render={
785 <Button785 <Button
786 type="button"786 type="button"
787 variant="ghost"787 variant={expanded ? "secondary" : "ghost-muted"}
788 size="icon-xs"788 size="icon-xs"
789 className="chat-markdown-chrome-action"
790 aria-pressed={expanded}789 aria-pressed={expanded}
791 onClick={toggleExpanded}790 onClick={toggleExpanded}
792 aria-label={expandLabel}791 aria-label={expandLabel}
...@@ -805,9 +804,8 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) {...@@ -805,9 +804,8 @@ function MarkdownTable({ children, ...props }: React.ComponentProps<"table">) {
805 render={804 render={
806 <Button805 <Button
807 type="button"806 type="button"
808 variant="ghost"807 variant="ghost-muted"
809 size="icon-xs"808 size="icon-xs"
810 className="chat-markdown-chrome-action"
811 aria-label={copyLabel}809 aria-label={copyLabel}
812 />810 />
813 }811 }
...@@ -993,9 +991,8 @@ function MarkdownCodeBlock({...@@ -993,9 +991,8 @@ function MarkdownCodeBlock({
993 render={991 render={
994 <Button992 <Button
995 type="button"993 type="button"
996 variant="ghost"994 variant={wrapped ? "secondary" : "ghost-muted"}
997 size="icon-xs"995 size="icon-xs"
998 className="chat-markdown-chrome-action"
999 aria-pressed={wrapped}996 aria-pressed={wrapped}
1000 onClick={() => setWrapped((value) => !value)}997 onClick={() => setWrapped((value) => !value)}
1001 aria-label={wrapLabel}998 aria-label={wrapLabel}
...@@ -1011,9 +1008,8 @@ function MarkdownCodeBlock({...@@ -1011,9 +1008,8 @@ function MarkdownCodeBlock({
1011 render={1008 render={
1012 <Button1009 <Button
1013 type="button"1010 type="button"
1014 variant="ghost"1011 variant="ghost-muted"
1015 size="icon-xs"1012 size="icon-xs"
1016 className="chat-markdown-chrome-action"
1017 onClick={handleCopy}1013 onClick={handleCopy}
1018 aria-label={copyLabel}1014 aria-label={copyLabel}
1019 />1015 />
apps/web/src/components/ChatView.tsx+1-1
...@@ -9991,7 +9991,7 @@ export default function ChatView(props: ChatViewProps) {...@@ -9991,7 +9991,7 @@ export default function ChatView(props: ChatViewProps) {
9991 composerRef.current?.restoreAfterTimelineReachedEnd();9991 composerRef.current?.restoreAfterTimelineReachedEnd();
9992 scrollToEnd(true);9992 scrollToEnd(true);
9993 }}9993 }}
9994 className="pointer-events-auto gap-1.5 rounded-full px-3 text-muted-foreground hover:text-foreground"9994 className="pointer-events-auto"
9995 size="xs"9995 size="xs"
9996 variant="glass"9996 variant="glass"
9997 >9997 >
apps/web/src/components/CommandPalette.tsx+4-8
...@@ -1528,9 +1528,8 @@ function OpenCommandPaletteDialog(props: {...@@ -1528,9 +1528,8 @@ function OpenCommandPaletteDialog(props: {
1528 <TooltipTrigger1528 <TooltipTrigger
1529 render={1529 render={
1530 <Button1530 <Button
1531 variant="outline"1531 variant="warning-outline"
1532 size="xs"1532 size="micro"
1533 className="h-5 rounded-[.25rem] px-1.5 text-[10px] text-warning-foreground"
1534 onClick={() => {1533 onClick={() => {
1535 openSourceControlSettings();1534 openSourceControlSettings();
1536 }}1535 }}
...@@ -2861,7 +2860,7 @@ function OpenCommandPaletteDialog(props: {...@@ -2861,7 +2860,7 @@ function OpenCommandPaletteDialog(props: {
2861 variant="outline"2860 variant="outline"
2862 size="xs"2861 size="xs"
2863 tabIndex={-1}2862 tabIndex={-1}
2864 className="absolute inset-e-2.5 top-1/2 gap-1.5 pe-1 ps-2 -translate-y-1/2"2863 className="absolute inset-e-2.5 top-1/2 -translate-y-1/2"
2865 aria-label={`${remoteProjectButtonLabel ?? "Continue"} (Enter)`}2864 aria-label={`${remoteProjectButtonLabel ?? "Continue"} (Enter)`}
2866 disabled={!canSubmitRemoteProjectFlow}2865 disabled={!canSubmitRemoteProjectFlow}
2867 onMouseDown={(event) => {2866 onMouseDown={(event) => {
...@@ -2888,10 +2887,7 @@ function OpenCommandPaletteDialog(props: {...@@ -2888,10 +2887,7 @@ function OpenCommandPaletteDialog(props: {
2888 variant="outline"2887 variant="outline"
2889 size="xs"2888 size="xs"
2890 tabIndex={-1}2889 tabIndex={-1}
2891 className={cn(2890 className="absolute inset-e-2.5 top-1/2 -translate-y-1/2"
2892 "absolute inset-e-2.5 top-1/2 pe-1 ps-2 -translate-y-1/2",
2893 hasHighlightedBrowseItem ? "gap-1" : "gap-1.5",
2894 )}
2895 aria-label={`${submitActionLabel} (${addShortcutLabel})`}2891 aria-label={`${submitActionLabel} (${addShortcutLabel})`}
2896 disabled={2892 disabled={
2897 !canCreateProjectInEnvironment(browseEnvironment?.connection.phase) ||2893 !canCreateProjectInEnvironment(browseEnvironment?.connection.phase) ||
apps/web/src/components/CustomSnoozeDialog.tsx+1-1
...@@ -119,7 +119,7 @@ function CustomSnoozeDialog() {...@@ -119,7 +119,7 @@ function CustomSnoozeDialog() {
119 <Button119 <Button
120 id={`${id}-date`}120 id={`${id}-date`}
121 variant="outline"121 variant="outline"
122 className="w-full justify-between font-normal"122 className="w-full justify-between"
123 />123 />
124 }124 }
125 >125 >
apps/web/src/components/DiffPanel.tsx+7-6
...@@ -1125,10 +1125,7 @@ export default function DiffPanel({...@@ -1125,10 +1125,7 @@ export default function DiffPanel({
1125 <Button1125 <Button
1126 size="icon-micro"1126 size="icon-micro"
1127 variant="ghost"1127 variant="ghost"
1128 className={cn(1128 className="-ms-0.5"
1129 "-ms-0.5 [--control-icon-color:currentColor] bg-transparent hover:bg-foreground/10",
1130 getDiffCollapseIconClassName(fileDiff),
1131 )}
1132 aria-label={1129 aria-label={
1133 collapsed ? `Expand ${filePath}` : `Collapse ${filePath}`1130 collapsed ? `Expand ${filePath}` : `Collapse ${filePath}`
1134 }1131 }
...@@ -1142,9 +1139,13 @@ export default function DiffPanel({...@@ -1142,9 +1139,13 @@ export default function DiffPanel({
1142 }1139 }
1143 >1140 >
1144 {collapsed ? (1141 {collapsed ? (
1145 <ChevronRightIcon className="size-4" />1142 <ChevronRightIcon
1143 className={cn("size-4", getDiffCollapseIconClassName(fileDiff))}
1144 />
1146 ) : (1145 ) : (
1147 <ChevronDownIcon className="size-4" />1146 <ChevronDownIcon
1147 className={cn("size-4", getDiffCollapseIconClassName(fileDiff))}
1148 />
1148 )}1149 )}
1149 </TooltipTrigger>1150 </TooltipTrigger>
1150 <TooltipPopup side="top">1151 <TooltipPopup side="top">
apps/web/src/components/GitActionsControl.tsx+7-16
...@@ -646,9 +646,8 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {...@@ -646,9 +646,8 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {
646 <TooltipTrigger646 <TooltipTrigger
647 render={647 render={
648 <Button648 <Button
649 variant="outline"649 variant="warning-outline"
650 size="xs"650 size="micro"
651 className="h-5 rounded-[.25rem] px-1.5 text-[10px] text-warning-foreground"
652 onClick={(event) => {651 onClick={(event) => {
653 event.preventDefault();652 event.preventDefault();
654 event.stopPropagation();653 event.stopPropagation();
...@@ -1799,14 +1798,7 @@ export default function GitActionsControl({...@@ -1799,14 +1798,7 @@ export default function GitActionsControl({
1799 <Popover>1798 <Popover>
1800 <PopoverTrigger1799 <PopoverTrigger
1801 openOnHover1800 openOnHover
1802 render={1801 render={<Button aria-disabled="true" size="xs" variant="outline" />}
1803 <Button
1804 aria-disabled="true"
1805 className="cursor-not-allowed rounded-e-none border-e-0 ps-[8.5px] opacity-64 before:rounded-e-none"
1806 size="xs"
1807 variant="outline"
1808 />
1809 }
1810 >1802 >
1811 <GitQuickActionIcon1803 <GitQuickActionIcon
1812 quickAction={quickAction}1804 quickAction={quickAction}
...@@ -1824,7 +1816,6 @@ export default function GitActionsControl({...@@ -1824,7 +1816,6 @@ export default function GitActionsControl({
1824 <Button1816 <Button
1825 variant="outline"1817 variant="outline"
1826 size="xs"1818 size="xs"
1827 className="ps-[8.5px]"
1828 disabled={isGitActionRunning || quickAction.disabled}1819 disabled={isGitActionRunning || quickAction.disabled}
1829 onClick={runQuickAction}1820 onClick={runQuickAction}
1830 >1821 >
...@@ -2056,16 +2047,16 @@ export default function GitActionsControl({...@@ -2056,16 +2047,16 @@ export default function GitActionsControl({
2056 Abort2047 Abort
2057 </Button>2048 </Button>
2058 <Button2049 <Button
2059 className="min-h-8 w-full max-w-full whitespace-normal py-1.5 leading-snug sm:min-h-7 sm:w-auto"2050 className="w-full max-w-full sm:w-auto"
2060 variant="outline"2051 variant="outline"
2061 size="sm"2052 size="sm-multiline"
2062 onClick={continuePendingDefaultBranchAction}2053 onClick={continuePendingDefaultBranchAction}
2063 >2054 >
2064 {pendingDefaultBranchActionCopy?.continueLabel ?? "Continue"}2055 {pendingDefaultBranchActionCopy?.continueLabel ?? "Continue"}
2065 </Button>2056 </Button>
2066 <Button2057 <Button
2067 className="min-h-8 w-full max-w-full whitespace-normal py-1.5 leading-snug sm:min-h-7 sm:w-auto"2058 className="w-full max-w-full sm:w-auto"
2068 size="sm"2059 size="sm-multiline"
2069 onClick={checkoutFeatureBranchAndContinuePendingAction}2060 onClick={checkoutFeatureBranchAndContinuePendingAction}
2070 >2061 >
2071 Check out feature branch & continue2062 Check out feature branch & continue
apps/web/src/components/ProjectScriptsControl.tsx+23-19
...@@ -192,24 +192,28 @@ export default function ProjectScriptsControl({...@@ -192,24 +192,28 @@ export default function ProjectScriptsControl({
192 <MenuShortcut className="ms-0">{shortcutLabel}</MenuShortcut>192 <MenuShortcut className="ms-0">{shortcutLabel}</MenuShortcut>
193 </span>193 </span>
194 ))}194 ))}
195 <Button195 <span
196 type="button"196 className={`absolute right-0 top-1/2 flex -translate-y-1/2 ${presentation === "menu" ? "" : "opacity-0 pointer-events-none transition-opacity group-hover:opacity-100 group-hover:pointer-events-auto group-focus-visible:opacity-100 group-focus-visible:pointer-events-auto"}`}
197 variant="ghost"
198 size="icon-xs"
199 className={`absolute right-0 top-1/2 size-6 -translate-y-1/2 ${presentation === "menu" ? "" : "opacity-0 pointer-events-none transition-opacity group-hover:opacity-100 group-hover:pointer-events-auto group-focus-visible:opacity-100 group-focus-visible:pointer-events-auto"}`}
200 aria-label={`Edit ${script.name}`}
201 onPointerDown={(event) => {
202 event.preventDefault();
203 event.stopPropagation();
204 }}
205 onClick={(event) => {
206 event.preventDefault();
207 event.stopPropagation();
208 openEditDialog(script);
209 }}
210 >197 >
211 <SettingsIcon className="size-3.5" />198 <Button
212 </Button>199 type="button"
200 variant="ghost"
201 size="icon-xs"
202 className="size-6"
203 aria-label={`Edit ${script.name}`}
204 onPointerDown={(event) => {
205 event.preventDefault();
206 event.stopPropagation();
207 }}
208 onClick={(event) => {
209 event.preventDefault();
210 event.stopPropagation();
211 openEditDialog(script);
212 }}
213 >
214 <SettingsIcon className="size-3.5" />
215 </Button>
216 </span>
213 </span>217 </span>
214 </MenuItem>218 </MenuItem>
215 );219 );
...@@ -269,7 +273,7 @@ export default function ProjectScriptsControl({...@@ -269,7 +273,7 @@ export default function ProjectScriptsControl({
269 <Button273 <Button
270 size="xs"274 size="xs"
271 variant="outline"275 variant="outline"
272 className="w-7 px-0 sm:w-6 @3xl/header-actions:w-auto! @3xl/header-actions:px-[calc(--spacing(2)-1px)]"276 className="w-7 sm:w-6 @3xl/header-actions:w-auto!"
273 aria-label={`Run ${primaryScript.name}`}277 aria-label={`Run ${primaryScript.name}`}
274 // The tooltip wrapper replaces data-slot="button", so themed278 // The tooltip wrapper replaces data-slot="button", so themed
275 // toolbar styling needs its own hook.279 // toolbar styling needs its own hook.
...@@ -329,7 +333,7 @@ export default function ProjectScriptsControl({...@@ -329,7 +333,7 @@ export default function ProjectScriptsControl({
329 <Button333 <Button
330 size="xs"334 size="xs"
331 variant="outline"335 variant="outline"
332 className="w-7 px-0 sm:w-6 @3xl/header-actions:w-auto! @3xl/header-actions:px-[calc(--spacing(2)-1px)]"336 className="w-7 sm:w-6 @3xl/header-actions:w-auto!"
333 aria-label="Add action"337 aria-label="Add action"
334 // The tooltip wrapper replaces data-slot="button", so themed338 // The tooltip wrapper replaces data-slot="button", so themed
335 // toolbar styling needs its own hook.339 // toolbar styling needs its own hook.
apps/web/src/components/ServerUpdateAction.tsx+2-2
...@@ -270,8 +270,8 @@ export function ServerUpdateAction({...@@ -270,8 +270,8 @@ export function ServerUpdateAction({
270 render={270 render={
271 <Button271 <Button
272 size="icon-xs"272 size="icon-xs"
273 variant="ghost"273 variant="ghost-muted"
274 className={className ?? "text-muted-foreground hover:text-foreground"}274 className={className}
275 aria-label={`${actionLabel} for ${serverLabel}`}275 aria-label={`${actionLabel} for ${serverLabel}`}
276 onClick={onClick}276 onClick={onClick}
277 />277 />
apps/web/src/components/Sidebar.tsx+1-1
...@@ -4500,7 +4500,7 @@ export default function Sidebar() {...@@ -4500,7 +4500,7 @@ export default function Sidebar() {
4500 tabIndex={-1}4500 tabIndex={-1}
4501 aria-hidden="true"4501 aria-hidden="true"
4502 title={`Project settings for ${project.displayName}`}4502 title={`Project settings for ${project.displayName}`}
4503 className="ml-auto focus-visible:bg-accent focus-visible:text-foreground"4503 className="ml-auto"
4504 onPointerDown={(event) => event.stopPropagation()}4504 onPointerDown={(event) => event.stopPropagation()}
4505 onClick={(event) => {4505 onClick={(event) => {
4506 void handleProjectSettings(event, project);4506 void handleProjectSettings(event, project);
apps/web/src/components/chat/AssistantSelectionToolbar.tsx+1-1
...@@ -134,7 +134,7 @@ export function AssistantSelectionToolbar({...@@ -134,7 +134,7 @@ export function AssistantSelectionToolbar({
134 variant="glass"134 variant="glass"
135 disabled={tooLong}135 disabled={tooLong}
136 aria-label={tooLong ? "Selection is too long to cite" : "Cite selection in composer"}136 aria-label={tooLong ? "Selection is too long to cite" : "Cite selection in composer"}
137 className="fixed z-50 max-w-[calc(100vw-1rem)] rounded-full px-2.5"137 className="fixed z-50 max-w-[calc(100vw-1rem)]"
138 style={{ left: selection.position.x, top: selection.position.y }}138 style={{ left: selection.position.x, top: selection.position.y }}
139 onPointerDown={(event) => event.preventDefault()}139 onPointerDown={(event) => event.preventDefault()}
140 onClick={cite}140 onClick={cite}
apps/web/src/components/chat/ContextWindowMeter.tsx+1-1
...@@ -45,7 +45,7 @@ export function ContextWindowMeter(props: {...@@ -45,7 +45,7 @@ export function ContextWindowMeter(props: {
45 <Button45 <Button
46 size="icon-sm"46 size="icon-sm"
47 variant="ghost-muted"47 variant="ghost-muted"
48 className="size-7 rounded-full hover:text-muted-foreground data-pressed:text-muted-foreground"48 className="size-7"
49 aria-label={49 aria-label={
50 usage.maxTokens !== null && usedPercentage50 usage.maxTokens !== null && usedPercentage
51 ? `Context window ${usedPercentage} used`51 ? `Context window ${usedPercentage} used`
apps/web/src/components/chat/ExpandedImageDialog.tsx+4-9
...@@ -193,7 +193,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({...@@ -193,7 +193,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({
193 type="button"193 type="button"
194 size="icon"194 size="icon"
195 variant="media-navigation"195 variant="media-navigation"
196 className="left-0 top-auto -bottom-12 translate-y-0 rounded-full bg-white/10 sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2"196 className="left-0 top-auto -bottom-12 translate-y-0 sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2"
197 aria-label="Previous media"197 aria-label="Previous media"
198 onClick={() => navigateImage(-1)}198 onClick={() => navigateImage(-1)}
199 >199 >
...@@ -252,12 +252,11 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({...@@ -252,12 +252,11 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({
252 <Button252 <Button
253 aria-label={contentsLabel}253 aria-label={contentsLabel}
254 aria-pressed={showingAccessibilityDetails}254 aria-pressed={showingAccessibilityDetails}
255 className="[--control-icon-color:currentColor] hover:bg-white/10 hover:text-white"
256 onClick={() =>255 onClick={() =>
257 setAccessibilityDetailsSrc(showingAccessibilityDetails ? null : item.src)256 setAccessibilityDetailsSrc(showingAccessibilityDetails ? null : item.src)
258 }257 }
259 size="icon-micro"258 size="icon-micro"
260 variant="ghost-muted"259 variant="overlay"
261 />260 />
262 }261 }
263 >262 >
...@@ -266,11 +265,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({...@@ -266,11 +265,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({
266 <TooltipPopup side="top">{contentsLabel}</TooltipPopup>265 <TooltipPopup side="top">{contentsLabel}</TooltipPopup>
267 </Tooltip>266 </Tooltip>
268 ) : item.source ? (267 ) : item.source ? (
269 <SnapShotContentsButton268 <SnapShotContentsButton source={item.source} side="top" />
270 source={item.source}
271 side="top"
272 className="hover:bg-white/10 hover:text-white"
273 />
274 ) : null}269 ) : null}
275 </div>270 </div>
276 </div>271 </div>
...@@ -280,7 +275,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({...@@ -280,7 +275,7 @@ export const ExpandedImageDialog = memo(function ExpandedImageDialog({
280 type="button"275 type="button"
281 size="icon"276 size="icon"
282 variant="media-navigation"277 variant="media-navigation"
283 className="right-0 top-auto -bottom-12 translate-y-0 rounded-full bg-white/10 sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2"278 className="right-0 top-auto -bottom-12 translate-y-0 sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2"
284 aria-label="Next media"279 aria-label="Next media"
285 onClick={() => navigateImage(1)}280 onClick={() => navigateImage(1)}
286 >281 >
apps/web/src/components/chat/MessageCopyButton.tsx+2-3
...@@ -2,7 +2,6 @@ import { memo, useRef } from "react";...@@ -2,7 +2,6 @@ import { memo, useRef } from "react";
2import { CopyIcon, CheckIcon } from "lucide-react";2import { CopyIcon, CheckIcon } from "lucide-react";
3import { Button } from "../ui/button";3import { Button } from "../ui/button";
4import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";4import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
5import { cn } from "~/lib/utils";
6import {5import {
7 ANCHORED_COPY_TOAST_TIMEOUT_MS,6 ANCHORED_COPY_TOAST_TIMEOUT_MS,
8 showAnchoredCopyErrorToast,7 showAnchoredCopyErrorToast,
...@@ -43,8 +42,8 @@ export const MessageCopyButton = memo(function MessageCopyButton({...@@ -43,8 +42,8 @@ export const MessageCopyButton = memo(function MessageCopyButton({
43 ref={ref}42 ref={ref}
44 type="button"43 type="button"
45 size={size}44 size={size}
46 variant={variant}45 variant={variant === "ghost" ? "ghost-muted" : variant}
47 className={cn("text-muted-foreground hover:text-foreground", className)}46 className={className}
48 />47 />
49 }48 }
50 >49 >
apps/web/src/components/chat/MessagesTimeline.tsx+2-2
...@@ -3956,11 +3956,11 @@ const CollapsibleUserMessageBody = memo(function CollapsibleUserMessageBody(prop...@@ -3956,11 +3956,11 @@ const CollapsibleUserMessageBody = memo(function CollapsibleUserMessageBody(prop
3956 <Button3956 <Button
3957 type="button"3957 type="button"
3958 size="xs"3958 size="xs"
3959 variant="ghost"3959 variant="ghost-muted"
3960 aria-expanded={expanded}3960 aria-expanded={expanded}
3961 data-scroll-anchor-ignore3961 data-scroll-anchor-ignore
3962 onClick={() => setExpanded((value) => !value)}3962 onClick={() => setExpanded((value) => !value)}
3963 className="-ml-1 h-6 rounded-md px-1.5 text-secondary-label text-xs hover:bg-muted/55 hover:text-message-foreground"3963 className="-ml-1"
3964 >3964 >
3965 {expanded ? "Show less" : "Show full message"}3965 {expanded ? "Show less" : "Show full message"}
3966 </Button>3966 </Button>
apps/web/src/components/chat/OpenInPicker.tsx-1
...@@ -353,7 +353,6 @@ export const OpenInPicker = memo(function OpenInPicker({...@@ -353,7 +353,6 @@ export const OpenInPicker = memo(function OpenInPicker({
353 <Group aria-label="Open in editor">353 <Group aria-label="Open in editor">
354 <Button354 <Button
355 aria-label={compact ? "Open file in preferred editor" : undefined}355 aria-label={compact ? "Open file in preferred editor" : undefined}
356 className="ps-[8.5px]"
357 size="xs"356 size="xs"
358 variant="outline"357 variant="outline"
359 disabled={!preferredEditor || !openInCwd || remote.mode === "remote-unavailable"}358 disabled={!preferredEditor || !openInCwd || remote.mode === "remote-unavailable"}
apps/web/src/components/chat/SnapShotAttachmentDetails.tsx+2-5
...@@ -153,7 +153,7 @@ export function SnapShotContentsButton({...@@ -153,7 +153,7 @@ export function SnapShotContentsButton({
153 className={className}153 className={className}
154 onClick={(event) => event.stopPropagation()}154 onClick={(event) => event.stopPropagation()}
155 size="icon-micro"155 size="icon-micro"
156 variant="ghost-muted"156 variant="overlay"
157 />157 />
158 }158 }
159 />159 />
...@@ -211,10 +211,7 @@ export function SnapShotAttachmentDetails({...@@ -211,10 +211,7 @@ export function SnapShotAttachmentDetails({
211 <div className="min-w-0 flex-1">211 <div className="min-w-0 flex-1">
212 <div className="flex min-w-0 items-center gap-1.5 text-[11px] font-medium leading-3.5 text-white">212 <div className="flex min-w-0 items-center gap-1.5 text-[11px] font-medium leading-3.5 text-white">
213 <span className="truncate">{source.appName}</span>213 <span className="truncate">{source.appName}</span>
214 <SnapShotContentsButton214 <SnapShotContentsButton source={source} className="pointer-events-auto" />
215 source={source}
216 className="pointer-events-auto text-white/60 hover:bg-white/10 hover:text-white focus-visible:ring-white/70"
217 />
218 </div>215 </div>
219 <div className="truncate text-[9px] leading-3.5 text-white/70">216 <div className="truncate text-[9px] leading-3.5 text-white/70">
220 {source.windowTitle || "Captured window"}217 {source.windowTitle || "Captured window"}
apps/web/src/components/diffs/DiffCommentAnnotation.tsx+10-9
...@@ -67,15 +67,16 @@ export function DiffCommentAnnotation({...@@ -67,15 +67,16 @@ export function DiffCommentAnnotation({
67 <MessageCircle className="mt-0.5 size-3.5 shrink-0 text-primary/70" aria-hidden="true" />67 <MessageCircle className="mt-0.5 size-3.5 shrink-0 text-primary/70" aria-hidden="true" />
68 <p className="min-w-0 flex-1 whitespace-pre-wrap text-[13px] leading-5">{displayedText}</p>68 <p className="min-w-0 flex-1 whitespace-pre-wrap text-[13px] leading-5">{displayedText}</p>
69 {onDelete ? (69 {onDelete ? (
70 <Button70 <span className="-my-1 -mr-1 flex shrink-0 opacity-0 transition-opacity group-hover/comment:opacity-100 focus-within:opacity-100 max-sm:opacity-100">
71 className="-my-1 -mr-1 shrink-0 opacity-0 transition-opacity group-hover/comment:opacity-100 focus-visible:opacity-100 max-sm:opacity-100"71 <Button
72 variant="ghost-muted"72 variant="ghost-muted"
73 size="icon-xs"73 size="icon-xs"
74 aria-label="Delete comment"74 aria-label="Delete comment"
75 onClick={onDelete}75 onClick={onDelete}
76 >76 >
77 <Trash2 className="size-3" />77 <Trash2 className="size-3" />
78 </Button>78 </Button>
79 </span>
79 ) : null}80 ) : null}
80 </div>81 </div>
81 );82 );
apps/web/src/components/onboarding/WelcomeWizard.tsx+5-7
...@@ -357,12 +357,13 @@ function ConnectionStep({...@@ -357,12 +357,13 @@ function ConnectionStep({
357 render={357 render={
358 <Button358 <Button
359 variant="ghost"359 variant="ghost"
360 className="h-auto min-h-14 w-full justify-start gap-3 px-3 py-3 text-left whitespace-normal sm:h-auto"360 size="sm-multiline"
361 className="min-h-14 w-full justify-start"
361 />362 />
362 }363 }
363 >364 >
364 <LinkIcon className="size-4 text-muted-foreground" />365 <LinkIcon className="size-4 text-muted-foreground" />
365 <span className="flex-1">Add a computer</span>366 <span className="flex-1 text-left">Add a computer</span>
366 <ChevronRightIcon367 <ChevronRightIcon
367 className={cn("size-4 text-muted-foreground", pairingOpen && "rotate-90")}368 className={cn("size-4 text-muted-foreground", pairingOpen && "rotate-90")}
368 />369 />
...@@ -429,14 +430,11 @@ function ConnectAccountOption({...@@ -429,14 +430,11 @@ function ConnectAccountOption({
429 }430 }
430 }}431 }}
431 render={432 render={
432 <Button433 <Button variant="ghost" size="sm-multiline" className="min-h-14 w-full justify-start" />
433 variant="ghost"
434 className="h-auto min-h-14 w-full justify-start gap-3 px-3 py-3 text-left whitespace-normal sm:h-auto"
435 />
436 }434 }
437 >435 >
438 <CloudIcon className="size-4 text-muted-foreground" />436 <CloudIcon className="size-4 text-muted-foreground" />
439 <span className="flex-1">T3 Connect</span>437 <span className="flex-1 text-left">T3 Connect</span>
440 <span className="text-xs text-muted-foreground">438 <span className="text-xs text-muted-foreground">
441 {!isLoaded439 {!isLoaded
442 ? "Loading sign-in…"440 ? "Loading sign-in…"
apps/web/src/components/preview/PreviewMoreMenu.tsx-1
...@@ -185,7 +185,6 @@ export function PreviewMoreMenu({...@@ -185,7 +185,6 @@ export function PreviewMoreMenu({
185 type="button"185 type="button"
186 onClick={callTab(bridge.resetZoom)}186 onClick={callTab(bridge.resetZoom)}
187 aria-label="Reset zoom"187 aria-label="Reset zoom"
188 className="[:hover,[data-pressed]]:bg-foreground/10"
189 disabled={tabDisabled}188 disabled={tabDisabled}
190 >189 >
191 <RotateCcw />190 <RotateCcw />
apps/web/src/components/projectScriptEditor.tsx+1-1
...@@ -319,7 +319,7 @@ export function ProjectScriptEditorDialog({...@@ -319,7 +319,7 @@ export function ProjectScriptEditorDialog({
319 <Button319 <Button
320 type="button"320 type="button"
321 variant="outline"321 variant="outline"
322 className="size-9 shrink-0 hover:bg-popover active:bg-popover data-pressed:bg-popover data-pressed:shadow-xs/5 data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:border-transparent dark:bg-white/[0.035] dark:data-pressed:before:shadow-none"322 className="size-9 shrink-0"
323 aria-label="Choose icon"323 aria-label="Choose icon"
324 />324 />
325 }325 }
apps/web/src/components/pullRequest/PullRequestCodeTab.tsx+1-1
...@@ -785,7 +785,7 @@ function PullRequestCodeTab({...@@ -785,7 +785,7 @@ function PullRequestCodeTab({
785 variant="ghost-muted"785 variant="ghost-muted"
786 aria-expanded={!collapsed}786 aria-expanded={!collapsed}
787 aria-label={collapsed ? "Expand diff" : "Collapse diff"}787 aria-label={collapsed ? "Expand diff" : "Collapse diff"}
788 className="mr-1 rounded hover:bg-transparent"788 className="mr-1"
789 onClick={(event) => {789 onClick={(event) => {
790 event.stopPropagation();790 event.stopPropagation();
791 toggleFile(item.id);791 toggleFile(item.id);
apps/web/src/components/pullRequest/PullRequestComposer.tsx+1-7
...@@ -78,13 +78,7 @@ export function PullRequestComposer({...@@ -78,13 +78,7 @@ export function PullRequestComposer({
78 }}78 }}
79 >79 >
80 <PopoverTrigger80 <PopoverTrigger
81 render={81 render={<Button size="icon" variant="glass" />}
82 <Button
83 size="icon"
84 variant="glass"
85 className="rounded-full shadow-lg [--glass-opacity:50%]"
86 />
87 }
88 // The only label this control has, so the pending count belongs in it: the badge beside82 // The only label this control has, so the pending count belongs in it: the badge beside
89 // the icon is decorative and a reader who cannot see it still needs the number.83 // the icon is decorative and a reader who cannot see it still needs the number.
90 aria-label={84 aria-label={
apps/web/src/components/pullRequest/PullRequestDetailPanel.tsx+1-2
...@@ -2662,8 +2662,7 @@ export function PullRequestDetailPanel({...@@ -2662,8 +2662,7 @@ export function PullRequestDetailPanel({
2662 </PullRequestMetaLine>2662 </PullRequestMetaLine>
2663 <Button2663 <Button
2664 size="xs"2664 size="xs"
2665 variant="ghost"2665 variant="ghost-muted"
2666 className="h-7 px-2 text-[10px] text-muted-foreground"
2667 aria-label={2666 aria-label={
2668 timelineOrder === "newest"2667 timelineOrder === "newest"
2669 ? "Show oldest activity first"2668 ? "Show oldest activity first"
apps/web/src/components/pullRequest/PullRequestEditButton.tsx+6-7
...@@ -12,16 +12,15 @@ export function PullRequestEditButton({...@@ -12,16 +12,15 @@ export function PullRequestEditButton({
12 "aria-label": string;12 "aria-label": string;
13}) {13}) {
14 return (14 return (
15 <Button15 <span
16 {...props}
17 size="icon-xs"
18 variant="ghost"
19 className={cn(16 className={cn(
20 "shrink-0 text-muted-foreground opacity-0 transition-opacity pointer-coarse:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 focus-visible:opacity-100 motion-reduce:transition-none",17 "flex shrink-0 opacity-0 transition-opacity pointer-coarse:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100 focus-within:opacity-100 motion-reduce:transition-none",
21 className,18 className,
22 )}19 )}
23 >20 >
24 <PencilIcon aria-hidden className="size-3" />21 <Button {...props} size="icon-xs" variant="ghost-muted">
25 </Button>22 <PencilIcon aria-hidden className="size-3" />
23 </Button>
24 </span>
26 );25 );
27}26}
apps/web/src/components/pullRequest/PullRequestReviewAnnotation.tsx+1-7
...@@ -312,7 +312,6 @@ export function ReviewThreadCard({...@@ -312,7 +312,6 @@ export function ReviewThreadCard({
312 <Button312 <Button
313 size="xs"313 size="xs"
314 variant="ghost"314 variant="ghost"
315 className="px-1"
316 disabled={loadingMore}315 disabled={loadingMore}
317 onClick={() => void loadMore()}316 onClick={() => void loadMore()}
318 >317 >
...@@ -352,12 +351,7 @@ export function ReviewThreadCard({...@@ -352,12 +351,7 @@ export function ReviewThreadCard({
352 </div>351 </div>
353 </div>352 </div>
354 ) : (353 ) : (
355 <Button354 <Button size="xs" variant="ghost" className="mt-2" onClick={() => setReplying(true)}>
356 size="xs"
357 variant="ghost"
358 className="mt-2 px-1"
359 onClick={() => setReplying(true)}
360 >
361 Reply355 Reply
362 </Button>356 </Button>
363 )357 )
apps/web/src/components/pullRequest/PullRequestSummaryTab.tsx+2-2
...@@ -922,8 +922,8 @@ export function PullRequestSummaryTab({...@@ -922,8 +922,8 @@ export function PullRequestSummaryTab({
922 actions={922 actions={
923 <Button923 <Button
924 size="xs"924 size="xs"
925 variant="ghost"925 variant="ghost-muted"
926 className="h-7 shrink-0 px-2 text-[10px] text-muted-foreground"926 className="shrink-0"
927 aria-label={927 aria-label={
928 commentOrder === "newest"928 commentOrder === "newest"
929 ? "Show oldest comments first"929 ? "Show oldest comments first"
apps/web/src/components/settings/ConnectionsSettings.tsx+2-11
...@@ -3680,11 +3680,7 @@ export function ConnectionsSettings() {...@@ -3680,11 +3680,7 @@ export function ConnectionsSettings() {
3680 headerAction={3680 headerAction={
3681 <div className="flex items-center gap-1">3681 <div className="flex items-center gap-1">
3682 {savedServerUpdateTargets.length > 0 ? (3682 {savedServerUpdateTargets.length > 0 ? (
3683 <ServerUpdatesAction3683 <ServerUpdatesAction targets={savedServerUpdateTargets} variant="ghost-muted" />
3684 targets={savedServerUpdateTargets}
3685 variant="ghost"
3686 className="font-normal text-muted-foreground/60 hover:text-muted-foreground"
3687 />
3688 ) : null}3684 ) : null}
3689 <Dialog3685 <Dialog
3690 open={addBackendDialogOpen}3686 open={addBackendDialogOpen}
...@@ -3700,12 +3696,7 @@ export function ConnectionsSettings() {...@@ -3700,12 +3696,7 @@ export function ConnectionsSettings() {
3700 render={3696 render={
3701 <DialogTrigger3697 <DialogTrigger
3702 render={3698 render={
3703 <Button3699 <Button size="xs" variant="ghost-muted" aria-label="Add environment">
3704 size="xs"
3705 variant="ghost"
3706 className="font-normal text-muted-foreground/60 hover:text-muted-foreground"
3707 aria-label="Add environment"
3708 >
3709 <PlusIcon className="size-3" />3700 <PlusIcon className="size-3" />
3710 <span>Add environment</span>3701 <span>Add environment</span>
3711 </Button>3702 </Button>
apps/web/src/components/settings/KeybindingsSettings.tsx+2-2
...@@ -891,12 +891,12 @@ function WhenClauseControl({...@@ -891,12 +891,12 @@ function WhenClauseControl({
891 <Button891 <Button
892 variant={expression ? "ghost" : "ghost-muted"}892 variant={expression ? "ghost" : "ghost-muted"}
893 size="micro"893 size="micro"
894 className="min-w-0 shrink font-mono"894 className="min-w-0 shrink"
895 />895 />
896 }896 }
897 aria-label={`Edit when clause for ${label}`}897 aria-label={`Edit when clause for ${label}`}
898 >898 >
899 <span className="truncate">{expression || "Always"}</span>899 <span className="truncate font-mono">{expression || "Always"}</span>
900 <ChevronDownIcon className="size-3.5 shrink-0 opacity-60" />900 <ChevronDownIcon className="size-3.5 shrink-0 opacity-60" />
901 </PopoverTrigger>901 </PopoverTrigger>
902 <PopoverContent align="start" sideOffset={6}>902 <PopoverContent align="start" sideOffset={6}>
apps/web/src/components/settings/ProjectActionsList.tsx+11-10
...@@ -51,16 +51,17 @@ export function ProjectActionsList({...@@ -51,16 +51,17 @@ export function ProjectActionsList({
51 {shortcutLabel ? (51 {shortcutLabel ? (
52 <span className="text-xs text-muted-foreground">{shortcutLabel}</span>52 <span className="text-xs text-muted-foreground">{shortcutLabel}</span>
53 ) : null}53 ) : null}
54 <Button54 <span className="flex shrink-0 opacity-0 group-focus-within:opacity-100 group-hover:opacity-100">
55 size="icon-xs"55 <Button
56 variant="ghost-muted"56 size="icon-xs"
57 className="shrink-0 opacity-0 group-focus-within:opacity-100 group-hover:opacity-100"57 variant="ghost-muted"
58 aria-label={`Edit ${script.name}`}58 aria-label={`Edit ${script.name}`}
59 disabled={disabled}59 disabled={disabled}
60 onClick={() => onEdit(script)}60 onClick={() => onEdit(script)}
61 >61 >
62 <SettingsIcon className="size-3.5" />62 <SettingsIcon className="size-3.5" />
63 </Button>63 </Button>
64 </span>
64 </>65 </>
65 }66 }
66 />67 />
apps/web/src/components/settings/ProviderAccentColorPicker.tsx+17-15
...@@ -92,21 +92,23 @@ function ProviderCustomColorPicker(props: {...@@ -92,21 +92,23 @@ function ProviderCustomColorPicker(props: {
92 />92 />
93 <PopoverPopup side="bottom" align="start" sideOffset={6} padding="none">93 <PopoverPopup side="bottom" align="start" sideOffset={6} padding="none">
94 <ProviderCustomColorPanel value={normalized} onCommit={props.onCommit} />94 <ProviderCustomColorPanel value={normalized} onCommit={props.onCommit} />
95 <PopoverClose95 <div className="border-t border-border/60 p-1">
96 render={96 <PopoverClose
97 <Button97 render={
98 type="button"98 <Button
99 size="sm"99 type="button"
100 variant="ghost"100 size="compact"
101 className="h-8 w-full justify-start rounded-none border-t border-border/60 px-3 text-xs text-muted-foreground [--control-icon-color:currentColor]"101 variant="ghost-muted"
102 onClick={props.onClear}102 className="w-full justify-start"
103 disabled={!props.value}103 onClick={props.onClear}
104 >104 disabled={!props.value}
105 <XIcon className="size-3.5" aria-hidden />105 >
106 Clear color106 <XIcon aria-hidden />
107 </Button>107 Clear color
108 }108 </Button>
109 />109 }
110 />
111 </div>
110 </PopoverPopup>112 </PopoverPopup>
111 </Popover>113 </Popover>
112 );114 );
apps/web/src/components/settings/SettingsSidebarNav.tsx+2-2
...@@ -265,8 +265,8 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) {...@@ -265,8 +265,8 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) {
265 <Button265 <Button
266 type="button"266 type="button"
267 size="icon-micro"267 size="icon-micro"
268 variant="ghost"268 variant="ghost-muted"
269 className="shrink-0 text-sidebar-muted-foreground hover:bg-sidebar-control-surface hover:text-sidebar-foreground"269 className="shrink-0"
270 aria-label="Clear settings search"270 aria-label="Clear settings search"
271 onClick={() => {271 onClick={() => {
272 clearSearch();272 clearSearch();
apps/web/src/components/sidebar/SidebarProviderUpdatePill.tsx+4-6
...@@ -11,7 +11,6 @@ import {...@@ -11,7 +11,6 @@ import {
11 type ProviderUpdateSidebarPillView,11 type ProviderUpdateSidebarPillView,
12} from "../ProviderUpdateLaunchNotification.logic";12} from "../ProviderUpdateLaunchNotification.logic";
13import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";13import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
14import { Button } from "../ui/button";
1514
16const PROVIDER_UPDATE_PILL_STYLES = {15const PROVIDER_UPDATE_PILL_STYLES = {
17 loading:16 loading:
...@@ -192,15 +191,14 @@ export function SidebarProviderUpdatePill() {...@@ -192,15 +191,14 @@ export function SidebarProviderUpdatePill() {
192 <Tooltip>191 <Tooltip>
193 <TooltipTrigger192 <TooltipTrigger
194 render={193 render={
195 <Button194 <button
196 size="icon-micro"195 type="button"
197 variant="ghost"
198 aria-label="Dismiss provider update notice"196 aria-label="Dismiss provider update notice"
199 className="relative z-[1] mr-1 [--control-icon-color:currentColor] rounded-md text-inherit opacity-70 hover:bg-transparent hover:opacity-100"197 className="relative z-[1] mr-1 flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-md opacity-70 outline-none hover:opacity-100 focus-visible:opacity-100 focus-visible:ring-2 focus-visible:ring-ring"
200 onClick={() => startExit(displayedView.key, null, displayedView.key)}198 onClick={() => startExit(displayedView.key, null, displayedView.key)}
201 >199 >
202 <XIcon className="size-3.5 shrink-0" />200 <XIcon className="size-3.5 shrink-0" />
203 </Button>201 </button>
204 }202 }
205 />203 />
206 <TooltipPopup side="top">Dismiss until provider status changes</TooltipPopup>204 <TooltipPopup side="top">Dismiss until provider status changes</TooltipPopup>
apps/web/src/components/sidebar/SidebarThreadHeader.tsx+2-2
...@@ -108,8 +108,8 @@ export function SidebarThreadHeader({...@@ -108,8 +108,8 @@ export function SidebarThreadHeader({
108 <Button108 <Button
109 type="button"109 type="button"
110 size="icon-micro"110 size="icon-micro"
111 variant="ghost"111 variant="ghost-muted"
112 className="shrink-0 text-sidebar-muted-foreground hover:bg-sidebar-control-surface hover:text-sidebar-foreground"112 className="shrink-0"
113 aria-label="Clear thread search"113 aria-label="Clear thread search"
114 onClick={() => {114 onClick={() => {
115 onClearSearch();115 onClearSearch();
apps/web/src/components/ui/button.tsx+2-2
...@@ -8,7 +8,7 @@ import type * as React from "react";...@@ -8,7 +8,7 @@ import type * as React from "react";
8import { cn } from "~/lib/utils";8import { cn } from "~/lib/utils";
99
10const buttonVariants = cva(10const buttonVariants = cva(
11 "[--control-icon-color:currentColor] [&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-[var(--control-radius)] border font-medium text-base outline-none transition-[box-shadow,scale] [&:active:not([aria-haspopup])]:scale-[0.97] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--control-radius)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 sm:text-sm [&_svg:not([class*='text-'])]:text-[var(--control-icon-color)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",11 "[--control-icon-color:currentColor] [&_svg]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-[var(--control-radius)] border font-medium text-base outline-none transition-[box-shadow,scale] [&:active:not([aria-haspopup])]:scale-[0.97] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--control-radius)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 aria-disabled:cursor-not-allowed aria-disabled:opacity-64 sm:text-sm [&_svg:not([class*='text-'])]:text-[var(--control-icon-color)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
12 {12 {
13 defaultVariants: {13 defaultVariants: {
14 size: "default",14 size: "default",
...@@ -52,7 +52,7 @@ const buttonVariants = cva(...@@ -52,7 +52,7 @@ const buttonVariants = cva(
52 "ghost-destructive":52 "ghost-destructive":
53 "[--control-icon-color:currentColor] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-destructive",53 "[--control-icon-color:currentColor] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-destructive",
54 glass:54 glass:
55 "surface-glass [--control-icon-color:var(--contrast-muted-foreground)] border-border/60 text-foreground shadow-sm [:hover,[data-pressed]]:border-border",55 "surface-glass [--control-icon-color:var(--contrast-muted-foreground)] rounded-full border-border/60 text-foreground shadow-sm before:rounded-full [:hover,[data-pressed]]:border-border",
56 link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",56 link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
57 "media-close":57 "media-close":
58 "[--control-icon-color:currentColor] border-transparent bg-black/65 text-white shadow-sm ring-1 ring-white/20 [:hover,[data-pressed]]:bg-black/80 focus-visible:ring-white",58 "[--control-icon-color:currentColor] border-transparent bg-black/65 text-white shadow-sm ring-1 ring-white/20 [:hover,[data-pressed]]:bg-black/80 focus-visible:ring-white",
apps/web/src/components/ui/input.tsx+3
...@@ -28,6 +28,9 @@ function Input({...@@ -28,6 +28,9 @@ function Input({
28 size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",28 size === "lg" && "h-9.5 leading-9.5 sm:h-8.5 sm:leading-8.5",
29 props.type === "search" &&29 props.type === "search" &&
30 "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",30 "[&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none [&::-webkit-search-results-button]:appearance-none [&::-webkit-search-results-decoration]:appearance-none",
31 // Number fields are typed into; browser spin buttons crowd narrow fields and step by 1.
32 props.type === "number" &&
33 "[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none",
31 props.type === "file" &&34 props.type === "file" &&
32 "text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",35 "text-muted-foreground file:me-3 file:bg-transparent file:font-medium file:text-foreground file:text-sm",
33 );36 );
apps/web/src/index.css+2-18
...@@ -1350,8 +1350,7 @@ html[data-theme-id] .chat-markdown .chat-markdown-codeblock pre {...@@ -1350,8 +1350,7 @@ html[data-theme-id] .chat-markdown .chat-markdown-codeblock pre {
1350 background-color: transparent;1350 background-color: transparent;
1351}1351}
13521352
1353html[data-theme-id] .chat-markdown .chat-markdown-codeblock-header,1353html[data-theme-id] .chat-markdown .chat-markdown-codeblock-header {
1354html[data-theme-id] .chat-markdown .chat-markdown-chrome-action {
1355 color: color-mix(in srgb, var(--code-foreground) 72%, transparent);1354 color: color-mix(in srgb, var(--code-foreground) 72%, transparent);
1356}1355}
13571356
...@@ -1377,11 +1376,6 @@ html[data-theme-id="t3-chat"] {...@@ -1377,11 +1376,6 @@ html[data-theme-id="t3-chat"] {
1377 }1376 }
1378}1377}
13791378
1380html[data-theme-id] .chat-markdown .chat-markdown-chrome-action:hover,
1381html[data-theme-id] .chat-markdown .chat-markdown-chrome-action[aria-pressed="true"] {
1382 color: var(--code-foreground);
1383}
1384
1385html[data-theme-id] [data-app-sidebar] {1379html[data-theme-id] [data-app-sidebar] {
1386 --background: var(--app-theme-canvas);1380 --background: var(--app-theme-canvas);
1387 --foreground: var(--app-theme-text);1381 --foreground: var(--app-theme-text);
...@@ -1858,20 +1852,10 @@ code {...@@ -1858,20 +1852,10 @@ code {
1858 background: color-mix(in srgb, var(--contrast-border) 78%, transparent);1852 background: color-mix(in srgb, var(--contrast-border) 78%, transparent);
1859}1853}
18601854
1861.chat-markdown .chat-markdown-codeblock-header,1855.chat-markdown .chat-markdown-codeblock-header {
1862.chat-markdown .chat-markdown-chrome-action {
1863 color: color-mix(in srgb, var(--contrast-foreground) 72%, transparent);1856 color: color-mix(in srgb, var(--contrast-foreground) 72%, transparent);
1864}1857}
18651858
1866.chat-markdown .chat-markdown-chrome-action:hover {
1867 color: var(--contrast-foreground);
1868}
1869
1870.chat-markdown .chat-markdown-chrome-action[aria-pressed="true"] {
1871 color: var(--contrast-foreground);
1872 background: color-mix(in srgb, var(--contrast-foreground) 8%, transparent);
1873}
1874
1875.chat-markdown .chat-markdown-codeblock pre {1859.chat-markdown .chat-markdown-codeblock pre {
1876 margin: 0;1860 margin: 0;
1877 border: none;1861 border: none;
scripts/lint-restyle-ceiling.ts+1-1
...@@ -8,7 +8,7 @@ import * as NodeURL from "node:url";...@@ -8,7 +8,7 @@ import * as NodeURL from "node:url";
8// components/ui exports are migrated to variants (see vite.config.ts). This gate keeps the8// components/ui exports are migrated to variants (see vite.config.ts). This gate keeps the
9// count from growing: CI fails when findings exceed the ceiling. Lower the ceiling when you9// count from growing: CI fails when findings exceed the ceiling. Lower the ceiling when you
10// migrate a file, and delete this script when the rule becomes an error.10// migrate a file, and delete this script when the rule becomes an error.
11export const RESTYLE_CEILING = 250;11export const RESTYLE_CEILING = 101;
1212
13const RULE = "shadcn(no-restyle)";13const RULE = "shadcn(no-restyle)";
1414