diff --git a/ui/src/components/NewIssueDialog.tsx b/ui/src/components/NewIssueDialog.tsx index 2881a7dc..95d30d2b 100644 --- a/ui/src/components/NewIssueDialog.tsx +++ b/ui/src/components/NewIssueDialog.tsx @@ -24,6 +24,7 @@ import { DialogContent, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { Popover, PopoverContent, @@ -1208,21 +1209,10 @@ export function NewIssueDialog() { {assigneeAdapterType === "claude_local" && (
Enable Chrome (--chrome)
- + setAssigneeChrome((value) => !value)} + />
)} diff --git a/ui/src/components/ProjectProperties.tsx b/ui/src/components/ProjectProperties.tsx index 6574091c..a13eb3cc 100644 --- a/ui/src/components/ProjectProperties.tsx +++ b/ui/src/components/ProjectProperties.tsx @@ -16,6 +16,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { AlertCircle, Archive, ArchiveRestore, Check, ExternalLink, Github, Loader2, Plus, Trash2, X } from "lucide-react"; import { ChoosePathButton } from "./PathInstructionsModal"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { DraftInput } from "./agent-config-primitives"; import { InlineEditor } from "./InlineEditor"; @@ -886,26 +887,14 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa {onUpdate || onFieldUpdate ? ( - + /> ) : ( {executionWorkspacesEnabled ? "Enabled" : "Disabled"} @@ -925,14 +914,9 @@ export function ProjectProperties({ project, onUpdate, onFieldUpdate, getFieldSa If disabled, new issues stay on the project's primary checkout unless someone opts in. - + />
diff --git a/ui/src/components/agent-config-primitives.tsx b/ui/src/components/agent-config-primitives.tsx index 76b3aef0..5c4c1491 100644 --- a/ui/src/components/agent-config-primitives.tsx +++ b/ui/src/components/agent-config-primitives.tsx @@ -4,6 +4,7 @@ import { TooltipTrigger, TooltipContent, } from "@/components/ui/tooltip"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { Dialog, DialogContent, @@ -111,23 +112,11 @@ export function ToggleField({ {label} {hint && }
- + /> ); } @@ -162,21 +151,10 @@ export function ToggleWithNumber({ {label} {hint && } - + {showNumber && (
diff --git a/ui/src/components/ui/toggle-switch.tsx b/ui/src/components/ui/toggle-switch.tsx new file mode 100644 index 00000000..d4995f25 --- /dev/null +++ b/ui/src/components/ui/toggle-switch.tsx @@ -0,0 +1,59 @@ +import * as React from "react"; +import { cn } from "@/lib/utils"; + +export interface ToggleSwitchProps + extends Omit, "onChange"> { + checked: boolean; + onCheckedChange: (checked: boolean) => void; + size?: "default" | "lg"; +} + +export const ToggleSwitch = React.forwardRef< + HTMLButtonElement, + ToggleSwitchProps +>( + ( + { checked, onCheckedChange, size = "default", className, disabled, ...props }, + ref, + ) => { + const isLg = size === "lg"; + + return ( + + ); + }, +); + +ToggleSwitch.displayName = "ToggleSwitch"; diff --git a/ui/src/pages/AgentDetail.tsx b/ui/src/pages/AgentDetail.tsx index 40d342c7..caa90578 100644 --- a/ui/src/pages/AgentDetail.tsx +++ b/ui/src/pages/AgentDetail.tsx @@ -25,6 +25,7 @@ import { queryKeys } from "../lib/queryKeys"; import { AgentConfigForm } from "../components/AgentConfigForm"; import { PageTabBar } from "../components/PageTabBar"; import { adapterLabels, roleLabels, help } from "../components/agent-config-primitives"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { MarkdownEditor } from "../components/MarkdownEditor"; import { assetsApi } from "../api/assets"; import { getUIAdapter, buildTranscript, onAdapterChange } from "../adapters"; @@ -1627,30 +1628,16 @@ function ConfigurationTab({ Lets this agent create or hire agents and implicitly assign tasks.

- + />
@@ -1659,30 +1646,16 @@ function ConfigurationTab({ {taskAssignHint}

- + />
diff --git a/ui/src/pages/InstanceExperimentalSettings.tsx b/ui/src/pages/InstanceExperimentalSettings.tsx index 050166ff..753ab5fd 100644 --- a/ui/src/pages/InstanceExperimentalSettings.tsx +++ b/ui/src/pages/InstanceExperimentalSettings.tsx @@ -4,7 +4,7 @@ import { FlaskConical } from "lucide-react"; import { instanceSettingsApi } from "@/api/instanceSettings"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { queryKeys } from "../lib/queryKeys"; -import { cn } from "../lib/utils"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; export function InstanceExperimentalSettings() { const { setBreadcrumbs } = useBreadcrumbs(); @@ -82,24 +82,12 @@ export function InstanceExperimentalSettings() { and existing issue runs.

- + aria-label="Toggle isolated workspaces experimental setting" + /> @@ -112,26 +100,12 @@ export function InstanceExperimentalSettings() { automatically when backend changes or migrations make the current boot stale.

- + aria-label="Toggle guarded dev-server auto-restart" + /> diff --git a/ui/src/pages/InstanceGeneralSettings.tsx b/ui/src/pages/InstanceGeneralSettings.tsx index 923c8cb8..28e00b29 100644 --- a/ui/src/pages/InstanceGeneralSettings.tsx +++ b/ui/src/pages/InstanceGeneralSettings.tsx @@ -7,6 +7,7 @@ import { instanceSettingsApi } from "@/api/instanceSettings"; import { Button } from "../components/ui/button"; import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { queryKeys } from "../lib/queryKeys"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { cn } from "../lib/utils"; const FEEDBACK_TERMS_URL = import.meta.env.VITE_FEEDBACK_TERMS_URL?.trim() || "https://paperclip.ing/tos"; @@ -95,28 +96,12 @@ export function InstanceGeneralSettings() { default.

- + aria-label="Toggle username log censoring" + /> @@ -129,24 +114,12 @@ export function InstanceGeneralSettings() { toggling panels. This is off by default.

- + aria-label="Toggle keyboard shortcuts" + /> diff --git a/ui/src/pages/RoutineDetail.tsx b/ui/src/pages/RoutineDetail.tsx index 55dc32f4..c1ca92e7 100644 --- a/ui/src/pages/RoutineDetail.tsx +++ b/ui/src/pages/RoutineDetail.tsx @@ -27,6 +27,7 @@ import { useToast } from "../context/ToastContext"; import { queryKeys } from "../lib/queryKeys"; import { buildRoutineTriggerPatch } from "../lib/routine-trigger-patch"; import { timeAgo } from "../lib/timeAgo"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { EmptyState } from "../components/EmptyState"; import { PageSkeleton } from "../components/PageSkeleton"; import { AgentIcon } from "../components/AgentIconPicker"; @@ -710,24 +711,13 @@ export function RoutineDetail() { }} disabled={runRoutine.isPending} /> - + aria-label={automationEnabled ? "Pause automatic triggers" : "Enable automatic triggers"} + /> {automationLabel} diff --git a/ui/src/pages/Routines.tsx b/ui/src/pages/Routines.tsx index fc856d72..b58cea8c 100644 --- a/ui/src/pages/Routines.tsx +++ b/ui/src/pages/Routines.tsx @@ -11,6 +11,7 @@ import { useBreadcrumbs } from "../context/BreadcrumbContext"; import { useToast } from "../context/ToastContext"; import { queryKeys } from "../lib/queryKeys"; import { getRecentAssigneeIds, sortAgentsByRecency, trackRecentAssignee } from "../lib/recent-assignees"; +import { ToggleSwitch } from "@/components/ui/toggle-switch"; import { EmptyState } from "../components/EmptyState"; import { PageSkeleton } from "../components/PageSkeleton"; import { AgentIcon } from "../components/AgentIconPicker"; @@ -640,29 +641,18 @@ export function Routines() { e.stopPropagation()}>
- + disabled={isStatusPending || isArchived} + aria-label={enabled ? `Disable ${routine.title}` : `Enable ${routine.title}`} + /> {isArchived ? "Archived" : enabled ? "On" : "Off"}