authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-22 12:22:16-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-22 12:22:16-07:00
log18aa7036732c0fc2e2ab79e54d5d8f59a160843d
tree26efc473bd11e289085597c6b3e033782d0224e3
parentf3d3fe4569274c5ee6f3c5435809330bef494a2d
signature Signed by PGP key B5690EEEBB952194

refactor(web): ghost-muted icons follow the text; add ghost-destructive (#13033)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

11 files changed, 24 insertions(+), 51 deletions(-)

apps/web/src/components/LegacySidebar.tsx-1
...@@ -3038,7 +3038,6 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(...@@ -3038,7 +3038,6 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
3038 variant="ghost-muted"3038 variant="ghost-muted"
3039 aria-label="Add project"3039 aria-label="Add project"
3040 data-testid="sidebar-add-project-trigger"3040 data-testid="sidebar-add-project-trigger"
3041 className="[--control-icon-color:currentColor] text-icon-muted"
3042 onClick={openAddProject}3041 onClick={openAddProject}
3043 />3042 />
3044 }3043 }
apps/web/src/components/RightPanelTabs.tsx+1-1
...@@ -559,7 +559,7 @@ function RightPanelEmptyState(props: {...@@ -559,7 +559,7 @@ function RightPanelEmptyState(props: {
559 render={559 render={
560 <Button560 <Button
561 aria-label="Open browser in a profile"561 aria-label="Open browser in a profile"
562 className="absolute top-1/2 right-8 -translate-y-1/2 [--control-icon-color:currentColor]"562 className="absolute top-1/2 right-8 -translate-y-1/2"
563 size="icon-xs"563 size="icon-xs"
564 variant="ghost-muted"564 variant="ghost-muted"
565 />565 />
apps/web/src/components/Sidebar.tsx+1-1
...@@ -4517,7 +4517,7 @@ export default function Sidebar() {...@@ -4517,7 +4517,7 @@ export default function Sidebar() {
4517 tabIndex={-1}4517 tabIndex={-1}
4518 aria-hidden="true"4518 aria-hidden="true"
4519 title={`Project settings for ${project.displayName}`}4519 title={`Project settings for ${project.displayName}`}
4520 className="ml-auto [--control-icon-color:currentColor] text-icon-muted focus-visible:bg-accent focus-visible:text-foreground"4520 className="ml-auto focus-visible:bg-accent focus-visible:text-foreground"
4521 onPointerDown={(event) => event.stopPropagation()}4521 onPointerDown={(event) => event.stopPropagation()}
4522 onClick={(event) => {4522 onClick={(event) => {
4523 void handleProjectSettings(event, project);4523 void handleProjectSettings(event, project);
apps/web/src/components/chat/SnapShotAttachmentDetails.tsx+1-1
...@@ -150,7 +150,7 @@ export function SnapShotContentsButton({...@@ -150,7 +150,7 @@ export function SnapShotContentsButton({
150 aria-label={150 aria-label={
151 includesAccessibility ? "View accessibility data" : "No accessibility data"151 includesAccessibility ? "View accessibility data" : "No accessibility data"
152 }152 }
153 className={cn("[--control-icon-color:currentColor]", 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="ghost-muted"
apps/web/src/components/pullRequest/PullRequestListFilters.tsx+1-8
...@@ -500,14 +500,7 @@ export function PullRequestFiltersMenu({...@@ -500,14 +500,7 @@ export function PullRequestFiltersMenu({
500 ];500 ];
501 return (501 return (
502 <Menu onOpenChange={onOpenChange}>502 <Menu onOpenChange={onOpenChange}>
503 <MenuTrigger503 <MenuTrigger render={<Button variant="outline" />}>
504 render={
505 <Button
506 className={filterCount > 0 ? "[--control-icon-color:currentColor]" : undefined}
507 variant="outline"
508 />
509 }
510 >
511 <ListFilterIcon className="size-4" />504 <ListFilterIcon className="size-4" />
512 <span>Filters</span>505 <span>Filters</span>
513 {filterCount > 0 ? (506 {filterCount > 0 ? (
apps/web/src/components/settings/ProviderInstanceCard.tsx+6-16
...@@ -300,10 +300,6 @@ function ProviderEnvironmentSection(props: {...@@ -300,10 +300,6 @@ function ProviderEnvironmentSection(props: {
300 type="button"300 type="button"
301 size="icon-micro"301 size="icon-micro"
302 variant="ghost-muted"302 variant="ghost-muted"
303 className={cn(
304 "[--control-icon-color:currentColor]",
305 variable.sensitive && "text-foreground",
306 )}
307 onClick={() => {303 onClick={() => {
308 const sensitive = !variable.sensitive;304 const sensitive = !variable.sensitive;
309 updateVariable(variable.id, {305 updateVariable(variable.id, {
...@@ -331,8 +327,7 @@ function ProviderEnvironmentSection(props: {...@@ -331,8 +327,7 @@ function ProviderEnvironmentSection(props: {
331 <Button327 <Button
332 type="button"328 type="button"
333 size="icon-micro"329 size="icon-micro"
334 variant="ghost-muted"330 variant="ghost-destructive"
335 className="[--control-icon-color:currentColor] hover:text-destructive"
336 onClick={() => removeVariable(variable.id)}331 onClick={() => removeVariable(variable.id)}
337 aria-label={`Remove environment variable ${variable.name || index + 1}`}332 aria-label={`Remove environment variable ${variable.name || index + 1}`}
338 >333 >
...@@ -704,16 +699,12 @@ export function ProviderInstanceCard({...@@ -704,16 +699,12 @@ export function ProviderInstanceCard({
704 <Button699 <Button
705 type="button"700 type="button"
706 size="icon-xs"701 size="icon-xs"
707 variant="ghost"702 variant="ghost-muted"
708 className={cn(
709 "[--control-icon-color:currentColor]",
710 versionAdvisory.emphasis === "strong"
711 ? "text-warning hover:text-warning"
712 : "text-muted-foreground hover:text-foreground",
713 )}
714 aria-label="Update available — view details"703 aria-label="Update available — view details"
715 >704 >
716 <ArrowUpCircleIcon />705 <ArrowUpCircleIcon
706 className={cn(versionAdvisory.emphasis === "strong" && "text-warning")}
707 />
717 </Button>708 </Button>
718 }709 }
719 />710 />
...@@ -793,9 +784,8 @@ export function ProviderInstanceCard({...@@ -793,9 +784,8 @@ export function ProviderInstanceCard({
793 <Button784 <Button
794 type="button"785 type="button"
795 size="icon-xs"786 size="icon-xs"
796 variant="ghost-muted"787 variant="ghost-destructive"
797 disabled={readOnly}788 disabled={readOnly}
798 className="[--control-icon-color:currentColor] hover:text-destructive"
799 onClick={onDelete}789 onClick={onDelete}
800 aria-label={`Delete instance ${instanceId}`}790 aria-label={`Delete instance ${instanceId}`}
801 >791 >
apps/web/src/components/settings/ProviderModelsSection.tsx+2-8
...@@ -312,13 +312,7 @@ export function ProviderModelsSection({...@@ -312,13 +312,7 @@ export function ProviderModelsSection({
312 render={312 render={
313 <Button313 <Button
314 size="icon-micro"314 size="icon-micro"
315 variant="ghost"315 variant="ghost-muted"
316 className={cn(
317 "[--control-icon-color:currentColor]",
318 isFavorite
319 ? "text-yellow-500 hover:text-yellow-600"
320 : "text-muted-foreground/40 hover:text-muted-foreground",
321 )}
322 onClick={() => handleToggleFavorite(model.slug)}316 onClick={() => handleToggleFavorite(model.slug)}
323 aria-label={`${isFavorite ? "Remove" : "Add"} ${model.name} ${317 aria-label={`${isFavorite ? "Remove" : "Add"} ${model.name} ${
324 isFavorite ? "from" : "to"318 isFavorite ? "from" : "to"
...@@ -326,7 +320,7 @@ export function ProviderModelsSection({...@@ -326,7 +320,7 @@ export function ProviderModelsSection({
326 />320 />
327 }321 }
328 >322 >
329 <StarIcon className={cn("size-3", isFavorite && "fill-current")} />323 <StarIcon className={cn("size-3", isFavorite && "fill-current text-warning")} />
330 </TooltipTrigger>324 </TooltipTrigger>
331 <TooltipPopup side="top">325 <TooltipPopup side="top">
332 {isFavorite ? "Remove from favorites" : "Add to favorites"}326 {isFavorite ? "Remove from favorites" : "Add to favorites"}
apps/web/src/components/settings/SettingInheritance.tsx+7-11
...@@ -208,22 +208,18 @@ export function SettingInheritance({...@@ -208,22 +208,18 @@ export function SettingInheritance({
208 size="icon-micro"208 size="icon-micro"
209 variant="ghost-muted"209 variant="ghost-muted"
210 aria-label={`${overrideSummary}. Show where this value comes from`}210 aria-label={`${overrideSummary}. Show where this value comes from`}
211 className={cn(
212 "[--control-icon-color:currentColor]",
213 state === "overridden"
214 ? "text-primary hover:text-primary"
215 : state === "mixed"
216 ? "text-warning hover:text-warning"
217 : state === "environment"
218 ? "text-foreground/70 hover:text-foreground"
219 : "text-muted-foreground/60 hover:text-foreground",
220 )}
221 />211 />
222 }212 }
223 />213 />
224 }214 }
225 >215 >
226 <LayersIcon className="size-3" />216 <LayersIcon
217 className={cn(
218 "size-3",
219 state === "overridden" && "text-primary",
220 state === "mixed" && "text-warning",
221 )}
222 />
227 </TooltipTrigger>223 </TooltipTrigger>
228 <TooltipPopup side="top">{overrideSummary}</TooltipPopup>224 <TooltipPopup side="top">{overrideSummary}</TooltipPopup>
229 </Tooltip>225 </Tooltip>
apps/web/src/components/settings/ThemeSettings.tsx+1-2
...@@ -387,8 +387,7 @@ function ThemeLibraryCard({...@@ -387,8 +387,7 @@ function ThemeLibraryCard({
387 : `Remove ${theme.label}`387 : `Remove ${theme.label}`
388 }388 }
389 size="icon-xs"389 size="icon-xs"
390 variant="ghost"390 variant="ghost-destructive"
391 className="text-muted-foreground hover:text-destructive"
392 onClick={(event) => {391 onClick={(event) => {
393 event.stopPropagation();392 event.stopPropagation();
394 onRemove();393 onRemove();
apps/web/src/components/ui/button.tsx+3-1
...@@ -49,7 +49,9 @@ const buttonVariants = cva(...@@ -49,7 +49,9 @@ const buttonVariants = cva(
49 ghost:49 ghost:
50 "[--control-icon-color:var(--contrast-muted-foreground)] border-transparent text-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",50 "[--control-icon-color:var(--contrast-muted-foreground)] border-transparent text-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
51 "ghost-muted":51 "ghost-muted":
52 "[--control-icon-color:var(--contrast-muted-foreground)] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground",52 "[--control-icon-color:currentColor] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-foreground",
53 "ghost-destructive":
54 "[--control-icon-color:currentColor] border-transparent text-muted-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent [:hover,[data-pressed]]:text-destructive",
53 glass:55 glass:
54 "surface-glass [--control-icon-color:var(--contrast-muted-foreground)] border-border/60 text-foreground shadow-sm [:hover,[data-pressed]]:border-border",56 "surface-glass [--control-icon-color:var(--contrast-muted-foreground)] border-border/60 text-foreground shadow-sm [:hover,[data-pressed]]:border-border",
55 link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",57 link: "border-transparent underline-offset-4 [:hover,[data-pressed]]:underline",
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 = 899;11export const RESTYLE_CEILING = 865;
1212
13const RULE = "shadcn(no-restyle)";13const RULE = "shadcn(no-restyle)";
1414