Public: anyone can read this; the crew can change it.

Settings › Origins speaks the home page's language #9802

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Settings › Origins now reads like the home page: headings over rows, with no `.card`. Type check and design-lint are clean. The origins tests, `web-origins` and `backups-parts` pass unchanged (197 pass). The new test passes with the change. I didn't run it against main, because my attempt to stash the change to check that ran in a broken command. It asserts `.card` is absent and the headings are p…

shipped production is serving it deploy 7ab3f87

opened this

Settings › Origins now reads like the home page: headings over rows, with no .card. Type check and design-lint are clean. The origins tests, web-origins and backups-parts pass unchanged (197 pass). The new test passes with the change. I didn't run it against main, because my attempt to stash the change to check that ran in a broken command. It asserts .card is absent and the headings are present, so it should fail on main.

What changed (markup only, in src/web/pages/origins.ts):

  • Sections: the three card( blocks and the frozen-mirrors listCard are now <section class="settings-block"> with an <h2>: Connected origins, Trusted internal hosts (admin only), Connect an origin (keeps id="connect"), and Frozen mirrors.
  • Rows: each connected origin and each frozen mirror is a row() in a .list. Each origin keeps its error, reauth and paused notes and its Sync, Repositories, Archived and Disconnect buttons.
  • Empty state: with no origins, one plain sentence reads "No origins connected. Connect another forge, GitHub, a Forgejo instance or a Gitea instance below and its repositories become mirrorable here."
  • Unchanged: accountSections keeps its signature. The connect, import and remove logic is untouched.
  • Docs and test: docs/design/areas/settings.md records the shape. test/origins-page-shape.test.ts is the new test.

What I left alone:

  • Repository rows: the repositories picker (origin-repos.ts) is a different page. The "their repositories" item is met only for the frozen mirrors, which are rows here.
  • .card-body: the collapsible connect paths still wrap their bodies in it, because the fold needs it for padding. It's a body class, not a .card.
  • Copy: I kept the "No origins connected" wording because two existing web-origins tests match that phrase.

To try it, open /settings/origins, or run bun test test/origins-page-shape.test.ts.

🤖 Generated with Claude Code

Closes #9787

commented

Settings › Origins now reads like the home page: headings over rows, with no .card. Type check and design-lint are clean. The origins tests, web-origins and backups-parts pass unchanged (197 pass). The new test passes with the change. I didn't run it against main, because my attempt to stash the change to check that ran in a broken command. It asserts .card is absent and the headings are present, so it should fail on main.

What changed (markup only, in src/web/pages/origins.ts):

  • Sections: the three card( blocks and the frozen-mirrors listCard are now <section class="settings-block"> with an <h2>: Connected origins, Trusted internal hosts (admin only), Connect an origin (keeps id="connect"), and Frozen mirrors.
  • Rows: each connected origin and each frozen mirror is a row() in a .list. Each origin keeps its error, reauth and paused notes and its Sync, Repositories, Archived and Disconnect buttons.
  • Empty state: with no origins, one plain sentence reads "No origins connected. Connect another forge, GitHub, a Forgejo instance or a Gitea instance below and its repositories become mirrorable here."
  • Unchanged: accountSections keeps its signature. The connect, import and remove logic is untouched.
  • Docs and test: docs/design/areas/settings.md records the shape. test/origins-page-shape.test.ts is the new test.

What I left alone:

  • Repository rows: the repositories picker (origin-repos.ts) is a different page. The "their repositories" item is met only for the frozen mirrors, which are rows here.
  • .card-body: the collapsible connect paths still wrap their bodies in it, because the fold needs it for padding. It's a body class, not a .card.
  • Copy: I kept the "No origins connected" wording because two existing web-origins tests match that phrase.

To try it, open /settings/origins, or run bun test test/origins-page-shape.test.ts.

🤖 Generated with Claude Code

commented

Settings › Origins now reads like the home page: headings over rows, with no .card. I've pushed a new commit with the missing "Try:" line, which should clear the gate rule that failed #9802. bun scripts/gate.ts ran clean here before the push. I haven't seen the forge's check re-run on it yet.

What changed (markup only, in src/web/pages/origins.ts):

  • Sections: the three card( blocks and the frozen-mirrors list are now <section class="settings-block"> with an <h2>: Connected origins, Trusted internal hosts (admin only), Connect an origin, and Frozen mirrors.
  • Rows: each connected origin and each frozen mirror is a row() in a .list. The error, reauth and paused notes and the Sync, Repositories, Archived and Disconnect buttons are unchanged.
  • Empty state: with no origins, one sentence says how to connect one: "No origins connected. Connect another forge, GitHub, a Forgejo instance or a Gitea instance below and its repositories become mirrorable here."
  • Unchanged: accountSections keeps its signature, and the connect, import and remove logic is untouched.
  • Docs and test: docs/design/areas/settings.md records the shape. test/origins-page-shape.test.ts checks the headings and that no .card is present. I did not run it against main.

Tests: type check and design-lint are clean. The origins tests, web-origins and backups-parts pass unchanged, and the new test passes.

What I left out:

  • Repository rows: the repositories picker (origin-repos.ts) is a different page, so only the frozen mirrors became rows here.
  • .card-body: the connect paths' collapsible bodies still use it, because the fold needs it for padding.
  • Empty-state wording: I kept the phrase "No origins connected" because two web-origins tests match it.

Try: open /settings/origins on the preview. You should see Connected origins, Trusted internal hosts and Connect an origin as headed blocks instead of cards.

🤖 Generated with Claude Code

Changes requested — before the latest push

Close, and the headings are right. One thing to fix first: the connected origins are not rows in one list. Each origin is wrapped in a new, unstyled div.origin-item holding its own one-row ul.list, and that class is in no stylesheet or design doc. Put all origins in one <ul class="list setting-list"> and drop the wrapper. Move each origin's Sync/Repositories/Archived/Disconnect buttons and its notes into the row's after/meta slots, or keep them as a sibling <li> in the same list. Principle 7, rows over boxes. Then: (1) docs/design/areas/settings.md says 'adds no component class', so either that stays true (no origin-item) or the class is documented; the first is better. (2) The long <p> lines in the empty state and the connect footnote should be wrapped like the surrounding source. (3) The test covers only the empty, admin case. Add a case with a connected origin that asserts a .list of rows, and one with a frozen mirror that asserts the 'Frozen mirrors' heading. Note: I could not view the preview signed in (it answers 303 to sign-in), so I judged the markup from the source.

commented

Settings › Origins now renders every connected origin as a row of one <ul class="list setting-list">, and the origin-item wrapper is gone. I pushed this to the same branch. The type check, bun scripts/design-lint.ts, bun scripts/gate.ts and the 36 tests in origins-page-shape and web-origins pass. I did not run the full suite; the forge's check does that on the push.

  • Rows: originCard in src/web/pages/origins.ts now returns a row() instead of a div holding its own list. The error text, re-auth and forge notes, the paused-writes toast, and the Sync now, Repositories, Archived and Disconnect buttons all go in the row's after slot. The health badge stays in trail. No new class is added, so docs/design/areas/settings.md ("adds no component class") is still true.
  • Long lines: the empty-state paragraph and the connect footnote are wrapped like the surrounding source.
  • Tests: test/origins-page-shape.test.ts has two new cases.

- With two connected origins, it asserts there is no origin-item, exactly one .list under "Connected origins", at least two rows, and that the buttons show. - With a mirror whose origin was deleted, it asserts the "Frozen mirrors" heading and the mirror's name.

The dedent I did on originCard left the indentation inside its after template slightly off from the surrounding style. It is cosmetic only, and I did not run a formatter over it.

commented

I merged main into the branch and pushed it, so the pull should merge cleanly again.

The only conflict was in docs/design/areas/settings.md. This pull added a paragraph on Settings › Origins, and main added one on Settings › Trusted. They are separate paragraphs, so I kept both.

The type check, bun scripts/gate.ts and bun scripts/design-lint.ts pass. So do the 70 tests in origins-page-shape, web-origins and trusted-sources. I did not run the full suite; the forge's check does that on the push.

Changes requested — before the latest push

The headings, the single .list of origin rows and the frozen-mirror rows are right, and the new test would fail on main. Four things to fix in this round.

  1. Fix first: originCard is badly indented, so the diff is unreadable. The row({...}) body, the after template and the bar buttons are at inconsistent depths, and the closing }); is stranded. Run the repo's formatter or re-indent by hand. Do this one first.
  2. The empty state is two sentences ("No origins connected. Connect another forge..."). Box 1 asks for one plain sentence that says how to connect one. Make it one, for example "Connect another forge, GitHub, a Forgejo instance or a Gitea instance below and its repositories become mirrorable here." The web-origins tests that match "No origins connected" would then need that phrase kept, so keep it as the lead: "No origins connected: connect another forge, GitHub, a Forgejo instance or a Gitea instance below."
  3. Box 1 says the connected origins and their repositories are rows. Only the frozen mirrors are rows here, and the repositories page is untouched. If you leave that out on purpose, say so in the pull body. I have marked the box as left.
  4. The origin's error text, notes and action buttons now sit inside the row's after slot as nested divs (field mt, bar mt). Check that they do not break the row layout at 390 px. Also tighten the test so it asserts the error and notes render inside the <li> of the row.
commented

Settings › Origins now uses the home page's layout: Connected origins, Frozen mirrors, Trusted internal hosts and Connect an origin are each a .settings-block with an <h2>. Each origin and each frozen mirror is a row() in a single .list, and the .card wrappers are gone.

This round, from review:

  • Indentation: originCard in src/web/pages/origins.ts is re-indented to match the surrounding code. The row({…}) body, the after template, the bar buttons and the closing }); now line up. No logic changed.
  • Empty state: it is one sentence, keeping the lead the web-origins tests match: "No origins connected: connect another forge, GitHub, a Forgejo instance or a Gitea instance below."
  • Layout at 390 px: the old layout was broken, at every width. Inside a .setting-list, the row's after slot is a right-aligned flex row placed beside the row, so an origin's error, notes and buttons were squeezed into a narrow column. The list now carries the attribute data-origins, not a new class, like the existing data-people. One rule in src/web/style/components.ts turns that slot into a full-width block under the row at every width, with min-width: 0 and overflow-wrap: anywhere so a long upstream error wraps instead of widening the page. This is recorded in docs/design/areas/settings.md.
  • Tests: test/origins-page-shape.test.ts adds an origin with a stored error that is also another forge. It checks that the error (with its id), the "Another forge." note and Sync now render inside that origin's <li>, in its .row-after. It also checks that the empty state is one sentence and that the stacking rule is in the stylesheet.

Left out on purpose: the per-origin repositories page (/settings/origins/:id/repos) is unchanged, and its repositories are not yet rows. Each origin row links to it with its Repositories button. Converting it is a separate page change and belongs in its own pull.

Checks: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean. scripts/fast.ts named 1,246 test files because a stylesheet changed, too many to run here, so I ran the 79 that cover origins, settings rows and design. All 513 tests in them pass; the forge's check on this push runs the full suite. I did not view the page at 390 px in a browser: the fit is pinned by the stylesheet rule and its test.

To try it, open /settings/origins with no origins to see the one-sentence empty state. Then connect one whose last sync failed: its error, notes and buttons sit under the origin's row, full width, on desktop and on a phone.

🤖 Generated with Claude Code

commented

Settings › Origins now uses the home page's layout: Connected origins, Frozen mirrors, Trusted internal hosts and Connect an origin are each a .settings-block with an <h2>. Each origin and each frozen mirror is a row() in a single .list, and the .card wrappers are gone.

From review:

  • Indentation: originCard in src/web/pages/origins.ts is re-indented to match the surrounding code. The row({…}) body, the after template, the bar buttons and the closing }); now line up. No logic changed.
  • Empty state: it is one sentence, keeping the lead the web-origins tests match: "No origins connected: connect another forge, GitHub, a Forgejo instance or a Gitea instance below."
  • Layout at 390 px: the old layout was broken, at every width. Inside a .setting-list, the row's after slot is a right-aligned flex row placed beside the row, so an origin's error, notes and buttons were squeezed into a narrow column. The list now carries the attribute data-origins, not a new class, like the existing data-people. One rule in src/web/style/components.ts turns that slot into a full-width block under the row at every width, with min-width: 0 and overflow-wrap: anywhere so a long upstream error wraps instead of widening the page. This is recorded in docs/design/areas/settings.md.
  • Tests: test/origins-page-shape.test.ts adds an origin with a stored error that is also another forge. It checks that the error (with its id), the "Another forge." note and Sync now render inside that origin's <li>, in its .row-after. It also checks that the empty state is one sentence and that the stacking rule is in the stylesheet.

The latest main is merged in. The one conflict was in docs/design/areas/settings.md, where main's new Settings › Telemetry paragraph landed next to the Origins one; both paragraphs are kept.

Left out on purpose: the per-origin repositories page (/settings/origins/:id/repos) is unchanged, and its repositories are not yet rows. Each origin row links to it with its Repositories button. Converting it is a separate page change and belongs in its own pull.

Checks: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean. scripts/fast.ts named 1,246 test files because a stylesheet changed, too many to run here. Before the merge, the 79 test files covering origins, settings rows and design passed (513 tests). After it, I re-ran 7 of them, plus main's new Telemetry test, and all 80 tests pass. The forge's check on this push runs the full suite. I did not view the page at 390 px in a browser: the fit is pinned by the stylesheet rule and its test.

To try it, open /settings/origins with no origins to see the one-sentence empty state. Then connect one whose last sync failed: its error, notes and buttons sit under the origin's row, full width, on desktop and on a phone.

🤖 Generated with Claude Code

commented

Settings › Origins now uses the home page's layout: Connected origins, Frozen mirrors, Trusted internal hosts and Connect an origin are each a .settings-block with an <h2>. Each origin and each frozen mirror is a row() in a single .list, and the .card wrappers are gone.

From review:

  • Indentation: originCard in src/web/pages/origins.ts is re-indented to match the surrounding code. The row({…}) body, the after template, the bar buttons and the closing }); now line up. No logic changed.
  • Empty state: it is one sentence, keeping the lead the web-origins tests match: "No origins connected: connect another forge, GitHub, a Forgejo instance or a Gitea instance below."
  • Layout at 390 px: the old layout was broken, at every width. Inside a .setting-list, the row's after slot is a right-aligned flex row placed beside the row, so an origin's error, notes and buttons were squeezed into a narrow column. The list now carries the attribute data-origins, not a new class, like the existing data-people. One rule in src/web/style/components.ts turns that slot into a full-width block under the row at every width, with min-width: 0 and overflow-wrap: anywhere so a long upstream error wraps instead of widening the page. This is recorded in docs/design/areas/settings.md.
  • Tests: test/origins-page-shape.test.ts adds an origin with a stored error that is also another forge. It checks that the error (with its id), the "Another forge." note and Sync now render inside that origin's <li>, in its .row-after. It also checks that the empty state is one sentence and that the stacking rule is in the stylesheet.

The latest main is merged in. Both merges conflicted only in docs/design/areas/settings.md, where main added its Settings › Telemetry and Settings › Cloud paragraphs next to the Origins one; all three paragraphs are kept.

Left out on purpose: the per-origin repositories page (/settings/origins/:id/repos) is unchanged, and its repositories are not yet rows. Each origin row links to it with its Repositories button. Converting it is a separate page change and belongs in its own pull.

Checks: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean after the latest merge. scripts/fast.ts named 1,246 test files because a stylesheet changed, too many to run here. Before the merges, the 79 test files covering origins, settings rows and design passed (513 tests). After the latest merge I re-ran 5 of them, including main's new Cloud test, and all 70 tests pass. The forge's check on this push runs the full suite. I did not view the page at 390 px in a browser: the fit is pinned by the stylesheet rule and its test.

To try it, open /settings/origins with no origins to see the one-sentence empty state. Then connect one whose last sync failed: its error, notes and buttons sit under the origin's row, full width, on desktop and on a phone.

🤖 Generated with Claude Code

Approved — before the latest push

All four earlier asks are met. (1) originCard is re-indented and reads cleanly. (2) The empty state is one sentence and keeps the "No origins connected" lead the web-origins tests match. (3) The repositories picker is a separate page, and the pull says so; frozen mirrors and origins are rows. (4) The after slot stacks full width at every width through data-origins, with min-width 0 and overflow-wrap, and the test asserts the error and notes render inside the origin row. The preview answers 200. Next: Non-blocking: convert the per-origin repositories page to rows in its own pull. Non-blocking: view /settings/origins at 390 px with a long upstream error to confirm the wrap, since the test only pins the stylesheet rule.

commented

Settings › Origins now uses the home page's layout: Connected origins, Frozen mirrors, Trusted internal hosts and Connect an origin are each a .settings-block with an <h2>. Each origin and each frozen mirror is a row() in a single .list, and the .card wrappers are gone.

From review:

  • Indentation: originCard in src/web/pages/origins.ts is re-indented to match the surrounding code. The row({…}) body, the after template, the bar buttons and the closing }); now line up. No logic changed.
  • Empty state: it is one sentence, keeping the lead the web-origins tests match: "No origins connected: connect another forge, GitHub, a Forgejo instance or a Gitea instance below."
  • Layout at 390 px: the old layout was broken, at every width. Inside a .setting-list, the row's after slot is a right-aligned flex row placed beside the row, so an origin's error, notes and buttons were squeezed into a narrow column. The list now carries the attribute data-origins, not a new class, like the existing data-people. One rule in src/web/style/components.ts turns that slot into a full-width block under the row at every width, with min-width: 0 and overflow-wrap: anywhere so a long upstream error wraps instead of widening the page. This is recorded in docs/design/areas/settings.md.
  • Tests: test/origins-page-shape.test.ts adds an origin with a stored error that is also another forge. It checks that the error (with its id), the "Another forge." note and Sync now render inside that origin's <li>, in its .row-after. It also checks that the empty state is one sentence and that the stacking rule is in the stylesheet.

The latest main is merged in. All three merges conflicted only in docs/design/areas/settings.md, where main added its Settings › Telemetry, Settings › Cloud and /oauth/authorize paragraphs next to the Origins one; every paragraph is kept.

Left out on purpose: the per-origin repositories page (/settings/origins/:id/repos) is unchanged, and its repositories are not yet rows. Each origin row links to it with its Repositories button. Converting it is a separate page change and belongs in its own pull.

Checks: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean after the latest merge. scripts/fast.ts named 1,246 test files because a stylesheet changed, too many to run here. Before the merges, the 79 test files covering origins, settings rows and design passed (513 tests). After the latest merge I re-ran 5 of them, including main's new OAuth page test, and all 72 tests pass. The forge's check on this push runs the full suite. I did not view the page at 390 px in a browser: the fit is pinned by the stylesheet rule and its test.

To try it, open /settings/origins with no origins to see the one-sentence empty state. Then connect one whose last sync failed: its error, notes and buttons sit under the origin's row, full width, on desktop and on a phone.

🤖 Generated with Claude Code

Approved

All four earlier asks are met. originCard is re-indented and readable. The empty state is one sentence that keeps the "No origins connected" lead. The error, notes and buttons render inside the origin's own li, and a test pins that. The data-origins rule stacks the after slot full width with min-width 0 and overflow-wrap, which fixes the 390 px squeeze. It is recorded in settings.md and has no new class. The preview answers 200. Next: (1) Non-blocking: the per-origin repositories page (/settings/origins/:id/repos) still is not rows, so give it its own pull. (2) Non-blocking: check /settings/origins at 390 px in a real browser, since the fit is only pinned by a stylesheet-string test.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs