Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

38 linesCodeBlameRaw
1import { useEffect } from "react";
2import { Outlet, useLocation } from "react-router";
3import { usePageNavigation } from "../../lib/use-page-navigation";
4
5import { ACCOUNT_SETTINGS, accountSettingsPage, settingsPathForHash } from "../../lib/account-settings";
6
7/**
8 * Your settings: each page under `/settings/<page>`, listed in the sidebar.
9 * The heading is named from the address.
10 *
11 * The settings used to be one page with a section per `#anchor`. A server
12 * never sees the anchor, so an old link (`/settings#emails`) arrives at the
13 * first page with the anchor still on it, and is sent on to its own page
14 * from here.
15 */
16export default function SettingsLayout() {
17 const { pathname, hash } = useLocation();
18 const { navigate } = usePageNavigation();
19 useEffect(() => {
20 const to = settingsPathForHash(hash);
21 if (to && to !== pathname) navigate(to, { replace: true });
22 }, [hash, pathname, navigate]);
23 const page = accountSettingsPage(pathname);
24 const about = page ? ACCOUNT_SETTINGS[page] : null;
25 return (
26 <main className="mx-auto max-w-5xl px-4 py-10 sm:px-8">
27 {about && (
28 <header className="mb-8 border-b border-line pb-5">
29 <h1 className="text-lg font-semibold tracking-tight">{about.heading ?? about.title}</h1>
30 <p className="mt-1 max-w-2xl text-sm text-muted">{about.about}</p>
31 </header>
32 )}
33 <div className="max-w-2xl">
34 <Outlet />
35 </div>
36 </main>
37 );
38}