Rank choice on the add-restaurant form as a button group

00e6765 · Gabriel Morell · 2026-10-28 21:46

8 files +28 -6
Message
{commit_body(@commit)}

Files changed

modified assets/f/css/style.css
+19 −0
@@ -15,3 +15,22 @@
15 15 /* Leaflet's panes run z-index 200-1000; give the map its own stacking context
16 16 so they stay inside it and daisyUI dropdowns (z-10) open over the map. */
17 17 .leaflet-container { isolation: isolate; z-index: 0; font: inherit; }
18 +
19 +/* Rank radios drawn as a button group (restaurants/new.html): the label is
20 + the button, the radio inside it is visually hidden. The checked one takes
21 + its rank's colour, as in the rank widget. Plain CSS rather than
22 + has-[:checked]: utilities, which Tailwind won't generate for daisyUI's
23 + component classes, and outside @layer so it's never purged. */
24 +.rank-pick:has(:focus-visible) { outline: 2px solid oklch(var(--bc)); outline-offset: 2px; }
25 +.rank-pick-obsessed:has(:checked) { @apply btn-warning; }
26 +.rank-pick-always:has(:checked) { @apply btn-success; }
27 +.rank-pick-positive:has(:checked) { @apply btn-accent; }
28 +.rank-pick-neutral:has(:checked) { @apply btn-neutral; }
29 +.rank-pick-never:has(:checked) { @apply btn-error; }
30 +/* daisyUI's colour classes only set --btn-color; .btn turns that into a
31 + background, which .btn-ghost then overrides with transparent. Paint it
32 + here, for whichever rank is checked. */
33 +.rank-pick:has(:checked) {
34 + background-color: oklch(var(--btn-color));
35 + border-color: oklch(var(--btn-color));
36 +}
modified templates/index.html
+2 −2
@@ -38,11 +38,11 @@
38 38 </div>
39 39 {% else %}
40 40 <section class="py-16 sm:py-24 text-center">
41 − <p class="font-mono text-xs uppercase tracking-[0.25em] text-accent mb-4">{{ app_name }}</p>
41 + <p class="font-mono text-xs uppercase tracking-[0.25em] text-accent mb-4">{{ app_name }}, provides</p>
42 42 <img src="/assets/img/fieri.webp" width="960" height="656"
43 43 class="mx-auto mb-8 w-full max-w-xl h-auto rounded-box shadow-lg"
44 44 alt="Anime-style Guy Fieri in sunglasses and a stars-and-stripes jacket, saying: You thought I would let you escape Flavortown so easily?"/>
45 − <h1 class="text-4xl sm:text-6xl font-bold tracking-tight">Not there again.</h1>
45 + <h1 class="text-4xl sm:text-6xl font-bold tracking-tight">ESCAPE FROM FLAVORTOWN</h1>
46 46 <p class="text-base-content/70 text-lg sm:text-xl mt-6 max-w-2xl mx-auto leading-relaxed">
47 47 Pin the places you eat on a map, say how you feel about each one
48 48 (obsessed, always, positive, neutral, or never), and let lunch pick itself
modified templates/restaurants/new.html
+7 −4
@@ -1,4 +1,5 @@
1 1 {% extends "root.html" %}
2 +{% from "_macros.html" import rank_icon %}
2 3
3 4 {% block content %}
4 5 <div class="space-y-4">
@@ -71,11 +72,13 @@
71 72 </label>
72 73 <fieldset class="sm:col-span-2">
73 74 <legend class="label-text text-xs mb-1">Your rank</legend>
74 − <div class="flex flex-wrap gap-3">
75 + {# Real radios, visually hidden inside button-styled labels: arrow keys,
76 + form posting and screen readers behave as with plain radios. #}
77 + <div class="join flex-wrap">
75 78 {% for r in ranks %}
76 − <label class="label cursor-pointer gap-2 py-0">
77 − <input type="radio" class="radio radio-sm" name="rank" value="{{ r }}" {% if r == "positive" %}checked{% endif %}/>
78 − <span class="capitalize">{{ r }}</span>
79 + <label class="join-item btn btn-sm btn-ghost border-base-300 rank-pick rank-pick-{{ r }}">
80 + <input type="radio" class="sr-only" name="rank" value="{{ r }}" {% if r == "positive" %}checked{% endif %}/>
81 + <i class="fas {{ rank_icon(r) }}"></i><span class="capitalize">{{ r }}</span>
79 82 </label>
80 83 {% endfor %}
81 84 </div>

Parents: a7c4c3c