[OCaml] High Intensity Training Online
refactor space workout form controls
Group each movement and set-ending control set so desktop and mobile layouts use one typographic rhythm. Keep legends separate from their controls and retain visible gaps between stacked fields.
Changed files
lib/presenter/pages_workout.ml
@@ -24,7 +24,8 @@
24
24
reps stay together, so a responsive layout cannot mix two movements. *)
25
25
let movement_group ~name ~load_id ~load_field ~reps_id ~reps_field ?load_value
26
26
?reps_value ?previous_load ?previous_reps ~reps_label () =
27
Removed:
let number_field ~input_id ~field ~value ~step_ ~label ~previous ~unit =
27
Added:
let number_field ~additional_class ~input_id ~field ~value ~step_ ~label
28
Added:
~previous ~unit =
28
29
let input =
29
30
void "input"
30
31
([
@@ -56,7 +57,7 @@
56
57
@ [ input; tag "span" [ class_ "input-unit" ] [ txt "%s" unit ] ])
57
58
in
58
59
tag "div"
59
Removed:
[ class_ "field field-number" ]
60
Added:
[ class_ "field field-number%s" additional_class ]
60
61
[
61
62
tag "label"
62
63
[ Dream_html.string_attr "for" "%s" input_id; class_ "sr-only" ]
@@ -71,10 +72,16 @@
71
72
[ class_ "movement-fieldset" ]
72
73
[
73
74
tag "legend" [] [ txt "%s" name ];
74
Removed:
number_field ~input_id:load_id ~field:load_field ~value:load_value
75
Removed:
~step_:"0.5" ~label:"Load (kg)" ~previous:previous_load ~unit:"kg";
76
Removed:
number_field ~input_id:reps_id ~field:reps_field ~value:reps_value
77
Removed:
~step_:"1" ~label:reps_label ~previous:previous_reps ~unit:"reps";
75
Added:
tag "div"
76
Added:
[ class_ "movement-controls" ]
77
Added:
[
78
Added:
number_field ~additional_class:"" ~input_id:load_id
79
Added:
~field:load_field ~value:load_value ~step_:"0.5"
80
Added:
~label:"Load (kg)" ~previous:previous_load ~unit:"kg";
81
Added:
number_field ~additional_class:" field-after-load"
82
Added:
~input_id:reps_id ~field:reps_field ~value:reps_value ~step_:"1"
83
Added:
~label:reps_label ~previous:previous_reps ~unit:"reps";
84
Added:
];
78
85
];
79
86
]
80
87
@@ -99,55 +106,60 @@
99
106
[
100
107
tag "legend" [] [ txt "Set ending" ];
101
108
tag "div"
102
Removed:
[ class_ "field field-ending" ]
109
Added:
[ class_ "set-ending-controls" ]
103
110
[
104
Removed:
tag "label"
111
Added:
tag "div"
112
Added:
[ class_ "field field-ending" ]
105
113
[
106
Removed:
Dream_html.string_attr "for" "%s" (field_id "extension");
107
Removed:
class_ "sr-only";
108
Removed:
]
109
Removed:
[ txt "Ending" ];
110
Removed:
extension_select ~selected ~input_id:(field_id "extension") ();
111
Removed:
];
112
Removed:
tag "div"
113
Removed:
[ class_ "field field-extension-amount" ]
114
Removed:
[
115
Removed:
tag "label"
116
Removed:
[
117
Removed:
Dream_html.string_attr "for" "%s" (field_id "extension_amount");
118
Removed:
class_ "sr-only";
119
Removed:
]
120
Removed:
[
121
Removed:
tag "span"
122
Removed:
[ class_ "amount-label-reps" ]
123
Removed:
[ txt "Extension reps" ];
124
Removed:
tag "span" [ class_ "amount-label-sep" ] [ txt " / " ];
125
Removed:
tag "span"
126
Removed:
[ class_ "amount-label-seconds" ]
127
Removed:
[ txt "Hold seconds" ];
114
Added:
tag "label"
115
Added:
[
116
Added:
Dream_html.string_attr "for" "%s" (field_id "extension");
117
Added:
class_ "sr-only";
118
Added:
]
119
Added:
[ txt "Ending" ];
120
Added:
extension_select ~selected ~input_id:(field_id "extension") ();
128
121
];
129
122
tag "div"
130
Removed:
[ class_ "input-group" ]
123
Added:
[ class_ "field field-extension-amount field-after-ending" ]
131
124
[
132
Removed:
void "input"
125
Added:
tag "label"
133
126
[
134
Removed:
type_ "number";
135
Removed:
name "extension_amount";
136
Removed:
Dream_html.string_attr "id" "%s"
127
Added:
Dream_html.string_attr "for" "%s"
137
128
(field_id "extension_amount");
138
Removed:
Dream_html.string_attr "min" "1";
139
Removed:
step "1";
140
Removed:
Dream_html.string_attr "value" "%s"
141
Removed:
selected_extension_amount;
142
Removed:
];
143
Removed:
tag "span"
144
Removed:
[ class_ "input-unit" ]
129
Added:
class_ "sr-only";
130
Added:
]
145
131
[
146
Removed:
tag "span" [ class_ "amount-label-reps" ] [ txt "reps" ];
132
Added:
tag "span"
133
Added:
[ class_ "amount-label-reps" ]
134
Added:
[ txt "Extension reps" ];
147
135
tag "span" [ class_ "amount-label-sep" ] [ txt " / " ];
148
136
tag "span"
149
137
[ class_ "amount-label-seconds" ]
150
Removed:
[ txt "seconds" ];
138
Added:
[ txt "Hold seconds" ];
139
Added:
];
140
Added:
tag "div"
141
Added:
[ class_ "input-group" ]
142
Added:
[
143
Added:
void "input"
144
Added:
[
145
Added:
type_ "number";
146
Added:
name "extension_amount";
147
Added:
Dream_html.string_attr "id" "%s"
148
Added:
(field_id "extension_amount");
149
Added:
Dream_html.string_attr "min" "1";
150
Added:
step "1";
151
Added:
Dream_html.string_attr "value" "%s"
152
Added:
selected_extension_amount;
153
Added:
];
154
Added:
tag "span"
155
Added:
[ class_ "input-unit" ]
156
Added:
[
157
Added:
tag "span" [ class_ "amount-label-reps" ] [ txt "reps" ];
158
Added:
tag "span" [ class_ "amount-label-sep" ] [ txt " / " ];
159
Added:
tag "span"
160
Added:
[ class_ "amount-label-seconds" ]
161
Added:
[ txt "seconds" ];
162
Added:
];
151
163
];
152
164
];
153
165
];
lib/web/assets/hito.css
@@ -352,6 +352,7 @@
352
352
353
353
legend {
354
354
max-width: 100%;
355
Added:
margin: 0 0 1rem;
355
356
padding: 0 0.35rem;
356
357
color: var(--ink);
357
358
font: 700 var(--font-size-small)/1.35 var(--sans);
@@ -930,7 +931,7 @@
930
931
.movement-list {
931
932
display: flex;
932
933
flex-direction: column;
933
Removed:
gap: 0.7rem;
934
Added:
gap: 1rem;
934
935
margin: 0;
935
936
padding: 0;
936
937
list-style: none;
@@ -938,36 +939,29 @@
938
939
.movement-group {
939
940
margin: 0;
940
941
}
941
Removed:
.movement-fieldset {
942
Removed:
display: flex;
943
Removed:
flex-wrap: wrap;
944
Removed:
align-items: center;
945
Removed:
gap: 0.6rem;
942
Added:
.movement-fieldset,
943
Added:
.set-ending {
946
944
margin: 0;
947
945
padding: 0;
948
946
border: 0;
949
947
}
950
Removed:
.movement-fieldset > legend {
951
Removed:
flex: 1 0 100%;
952
Removed:
}
953
Removed:
.movement-fieldset > .field,
954
Removed:
.set-ending > .field-ending {
955
Removed:
flex: 1 1 15rem;
956
Removed:
}
957
Removed:
.set-ending > .field-extension-amount {
958
Removed:
flex: 0 1 18rem;
959
Removed:
}
960
948
.movement-fieldset > legend,
961
949
.set-ending > legend {
962
Removed:
margin: 0 0 0.25rem;
963
Removed:
padding: 0;
950
Added:
margin: 0;
951
Added:
padding: 0 0 0.75rem;
964
952
color: var(--ink);
965
953
font: 600 var(--font-size-lead)/1.2 var(--sans);
966
954
letter-spacing: -0.01em;
967
955
text-transform: none;
968
956
}
969
Removed:
.movement-fieldset > .field,
970
Removed:
.set-ending > .field {
957
Added:
.movement-controls,
958
Added:
.set-ending-controls {
959
Added:
display: grid;
960
Added:
grid-template-columns: repeat(2, minmax(0, 1fr));
961
Added:
gap: 0.6rem;
962
Added:
}
963
Added:
.movement-controls > .field,
964
Added:
.set-ending-controls > .field {
971
965
min-width: 0;
972
966
margin: 0;
973
967
}
@@ -1025,18 +1019,6 @@
1025
1019
}
1026
1020
/* The set ending is a property of the completed stimulus. Its spacing and
1027
1021
legend make that distinction clear without a second card. */
1028
Removed:
.set-ending {
1029
Removed:
display: flex;
1030
Removed:
flex-wrap: wrap;
1031
Removed:
align-items: center;
1032
Removed:
gap: 0.6rem;
1033
Removed:
margin: 0.1rem 0 0;
1034
Removed:
padding: 0.9rem 0 0;
1035
Removed:
border: 0;
1036
Removed:
}
1037
Removed:
.set-ending > legend {
1038
Removed:
flex: 1 0 100%;
1039
Removed:
}
1040
1022
.record-action { margin: 0 !important; }
1041
1023
.correction-actions {
1042
1024
display: grid;
@@ -1366,17 +1348,18 @@
1366
1348
}
1367
1349
1368
1350
/* One column: a movement and its ending each take the full width. */
1369
Removed:
.movement-fieldset,
1370
Removed:
.set-ending {
1371
Removed:
flex-direction: column;
1372
Removed:
align-items: stretch;
1351
Added:
.movement-controls,
1352
Added:
.set-ending-controls {
1353
Added:
grid-template-columns: 1fr;
1354
Added:
gap: 0;
1373
1355
}
1374
Removed:
.movement-fieldset > legend,
1375
Removed:
.movement-fieldset > .field,
1376
Removed:
.set-ending > legend,
1377
Removed:
.set-ending > .field {
1378
Removed:
flex: 0 0 auto;
1379
Removed:
width: 100%;
1356
Added:
.movement-controls > .field,
1357
Added:
.set-ending-controls > .field {
1358
Added:
margin-bottom: 0.6rem;
1359
Added:
}
1360
Added:
.movement-controls > .field:last-child,
1361
Added:
.set-ending-controls > .field:last-child {
1362
Added:
margin-bottom: 0;
1380
1363
}
1381
1364
.correction-actions {
1382
1365
grid-template-columns: 1fr;