admin: tighten the editor form's rhythm
Short boxes under their captions, the stack closed one step, and the\nback link on the details page's caption-to-card spacing.
Assisted-by: GLM-5.3 via pi
diff --git a/lib/pro_tacts/admin/contacts_edit.rb b/lib/pro_tacts/admin/contacts_edit.rb
index 570e2cc..9f43cb2 100644
--- a/lib/pro_tacts/admin/contacts_edit.rb
+++ b/lib/pro_tacts/admin/contacts_edit.rb
@@ -39,36 +39,40 @@ module ProTacts
def view_template
render Layout.new(title: "Edit #{@contact.name || @contact.id}", notice: @notice) do
- a(href: "/contacts/#{@contact.id}", class: "type-label") {
- "‹ #{@contact.name || @contact.id}"
- }
- div(class: "card") do
- div(class: "card-body") do
- form(action: "/contacts/#{@contact.id}", method: "post", class: "field-stack") do
- input(type: "hidden", name: "etag", value: @contact.etag)
- label(class: "field") do
- plain "First"
- input(type: "text", name: "first", value: @first,
- required: true, autofocus: true)
- end
- label(class: "field") do
- plain "Last"
- input(type: "text", name: "last", value: @last)
- end
- label(class: "field") do
- plain "Nickname"
- input(type: "text", name: "nickname", value: @contact.nickname)
- end
- label(class: "field") do
- plain "Note"
- textarea(name: "note", rows: 4) { @contact.notes.to_s }
- end
- # Save is the form's submit; Cancel is navigation — a
- # link in Gloss's `.btn` contract, which is what an
- # anchor that acts like a button opts into.
- div(class: "form-actions") do
- button(type: "submit", data: {variant: "primary"}) { "Save" }
- a(href: "/contacts/#{@contact.id}", class: "btn") { "Cancel" }
+ # The caption-to-card block the details page uses (.record in
+ # admin.css): the back link is this card's caption row too.
+ div(class: "record") do
+ a(href: "/contacts/#{@contact.id}", class: "type-label") {
+ "‹ #{@contact.name || @contact.id}"
+ }
+ div(class: "card") do
+ div(class: "card-body") do
+ form(action: "/contacts/#{@contact.id}", method: "post", class: "field-stack") do
+ input(type: "hidden", name: "etag", value: @contact.etag)
+ label(class: "field") do
+ plain "First"
+ input(type: "text", name: "first", value: @first,
+ required: true, autofocus: true)
+ end
+ label(class: "field") do
+ plain "Last"
+ input(type: "text", name: "last", value: @last)
+ end
+ label(class: "field") do
+ plain "Nickname"
+ input(type: "text", name: "nickname", value: @contact.nickname)
+ end
+ label(class: "field") do
+ plain "Note"
+ textarea(name: "note", rows: 4) { @contact.notes.to_s }
+ end
+ # Save is the form's submit; Cancel is navigation — a
+ # link in Gloss's `.btn` contract, which is what an
+ # anchor that acts like a button opts into.
+ div(class: "form-actions") do
+ button(type: "submit", data: {variant: "primary"}) { "Save" }
+ a(href: "/contacts/#{@contact.id}", class: "btn") { "Cancel" }
+ end
end
end
end
diff --git a/public/admin.css b/public/admin.css
index 215f89b..ca39ade 100644
--- a/public/admin.css
+++ b/public/admin.css
@@ -26,6 +26,18 @@
justify-content: space-between;
}
+/* A form in a card keeps a tighter rhythm than Gloss's form-body
+ defaults: the stack closes from s to xs, and the boxes shed half
+ their block padding — the same shedding the header's search does —
+ so short boxes sit close under their captions. Scoped to the
+ card-body form rather than overriding field.css globally; the
+ label in the input selector out-specifies field.css's input rule
+ rather than relying on stylesheet order (see the header search's
+ note). */
+.card-body .field-stack { gap: var(--gl-space-xs); }
+.card-body label.field > input,
+.card-body label.field > textarea { padding-block: var(--gl-space-2xs); }
+
/* The editor's submit row: the buttons sit beside each other under
the stacked fields, rather than in the stack's own gap. */
.form-actions {