contacts edit: a handle's two fields on one line
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01U77d1jrGYSKCTjsYWetd5d
change
commit 45c8124bf03ff7fa2d30b1fc5a233509e5c6d09e
author Claude <noreply@anthropic.com>
date
parent 4f590d9a
diff --git a/lib/pro_tacts/admin/contacts_edit.rb b/lib/pro_tacts/admin/contacts_edit.rb
index 011d117..3661d2c 100644
--- a/lib/pro_tacts/admin/contacts_edit.rb
+++ b/lib/pro_tacts/admin/contacts_edit.rb
@@ -73,7 +73,8 @@ module ProTacts
 
       # A handle row's two fields, the service first because it says
       # what the handle is (docs/plans/2026-10-18-signal-handles.md,
-      # "The service is the row's"). Field name to placeholder, the
+      # "The service is the row's"), side by side on one line as a
+      # birthday's are (admin.css). Field name to placeholder, the
       # address fields' shape.
       HANDLE_FIELDS = [
         ["service", "service"],
@@ -344,7 +345,7 @@ module ProTacts
             # The handle kind: the standing row's two fields, named by
             # the add index for the address's reason.
             template("x-if": "kind === 'handle'") do
-              div(class: "field-stack") do
+              div(class: "handle-row") do
                 HANDLE_FIELDS.each_with_index do |(field, label), index|
                   input(type: "text", ":name": "`new_handle[${i}][#{field}]`",
                         placeholder: label, aria_label: label,
@@ -524,7 +525,7 @@ module ProTacts
       def handle_row(handle)
         div(class: "field", data: {blank_removes: true}) do
           span { "handle" }
-          div(class: "field-stack") do
+          div(class: "handle-row") do
             HANDLE_FIELDS.each do |field, label|
               input(type: "text", name: "handle[#{handle.line.digest}][#{field}]",
                     value: handle.public_send(field), placeholder: label, aria_label: label)
diff --git a/public/admin.css b/public/admin.css
index a0e0bd2..a94ae28 100644
--- a/public/admin.css
+++ b/public/admin.css
@@ -250,6 +250,24 @@
   color: var(--gl-color-danger);
 }
 
+/* A handle row's two fields — service and handle — on one line in
+   the value column: the service names what the handle is, so the two
+   read as one value, the birthday row's reading. The service is the
+   shorter word and takes the narrower share; both shed their floor so
+   the pair fits a phone's value column rather than widening it. */
+.card-body form.field-stack .field > .handle-row {
+  display: flex;
+  gap: var(--gl-space-2xs);
+}
+.card-body form.field-stack .field > .handle-row > input {
+  flex: 1 1 0;
+  min-width: 0;
+  padding-block: var(--gl-space-3xs);
+}
+.card-body form.field-stack .field > .handle-row > input:last-child {
+  flex-grow: 2;
+}
+
 /* The date line breaks in two when its row cannot hold a whole
    date: a month name, two year boxes, and the two icon buttons need
    ~20rem side by side, and on a phone the value column has a
diff --git a/test/pro_tacts/admin/test_contacts_pages.rb b/test/pro_tacts/admin/test_contacts_pages.rb
index 5850c00..5c4ea78 100644
--- a/test/pro_tacts/admin/test_contacts_pages.rb
+++ b/test/pro_tacts/admin/test_contacts_pages.rb
@@ -2171,7 +2171,7 @@ class AdminContactsPagesTest < Minitest::Test
 
       digest = store.contact("ada").handles.first.line.digest
       assert_includes last_response.body,
-        '<div class="field" data-blank-removes><span>handle</span><div class="field-stack">' \
+        '<div class="field" data-blank-removes><span>handle</span><div class="handle-row">' \
         '<input type="text" name="handle[' + digest + '][service]" value="signal" placeholder="service" aria-label="service">' \
         '<input type="text" name="handle[' + digest + '][value]" value="ada.42" placeholder="handle" aria-label="handle">' \
         '</div></div>'
@@ -2781,7 +2781,7 @@ class AdminContactsPagesTest < Minitest::Test
       # The handle kind: the standing row's two fields, named by the
       # add index as the address's are.
       assert_includes body,
-        '<template x-if="kind === \'handle\'"><div class="field-stack">' \
+        '<template x-if="kind === \'handle\'"><div class="handle-row">' \
         '<input type="text" :name="`new_handle[${i}][service]`" placeholder="service" aria-label="service" x-init="$el.focus()">' \
         '<input type="text" :name="`new_handle[${i}][value]`" placeholder="handle" aria-label="handle">' \
         '</div></template>'