| author | |
| committer | |
| log | 83bbfa7e87e16a3c21413fe55524c1d05ce88dab |
| tree | d4d6fc2ec60a35b3a97f1db47f30676c40585814 |
| parent | 1c2f933892cce833823fcfbf3099a51813ba67fb |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>12 files changed, 52 insertions(+), 71 deletions(-)
apps/web/src/components/CommandPalette.tsx+2-2| ... | @@ -2874,7 +2874,7 @@ function OpenCommandPaletteDialog(props: { | ... | @@ -2874,7 +2874,7 @@ function OpenCommandPaletteDialog(props: { |
| 2874 | } | 2874 | } |
| 2875 | > | 2875 | > |
| 2876 | <span>{isRemoteProjectPending ? "Working" : remoteProjectButtonLabel}</span> | 2876 | <span>{isRemoteProjectPending ? "Working" : remoteProjectButtonLabel}</span> |
| 2877 | <KbdGroup className="pointer-events-none -me-0.5 items-center gap-1"> | 2877 | <KbdGroup className="pointer-events-none -me-0.5"> |
| 2878 | <Kbd>Enter</Kbd> | 2878 | <Kbd>Enter</Kbd> |
| 2879 | </KbdGroup> | 2879 | </KbdGroup> |
| 2880 | </TooltipTrigger> | 2880 | </TooltipTrigger> |
| ... | @@ -2917,7 +2917,7 @@ function OpenCommandPaletteDialog(props: { | ... | @@ -2917,7 +2917,7 @@ function OpenCommandPaletteDialog(props: { |
| 2917 | <span> | 2917 | <span> |
| 2918 | {isCloneDestinationStep && isRemoteProjectPending ? "Cloning" : submitActionLabel} | 2918 | {isCloneDestinationStep && isRemoteProjectPending ? "Cloning" : submitActionLabel} |
| 2919 | </span> | 2919 | </span> |
| 2920 | <KbdGroup className="pointer-events-none -me-0.5 items-center gap-1"> | 2920 | <KbdGroup className="pointer-events-none -me-0.5"> |
| 2921 | <Kbd>{hasHighlightedBrowseItem ? `${submitModifierLabel} Enter` : "Enter"}</Kbd> | 2921 | <Kbd>{hasHighlightedBrowseItem ? `${submitModifierLabel} Enter` : "Enter"}</Kbd> |
| 2922 | </KbdGroup> | 2922 | </KbdGroup> |
| 2923 | </TooltipTrigger> | 2923 | </TooltipTrigger> |
apps/web/src/components/CommandPaletteContent.tsx+4-4| ... | @@ -52,7 +52,7 @@ export function CommandPaletteContent({ | ... | @@ -52,7 +52,7 @@ export function CommandPaletteContent({ |
| 52 | <CommandPanel className={panelClassName}>{children}</CommandPanel> | 52 | <CommandPanel className={panelClassName}>{children}</CommandPanel> |
| 53 | <CommandFooter className="gap-3 max-sm:flex-col max-sm:items-start"> | 53 | <CommandFooter className="gap-3 max-sm:flex-col max-sm:items-start"> |
| 54 | <div className="flex items-center gap-3"> | 54 | <div className="flex items-center gap-3"> |
| 55 | <KbdGroup className="items-center gap-1.5"> | 55 | <KbdGroup> |
| 56 | <Kbd> | 56 | <Kbd> |
| 57 | <ArrowUpIcon /> | 57 | <ArrowUpIcon /> |
| 58 | </Kbd> | 58 | </Kbd> |
| ... | @@ -62,18 +62,18 @@ export function CommandPaletteContent({ | ... | @@ -62,18 +62,18 @@ export function CommandPaletteContent({ |
| 62 | <span>Navigate</span> | 62 | <span>Navigate</span> |
| 63 | </KbdGroup> | 63 | </KbdGroup> |
| 64 | {footerActionLabel !== undefined ? ( | 64 | {footerActionLabel !== undefined ? ( |
| 65 | <KbdGroup className="items-center gap-1.5"> | 65 | <KbdGroup> |
| 66 | <Kbd>Enter</Kbd> | 66 | <Kbd>Enter</Kbd> |
| 67 | <span>{footerActionLabel}</span> | 67 | <span>{footerActionLabel}</span> |
| 68 | </KbdGroup> | 68 | </KbdGroup> |
| 69 | ) : null} | 69 | ) : null} |
| 70 | {showBackHint ? ( | 70 | {showBackHint ? ( |
| 71 | <KbdGroup className="items-center gap-1.5"> | 71 | <KbdGroup> |
| 72 | <Kbd>Backspace</Kbd> | 72 | <Kbd>Backspace</Kbd> |
| 73 | <span>Back</span> | 73 | <span>Back</span> |
| 74 | </KbdGroup> | 74 | </KbdGroup> |
| 75 | ) : null} | 75 | ) : null} |
| 76 | <KbdGroup className="items-center gap-1.5"> | 76 | <KbdGroup> |
| 77 | <Kbd>Esc</Kbd> | 77 | <Kbd>Esc</Kbd> |
| 78 | <span>{escapeLabel}</span> | 78 | <span>{escapeLabel}</span> |
| 79 | </KbdGroup> | 79 | </KbdGroup> |
apps/web/src/components/LegacySidebar.tsx+5-14| ... | @@ -2673,18 +2673,13 @@ function LocalSecondaryStatus() { | ... | @@ -2673,18 +2673,13 @@ function LocalSecondaryStatus() { |
| 2673 | return ( | 2673 | return ( |
| 2674 | <SidebarGroup> | 2674 | <SidebarGroup> |
| 2675 | {connecting.length > 0 ? ( | 2675 | {connecting.length > 0 ? ( |
| 2676 | <Alert | 2676 | <Alert variant="sidebar"> |
| 2677 | variant="default" | ||
| 2678 | className="rounded-2xl border-border/40 bg-accent/40 text-muted-foreground" | ||
| 2679 | > | ||
| 2680 | <Spinner /> | 2677 | <Spinner /> |
| 2681 | <AlertTitle className="text-xs font-medium text-foreground"> | 2678 | <AlertTitle>Connecting {connecting.join(", ")}</AlertTitle> |
| 2682 | Connecting {connecting.join(", ")} | ||
| 2683 | </AlertTitle> | ||
| 2684 | </Alert> | 2679 | </Alert> |
| 2685 | ) : null} | 2680 | ) : null} |
| 2686 | {failed.length > 0 ? ( | 2681 | {failed.length > 0 ? ( |
| 2687 | <Alert variant="warning" className="rounded-2xl border-warning/40 bg-warning/8"> | 2682 | <Alert variant="warning"> |
| 2688 | <TriangleAlertIcon /> | 2683 | <TriangleAlertIcon /> |
| 2689 | <AlertTitle>Couldn't connect {failed.map((entry) => entry.label).join(", ")}</AlertTitle> | 2684 | <AlertTitle>Couldn't connect {failed.map((entry) => entry.label).join(", ")}</AlertTitle> |
| 2690 | <AlertDescription> | 2685 | <AlertDescription> |
| ... | @@ -2980,11 +2975,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent( | ... | @@ -2980,11 +2975,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent( |
| 2980 | > | 2975 | > |
| 2981 | <SearchIcon /> | 2976 | <SearchIcon /> |
| 2982 | <span className="flex-1 truncate">Search</span> | 2977 | <span className="flex-1 truncate">Search</span> |
| 2983 | {commandPaletteShortcutLabel ? ( | 2978 | {commandPaletteShortcutLabel ? <Kbd>{commandPaletteShortcutLabel}</Kbd> : null} |
| 2984 | <Kbd className="h-4 min-w-0 rounded-sm px-1.5 text-[10px]"> | ||
| 2985 | {commandPaletteShortcutLabel} | ||
| 2986 | </Kbd> | ||
| 2987 | ) : null} | ||
| 2988 | </CommandDialogTrigger> | 2979 | </CommandDialogTrigger> |
| 2989 | </SidebarMenuItem> | 2980 | </SidebarMenuItem> |
| 2990 | </SidebarMenu> | 2981 | </SidebarMenu> |
| ... | @@ -2993,7 +2984,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent( | ... | @@ -2993,7 +2984,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent( |
| 2993 | > | 2984 | > |
| 2994 | {showArm64IntelBuildWarning && arm64IntelBuildWarningDescription ? ( | 2985 | {showArm64IntelBuildWarning && arm64IntelBuildWarningDescription ? ( |
| 2995 | <SidebarGroup> | 2986 | <SidebarGroup> |
| 2996 | <Alert variant="warning" className="rounded-2xl border-warning/40 bg-warning/8"> | 2987 | <Alert variant="warning"> |
| 2997 | <TriangleAlertIcon /> | 2988 | <TriangleAlertIcon /> |
| 2998 | <AlertTitle>Intel build on Apple Silicon</AlertTitle> | 2989 | <AlertTitle>Intel build on Apple Silicon</AlertTitle> |
| 2999 | <AlertDescription>{arm64IntelBuildWarningDescription}</AlertDescription> | 2990 | <AlertDescription>{arm64IntelBuildWarningDescription}</AlertDescription> |
apps/web/src/components/chat/ModelListRow.tsx+1-3| ... | @@ -98,9 +98,7 @@ export const ModelListRow = memo(function ModelListRow(props: { | ... | @@ -98,9 +98,7 @@ export const ModelListRow = memo(function ModelListRow(props: { |
| 98 | {props.showSelection && props.isSelected ? ( | 98 | {props.showSelection && props.isSelected ? ( |
| 99 | <CheckIcon className="size-3.5" aria-hidden="true" /> | 99 | <CheckIcon className="size-3.5" aria-hidden="true" /> |
| 100 | ) : null} | 100 | ) : null} |
| 101 | {props.jumpLabel ? ( | 101 | {props.jumpLabel ? <Kbd>{props.jumpLabel}</Kbd> : null} |
| 102 | <Kbd className="h-4 min-w-0 rounded-sm px-1.5 text-[10px]">{props.jumpLabel}</Kbd> | ||
| 103 | ) : null} | ||
| 104 | <Tooltip> | 102 | <Tooltip> |
| 105 | <TooltipTrigger | 103 | <TooltipTrigger |
| 106 | render={ | 104 | render={ |
apps/web/src/components/chat/ProviderStatusBanner.tsx+24-35| ... | @@ -1,8 +1,8 @@ | ... | @@ -1,8 +1,8 @@ |
| 1 | import { type ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; | 1 | import { type ProviderInstanceId, type ServerProvider } from "@t3tools/contracts"; |
| 2 | import { memo } from "react"; | 2 | import { memo } from "react"; |
| 3 | import { InfoIcon, XIcon } from "lucide-react"; | 3 | import { InfoIcon, XIcon } from "lucide-react"; |
| 4 | import { cn } from "~/lib/utils"; | 4 | import { Alert, AlertAction, AlertDescription, AlertTitle } from "../ui/alert"; |
| 5 | import { Button } from "../ui/button"; | 5 | import { Button, InlineButton } from "../ui/button"; |
| 6 | import { formatProviderDriverKindLabel } from "../../providerModels"; | 6 | import { formatProviderDriverKindLabel } from "../../providerModels"; |
| 7 | import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; | 7 | import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip"; |
| 8 | 8 | ||
| ... | @@ -83,48 +83,37 @@ export const ProviderStatusBanner = memo(function ProviderStatusBanner({ | ... | @@ -83,48 +83,37 @@ export const ProviderStatusBanner = memo(function ProviderStatusBanner({ |
| 83 | 83 | ||
| 84 | return ( | 84 | return ( |
| 85 | <div className="pointer-events-auto mx-auto w-fit max-w-[calc(100%-2rem)] pt-3"> | 85 | <div className="pointer-events-auto mx-auto w-fit max-w-[calc(100%-2rem)] pt-3"> |
| 86 | <div | 86 | <Alert |
| 87 | className={cn( | 87 | variant={status.status === "warning" ? "warning" : "error"} |
| 88 | "alert-glass relative inline-flex items-center gap-3 rounded-xl border py-3 ps-3.5 pe-10 text-card-foreground text-sm", | 88 | surface="glass" |
| 89 | status.status === "warning" | 89 | controlAlignment="first-line" |
| 90 | ? "border-warning/32 [&_svg]:text-warning" | ||
| 91 | : "border-destructive/32 text-destructive-foreground [&_svg]:text-destructive", | ||
| 92 | )} | ||
| 93 | data-variant={status.status === "warning" ? "warning" : "error"} | ||
| 94 | role="alert" | ||
| 95 | > | 90 | > |
| 96 | <InfoIcon className="size-4 shrink-0" aria-hidden /> | 91 | <InfoIcon /> |
| 97 | <div className="flex min-w-0 flex-col gap-1"> | 92 | <AlertTitle>{title}</AlertTitle> |
| 98 | <div className="font-medium">{title}</div> | 93 | <AlertDescription> |
| 99 | <Tooltip> | 94 | <Tooltip> |
| 100 | <TooltipTrigger | 95 | <TooltipTrigger render={<div className="line-clamp-3" />}>{message}</TooltipTrigger> |
| 101 | render={<div className="line-clamp-3 text-muted-foreground">{message}</div>} | ||
| 102 | /> | ||
| 103 | <TooltipPopup side="top" className="whitespace-pre-wrap"> | 96 | <TooltipPopup side="top" className="whitespace-pre-wrap"> |
| 104 | {message} | 97 | {message} |
| 105 | </TooltipPopup> | 98 | </TooltipPopup> |
| 106 | </Tooltip> | 99 | </Tooltip> |
| 107 | {onOpenProviderSetup && hasProviderSetup(status) ? ( | 100 | {onOpenProviderSetup && hasProviderSetup(status) ? ( |
| 108 | <Button | 101 | <InlineButton onClick={() => onOpenProviderSetup(status.instanceId)}> |
| 109 | className="self-start px-0 text-foreground" | ||
| 110 | onClick={() => onOpenProviderSetup(status.instanceId)} | ||
| 111 | size="xs" | ||
| 112 | variant="link" | ||
| 113 | > | ||
| 114 | Open provider setup | 102 | Open provider setup |
| 115 | </Button> | 103 | </InlineButton> |
| 116 | ) : null} | 104 | ) : null} |
| 117 | </div> | 105 | </AlertDescription> |
| 118 | <Button | 106 | <AlertAction> |
| 119 | aria-label={`Dismiss ${providerName} provider ${status.status}`} | 107 | <Button |
| 120 | className="absolute top-2 right-2 size-6" | 108 | aria-label={`Dismiss ${providerName} provider ${status.status}`} |
| 121 | onClick={onDismiss} | 109 | onClick={onDismiss} |
| 122 | size="icon-xs" | 110 | size="icon-xs" |
| 123 | variant="ghost-muted" | 111 | variant="ghost-muted" |
| 124 | > | 112 | > |
| 125 | <XIcon aria-hidden className="size-3.5" /> | 113 | <XIcon /> |
| 126 | </Button> | 114 | </Button> |
| 127 | </div> | 115 | </AlertAction> |
| 116 | </Alert> | ||
| 128 | </div> | 117 | </div> |
| 129 | ); | 118 | ); |
| 130 | }); | 119 | }); |
apps/web/src/components/chat/ThreadErrorBanner.tsx+1-6| ... | @@ -43,12 +43,7 @@ export const ThreadErrorBanner = memo(function ThreadErrorBanner({ | ... | @@ -43,12 +43,7 @@ export const ThreadErrorBanner = memo(function ThreadErrorBanner({ |
| 43 | if (!error) return null; | 43 | if (!error) return null; |
| 44 | return ( | 44 | return ( |
| 45 | <div className="pointer-events-auto mx-auto w-fit max-w-[min(48rem,calc(100%-2rem))] pt-3"> | 45 | <div className="pointer-events-auto mx-auto w-fit max-w-[min(48rem,calc(100%-2rem))] pt-3"> |
| 46 | <Alert | 46 | <Alert variant="error" surface="glass" controlAlignment="first-line"> |
| 47 | variant="error" | ||
| 48 | controlAlignment="first-line" | ||
| 49 | className="alert-glass" | ||
| 50 | data-variant="error" | ||
| 51 | > | ||
| 52 | <CircleAlertIcon /> | 47 | <CircleAlertIcon /> |
| 53 | <AlertDescription> | 48 | <AlertDescription> |
| 54 | <Tooltip> | 49 | <Tooltip> |
apps/web/src/components/desktop/SnapShotShortcutKeys.tsx+1-1| ... | @@ -16,7 +16,7 @@ export function SnapShotShortcutKeys({ | ... | @@ -16,7 +16,7 @@ export function SnapShotShortcutKeys({ |
| 16 | const seen = seenLabels.get(label) ?? 0; | 16 | const seen = seenLabels.get(label) ?? 0; |
| 17 | seenLabels.set(label, seen + 1); | 17 | seenLabels.set(label, seen + 1); |
| 18 | return ( | 18 | return ( |
| 19 | <Kbd aria-hidden className="min-w-6 justify-center px-1.5" key={`${label}-${seen}`}> | 19 | <Kbd aria-hidden key={`${label}-${seen}`}> |
| 20 | {label} | 20 | {label} |
| 21 | </Kbd> | 21 | </Kbd> |
| 22 | ); | 22 | ); |
apps/web/src/components/settings/KeybindingsSettings.tsx+2-2| ... | @@ -79,9 +79,9 @@ function KeybindingPill({ value }: { value: string }) { | ... | @@ -79,9 +79,9 @@ function KeybindingPill({ value }: { value: string }) { |
| 79 | return { part, key: seen === 0 ? part : `${part}-${seen}` }; | 79 | return { part, key: seen === 0 ? part : `${part}-${seen}` }; |
| 80 | }); | 80 | }); |
| 81 | return ( | 81 | return ( |
| 82 | <KbdGroup className="bg-transparent p-0 shadow-none"> | 82 | <KbdGroup> |
| 83 | {parts.map(({ part, key }) => ( | 83 | {parts.map(({ part, key }) => ( |
| 84 | <Kbd key={key} className="min-w-6 justify-center px-1.5"> | 84 | <Kbd key={key}> |
| 85 | {part === "mod" | 85 | {part === "mod" |
| 86 | ? navigator.platform.toLowerCase().includes("mac") | 86 | ? navigator.platform.toLowerCase().includes("mac") |
| 87 | ? "⌘" | 87 | ? "⌘" |
apps/web/src/components/settings/SettingsSidebarNav.tsx+1-1| ... | @@ -275,7 +275,7 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { | ... | @@ -275,7 +275,7 @@ export function SettingsSidebarNav({ pathname }: { pathname: string }) { |
| 275 | <XIcon className="size-3" /> | 275 | <XIcon className="size-3" /> |
| 276 | </Button> | 276 | </Button> |
| 277 | ) : ( | 277 | ) : ( |
| 278 | <Kbd className="h-4 min-w-0 rounded-sm px-1.5 text-[10px]">/</Kbd> | 278 | <Kbd>/</Kbd> |
| 279 | )} | 279 | )} |
| 280 | </div> | 280 | </div> |
| 281 | {isSearching && results.length === 0 ? ( | 281 | {isSearching && results.length === 0 ? ( |
apps/web/src/components/sidebar/SidebarUpdatePill.tsx+1-1| ... | @@ -100,7 +100,7 @@ function SidebarUpdateArchitectureWarningContent() { | ... | @@ -100,7 +100,7 @@ function SidebarUpdateArchitectureWarningContent() { |
| 100 | if (!visible || !description) return null; | 100 | if (!visible || !description) return null; |
| 101 | 101 | ||
| 102 | return ( | 102 | return ( |
| 103 | <Alert variant="warning" className="rounded-2xl border-warning/40 bg-warning/8 text-xs"> | 103 | <Alert variant="warning"> |
| 104 | <TriangleAlertIcon /> | 104 | <TriangleAlertIcon /> |
| 105 | <AlertTitle>Intel build on Apple Silicon</AlertTitle> | 105 | <AlertTitle>Intel build on Apple Silicon</AlertTitle> |
| 106 | <AlertDescription>{description}</AlertDescription> | 106 | <AlertDescription>{description}</AlertDescription> |
apps/web/src/components/ui/alert.tsx+9-1| ... | @@ -6,9 +6,15 @@ import { cn } from "~/lib/utils"; | ... | @@ -6,9 +6,15 @@ import { cn } from "~/lib/utils"; |
| 6 | 6 | ||
| 7 | const alertVariants = cva("relative rounded-xl border px-3.5 py-3 text-card-foreground text-sm", { | 7 | const alertVariants = cva("relative rounded-xl border px-3.5 py-3 text-card-foreground text-sm", { |
| 8 | defaultVariants: { | 8 | defaultVariants: { |
| 9 | surface: "default", | ||
| 9 | variant: "default", | 10 | variant: "default", |
| 10 | }, | 11 | }, |
| 11 | variants: { | 12 | variants: { |
| 13 | // "glass" floats the alert over content; alert-glass tints from data-variant. | ||
| 14 | surface: { | ||
| 15 | default: "", | ||
| 16 | glass: "alert-glass", | ||
| 17 | }, | ||
| 12 | variant: { | 18 | variant: { |
| 13 | default: "bg-transparent dark:bg-input/32 [&_svg]:text-muted-foreground", | 19 | default: "bg-transparent dark:bg-input/32 [&_svg]:text-muted-foreground", |
| 14 | sidebar: | 20 | sidebar: |
| ... | @@ -45,6 +51,7 @@ function alertChildSlot(child: React.ReactElement): string | undefined { | ... | @@ -45,6 +51,7 @@ function alertChildSlot(child: React.ReactElement): string | undefined { |
| 45 | function Alert({ | 51 | function Alert({ |
| 46 | className, | 52 | className, |
| 47 | variant, | 53 | variant, |
| 54 | surface, | ||
| 48 | controlAlignment = "center", | 55 | controlAlignment = "center", |
| 49 | children, | 56 | children, |
| 50 | ...props | 57 | ...props |
| ... | @@ -73,8 +80,9 @@ function Alert({ | ... | @@ -73,8 +80,9 @@ function Alert({ |
| 73 | 80 | ||
| 74 | return ( | 81 | return ( |
| 75 | <div | 82 | <div |
| 76 | className={cn(alertVariants({ variant }), className)} | 83 | className={cn(alertVariants({ surface, variant }), className)} |
| 77 | data-slot="alert" | 84 | data-slot="alert" |
| 85 | data-variant={variant ?? "default"} | ||
| 78 | role="alert" | 86 | role="alert" |
| 79 | {...props} | 87 | {...props} |
| 80 | > | 88 | > |
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 the | 8 | // 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 you | 9 | // 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. |
| 11 | export const RESTYLE_CEILING = 668; | 11 | export const RESTYLE_CEILING = 628; |
| 12 | 12 | ||
| 13 | const RULE = "shadcn(no-restyle)"; | 13 | const RULE = "shadcn(no-restyle)"; |
| 14 | 14 |