feat: booking UI design polish (closes #7) #8
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/gcal-scheduler!8
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "7-booking-ui-design-polish"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
static/index.htmlChanges
@font-facefallback metrics for CLS reduction; defined modular type scale (--step-0through--step-3).booking-card(kept class for JS); two-column form layout on desktop (slot summary sidebar + form fields).brand-markin<a>linking to LinkedIn; converted.brand-iconto pure typographic letterform.day-groupfadeInUp (50ms via--iCSS var set in JS); form slideUp; success checkmark SVG stroke draw-in; details fade-up -- all gated behind@media (prefers-reduced-motion: no-preference)--space-xsthrough--space-2xl) replacing hardcoded pixelsmin-height: 44pxon all interactive elements--color-placeholder: #9A8F82for 3:1+ WCAG ratio@media (hover: hover)to prevent sticky states on touchpadding-bottom: env(safe-area-inset-bottom)for notched devices--ease-out-quartcustom property; transition from180ms easeto140ms cubic-bezier(0.25, 1, 0.5, 1)Test Plan
GET /api/availability,POST /api/book)prefers-reduced-motion: reduce-- animations disabledReview Checklist
Related
Self-Review
Result: PASS -- no blockers.
Checklist
static/index.html), 300 additions / 141 deletionsGET /api/availability,POST /api/book)visitor_name,visitor_email,note).card-dividerelement preserved (JS toggles display).booking-cardclass preserved (JS scrolls to it)dayDiv.style.setProperty('--i', i)inrenderSlotsNotes
.success-detailsbase style setsopacity: 0for the fade-up animation entry state. The@media (prefers-reduced-motion: reduce)block correctly overrides this toopacity: 1 !important, so success details are always visible regardless of motion preference.--color-stone(#C4BAA8) to--color-warm-gray(#8A8178) -- not in the spec but fixes a contrast issue (stone on cream was ~2.3:1, warm-gray is ~4.2:1).@media (hover: hover)to prevent sticky hover states on touch devices. The:focus-visiblestyles remain outside the media query so keyboard navigation always works.PR #8 Review
Single-file design polish of
static/index.html(300 insertions, 141 deletions). Font swap (Inter to Libre Franklin), semantic spacing tokens, hover-only media query, motion gating, touch target enforcement, two-column form layout on desktop, inline SVG favicon, and brand link to LinkedIn.BLOCKERS
None found. This is a well-scoped, CSS/HTML-only design polish. The changes are correct and safe:
GET /api/availabilityandPOST /api/bookcalls in the JS are untouched. Form fieldnameattributes (visitor_name,visitor_email,note) unchanged. All DOM IDs referenced by JS (slots-container,form-section,booking-form,submit-btn, etc.) are present and correctly nested.dayDiv.style.setProperty('--i', i)to drive staggered animation delay -- correct and harmless.roleattributes,aria-label,aria-pressed,aria-required,aria-describedby, skip link,.sr-onlyutility, androle="alert"on error elements are retained.NITS
stroke-dasharray: 30/stroke-dashoffset: 30magic number. The checkmark polyline draw-in animation uses30for bothstroke-dasharrayandstroke-dashoffset. The actual path length of<polyline points="20 6 9 17 4 12">is approximately 22.6 units (calculated from the two line segments). A value of 30 works (it just means the dash extends past the end of the stroke), but for precision,pathLength="1"on the SVG element withstroke-dasharray: 1/stroke-dashoffset: 1would be more self-documenting. Non-blocking.success-detailsstarts withopacity: 0but noprefers-reduced-motionoverride initially. The.success-detailsdiv getsopacity: 0in the base styles (line in diff:+ opacity: 0;). ThefadeUpanimation (insideprefers-reduced-motion: no-preference) sets it toopacity: 1viaforwards. Theprefers-reduced-motion: reduceblock correctly forcesopacity: 1 !important. This is handled correctly -- just noting it is subtle logic that is easy to break if someone moves the reduced-motion block.Pre-existing CI issue (not introduced by this PR).
.woodpecker.yamlline 25 usestags: $CI_COMMIT_SHAwhich should betags: ${CI_COMMIT_SHA}for Woodpecker's kaniko plugin to expand the variable. This is a known issue across other repos and is not in scope for this PR.brand-linkopens LinkedIn in new tab without visible external-link indicator. The<a>wrapping.brand-markhastarget="_blank" rel="noopener"which is correct for security, but there is no visual cue (icon or text) indicating the link leaves the site. Consider adding anaria-labellike"Pal-E Agency (opens LinkedIn profile)"for screen reader clarity. Non-blocking.Mixed spacing: one hardcoded
margin-bottom: 6pxremains on.brand-mark. Most pixel values were migrated tovar(--space-*)tokens, but.brand-markstill hasmargin-bottom: 6px. If the intent was a full migration to design tokens, this is a leftover. Non-blocking.SOP COMPLIANCE
7-booking-ui-design-polishreferences issue #7)feat: booking UI design polish (closes #7))Closes #7)VERDICT: APPROVED