From d0f1348f50f6812993033072ae1be0c80b6d9c15 Mon Sep 17 00:00:00 2001 From: sneak Date: Fri, 2 Oct 2026 04:17:16 +0000 Subject: [PATCH] Wrap the top bar's buttons onto a second row when narrow (closes #272) The top bar's two sides were held apart only by justify-between, with no gap and no wrapping, so at 390 px "by @sneak" ended where the New App button began. The bar's row now wraps and has a gap: in a window too narrow for one row, New App and Logout move to a second row; on wider windows the bar looks as before. Model: opus-5-5 --- TODO.md | 4 ++++ internal/handlers/dashboard_layout_test.go | 23 ++++++++++++++++++++++ templates/base.html | 2 +- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index e14276c..d45aee2 100644 --- a/TODO.md +++ b/TODO.md @@ -20,6 +20,10 @@ regress. # Completed Steps +- 2026-10-02: In a window too narrow for the top bar, such as 390 px, the New + App and Logout buttons move to a second row instead of running into "by + @sneak"; the bar keeps a gap between its two sides at every width (#272). + - 2026-10-02: On the Applications list, a long repository URL now wraps within its column instead of making the table wider than its card, which cut off the Actions column and the Deploy buttons. In a window too narrow for the table, diff --git a/internal/handlers/dashboard_layout_test.go b/internal/handlers/dashboard_layout_test.go index 2ab09da..1d572b8 100644 --- a/internal/handlers/dashboard_layout_test.go +++ b/internal/handlers/dashboard_layout_test.go @@ -52,3 +52,26 @@ func TestDashboardTableFitsCard(t *testing.T) { assert.Contains(t, cellTag, "whitespace-normal") assert.Contains(t, cellTag, "break-all") } + +// TestTopBarWrapsWhenNarrow checks that the top bar keeps a gap between the +// µPaaS title and the New App and Logout buttons, and puts the buttons on a +// second row in a window too narrow for one, instead of letting them meet. +func TestTopBarWrapsWhenNarrow(t *testing.T) { + t.Parallel() + + testCtx := setupTestHandlers(t) + + request := httptest.NewRequestWithContext(t.Context(), http.MethodGet, "/", nil) + recorder := httptest.NewRecorder() + + testCtx.handlers.HandleDashboard().ServeHTTP(recorder, request) + + require.Equal(t, http.StatusOK, recorder.Code) + + _, afterNav, found := strings.Cut(recorder.Body.String(), `