authorgravatar for zortosdev@proton.meZortos <zortosdev@proton.me> 2026-03-13 03:26:14+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-03-12 19:26:14-07:00
log36473f7de6f32bb2765e0ad2b08e2a0c2e737d63
tree0e6425d18689ab713e341213387763824261da1a
parenta14debc83e04ee4b28d9e3eb830f0cf74d489f93
signature Signed by PGP key B5690EEEBB952194

feat: replace worktree toggle with discoverable Select dropdown (#1001)

Co-authored-by: Julius Marminge <julius0216@outlook.com>

2 files changed, 52 insertions(+), 17 deletions(-)

apps/web/src/components/BranchToolbar.tsx+51-17
......@@ -1,4 +1,5 @@
11import type { ThreadId } from "@t3tools/contracts";
2import { FolderIcon, GitForkIcon } from "lucide-react";
23import { useCallback } from "react";
34
45import { newCommandId } from "../lib/utils";
......@@ -11,8 +12,14 @@ import {
1112 resolveEffectiveEnvMode,
1213} from "./BranchToolbar.logic";
1314import { BranchToolbarBranchSelector } from "./BranchToolbarBranchSelector";
15import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "./ui/select";
1416import { Button } from "./ui/button";
1517
18const envModeItems = [
19 { value: "local", label: "Local" },
20 { value: "worktree", label: "New worktree" },
21] as const;
22
1623interface BranchToolbarProps {
1724 threadId: ThreadId;
1825 onEnvModeChange: (mode: EnvMode) => void;
......@@ -104,23 +111,50 @@ export default function BranchToolbar({
104111
105112 return (
106113 <div className="mx-auto flex w-full max-w-3xl items-center justify-between px-5 pb-3 pt-1">
107 <div className="flex items-center gap-2">
108 {envLocked || activeWorktreePath ? (
109 <span className="border border-transparent px-[calc(--spacing(2)-1px)] text-sm font-medium text-muted-foreground/70 sm:text-xs">
110 {activeWorktreePath ? "Worktree" : "Local"}
111 </span>
112 ) : (
113 <Button
114 type="button"
115 variant="ghost"
116 className="text-muted-foreground/70 hover:text-foreground/80"
117 size="xs"
118 onClick={() => onEnvModeChange(effectiveEnvMode === "local" ? "worktree" : "local")}
119 >
120 {effectiveEnvMode === "worktree" ? "New worktree" : "Local"}
121 </Button>
122 )}
123 </div>
114 {envLocked || activeWorktreePath ? (
115 <span className="inline-flex items-center gap-1 border border-transparent px-[calc(--spacing(3)-1px)] text-sm font-medium text-muted-foreground/70 sm:text-xs">
116 {activeWorktreePath ? (
117 <>
118 <GitForkIcon className="size-3" />
119 Worktree
120 </>
121 ) : (
122 <>
123 <FolderIcon className="size-3" />
124 Local
125 </>
126 )}
127 </span>
128 ) : (
129 <Select
130 value={effectiveEnvMode}
131 onValueChange={(value) => onEnvModeChange(value as EnvMode)}
132 items={envModeItems}
133 >
134 <SelectTrigger variant="ghost" size="xs" className="font-medium">
135 {effectiveEnvMode === "worktree" ? (
136 <GitForkIcon className="size-3" />
137 ) : (
138 <FolderIcon className="size-3" />
139 )}
140 <SelectValue />
141 </SelectTrigger>
142 <SelectPopup>
143 <SelectItem value="local">
144 <span className="inline-flex items-center gap-1.5">
145 <FolderIcon className="size-3" />
146 Local
147 </span>
148 </SelectItem>
149 <SelectItem value="worktree">
150 <span className="inline-flex items-center gap-1.5">
151 <GitForkIcon className="size-3" />
152 New worktree
153 </span>
154 </SelectItem>
155 </SelectPopup>
156 </Select>
157 )}
124158
125159 <BranchToolbarBranchSelector
126160 activeProjectCwd={activeProject.cwd}
apps/web/src/components/ui/select.tsx+1
......@@ -29,6 +29,7 @@ const selectTriggerVariants = cva(
2929 default: "min-h-9 px-[calc(--spacing(3)-1px)] sm:min-h-8",
3030 lg: "min-h-10 px-[calc(--spacing(3)-1px)] sm:min-h-9",
3131 sm: "min-h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:min-h-7",
32 xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5",
3233 },
3334 },
3435 },