Not found and error pages have one main landmark: their own when signed out, the shell's when signed in
4 files+22−70/4 viewed
| 1 | + | import { type ComponentProps, createContext, useContext } from "react"; | |
| 2 | + | ||
| 3 | + | /** True inside the app shell, whose `<main id="content">` already holds the page. */ | |
| 4 | + | export const InMain = createContext(false); | |
| 5 | + | ||
| 6 | + | /** | |
| 7 | + | * A page's main landmark: `<main>` where nothing above is one (signed out), | |
| 8 | + | * a plain `<div>` inside the shell, so a page never has two. | |
| 9 | + | */ | |
| 10 | + | export function PageMain(props: ComponentProps<"main">) { | |
| 11 | + | return useContext(InMain) ? <div {...props} /> : <main {...props} />; | |
| 12 | + | } |
| 5 | 5 | import { withNext } from "../lib/next"; | |
| 6 | 6 | import { useSignUpCopy } from "../lib/registration"; | |
| 7 | 7 | import { missingKind, notFoundCopy } from "../lib/not-found"; | |
| 8 | + | import { PageMain } from "./landmark"; | |
| 8 | 9 | import { Pixel404 } from "./logo"; | |
| 9 | 10 | import { ButtonLink, SubmitButton } from "./ui"; | |
| 10 | 11 | ||
| ⋯ | |||
| 29 | 30 | const here = pathname + search; | |
| 30 | 31 | const signUp = useSignUpCopy(); | |
| 31 | 32 | return ( | |
| 32 | − | <main className="mx-auto flex max-w-lg flex-col items-center px-4 py-20 text-center sm:py-28"> | |
| 33 | + | <PageMain className="mx-auto flex max-w-lg flex-col items-center px-4 py-20 text-center sm:py-28"> | |
| 33 | 34 | <Pixel404 className="text-[3.5rem] sm:text-[4.5rem]" /> | |
| 34 | 35 | <h1 className="mt-10 text-balance text-2xl font-semibold tracking-tight">{copy.title}</h1> | |
| 35 | 36 | <p className="mt-2 text-balance text-muted">{copy.body}</p> | |
| ⋯ | |||
| 82 | 83 | </SubmitButton> | |
| 83 | 84 | </Form> | |
| 84 | 85 | )} | |
| 85 | − | </main> | |
| 86 | + | </PageMain> | |
| 86 | 87 | ); | |
| 87 | 88 | } | |
| 4 | 4 | ||
| 5 | 5 | import { type Abilities, type InboxCounts, type Membership, type Spike, type User, mayCreateTeams } from "@g1t/contracts"; | |
| 6 | 6 | ||
| 7 | + | import { InMain } from "./landmark"; | |
| 7 | 8 | import { CommandPalette, type PaletteCommand, PaletteKey, usePaletteShortcut } from "./command-palette"; | |
| 8 | 9 | import { AgentButton, InboxBell } from "./inbox"; | |
| 9 | 10 | import { PinButton } from "./pin-button"; | |
| ⋯ | |||
| 1915 | 1916 | </header> | |
| 1916 | 1917 | {banner} | |
| 1917 | 1918 | <main id="content" tabIndex={-1} {...leaving} className={`min-w-0 grow outline-none ${leaving.className}`}> | |
| 1918 | − | {children} | |
| 1919 | + | <InMain.Provider value={true}>{children}</InMain.Provider> | |
| 1919 | 1920 | </main> | |
| 1920 | 1921 | </div> | |
| 1921 | 1922 | <CommandPalette | |
| 53 | 53 | import { PolicyNotice } from "./components/policy-notice"; | |
| 54 | 54 | import { readCookie } from "./lib/mission"; | |
| 55 | 55 | import { WORKSPACE_COOKIE, workspaceFor } from "./lib/workspace-choice"; | |
| 56 | + | import { PageMain } from "./components/landmark"; | |
| 56 | 57 | import { NotFound } from "./components/not-found"; | |
| 57 | 58 | import { usesAppShell } from "./lib/chrome"; | |
| 58 | 59 | import { CommandPalette, type PaletteCommand, PaletteKey, usePaletteShortcut } from "./components/command-palette"; | |
| ⋯ | |||
| 578 | 579 | }, [reload, href]); | |
| 579 | 580 | if (reload) { | |
| 580 | 581 | return ( | |
| 581 | − | <main className="mx-auto max-w-xl px-4 py-32 text-center text-sm text-muted" aria-busy="true"> | |
| 582 | + | <PageMain className="mx-auto max-w-xl px-4 py-32 text-center text-sm text-muted" aria-busy="true"> | |
| 582 | 583 | <title>Loading · g1t</title> | |
| 583 | 584 | Loading the latest version of g1t… | |
| 584 | − | </main> | |
| 585 | + | </PageMain> | |
| 585 | 586 | ); | |
| 586 | 587 | } | |
| 587 | 588 | ||
| ⋯ | |||
| 608 | 609 | } | |
| 609 | 610 | ||
| 610 | 611 | return ( | |
| 611 | − | <main className="mx-auto max-w-xl px-4 py-32 text-center"> | |
| 612 | + | <PageMain className="mx-auto max-w-xl px-4 py-32 text-center"> | |
| 612 | 613 | <h1 className="text-2xl font-semibold tracking-tight">{title}</h1> | |
| 613 | 614 | <p className="mt-3 text-muted">{details}</p> | |
| 614 | 615 | <div className="mt-8"> | |
| ⋯ | |||
| 621 | 622 | <code>{stack}</code> | |
| 622 | 623 | </pre> | |
| 623 | 624 | )} | |
| 624 | − | </main> | |
| 625 | + | </PageMain> | |
| 625 | 626 | ); | |
| 626 | 627 | } | |