Skip to content

Commit 32dd506

Browse files
fix(pygal): address review feedback for line-retention-cohort
Attempt 2/3 - fixes based on AI review
1 parent 2674a10 commit 32dd506

1 file changed

Lines changed: 38 additions & 18 deletions

File tree

  • plots/line-retention-cohort/implementations

plots/line-retention-cohort/implementations/pygal.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" pyplots.ai
1+
"""pyplots.ai
22
line-retention-cohort: User Retention Curve by Cohort
33
Library: pygal 3.1.0 | Python 3.14.3
44
Quality: 81/100 | Created: 2026-03-16
@@ -31,28 +31,37 @@
3131
retention.append(max(round(prev - max(drop, 0.5), 1), 5.0))
3232
retention_data[cohort] = retention
3333

34-
# Style - reference line color first, then cohort colors fading from muted to vivid
34+
# Style - threshold line first, then cohort colors with higher minimum opacity
3535
colors_with_opacity = (
36-
"rgba(180, 60, 60, 0.6)",
37-
"rgba(48, 105, 152, 0.45)",
38-
"rgba(232, 119, 93, 0.55)",
39-
"rgba(80, 168, 110, 0.70)",
40-
"rgba(212, 168, 67, 0.85)",
41-
"rgba(139, 107, 174, 1.0)",
36+
"rgba(200, 50, 50, 0.85)",
37+
"rgba(48, 105, 152, 0.65)",
38+
"rgba(220, 100, 70, 0.75)",
39+
"rgba(60, 160, 100, 0.85)",
40+
"rgba(200, 155, 50, 0.92)",
41+
"rgba(130, 90, 170, 1.0)",
4242
)
4343

4444
custom_style = Style(
45-
background="white",
46-
plot_background="white",
47-
foreground="#333",
48-
foreground_strong="#333",
49-
foreground_subtle="#cccccc",
45+
background="#fafafa",
46+
plot_background="#fafafa",
47+
foreground="#2a2a2a",
48+
foreground_strong="#1a1a1a",
49+
foreground_subtle="#d8d8d8",
5050
colors=colors_with_opacity,
5151
title_font_size=72,
5252
label_font_size=48,
5353
major_label_font_size=42,
5454
legend_font_size=40,
5555
value_font_size=36,
56+
opacity=".95",
57+
opacity_hover="1",
58+
transition="200ms ease-in",
59+
font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
60+
title_font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
61+
legend_font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
62+
label_font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
63+
major_label_font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
64+
value_font_family="'Segoe UI', 'Helvetica Neue', Arial, sans-serif",
5665
)
5766

5867
# Plot
@@ -69,35 +78,46 @@
6978
show_y_guides=True,
7079
show_x_guides=False,
7180
legend_at_bottom=True,
81+
legend_at_bottom_columns=3,
7282
truncate_legend=-1,
7383
range=(0, 105),
7484
x_label_rotation=0,
7585
value_formatter=lambda x: f"{x:.0f}%" if x is not None else "",
7686
tooltip_fancy_mode=True,
87+
tooltip_border_radius=6,
7788
interpolate="cubic",
89+
show_minor_x_labels=False,
90+
y_labels=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100],
91+
margin_top=40,
92+
margin_bottom=60,
93+
spacing=30,
7894
)
7995

8096
chart.x_labels = [str(w) for w in weeks]
97+
chart.x_labels_major = ["0", "3", "6", "9", "12"]
8198

82-
# Add reference threshold line at 20% retention
99+
# Add reference threshold line at 20% retention - bold and visible
83100
chart.add(
84-
"20% Retention Threshold",
101+
"\u2500\u2500 20% Retention Threshold",
85102
[20.0] * len(weeks),
86-
stroke_style={"width": 2, "dasharray": "12, 8"},
103+
stroke_style={"width": 3, "dasharray": "16, 8"},
87104
show_dots=False,
88105
dots_size=0,
89106
)
90107

91108
# Add cohorts with increasing stroke width for newer cohorts
92-
stroke_widths = [2, 3, 4, 5, 7]
109+
stroke_widths = [3, 3.5, 4, 5, 7]
93110
dot_sizes = [4, 5, 5, 6, 8]
94111
cohort_list = list(cohorts.items())
95112

96113
for i, (cohort, params) in enumerate(cohort_list):
97114
label = f"{cohort} (n={params['size']:,})"
98115
chart.add(
99116
label,
100-
[{"value": v, "label": f"Week {w}: {v:.1f}% retained"} for w, v in zip(weeks, retention_data[cohort], strict=True)],
117+
[
118+
{"value": v, "label": f"Week {w}: {v:.1f}% retained"}
119+
for w, v in zip(weeks, retention_data[cohort], strict=True)
120+
],
101121
stroke_style={"width": stroke_widths[i]},
102122
dots_size=dot_sizes[i],
103123
)

0 commit comments

Comments
 (0)