[OCaml] High Intensity Training Online
feat Drop the Load and Reps column headings
A pre-exhaust pair rendered a heading row — Load (kg), Reps — above its inputs, and a single exercise rendered the same words as visible labels. Both repeat what the inputs already say through their kg and reps placeholders. Remove the heading row and make every per-input label screen-reader-only, so each field keeps its accessible name while the visible form carries the meaning once, in the input itself.
Changed files
lib/presenter/pages_workout.ml
@@ -45,8 +45,8 @@
45
45
[ txt "%s" (errors_to_text [ (field, error) ]) ];
46
46
]
47
47
48
Removed:
let input_row ?value:v ?(invalid = false) ?placeholder ?(hide_label = false)
49
Removed:
~input_id (field : string) label =
48
Added:
let input_row ?value:v ?(invalid = false) ?placeholder ~input_id
49
Added:
(field : string) label =
50
50
let error_attrs =
51
51
if invalid then
52
52
[
@@ -64,10 +64,7 @@
64
64
[ class_ "field" ]
65
65
[
66
66
tag "label"
67
Removed:
[
68
Removed:
Dream_html.string_attr "for" "%s" input_id;
69
Removed:
class_ (if hide_label then "sr-only" else "");
70
Removed:
]
67
Added:
[ Dream_html.string_attr "for" "%s" input_id; class_ "sr-only" ]
71
68
[ txt "%s" label ];
72
69
void "input"
73
70
([
@@ -91,32 +88,19 @@
91
88
load, and reps columns line up across the whole fieldset. The name reads as a
92
89
heading, the inputs as labelled fields. *)
93
90
let movement_row ~(errors : (string * string) list) ~name ~load_id ~load_field
94
Removed:
~reps_id ~reps_field ?load_value ?reps_value ~reps_label
95
Removed:
?(hide_labels = false) () =
91
Added:
~reps_id ~reps_field ?load_value ?reps_value ~reps_label () =
96
92
tag "div"
97
93
[ class_ "movement" ]
98
94
[
99
95
tag "p" [ class_ "exercise-name" ] [ txt "%s" name ];
100
Removed:
input_row ?value:load_value ~placeholder:"kg" ~hide_label:hide_labels
96
Added:
input_row ?value:load_value ~placeholder:"kg"
101
97
~invalid:(List.mem_assoc load_field errors)
102
98
~input_id:load_id load_field "Load (kg)";
103
Removed:
input_row ?value:reps_value ~placeholder:"reps" ~hide_label:hide_labels
99
Added:
input_row ?value:reps_value ~placeholder:"reps"
104
100
~invalid:(List.mem_assoc reps_field errors)
105
101
~input_id:reps_id reps_field reps_label;
106
102
]
107
103
108
Removed:
(* A shared heading row for a multi-exercise group: empty name cell, then the
109
Removed:
Load and Reps column headings. Rendered once as cells of the fieldset grid so
110
Removed:
the labels are not repeated above every input. *)
111
Removed:
let exercise_fields_head ~reps_label () =
112
Removed:
tag "div"
113
Removed:
[ class_ "movement movement-head" ]
114
Removed:
[
115
Removed:
tag "span" [ class_ "exercise-name" ] [ txt "" ];
116
Removed:
tag "span" [ class_ "col-heading" ] [ txt "Load (kg)" ];
117
Removed:
tag "span" [ class_ "col-heading" ] [ txt "%s" reps_label ];
118
Removed:
]
119
Removed:
120
104
(* [movements] carries the record/correction field spec the controller built
121
105
from the slot's prescription: one row for a single exercise, two for a
122
106
pre-exhaust pair, each already pre-filled when correcting. [submit] names the
@@ -127,26 +111,13 @@
127
111
~(errors : (string * string) list) () =
128
112
let field_id field = Printf.sprintf "slot-%d-%s" slot field in
129
113
let selected = selected_extension in
130
Removed:
(* A single-exercise slot shows one row with a visible "Reps to failure"
131
Removed:
label. A pre-exhaust pair shows a shared column heading and hides the
132
Removed:
per-row labels. *)
133
Removed:
let hide_labels = List.length movements > 1 in
134
Removed:
let head =
135
Removed:
match movements with
136
Removed:
| first :: _ :: _ ->
137
Removed:
[
138
Removed:
exercise_fields_head ~reps_label:first.View_model.Workout.reps_label
139
Removed:
();
140
Removed:
]
141
Removed:
| _ -> []
142
Removed:
in
143
114
let movement_of (m : View_model.Workout.movement) =
144
115
movement_row ~errors ~name:m.name ~load_id:(field_id m.load_field)
145
116
~load_field:m.load_field ~reps_id:(field_id m.reps_field)
146
117
~reps_field:m.reps_field ?load_value:m.load_value ?reps_value:m.reps_value
147
Removed:
~reps_label:m.reps_label ~hide_labels ()
118
Added:
~reps_label:m.reps_label ()
148
119
in
149
Removed:
let fields = head @ List.map movement_of movements in
120
Added:
let fields = List.map movement_of movements in
150
121
(* The error rows follow the fields present, so a single-exercise slot reports
151
122
load/reps and a pre-exhaust slot reports the iso/comp fields. *)
152
123
let field_names =
lib/web/assets/hito.css
@@ -591,18 +591,8 @@
591
591
}
592
592
}
593
593
594
Removed:
/* A shared heading row: the Load and Reps column headings shown once above a
595
Removed:
multi-exercise group, so the labels are not repeated above every input. The
596
Removed:
cells sit in the same grid columns as the movement inputs below them. */
597
Removed:
.col-heading {
598
Removed:
color: var(--ink);
599
Removed:
font-size: var(--font-size-small);
600
Removed:
font-weight: 700;
601
Removed:
align-self: end;
602
Removed:
}
603
Removed:
604
594
/* Visually hidden but available to assistive technology: the per-input labels
605
Removed:
stay for screen readers while the visible headings carry the column names. */
595
Added:
stay for screen readers while the placeholders carry the visible meaning. */
606
596
.sr-only {
607
597
position: absolute;
608
598
width: 1px;