flagon-io/g1t

public

Git for AI scale: a forge for thousands of agents working on the same code at once.

Commit

Account settings in the same shape as a workspace's

The personal settings page gets the plain title the workspace's pages have, and the sidebar slides over to its sections (SSH keys, access tokens, connected applications) with an arrow back to mission control.

syntaqxcommitted Parent332205dBrowse files
2 files+54−110/2 viewed
+42−3
285285 );
286286 }
287287
288+/** Your own settings, as the sidebar shows them on the settings page. */
289+function AccountSettingsMenu({ open }: { open: boolean }) {
290+ const { hash } = useLocation();
291+ const item = (id: string, icon: ReactNode, label: string) => (
292+ <Link
293+ to={`/settings#${id}`}
294+ className={`group flex h-8 items-center gap-2.5 rounded-md px-2 text-[0.8125rem] transition-colors ${
295+ hash === `#${id}` ? "bg-raised font-medium text-fg" : "text-muted hover:bg-raised/60 hover:text-fg"
296+ }`}
297+ >
298+ <span className="shrink-0 text-faint group-hover:text-muted">{icon}</span>
299+ {label}
300+ </Link>
301+ );
302+ return (
303+ <nav
304+ aria-label="Your settings"
305+ inert={!open}
306+ className={`${SLIDE} ${open ? "translate-x-0 opacity-100" : "pointer-events-none translate-x-full opacity-0"}`}
307+ >
308+ <Link
309+ to="/"
310+ className="group mt-3 flex h-8 items-center gap-2 rounded-md px-2 text-[0.8125rem] text-muted transition-colors hover:bg-raised/60 hover:text-fg"
311+ >
312+ <ArrowLeft size={15} className="text-faint transition-transform group-hover:-translate-x-0.5 group-hover:text-muted" />
313+ Mission control
314+ </Link>
315+ <SidebarGroup title="Account">
316+ {item("ssh-keys", <KeyRound size={15} />, "SSH keys")}
317+ {item("tokens", <Lock size={15} />, "Access tokens")}
318+ {item("applications", <Plug size={15} />, "Connected applications")}
319+ </SidebarGroup>
320+ </nav>
321+ );
322+}
323+
288324 function Sidebar({ user, shell, onFind }: { user: User; shell: ShellData; onFind: () => void }) {
289325 const ws = shell.workspace;
290326 const { pathname } = useLocation();
292328 // On a workspace's settings page, or on the way to one, its settings take
293329 // the sidebar over.
294330 const inSettings = ws != null && SETTINGS_PAGE.exec(going ?? pathname)?.[1]?.toLowerCase() === ws.slug;
331+ const inAccount = (going ?? pathname) === "/settings";
332+ const away = inSettings || inAccount;
295333 const active = shell.repo;
296334 const repoBase = active ? `/${active.namespace}/${active.name}` : null;
297335 // The repository being looked at is listed even when it is someone else's.
325363 <div className="relative min-h-0 grow overflow-hidden">
326364 <nav
327365 aria-label="g1t"
328− inert={inSettings}
329− className={`${SLIDE} ${inSettings ? "pointer-events-none -translate-x-1/3 opacity-0" : "translate-x-0 opacity-100"}`}
366+ inert={away}
367+ className={`${SLIDE} ${away ? "pointer-events-none -translate-x-1/3 opacity-0" : "translate-x-0 opacity-100"}`}
330368 >
331369 <div className="mt-3 space-y-px">
332370 <SidebarLink to="/" end icon={<LayoutDashboard size={15} />}>
438476 </SidebarGroup>
439477 </nav>
440478 {ws && <SettingsMenu slug={ws.slug} owner={ws.role === "owner"} open={inSettings} />}
479+ <AccountSettingsMenu open={inAccount} />
441480 </div>
442481
443482 <div className="space-y-2 p-2">
472511 if (parts.length === 0) return <span className="text-sm font-medium">Mission control</span>;
473512 if (reserved.includes(parts[0]!)) {
474513 const words: Record<string, string> = {
475− settings: "Your settings",
514+ settings: "Account",
476515 explore: "Explore",
477516 new: "New repository",
478517 search: "Search",
+12−8
8080 }: Route.ComponentProps) {
8181 const { user, keys, tokens, applications } = loaderData;
8282 return (
83− <main className="mx-auto max-w-2xl space-y-12 px-4 py-12">
84− <h1 className="text-xl font-semibold">
85− Settings <span className="font-mono text-muted">{user.username}</span>
86− </h1>
87−
88− <section>
83+ <main className="mx-auto max-w-5xl px-4 py-10 sm:px-8">
84+ <header className="mb-8 border-b border-line pb-6">
85+ <h1 className="text-2xl font-semibold tracking-tight">Account</h1>
86+ <p className="mt-1.5 text-sm text-muted">
87+ How <span className="font-mono text-fg">{user.username}</span> signs in from git, tools and agents.
88+ </p>
89+ </header>
90+ <div className="max-w-2xl space-y-12">
91+ <section id="ssh-keys" className="scroll-mt-20">
8992 <h2 className="font-medium">SSH keys</h2>
9093 <ul className="mt-4 divide-y divide-line rounded-md border border-line empty:hidden">
9194 {keys.map((key) => (
113116 </Form>
114117 </section>
115118
116− <section>
119+ <section id="tokens" className="scroll-mt-20">
117120 <h2 className="font-medium">Access tokens</h2>
118121 <p className="mt-1 text-sm text-muted">
119122 Use a token as the password when git asks for one over HTTPS, and to
176179 </Form>
177180 </section>
178181
179− <section>
182+ <section id="applications" className="scroll-mt-20">
180183 <h2 className="font-medium">Connected applications</h2>
181184 <p className="mt-1 text-sm text-muted">
182185 Applications you signed in to through your browser, such as an agent
206209 </ul>
207210 )}
208211 </section>
212+ </div>
209213 </main>
210214 );
211215 }