From 5c366b8964e5ef78740b278d08f376c395442a8b Mon Sep 17 00:00:00 2001 From: whereareiam Date: Sat, 31 Oct 2026 21:22:12 +0100 Subject: [PATCH] feat(home): switch the sidebar's repositories for your organizations The home sidebar listed only repositories, so an organization was only reachable through the account switcher. With organizations, the Repositories heading now opens a menu, as GitHub's single-choice menus do, that swaps the list for the signed-in user's organizations, each linking to its page. Forgejo's dashboard already lists them, so nothing is fetched. The choice is kept in the browser and restored before the first paint, so someone who keeps Repositories sees GitHub's sidebar with a caret after the heading. Without organizations the heading stays plain. Co-Authored-By: Claude Opus 5.5 --- src/build-output.test.ts | 7 ++++ styles/pages/dashboard-home.css | 39 +++++++++++++++++++++ templates/user/dashboard/dashboard.tmpl | 44 ++++++++++++++++++++++-- templates/user/dashboard/home_lists.tmpl | 2 ++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 templates/user/dashboard/home_lists.tmpl diff --git a/src/build-output.test.ts b/src/build-output.test.ts index 0f0979a7..0f8d9e76 100644 --- a/src/build-output.test.ts +++ b/src/build-output.test.ts @@ -1357,6 +1357,13 @@ describe("Forgejo 15 native integration", () => { expect(home).toContain('{{template "components/dashboard/context/context" dict "Data" . "Page" ""}}'); expect(home).toContain('{{template "components/dashboard/context/pages" dict "Data" . "Current" "home"}}'); expect(home).toContain('template "components/repository/picker/picker"'); + // With organizations, the repositories heading opens a menu that swaps in the organizations, chosen before paint. + expect(home).toContain('"Items" "user/dashboard/home_lists"'); + expect(home).toContain("{{range .Orgs}}"); + expect(home).toContain('localStorage.getItem(key) === "organizations"'); + // Switching lists is not an unsaved change: Forgejo's leave-page warning skips the form. + expect(home).toContain('
'); + expect(read("templates", "user", "dashboard", "home_lists.tmpl")).toContain('"Value" "organizations"'); expect(home).not.toContain('template "user/heatmap"'); expect(home).not.toContain('template "user/dashboard/repolist"'); // The feed in day groups beside the work rail; the profile keeps Forgejo's own feed. diff --git a/styles/pages/dashboard-home.css b/styles/pages/dashboard-home.css index 74481e85..848cb791 100644 --- a/styles/pages/dashboard-home.css +++ b/styles/pages/dashboard-home.css @@ -26,6 +26,45 @@ color: var(--color-text-light-1); } +/* With organizations, the heading is a quiet menu that reads like the plain heading: its text, then a caret. */ +/* Fomantic's .ui.form sets 14px; the heading's 12px/600 passes through to the trigger instead. */ +.ui.form.github-home-list-form { + display: inline-block; + margin: 0; + font: inherit; +} + +.github-home-list-menu > summary.theme-control { + gap: 2px; + height: auto; + min-height: 0; + margin-left: -4px; + padding: 2px 4px; + color: inherit; + font: inherit; +} + +.github-home-list-menu > summary.theme-control > .svg { + color: inherit; +} + +.github-home-list-menu > .theme-dropdown-panel { + inset: calc(100% + 4px) auto auto 0; + width: 200px; +} + +/* One list at a time; the organizations show once chosen. */ +.github-home-repositories[data-github-home-list="repositories"] > .github-home-organizations, +.github-home-repositories[data-github-home-list="organizations"] > .theme-repo-picker, +.github-home-repositories[data-github-home-list="organizations"] .theme-icon-button[data-theme-repo-picker-toggle] { + display: none; +} + +.github-home-organizations .ui.avatar { + flex: none; + border-radius: 4px; +} + .page-content.theme-sidebar-layout[data-theme-sidebar] > .ui.container.theme-sidebar-main.github-home-main { max-width: 1280px !important; } diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl index f5eb18ce..f0c0481e 100644 --- a/templates/user/dashboard/dashboard.tmpl +++ b/templates/user/dashboard/dashboard.tmpl @@ -11,14 +11,54 @@ organization's pages in the sidebar. */}} {{template "components/dashboard/context/context" dict "Data" . "Page" ""}} {{template "components/dashboard/context/pages" dict "Data" . "Current" "home"}}
-
+ {{/* GitHub's heading over the top repositories. With organizations, the heading opens a menu that swaps the list + for them; the choice is kept in the browser and restored before the first paint. */}} +
-

{{ctx.Locale.Tr "home.my_repos"}}

+

+ {{- /* The form only gives the options the dropdown's form styles; choosing one never submits it, and ignore-dirty keeps Forgejo from warning about unsaved changes. */}} + {{- if .Orgs}}{{template "components/common/dropdown/dropdown" dict "Kind" "single" "Quiet" true "Label" (ctx.Locale.Tr "home.my_repos") "UpdateLabel" true "Class" "github-home-list-menu" "Items" "user/dashboard/home_lists" "Data" (dict "Context" ctx)}} + {{- else}}{{ctx.Locale.Tr "home.my_repos"}}{{end -}} +

{{$teamID := 0}}{{if .Team}}{{$teamID = .Team.ID}}{{end}} {{template "components/repository/picker/picker" dict "ID" "github-home-repositories" "UID" $user.ID "Team" $teamID "FullName" true "Limit" 10 "More" true "Label" (ctx.Locale.Tr "home.my_repos")}} + {{if .Orgs}} + + {{end}}
+ {{if .Orgs}} + + {{end}} {{template "components/common/sidebar/toggle" .}} diff --git a/templates/user/dashboard/home_lists.tmpl b/templates/user/dashboard/home_lists.tmpl new file mode 100644 index 00000000..e5e21773 --- /dev/null +++ b/templates/user/dashboard/home_lists.tmpl @@ -0,0 +1,2 @@ +{{template "components/common/dropdown/option" dict "Type" "radio" "Name" "github-home-list" "Value" "repositories" "Label" (ctx.Locale.Tr "home.my_repos") "Checked" true}} +{{template "components/common/dropdown/option" dict "Type" "radio" "Name" "github-home-list" "Value" "organizations" "Label" (ctx.Locale.Tr "home.my_orgs")}}