Repository navigation
Give appraisal intake fields persistent, programmatic labels #154
Changes from 7 commits
c0607b8
0528571
f5fcb9b
e2000ef
b3fc542
bc87051
f0acbfa
dc3aa86
e1a9baf
d1e3902
7e9b858
7119d95
62ca3e2
e9213bb
ae961e2
14f0e80
e2259d8
09ac0b5
3ccbde1
9a011cf
8b619a9
cc2f48f
94b3539
1add021
fcb425c
1724bb3
96be299
f0aa5d3
26ae9e3
e03c97c
2d2c9a6
4177a8a
1476541
bb5b67b
94d7f43
1007c10
763b078
ab96019
fd8e290
fc7c6b4
07d5716
ea49ab8
d557be6
b77a837
e8975ca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,15 +97,19 @@ footer a:hover{color:var(--ink)} | |
| [data-r].in{opacity:1;transform:none} | ||
| } | ||
|
|
||
| /* two-field lead form — website + email, still one line on desktop */ | ||
| /* two-field lead form — website + email, still one line on desktop. | ||
| Each field carries a persistent <label> caption: placeholder text alone | ||
| disappears as buyers type, so the caption never doubles as the label. */ | ||
| form.lead.two{max-width:720px;padding:7px 7px 7px 0;overflow:hidden} | ||
| form.lead.two input{flex:1 1 0;min-width:0;padding:12px 18px 12px 24px} | ||
| form.lead.two input:first-child{border-right:1px solid var(--line)} | ||
| form.lead.two label{display:grid;gap:2px;flex:1 1 0;min-width:0;padding:10px 18px 11px 24px} | ||
| form.lead.two label + label{border-left:1px solid var(--line);padding-left:18px} | ||
| form.lead.two label span{font-size:10px;letter-spacing:.13em;text-transform:uppercase;font-weight:600;color:var(--muted)} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On Useful? React with 👍 / 👎. |
||
| form.lead.two input{padding:0;width:100%} | ||
| form.lead.two button{flex:0 0 auto} | ||
| @media (max-width:760px){ | ||
| form.lead.two{flex-direction:column;align-items:stretch;border-radius:20px;padding:8px;max-width:100%} | ||
| form.lead.two input{padding:14px 18px} | ||
| form.lead.two input:first-child{border-right:0;border-bottom:1px solid var(--line)} | ||
| form.lead.two label{padding:12px 14px} | ||
| form.lead.two label + label{border-left:0;border-top:1px solid var(--line)} | ||
| form.lead.two button{width:100%} | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1633,12 +1633,12 @@ for (const [pageName, pageHtml] of titlePages) { | |
| } | ||
|
|
||
| // ---- Intake field labels (activation) ------------------------------------- | ||
| // Both appraisal intake forms (homepage and /audit) labelled their fields | ||
| // only with placeholder text, which disappears the moment a buyer starts | ||
| // typing and is not a persistent programmatic label. Each intake input must | ||
| // carry a non-empty aria-label so the field keeps its name for assistive | ||
| // tech and for the browser's own validation announcements, no matter what | ||
| // the field contains. | ||
| // Both appraisal intake forms (homepage and /audit) must label each field | ||
| // persistently AND programmatically: a visible <label> bound to the input via | ||
| // label[for]/input[id], so the name survives typing and is exposed to | ||
| // assistive tech and the browser's validation announcements. aria-label alone | ||
| // is programmatic but invisible; placeholder-only labels disappear the moment | ||
| // a buyer starts typing — neither is enough. | ||
| const intakePages = [ | ||
| ["homepage", siteHome], | ||
| ["audit page", siteAudit] | ||
|
|
@@ -1648,9 +1648,16 @@ for (const [pageName, pageHtml] of intakePages) { | |
| for (const input of pageHtml.matchAll(/<input\b[^>]*>/gi)) { | ||
| const tag = input[0]; | ||
| if (!/\bname="(?:website|email)"/.test(tag)) continue; | ||
|
Comment on lines
1960
to
1962
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If either page's email input is deleted or its Useful? React with 👍 / 👎. |
||
| const aria = tag.match(/\baria-label="([^"]*)"/)?.[1] ?? ""; | ||
| if (!aria.trim()) { | ||
| failures.push(`Intake input on ${pageName} must carry a persistent programmatic aria-label (placeholder-only labels disappear as buyers type): ${tag}`); | ||
| const id = tag.match(/\bid="([^"]*)"/)?.[1] ?? ""; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If an intake input's Useful? React with 👍 / 👎. |
||
| if (!id.trim()) { | ||
| failures.push(`Intake input on ${pageName} must carry an id so a persistent <label> can bind to it: ${tag}`); | ||
| continue; | ||
| } | ||
| const labelBody = pageHtml.match( | ||
| new RegExp(`<label\\b[^>]*\\bfor="${id}"[^>]*>([\\s\\S]*?)<\\/label>`, "i") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an otherwise valid HTML ID contains a regular-expression metacharacter, this check can accept a mismatched label association. For example, an input with Useful? React with 👍 / 👎. |
||
| )?.[1] ?? ""; | ||
|
Comment on lines
+1968
to
+1970
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If a future edit accidentally assigns the same Useful? React with 👍 / 👎.
Comment on lines
+1968
to
+1970
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If an intake form is commented out while its old markup remains in the page, both the input scan and this label lookup still inspect the commented markup, so the check reports success even though the browser serves no intake controls. Strip HTML comments before scanning, as the canonical-link check above already does, so only live inputs and labels can satisfy this regression guard. Useful? React with 👍 / 👎. |
||
| if (!labelBody.trim()) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a caption is emptied or removed while the input remains inside its Useful? React with 👍 / 👎. |
||
| failures.push(`Intake input on ${pageName} must be bound to a persistent programmatic <label for="${id}"> (placeholder-only labels disappear as buyers type): ${tag}`); | ||
|
Comment on lines
+1968
to
+1972
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Validate label text, not only label markup.
🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The homepage loads only
index.css, while the new label-column rules were added exclusively toshared.css, which is used by/audit. Consequently, on/the existingform.two inputrules still assume the inputs are direct flex children: the wrapper labels receive no flex sizing or grid layout, the captions remain unstyled inline content, and both nested inputs matchinput:first-of-type, producing incorrect dividers and sizing in the primary intake form. Mirror the label rules inindex.cssor load a stylesheet that supplies them.Useful? React with 👍 / 👎.