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.

Commit
683375b2ec8db127947e4a42f0437aa253858d84
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/presenter/pages_workout.ml
index 596ab5cc..e81aa343 100644..100644
@@ -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
index ab92662a..e4d6bb57 100644..100644
@@ -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;