aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--web/static/style.css23
-rw-r--r--web/templates.templ55
2 files changed, 39 insertions, 39 deletions
diff --git a/web/static/style.css b/web/static/style.css
index 3c9c05b..755a5cb 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -157,15 +157,28 @@ select { border: 1px solid var(--color-input-border); border-radius: .55rem; pad
.section-heading .eyebrow { margin-bottom: .2rem; }
.section-heading h2 { margin: 0; font-size: 1.2rem; }
.section-count { display: grid; place-items: center; min-width: 2rem; height: 2rem; border-radius: 999px; background: var(--color-secondary-surface); color: var(--color-forest); font-weight: 800; }
-.categories-panel { padding: 1rem 1.25rem; }
-.categories-layout { display: flex; align-items: center; justify-content: space-between; gap: 1.25rem; flex-wrap: wrap; }
+.categories-panel { padding: 0; overflow: hidden; }
+.categories-details { display: block; }
+.categories-summary { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem 1.25rem; cursor: pointer; list-style: none; }
+.categories-summary::-webkit-details-marker { display: none; }
+.categories-summary::marker { display: none; }
+.categories-summary:hover { background: var(--color-secondary-surface); }
+.categories-summary:focus-visible { outline: .2rem solid var(--color-focus); outline-offset: -.2rem; }
.categories-heading { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.categories-heading .eyebrow { margin: 0; }
.categories-heading h2 { margin: 0; font-size: 1.1rem; }
+.categories-chevron { color: var(--color-accent); font-size: 1.5rem; font-weight: 500; line-height: 1; transition: transform .2s; }
+.categories-details[open] .categories-chevron { transform: rotate(180deg); }
+.categories-details[open] .categories-summary { border-bottom: 1px solid var(--color-border-subtle); }
.category-badge { display: inline-flex; align-items: center; border-radius: 999px; padding: .35rem .65rem; background: var(--color-notice-surface); color: var(--color-notice-text); font-size: .75rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; }
-.category-form { display: flex; align-items: end; gap: .65rem; flex-wrap: wrap; margin-left: auto; }
-.category-form label { min-width: 8.5rem; }
-.category-form select { min-width: 8.5rem; }
+.category-form { display: flex; align-items: end; gap: 1rem 1.25rem; flex-wrap: wrap; padding: 1rem 1.25rem; }
+.category-fieldset { display: grid; gap: .35rem; margin: 0; padding: 0; border: 0; min-width: 0; }
+.category-fieldset legend { padding: 0; color: var(--color-muted); font-size: .85rem; font-weight: 650; }
+.category-options { display: grid; gap: .4rem; }
+.category-option { display: inline-flex; align-items: center; gap: .35rem; border: 1px solid var(--color-input-border); border-radius: 999px; padding: .4rem .65rem; background: var(--color-surface); color: var(--color-foreground); font-size: .85rem; font-weight: 650; cursor: pointer; }
+.category-option:has(input:checked) { border-color: var(--color-leaf); background: var(--color-secondary-surface); color: var(--color-forest); }
+.category-option input { accent-color: var(--color-accent); }
+.category-option:focus-within { outline: .2rem solid var(--color-focus); outline-offset: .1rem; }
.category-form .button { align-self: end; padding: .55rem .9rem; }
.data-quality-bulk { display: flex; align-items: end; gap: .75rem; flex-wrap: wrap; margin-bottom: 1rem; }
.data-quality-bulk label { min-width: 8.5rem; }
diff --git a/web/templates.templ b/web/templates.templ
index 8fbed0c..10008d2 100644
--- a/web/templates.templ
+++ b/web/templates.templ
@@ -228,47 +228,34 @@ templ RideDetailContent(data RideDetailView) {
</dl>
</section>
<section class="panel categories-panel">
- <div class="categories-layout">
- <div class="categories-heading">
- <p class="eyebrow">Curation</p>
- <h2>Categories</h2>
- </div>
+ <details class="categories-details" open?={ data.Ride.BikeType == "" && data.Ride.RideType == "" }>
+ <summary class="categories-summary">
+ <div class="categories-heading">
+ <p class="eyebrow">Curation</p>
+ <h2>Categories</h2>
+ </div>
+ <span class="categories-chevron" aria-hidden="true">⌄</span>
+ </summary>
<form method="post" action={ templ.URL(rideCategoriesUpdateURL(data.Ride.ID)) } class="category-form">
- <label for="ride-bike-type">Bike type
- <select id="ride-bike-type" name="bike_type" required>
- if data.Ride.BikeType == "" {
- <option value="" selected>—</option>
- } else {
- <option value="">—</option>
- }
+ <fieldset class="category-fieldset">
+ <legend>Bike type</legend>
+ <div class="category-options">
for _, opt := range bikeTypeOptions {
- if data.Ride.BikeType == opt {
- <option value={ string(opt) } selected>{ bikeTypeLabels[opt] }</option>
- } else {
- <option value={ string(opt) }>{ bikeTypeLabels[opt] }</option>
- }
- }
- </select>
- </label>
- <label for="ride-ride-type">Ride type
- <select id="ride-ride-type" name="ride_type" required>
- if data.Ride.RideType == "" {
- <option value="" selected>—</option>
- } else {
- <option value="">—</option>
+ <label class="category-option"><input type="radio" name="bike_type" value={ string(opt) } required checked?={ data.Ride.BikeType == opt }/><span>{ bikeTypeLabels[opt] }</span></label>
}
+ </div>
+ </fieldset>
+ <fieldset class="category-fieldset">
+ <legend>Ride type</legend>
+ <div class="category-options">
for _, opt := range rideTypeOptions {
- if data.Ride.RideType == opt {
- <option value={ string(opt) } selected>{ rideTypeLabels[opt] }</option>
- } else {
- <option value={ string(opt) }>{ rideTypeLabels[opt] }</option>
- }
+ <label class="category-option"><input type="radio" name="ride_type" value={ string(opt) } required checked?={ data.Ride.RideType == opt }/><span>{ rideTypeLabels[opt] }</span></label>
}
- </select>
- </label>
+ </div>
+ </fieldset>
<button class="button" type="submit">Save</button>
</form>
- </div>
+ </details>
</section>
if data.HasRoute {
if len(data.Profile.OfficialClimbs()) > 0 {