[OCaml] High Intensity Training Online
style improve optical balance of the progress charts
- Wider aspect (640x260) and fixed side gutters, so stacked charts share one left edge and sparse two-point series no longer look empty. - Faint horizontal gridlines anchor the lines and give mid-value reference. - Bind each heading, legend, and chart into one group with a clear gap between blocks, and anchor the kg/reps titles just above their axes. - Differentiate the series so weight leads: solid oxblood weight line, dashed brass reps line, with matching legend swatches.
Changed files
lib/presenter/svg_chart.ml
@@ -16,13 +16,16 @@
16
16
let sattr = string_attr
17
17
let fattr = float_attr
18
18
19
Removed:
(* Fixed drawing surface. The viewBox scales to the container width via CSS. *)
19
Added:
(* Fixed drawing surface. The viewBox scales to the container width via CSS. A
20
Added:
wider-than-tall aspect keeps sparse two-point series from looking empty. The
21
Added:
side gutters are fixed, so every chart's plot area starts at the same x and
22
Added:
the stacked charts share one clean left edge. *)
20
23
let width = 640.
21
Removed:
let height = 320.
22
Removed:
let pad_left = 48.
23
Removed:
let pad_right = 48.
24
Removed:
let pad_top = 24.
25
Removed:
let pad_bottom = 36.
24
Added:
let height = 260.
25
Added:
let pad_left = 52.
26
Added:
let pad_right = 52.
27
Added:
let pad_top = 22.
28
Added:
let pad_bottom = 34.
26
29
let plot_w = width -. pad_left -. pad_right
27
30
let plot_h = height -. pad_top -. pad_bottom
28
31
@@ -72,6 +75,20 @@
72
75
]
73
76
[]
74
77
78
Added:
(* A faint full-width horizontal rule at fraction [f] of the plot height, to
79
Added:
anchor the lines without competing with them. *)
80
Added:
let gridline f =
81
Added:
let y = pad_top +. (plot_h *. f) in
82
Added:
line
83
Added:
[
84
Added:
sattr "class" "chart-grid";
85
Added:
fattr "x1" pad_left;
86
Added:
fattr "y1" y;
87
Added:
fattr "x2" (pad_left +. plot_w);
88
Added:
fattr "y2" y;
89
Added:
]
90
Added:
[]
91
Added:
75
92
let axis_label ~x ~y ~anchor ~css_class s =
76
93
text
77
94
[
@@ -127,16 +144,20 @@
127
144
| [] -> ""
128
145
in
129
146
[
147
Added:
(* Faint gridlines first, so axes and series sit on top. *)
148
Added:
gridline 0.25;
149
Added:
gridline 0.5;
150
Added:
gridline 0.75;
130
151
(* Axes: left (weight), right (reps), and a baseline. *)
131
152
axis_line ~x1:pad_left ~y1:pad_top ~x2:pad_left ~y2:(pad_top +. plot_h);
132
153
axis_line ~x1:(pad_left +. plot_w) ~y1:pad_top ~x2:(pad_left +. plot_w)
133
154
~y2:(pad_top +. plot_h);
134
155
axis_line ~x1:pad_left ~y1:(pad_top +. plot_h) ~x2:(pad_left +. plot_w)
135
156
~y2:(pad_top +. plot_h);
136
Removed:
(* Axis titles. *)
137
Removed:
axis_label ~x:pad_left ~y:(pad_top -. 10.) ~anchor:"middle"
157
Added:
(* Axis titles, anchored just above their axis. *)
158
Added:
axis_label ~x:pad_left ~y:(pad_top -. 8.) ~anchor:"middle"
138
159
~css_class:"chart-axis-title weight" "kg";
139
Removed:
axis_label ~x:(pad_left +. plot_w) ~y:(pad_top -. 10.) ~anchor:"middle"
160
Added:
axis_label ~x:(pad_left +. plot_w) ~y:(pad_top -. 8.) ~anchor:"middle"
140
161
~css_class:"chart-axis-title reps" "reps";
141
162
(* Left axis bounds (weight, kg). *)
142
163
axis_label ~x:(pad_left -. 6.) ~y:(pad_top +. 4.) ~anchor:"end"
lib/web/assets/hito.css
@@ -763,50 +763,54 @@
763
763
/* The action bar under the logbook heading. */
764
764
.logbook-actions-bar { margin: 0.5rem 0 1rem; }
765
765
766
Removed:
/* The progress page: a no-JS exercise search and a dual-axis line chart. */
767
Removed:
.progress-search {
768
Removed:
display: flex;
769
Removed:
flex-wrap: wrap;
770
Removed:
gap: 0.5rem;
771
Removed:
align-items: end;
772
Removed:
margin: 1rem 0 1.5rem;
766
Added:
/* The progress page: one dual-axis line chart per chartable exercise. Each
767
Added:
block binds its heading, legend, and chart into one group with a clear gap
768
Added:
to the next. */
769
Added:
.progress-chart-section {
770
Added:
margin: 0 0 2rem;
773
771
}
774
Removed:
.progress-search label {
775
Removed:
flex: 0 0 100%;
776
Removed:
margin: 0;
772
Added:
.progress-chart-section h2 {
773
Added:
margin-bottom: 0.25rem;
777
774
}
778
Removed:
.progress-search input { flex: 1 1 14rem; }
779
Removed:
.progress-search button { flex: 0 0 auto; }
780
Removed:
781
Removed:
.progress-chart-section { margin-top: 1rem; }
782
775
.chart-legend {
783
776
display: flex;
784
777
flex-wrap: wrap;
785
778
gap: 1rem;
786
Removed:
margin: 0.5rem 0 1rem;
779
Added:
margin: 0 0 0.35rem;
787
780
font-size: var(--font-size-small);
781
Added:
color: var(--muted-ink);
788
782
}
789
783
.chart-legend-item { display: inline-flex; align-items: center; gap: 0.4rem; }
790
784
.chart-legend-item::before {
791
785
content: "";
792
Removed:
width: 1.1rem;
793
Removed:
height: 0.2rem;
794
Removed:
border-radius: 999px;
786
Added:
width: 1.4rem;
787
Added:
height: 0;
788
Added:
border-top: 2px solid;
795
789
}
796
Removed:
.chart-legend-item.weight::before { background: var(--oxblood); }
797
Removed:
.chart-legend-item.reps::before { background: var(--brass); }
790
Added:
.chart-legend-item.weight::before { border-top-color: var(--oxblood); }
791
Added:
.chart-legend-item.reps::before {
792
Added:
border-top-color: var(--brass);
793
Added:
border-top-style: dashed;
794
Added:
}
798
795
799
796
/* The chart scales to its container; the viewBox does the layout. */
800
797
.progress-chart {
798
Added:
display: block;
801
799
width: 100%;
802
800
height: auto;
803
801
max-width: 40rem;
804
802
}
805
803
.chart-axis { stroke: var(--rule-strong); stroke-width: 1; }
804
Added:
.chart-grid { stroke: var(--rule); stroke-width: 1; opacity: 0.5; }
806
805
.chart-tick { font: 500 0.7rem var(--mono); fill: var(--muted-ink); }
806
Added:
.chart-axis-title { font: 700 0.72rem var(--sans); }
807
Added:
.chart-axis-title.weight { fill: var(--oxblood-dark); }
808
Added:
.chart-axis-title.reps { fill: var(--brass); }
809
Added:
/* Weight is the primary series: a solid oxblood line leads. Reps is secondary:
810
Added:
a dashed brass line, so the two never blur together on a busy chart. */
807
811
.chart-series { fill: none; stroke-width: 2; }
808
812
.chart-series.weight { stroke: var(--oxblood); }
809
Removed:
.chart-series.reps { stroke: var(--brass); }
813
Added:
.chart-series.reps { stroke: var(--brass); stroke-dasharray: 5 3; }
810
814
@keyframes logbook-detail-open {
811
815
from { opacity: 0; transform: translateY(-0.25rem); }
812
816
to { opacity: 1; transform: none; }