feat: SPA topbar with repo name and theme toggle#17
Merged
Conversation
Adds a sticky topbar above the chapter UI showing the git repo basename on the left (new `repoName` field on the chapters response) and a Sun/Moon/ System dropdown on the right that persists to `localStorage["ui-theme"]`. Mirrors the hosted stage monorepo's theme system: an inline IIFE in index.html applies the persisted class before paint to avoid FOUC. Refactors PullRequestLayout to use a shared `useChapters(runId)` hook so the topbar and the chapter list share one cache entry, and offsets the sticky tab nav (`top-12`) and `--content-top` to clear the new topbar.
There was a problem hiding this comment.
Code Review
This pull request implements a comprehensive theme management system, including a pre-paint script to prevent theme flashing and a new theme toggle component. It also introduces a global Topbar that displays the repository name, which was added to the run data models. The PullRequestLayout was refactored to use a centralized useChapters hook and its layout was updated to accommodate the new header. Feedback was provided to adjust the --content-top variable in the sticky navigation bar to 6rem to avoid overlapping with chapter file headers.
The topbar was showing the worktree directory basename, which for Conductor worktrees (and any clone into a renamed directory) is the workspace name, not the repo name. Switch to parsing `git remote get-url origin` and fall back to the basename only when there's no remote. Snapshot the URL on `chapter_run.originUrl` at import time so the run keeps reading consistently if the remote is later renamed — same shape as `repoRoot`/`baseSha`/`headSha`. Adds an additive nullable column (no backfill needed; old rows fall back to basename). - New `packages/cli/src/git.ts` consolidates git introspection (`readRepoContext`, `readRepoRoot`, `parseRepoName`, `NotInGitRepoError`). `db/path.ts` now only does path resolution. - `insertChaptersFile` takes a `RepoContext` instead of a bare `repoRoot` string, per AGENTS.md "consolidate sibling props that travel together". - `parseRepoName` handles SSH/HTTPS/ssh:// URLs with or without `.git`, with full unit-test coverage (6 cases) for the parser.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a sticky topbar to the stage-cli SPA matching the hosted stage monorepo: git repo basename on the left and a Sun/Moon/System theme dropdown on the right that persists to
localStorage["ui-theme"]. An inline IIFE inindex.htmlapplies the persisted theme class to<html>before paint to avoid a flash of the wrong theme.Changes
packages/types/src/chapters.ts+packages/cli/src/routes/runs.ts: addrepoName(basename of the run'srepoRoot) toChapterRunSchema/ the/api/runs/:runId/chaptersresponse.packages/web/src/lib/theme.tsx: ports the monorepo'sThemeProvider/useTheme(light/dark/system,USER_THEME/APP_THEMEenums, system-preference media-query subscription).packages/web/src/components/{layout/topbar.tsx,layout/theme-toggle.tsx,ui/dropdown-menu.tsx}: new sticky topbar (h-12 z-30), shadcn-style theme toggle, and a trimmed shadcn dropdown-menu (added@radix-ui/react-dropdown-menu).packages/web/src/lib/use-chapters.ts: shareduseChapters(runId)hook so Topbar andPullRequestLayoutdedupe via the same TanStack Query key.packages/web/src/{App.tsx,main.tsx}: wraps the app in<ThemeProvider>and renders<Topbar />above both the empty state andPullRequestLayout.packages/web/src/routes/pull-request-layout.tsx+globals.css: tab nav moved tosticky top-12,--content-topbumped to3remso chapter file headers clear the topbar.Testing
pnpm typecheck/pnpm lint/pnpm test(72/72 passing)./api/runs/<id>/chaptersagainst a fixture run — confirmedrun.repoName === "monterrey-v3".index.htmlships the FOUC-prevention IIFE and the JS bundle containsToggle theme,repoName, andui-theme. Did not visually inspect in a real browser — recommend eyeballing the dropdown + dark/light switch before merging.