1 Commits
Author SHA1 Message Date
sneak d0f1348f50 Wrap the top bar's buttons onto a second row when narrow (closes #272)
Check / check (pull_request) Skipped
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
2026-10-02 04:17:16 +00:00
3 changed files with 28 additions and 1 deletions
+4
View File
@@ -20,6 +20,10 @@ regress.
# Completed Steps # 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 - 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 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, Actions column and the Deploy buttons. In a window too narrow for the table,
@@ -52,3 +52,26 @@ func TestDashboardTableFitsCard(t *testing.T) {
assert.Contains(t, cellTag, "whitespace-normal") assert.Contains(t, cellTag, "whitespace-normal")
assert.Contains(t, cellTag, "break-all") 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(), `<nav class="app-bar">`)
require.True(t, found, "dashboard has no top bar")
rowTag, _, _ := strings.Cut(strings.TrimSpace(afterNav), ">")
assert.Contains(t, rowTag, "flex-wrap")
assert.Contains(t, rowTag, "gap-")
}
+1 -1
View File
@@ -26,7 +26,7 @@
{{define "nav"}} {{define "nav"}}
<nav class="app-bar"> <nav class="app-bar">
<div class="max-w-6xl mx-auto flex justify-between items-center"> <div class="max-w-6xl mx-auto flex flex-wrap justify-between items-center gap-3">
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<a href="/" class="text-xl font-medium text-gray-900 hover:text-primary-600 transition-colors">µPaaS</a> <a href="/" class="text-xl font-medium text-gray-900 hover:text-primary-600 transition-colors">µPaaS</a>
<span class="text-sm text-gray-500">by <a href="https://sneak.berlin" class="text-primary-600 hover:text-primary-800">@sneak</a></span> <span class="text-sm text-gray-500">by <a href="https://sneak.berlin" class="text-primary-600 hover:text-primary-800">@sneak</a></span>