From 06083b19a2194340e6c7be4b13ac91c01d14c829 Mon Sep 17 00:00:00 2001 From: sneak Date: Fri, 2 Oct 2026 14:39:53 +0000 Subject: [PATCH] Make every clickable control look clickable, in two shared styles (closes #375) Buttons keep btn-primary, btn-secondary and btn-danger and gain a pointer cursor; the site name and the navigation links become btn-secondary buttons. Every control that was plain coloured text (Copy, both Add, the row actions, Resubmit, Replay, the back, footer and download links) now uses btn-small, bordered at rest with hover and focus states. Each card on the webhook list shows an Open label in btn-small and takes its focus outline. Both styles are in static/css/style.css, which the layout now loads. The event log's clickable rows become buttons, so they work by keyboard; Replay moves beside its delivery's row. Rows on the webhook page and in the event log wrap at phone width. The browser test now checks that Copy reads "Copied". Model: opus-5-5 --- README.md | 21 +++++----- internal/handlers/ui_copy_test.go | 11 ++--- internal/server/alpine_browser_test.go | 38 ++++++++++++++++- internal/server/routes_test.go | 4 +- static/css/style.css | 49 +++++++++++++++++++++- templates/base.html | 4 +- templates/htmlheader.html | 1 + templates/navbar.html | 20 ++++----- templates/source_detail.html | 32 +++++++-------- templates/source_edit.html | 2 +- templates/source_logs.html | 56 +++++++++++++------------- templates/sources_list.html | 7 +++- templates/sources_new.html | 2 +- templates/target_edit.html | 2 +- 14 files changed, 171 insertions(+), 78 deletions(-) diff --git a/README.md b/README.md index 55b45f9..1f845f4 100644 --- a/README.md +++ b/README.md @@ -1326,15 +1326,16 @@ A browser test in `internal/server` loads the webhook page and the event log under the real policy and checks that: both add forms stay hidden until Add is clicked; choosing Slack in the add target form leaves the HTTP fields out of what it submits, also after leaving the page and going back to it, when the -browser restores the choice; an event expands and collapses, and so do a -delivery's attempts inside it; and at phone width the menu button opens and -closes the mobile menu. It also fails if the browser reports a console warning -or error, an uncaught exception, or anything the policy refused. `make check` -and the image build lint it but do not run it, and `make test` leaves it out -(its file is built only with the `browser` build tag). Run it with -`make test-browser` after changing `templates/` or `static/js/`: that builds -`Dockerfile.browser`, which runs the test in a digest-pinned headless browser -image, so the host needs no browser. +browser restores the choice; the Copy button beside an entrypoint URL reads +"Copied" once clicked; an event expands and collapses, and so do a delivery's +attempts inside it; and at phone width the menu button opens and closes the +mobile menu. It also fails if the browser reports a console warning or error, +an uncaught exception, or anything the policy refused. `make check` and the +image build lint it but do not run it, and `make test` leaves it out (its file +is built only with the `browser` build tag). Run it with `make test-browser` +after changing `templates/` or `static/js/`: that builds `Dockerfile.browser`, +which runs the test in a digest-pinned headless browser image, so the host +needs no browser. The package's tarball is committed as `3p/alpinejs-csp-3.14.9.tgz`, byte for byte as the npm registry publishes it. It is a dependency, not this repo's build @@ -3026,7 +3027,7 @@ webhooker/ │ ├── static.go # //go:embed directive │ ├── css/input.css # Tailwind input, source for tailwind.css (make css) │ ├── css/tailwind.css # Generated stylesheet the pages load -│ ├── css/style.css # Older hand-written stylesheet, no longer loaded +│ ├── css/style.css # Hand-written, loaded after tailwind.css: btn-small, the pointer cursor for input.css's buttons, the webhook list cards' focus outline │ ├── js/app.js # Copy-to-clipboard, and the Alpine.js components │ └── js/alpine.min.js # Alpine.js CSP build, extracted from 3p/ by make assets, not committed ├── templates/ # Go HTML templates (base, login, sources, etc.) diff --git a/internal/handlers/ui_copy_test.go b/internal/handlers/ui_copy_test.go index ddf4186..206f07e 100644 --- a/internal/handlers/ui_copy_test.go +++ b/internal/handlers/ui_copy_test.go @@ -82,9 +82,9 @@ func TestNavbarUsesWebhookTerminology(t *testing.T) { }) assert.Contains(t, body, "Retention: 14 days") - assert.Contains(t, body, `class="btn-text">Webhooks`) + assert.Contains(t, body, `class="btn-secondary">Webhooks`) assert.Contains( - t, body, `class="btn-text w-full text-left">Webhooks`, + t, body, `class="btn-secondary w-full">Webhooks`, ) assert.Contains( t, body, @@ -163,7 +163,7 @@ func TestEventLogPageIsCalledFullEventLog(t *testing.T) { ) assert.Contains( t, detailBody, - `Full Event Log`, + `Full Event Log`, "the link under recent events", ) @@ -331,8 +331,9 @@ func TestEntrypointCopyButtonIsProgressiveEnhancement(t *testing.T) { assert.Contains(t, body, "https://hooks.example.com/h/abc123") assert.Contains( t, body, - `hidden data-copy-target="entrypoint-url-ep-1"`, - "the button must start hidden and be revealed by script", + ` + {{end}} {{end}} diff --git a/templates/source_detail.html b/templates/source_detail.html index cf75cc6..0cb0a66 100644 --- a/templates/source_detail.html +++ b/templates/source_detail.html @@ -9,7 +9,7 @@ no class this wide. -->
- ← Back to webhooks + ← Back to webhooks

{{.Webhook.Name}}

@@ -35,8 +35,8 @@

Entrypoints

-
- +
@@ -79,7 +79,7 @@ {{$.BaseURL}}/h/{{.Path}} - +
@@ -94,8 +94,8 @@

Targets

-
- +
@@ -188,7 +188,7 @@

50 Most Recent Events

- Full Event Log + Full Event Log
{{range .Events}} diff --git a/templates/source_edit.html b/templates/source_edit.html index 9b54780..43d2c4f 100644 --- a/templates/source_edit.html +++ b/templates/source_edit.html @@ -5,7 +5,7 @@ {{define "content"}}
diff --git a/templates/source_logs.html b/templates/source_logs.html index 019d729..d17c304 100644 --- a/templates/source_logs.html +++ b/templates/source_logs.html @@ -5,7 +5,7 @@ {{define "content"}}
- ← Back to {{.Webhook.Name}} + ← Back to {{.Webhook.Name}}

Full Event Log

{{.TotalEvents}} total event{{if ne .TotalEvents 1}}s{{end}} @@ -16,8 +16,8 @@
{{range .Events}}
-
-
+
-
+ + {{range .Deliveries}} {{.Target.DisplayName}}: {{.Status}} @@ -38,8 +38,8 @@ -
-
+ +
@@ -50,12 +50,12 @@
- +
{{.Body}}
{{if .BodyTruncated}} -

Body truncated for display: showing {{.BodyShownBytes}} of {{.BodyBytes}} bytes. The stored body is unchanged — download the full body.

+

Body truncated for display: showing {{.BodyShownBytes}} of {{.BodyBytes}} bytes. The stored body is unchanged — download the full body.

{{end}} {{if .Deliveries}} @@ -64,24 +64,26 @@
{{range .Deliveries}}
-
-
- {{.Target.DisplayName}} - {{.Status}} -
-
- {{if .Status.Terminal}} -
- - - -
- {{end}} - {{.AttemptCount}} attempt{{if ne .AttemptCount 1}}s{{end}} - - - -
+
+ + {{if .Status.Terminal}} +
+ + + +
+ {{end}}
diff --git a/templates/sources_list.html b/templates/sources_list.html index 18ce43d..927598a 100644 --- a/templates/sources_list.html +++ b/templates/sources_list.html @@ -25,7 +25,12 @@

{{.Description}}

{{end}}
- Retention: {{.RetentionLabel}} +
+ Retention: {{.RetentionLabel}} + + Open → +
{{.EntrypointCount}} entrypoint{{if ne .EntrypointCount 1}}s{{end}}{{if .InactiveEntrypointCount}}, {{.InactiveEntrypointCount}} inactive{{end}} diff --git a/templates/sources_new.html b/templates/sources_new.html index 41fe41c..a3181f9 100644 --- a/templates/sources_new.html +++ b/templates/sources_new.html @@ -5,7 +5,7 @@ {{define "content"}}
diff --git a/templates/target_edit.html b/templates/target_edit.html index 0f43d8b..59b2fec 100644 --- a/templates/target_edit.html +++ b/templates/target_edit.html @@ -5,7 +5,7 @@ {{define "content"}}
- ← Back to {{.Webhook.Name}} + ← Back to {{.Webhook.Name}}

Edit Target

Type: {{.Target.Type}}. A target's type cannot be changed; create a new target to deliver a different way.

-- 2.54.0