Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions apps/web/src/components/DiffPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -800,8 +800,9 @@ export default function DiffPanel({
</Tooltip>
)}
<ToggleGroup
className="shrink-0 gap-1"
size="sm"
aria-label="Diff layout"
className="shrink-0"
variant="segmented"
value={[diffLayout]}
onValueChange={(value) => {
const next = value[0];
Expand All @@ -810,10 +811,10 @@ export default function DiffPanel({
}
}}
>
<Toggle aria-label="Stacked diff view" value="stacked" variant="ghost">
<Toggle aria-label="Stacked diff view" value="stacked">
<Rows3Icon className="size-3.5" />
</Toggle>
<Toggle aria-label="Split diff view" value="split" variant="ghost">
<Toggle aria-label="Split diff view" value="split">
<Columns2Icon className="size-3.5" />
</Toggle>
</ToggleGroup>
Expand Down
38 changes: 13 additions & 25 deletions apps/web/src/components/GitActionsControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { Radio as RadioPrimitive } from "@base-ui/react/radio";
import { AzureDevOpsIcon, BitbucketIcon, GitHubIcon, GitLabIcon } from "~/components/Icons";
import { RadioGroup } from "~/components/ui/radio-group";
import { Spinner } from "~/components/ui/spinner";
import { Toggle, ToggleGroup } from "~/components/ui/toggle-group";
import { cn } from "~/lib/utils";
import {
buildGitActionProgressStages,
Expand Down Expand Up @@ -830,34 +831,21 @@ function PublishRepositoryDialog(props: PublishRepositoryDialogProps) {
>
Protocol
</span>
<RadioGroup
value={publishProtocol}
onValueChange={(value) =>
setPublishProtocol(value as SourceControlCloneProtocol)
}
<ToggleGroup
Comment thread
macroscopeapp[bot] marked this conversation as resolved.
Outdated
variant="segmented"
value={[publishProtocol]}
onValueChange={(next) => {
const protocol = next[0];
if (protocol === "ssh" || protocol === "https") {
setPublishProtocol(protocol);
}
}}
aria-labelledby="publish-protocol-label"
disabled={publishRepositoryAction.isPending}
className="grid grid-cols-2 gap-2"
>
{(["ssh", "https"] as const).map((value) => {
const isSelected = publishProtocol === value;
return (
<RadioPrimitive.Root
key={value}
value={value}
className={cn(
"rounded-md border px-3 py-1.5 text-center text-sm font-medium outline-none transition",
"focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
isSelected
? "border-primary bg-background ring-2 ring-primary/35 text-foreground dark:border-transparent dark:bg-primary/10 dark:ring-1 dark:ring-primary/30"
: "border-border bg-background text-muted-foreground hover:border-foreground/20 hover:text-foreground dark:border-transparent dark:bg-white/[0.035]",
)}
>
{value === "ssh" ? "SSH" : "HTTPS"}
</RadioPrimitive.Root>
);
})}
</RadioGroup>
<Toggle value="ssh">SSH</Toggle>
<Toggle value="https">HTTPS</Toggle>
</ToggleGroup>
</div>
</div>
) : null}
Expand Down
9 changes: 5 additions & 4 deletions apps/web/src/components/pullRequest/PullRequestCodeTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1138,8 +1138,9 @@ export function PullRequestCodeTab({
</Tooltip>
) : null}
<ToggleGroup
className="shrink-0 gap-1"
size="sm"
aria-label="Diff layout"
className="shrink-0"
variant="segmented"
value={[diffLayout]}
onValueChange={(value) => {
const next = value[0];
Expand All @@ -1148,10 +1149,10 @@ export function PullRequestCodeTab({
}
}}
>
<Toggle aria-label="Stacked diff view" value="stacked" variant="ghost">
<Toggle aria-label="Stacked diff view" value="stacked">
<Rows3Icon className="size-3.5" />
</Toggle>
<Toggle aria-label="Split diff view" value="split" variant="ghost">
<Toggle aria-label="Split diff view" value="split">
<Columns2Icon className="size-3.5" />
</Toggle>
</ToggleGroup>
Expand Down
32 changes: 14 additions & 18 deletions apps/web/src/components/pullRequest/PullRequestMarkdownEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { cn } from "~/lib/utils";

import { Button } from "../ui/button";
import { Textarea } from "../ui/textarea";
import { Toggle, ToggleGroup } from "../ui/toggle-group";
import { PullRequestMarkdown } from "./PullRequestMarkdown";

/**
Expand Down Expand Up @@ -64,24 +65,19 @@ export function PullRequestMarkdownEditor({
onCancel();
}}
>
<div className="flex items-center gap-1">
<Button
size="xs"
variant={preview ? "ghost" : "outline"}
disabled={saving}
onClick={() => setPreview(false)}
>
Write
</Button>
<Button
size="xs"
variant={preview ? "outline" : "ghost"}
disabled={saving}
onClick={() => setPreview(true)}
>
Preview
</Button>
</div>
<ToggleGroup
aria-label="Markdown editor mode"
variant="segmented"
value={[preview ? "preview" : "write"]}
disabled={saving}
onValueChange={(next) => {
const mode = next[0];
if (mode === "write" || mode === "preview") setPreview(mode === "preview");
}}
>
<Toggle value="write">Write</Toggle>
<Toggle value="preview">Preview</Toggle>
</ToggleGroup>
{preview ? (
<div className="rounded-lg border border-border/60 px-3 py-2">
{empty ? (
Expand Down
27 changes: 15 additions & 12 deletions apps/web/src/components/settings/DiagnosticsSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { usePrimaryEnvironment } from "../../state/environments";
import { useCopyToClipboard } from "../../hooks/useCopyToClipboard";
import { Button } from "../ui/button";
import { ScrollArea } from "../ui/scroll-area";
import { Toggle, ToggleGroup } from "../ui/toggle-group";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { toastManager } from "../ui/toast";
import { ExpandableText } from "./ExpandableText";
Expand Down Expand Up @@ -599,21 +600,23 @@ function ResourceHistoryWindowSelector({
onSelect: (windowMs: number) => void;
}) {
return (
<div className="flex items-center rounded-md border border-border/60 p-0.5">
<ToggleGroup
aria-label="Process history period"
variant="segmented"
value={[String(selectedWindowMs)]}
onValueChange={(next) => {
const selected = RESOURCE_HISTORY_WINDOWS.find(
(option) => String(option.windowMs) === next[0],
);
if (selected) onSelect(selected.windowMs);
}}
>
{RESOURCE_HISTORY_WINDOWS.map((option) => (
<button
key={option.windowMs}
type="button"
className={cn(
"cursor-pointer h-6 rounded-sm px-2 text-[11px] font-medium text-muted-foreground hover:text-foreground",
selectedWindowMs === option.windowMs && "bg-muted text-foreground",
)}
onClick={() => onSelect(option.windowMs)}
>
<Toggle key={option.windowMs} value={String(option.windowMs)}>
{option.label}
</button>
</Toggle>
))}
</div>
</ToggleGroup>
);
}

Expand Down
25 changes: 14 additions & 11 deletions apps/web/src/components/settings/ProviderSettingsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import {
NumberFieldInput,
} from "../ui/number-field";
import { ScrollArea } from "../ui/scroll-area";
import { Toggle, ToggleGroup } from "../ui/toggle-group";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { stackedThreadToast, toastManager } from "../ui/toast";
import { AddProviderInstanceDialog } from "./AddProviderInstanceDialog";
Expand All @@ -80,7 +81,6 @@ import { ProviderInstanceCard } from "./ProviderInstanceCard";
import { UsageProviderSettings } from "./UsageProviderSettings";
import { ProviderSetupSection, readAntigravityAuthMethod } from "./ProviderSetupSection";
import { DRIVER_OPTIONS, getDriverOption } from "./providerDriverMeta";
import { providerSettingsTabClassName } from "./providerSettingsTabs";
import { searchableSetting } from "./settingsSearch";
import {
backgroundActivityOverrideSettings,
Expand Down Expand Up @@ -326,22 +326,25 @@ function ProviderSettingsPanelContent(target: ProviderSettingsTarget) {
const deviceTabs =
!onlyPrimaryDevice && options.length > 0 ? (
<ScrollArea hideScrollbars scrollFade className="h-11 min-w-0 flex-1 rounded-none">
<div role="group" aria-label="Devices" className="flex h-full w-max min-w-full px-1">
<ToggleGroup
aria-label="Devices"
variant="segmented"
className="my-2"
value={effectiveEnvironmentId ? [effectiveEnvironmentId] : []}
onValueChange={(next) => {
const environment = options.find((option) => option.environmentId === next[0]);
if (environment) setSelectedEnvironmentId(environment.environmentId);
}}
>
{options.map((environment) => {
const machine = resolveEnvironmentMachineKind(environment.serverConfig);
const selected = environment.environmentId === effectiveEnvironmentId;
const detail = providerEnvironmentDetail(environment);
const statusText = connectionStatusTitle(environment.connection);
return (
<Tooltip key={environment.environmentId}>
<TooltipTrigger
render={
<button
type="button"
aria-pressed={selected}
className={cn(providerSettingsTabClassName(selected), "gap-2 text-left")}
onClick={() => setSelectedEnvironmentId(environment.environmentId)}
>
<Toggle value={environment.environmentId} className="gap-2 text-left">
<EnvironmentMachineIcon
kind={machine}
className="size-3.5 shrink-0"
Expand All @@ -357,7 +360,7 @@ function ProviderSettingsPanelContent(target: ProviderSettingsTarget) {
<span className="sr-only">
{detail}, {statusText}
</span>
</button>
</Toggle>
}
/>
<TooltipPopup side="top">
Expand All @@ -366,7 +369,7 @@ function ProviderSettingsPanelContent(target: ProviderSettingsTarget) {
</Tooltip>
);
})}
</div>
</ToggleGroup>
</ScrollArea>
) : null;

Expand Down
25 changes: 13 additions & 12 deletions apps/web/src/components/settings/ResourceTelemetryDiagnostics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { useAtomCommand } from "../../state/use-atom-command";
import { formatRelativeTime } from "../../timestampFormat";
import { Button } from "../ui/button";
import { ScrollArea } from "../ui/scroll-area";
import { Toggle, ToggleGroup } from "../ui/toggle-group";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { toastManager } from "../ui/toast";
import {
Expand Down Expand Up @@ -378,21 +379,21 @@ function HistoryWindowSelector({
onSelect: (windowMs: number) => void;
}) {
return (
<div className="flex items-center rounded-md border border-border/60 p-0.5">
<ToggleGroup
aria-label="Resource history period"
variant="segmented"
value={[String(selectedWindowMs)]}
onValueChange={(next) => {
const selected = HISTORY_WINDOWS.find((option) => String(option.windowMs) === next[0]);
if (selected) onSelect(selected.windowMs);
}}
>
{HISTORY_WINDOWS.map((option) => (
<button
key={option.windowMs}
type="button"
className={cn(
"cursor-pointer h-6 rounded-sm px-2 text-[11px] font-medium text-muted-foreground hover:text-foreground",
selectedWindowMs === option.windowMs && "bg-muted text-foreground",
)}
onClick={() => onSelect(option.windowMs)}
>
<Toggle key={option.windowMs} value={String(option.windowMs)}>
{option.label}
</button>
</Toggle>
))}
</div>
</ToggleGroup>
);
}

Expand Down
31 changes: 19 additions & 12 deletions apps/web/src/components/settings/ThemeEditorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { cn } from "../../lib/utils";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import { Switch } from "../ui/switch";
import { Toggle, ToggleGroup } from "../ui/toggle-group";
import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
import { getThemeRoleLabel, ThemeColorField } from "./ThemeColorPicker";
import {
Expand Down Expand Up @@ -942,24 +943,17 @@ export function ThemeEditorPanel({
);

const renderAppearanceButton = (appearance: ThemeAppearance) => {
const isActive = activeAppearance === appearance;
const lockReason = appearanceLockReason(appearance);
// A locked mode stays hoverable so the tooltip can say why it is off;
// a real disabled attribute would swallow the pointer events.
const button = (
<Button
<Toggle
aria-disabled={lockReason !== null}
aria-pressed={isActive}
size="sm"
value={appearance}
className={lockReason !== null ? "opacity-50" : undefined}
style={isActive ? { boxShadow: "inset 0 0 0 1px var(--ring)" } : undefined}
variant={isActive ? "secondary" : "outline"}
onClick={() => {
if (lockReason === null) setActiveAppearance(appearance);
}}
>
{appearance === "light" ? "Light" : "Dark"}
</Button>
</Toggle>
);
if (lockReason === null) return button;
return (
Expand All @@ -973,10 +967,23 @@ export function ThemeEditorPanel({
const renderAppearanceButtons = () => (
<div className="grid grid-cols-[minmax(0,1fr)_minmax(0,2fr)] items-center gap-3">
<span className="text-sm font-medium">Appearance</span>
<div aria-label="Theme appearance" className="grid grid-cols-2 gap-2" role="group">
<ToggleGroup
aria-label="Theme appearance"
variant="segmented"
value={[activeAppearance]}
onValueChange={(next) => {
const appearance = next[0];
if (
(appearance === "light" || appearance === "dark") &&
appearanceLockReason(appearance) === null
) {
setActiveAppearance(appearance);
}
}}
>
{renderAppearanceButton("light")}
{renderAppearanceButton("dark")}
</div>
</ToggleGroup>
</div>
);

Expand Down
10 changes: 0 additions & 10 deletions apps/web/src/components/settings/providerSettingsTabs.ts

This file was deleted.

2 changes: 1 addition & 1 deletion apps/web/src/components/ui/toggle-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const ToggleGroupContext = React.createContext<VariantProps<typeof toggleVariant

function ToggleGroup({
className,
variant = "default",
variant = "segmented",
size = variant === "segmented" ? "segmented" : "default",
orientation = "horizontal",
children,
Expand Down
Loading