summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-17 10:57:22 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-17 10:57:22 +0200
commit2890f7cfbe9c6bca3210a23bb2275847d38b39cc (patch)
tree2bae61b36668b4a720dd7b7eac1af25ca9885851
parent298677d6b7e4f55a6076e9043b62bfebf6ff3350 (diff)
refactor(web): tidy climb matching controls
-rw-r--r--web/static/style.css10
-rw-r--r--web/templates.templ14
-rw-r--r--web/templates_templ.go20
3 files changed, 21 insertions, 23 deletions
diff --git a/web/static/style.css b/web/static/style.css
index e32525d..8c1d39f 100644
--- a/web/static/style.css
+++ b/web/static/style.css
@@ -128,19 +128,17 @@ th { color: var(--color-subtle); font-size: .78rem; letter-spacing: .08em; text-
.profile-band-9-plus { background: var(--color-profile-9-plus); }
.climb-list { display: grid; gap: 1rem; margin-top: 1.25rem; }
.climb-item { padding-top: 1rem; border-top: 1px solid var(--color-border-subtle); }
+.climb-item.focused { background: var(--color-plot-surface); }
.climb-item-heading { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
-.todo-item { padding-left: .8rem; border-left: .2rem solid var(--color-accent); }
-.todo-item.focused { border-left-color: var(--color-forest); background: var(--color-plot-surface); }
-.todo-check { display: inline-block; width: .9rem; height: .9rem; margin-right: .5rem; border: 2px solid var(--color-accent); border-radius: .2rem; vertical-align: -.05rem; }
.climb-number { display: inline-block; margin-right: .45rem; color: var(--color-accent); font-size: .78rem; letter-spacing: .08em; text-transform: uppercase; }
.climb-item-heading > span, .climb-status { color: var(--color-muted); font-size: .9rem; }
.climb-metrics { margin: .35rem 0 0; color: var(--color-muted); font-size: .9rem; }
.climb-status { margin: .35rem 0 0; }
.climb-status.matched { color: var(--color-notice-text); }
.official-climb-form { display: grid; gap: .8rem; margin-top: .8rem; padding: .8rem; border: 1px solid var(--color-border-subtle); border-radius: .65rem; background: var(--color-plot-surface); }
-.boundary-controls { display: flex; gap: .75rem; flex-wrap: wrap; }
-.boundary-controls > div { display: grid; gap: .35rem; }
-.boundary-controls > div > div { display: flex; gap: .35rem; flex-wrap: wrap; }
+.boundary-controls { display: grid; grid-template-columns: max-content minmax(0, 1fr) minmax(0, 1fr) max-content; align-items: center; gap: .35rem; white-space: nowrap; }
+.boundary-controls > div { display: contents; }
+.boundary-controls .button { width: 100%; padding: .45rem .6rem; font-size: .8rem; }
.boundary-controls output { color: var(--color-muted); font-size: .85rem; }
.boundary-controls .button.active { outline: .2rem solid var(--color-focus); }
.boundary-preview { color: var(--color-notice-text); font-size: .9rem; }
diff --git a/web/templates.templ b/web/templates.templ
index 7d606bd..795af43 100644
--- a/web/templates.templ
+++ b/web/templates.templ
@@ -125,9 +125,9 @@ templ RideDetailContent(data RideDetailView) {
</nav>
<div class="climb-list" data-climb-list>
for _, climb := range data.Profile.UnmatchedClimbs() {
- <article class="climb-item todo-item" data-climb-item data-climb-index={ formatRouteIndex(climb.Index) }>
+ <article class="climb-item" data-climb-item data-climb-index={ formatRouteIndex(climb.Index) }>
<div class="climb-item-heading">
- <strong><span class="todo-check" aria-hidden="true"></span><span class="climb-number">Climb { formatClimbNumber(climb.Index) }</span>{ climb.Name }</strong>
+ <strong><span class="climb-number">Climb { formatClimbNumber(climb.Index) }</span>{ climb.Name }</strong>
<span class="climb-range" data-climb-summary>{ formatProfileDistance(climb.StartKm) }–{ formatProfileDistance(climb.EndKm) }</span>
</div>
<p class="climb-metrics" data-climb-metrics>{ climb.Category } · { formatProfileDistance(climb.DistanceKm) } at { formatSlope(climb.SlopePercent) } · Cotacol { formatCotacol(climb.Cotacol) }</p>
@@ -135,11 +135,11 @@ templ RideDetailContent(data RideDetailView) {
<form class="official-climb-form" data-official-climb-form method="post" action={ templ.URL(officialClimbCreateURL(data.Ride.ID)) }>
<label>Name<input type="text" name="name" required placeholder="Official climb name"/></label>
<input type="hidden" name="start_index" value={ formatRouteIndex(climb.StartIndex) } data-boundary-input="start"/>
- <input type="hidden" name="end_index" value={ formatRouteIndex(climb.EndIndex) } data-boundary-input="end"/>
- <div class="boundary-controls">
- <div><strong>Start</strong><div><button class="button secondary" type="button" data-boundary-button="start" data-boundary-source="profile">Select on profile</button><button class="button secondary" type="button" data-boundary-button="start" data-boundary-source="map">Select on map</button></div><output data-boundary-output="start">{ formatProfileDistance(climb.StartKm) }</output></div>
- <div><strong>End</strong><div><button class="button secondary" type="button" data-boundary-button="end" data-boundary-source="profile">Select on profile</button><button class="button secondary" type="button" data-boundary-button="end" data-boundary-source="map">Select on map</button></div><output data-boundary-output="end">{ formatProfileDistance(climb.EndKm) }</output></div>
- </div>
+ <input type="hidden" name="end_index" value={ formatRouteIndex(climb.EndIndex) } data-boundary-input="end"/>
+ <div class="boundary-controls">
+ <div><strong>Start</strong><button class="button secondary" type="button" data-boundary-button="start" data-boundary-source="profile" aria-label="Select on profile for start">Profile</button><button class="button secondary" type="button" data-boundary-button="start" data-boundary-source="map" aria-label="Select on map for start">Map</button><output data-boundary-output="start">{ formatProfileDistance(climb.StartKm) }</output></div>
+ <div><strong>End</strong><button class="button secondary" type="button" data-boundary-button="end" data-boundary-source="profile" aria-label="Select on profile for end">Profile</button><button class="button secondary" type="button" data-boundary-button="end" data-boundary-source="map" aria-label="Select on map for end">Map</button><output data-boundary-output="end">{ formatProfileDistance(climb.EndKm) }</output></div>
+ </div>
<output class="boundary-preview" data-boundary-preview>Preview the corrected climb boundaries.</output>
<button class="button" type="submit">Save official climb</button>
</form>
diff --git a/web/templates_templ.go b/web/templates_templ.go
index 9ad0795..882107a 100644
--- a/web/templates_templ.go
+++ b/web/templates_templ.go
@@ -702,27 +702,27 @@ func RideDetailContent(data RideDetailView) templ.Component {
return templ_7745c5c3_Err
}
for _, climb := range data.Profile.UnmatchedClimbs() {
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"climb-item todo-item\" data-climb-item data-climb-index=\"")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"climb-item\" data-climb-item data-climb-index=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var43 string
templ_7745c5c3_Var43, templ_7745c5c3_Err = templ.JoinStringErrs(formatRouteIndex(climb.Index))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 128, Col: 109}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 128, Col: 99}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var43))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div class=\"climb-item-heading\"><strong><span class=\"todo-check\" aria-hidden=\"true\"></span><span class=\"climb-number\">Climb ")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><div class=\"climb-item-heading\"><strong><span class=\"climb-number\">Climb ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var44 string
templ_7745c5c3_Var44, templ_7745c5c3_Err = templ.JoinStringErrs(formatClimbNumber(climb.Index))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 130, Col: 133}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 130, Col: 82}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var44))
if templ_7745c5c3_Err != nil {
@@ -735,7 +735,7 @@ func RideDetailContent(data RideDetailView) templ.Component {
var templ_7745c5c3_Var45 string
templ_7745c5c3_Var45, templ_7745c5c3_Err = templ.JoinStringErrs(climb.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 130, Col: 154}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 130, Col: 103}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var45))
if templ_7745c5c3_Err != nil {
@@ -848,33 +848,33 @@ func RideDetailContent(data RideDetailView) templ.Component {
var templ_7745c5c3_Var54 string
templ_7745c5c3_Var54, templ_7745c5c3_Err = templ.JoinStringErrs(formatRouteIndex(climb.EndIndex))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 138, Col: 88}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 138, Col: 87}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var54))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-boundary-input=\"end\"><div class=\"boundary-controls\"><div><strong>Start</strong><div><button class=\"button secondary\" type=\"button\" data-boundary-button=\"start\" data-boundary-source=\"profile\">Select on profile</button><button class=\"button secondary\" type=\"button\" data-boundary-button=\"start\" data-boundary-source=\"map\">Select on map</button></div><output data-boundary-output=\"start\">")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" data-boundary-input=\"end\"><div class=\"boundary-controls\"><div><strong>Start</strong><button class=\"button secondary\" type=\"button\" data-boundary-button=\"start\" data-boundary-source=\"profile\" aria-label=\"Select on profile for start\">Profile</button><button class=\"button secondary\" type=\"button\" data-boundary-button=\"start\" data-boundary-source=\"map\" aria-label=\"Select on map for start\">Map</button><output data-boundary-output=\"start\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var55 string
templ_7745c5c3_Var55, templ_7745c5c3_Err = templ.JoinStringErrs(formatProfileDistance(climb.StartKm))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 140, Col: 382}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 140, Col: 428}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var55))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
- _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</output></div><div><strong>End</strong><div><button class=\"button secondary\" type=\"button\" data-boundary-button=\"end\" data-boundary-source=\"profile\">Select on profile</button><button class=\"button secondary\" type=\"button\" data-boundary-button=\"end\" data-boundary-source=\"map\">Select on map</button></div><output data-boundary-output=\"end\">")
+ _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</output></div><div><strong>End</strong><button class=\"button secondary\" type=\"button\" data-boundary-button=\"end\" data-boundary-source=\"profile\" aria-label=\"Select on profile for end\">Profile</button><button class=\"button secondary\" type=\"button\" data-boundary-button=\"end\" data-boundary-source=\"map\" aria-label=\"Select on map for end\">Map</button><output data-boundary-output=\"end\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var56 string
templ_7745c5c3_Var56, templ_7745c5c3_Err = templ.JoinStringErrs(formatProfileDistance(climb.EndKm))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 141, Col: 372}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/templates.templ`, Line: 141, Col: 414}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var56))
if templ_7745c5c3_Err != nil {