Skip to content

Commit df51292

Browse files
feat(plotly): implement timeline-basic (#2452)
## Implementation: `timeline-basic` - plotly Implements the **plotly** version of `timeline-basic`. **File:** `plots/timeline-basic/implementations/plotly.py` --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20584328110)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 97500ac commit df51292

2 files changed

Lines changed: 193 additions & 0 deletions

File tree

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
""" pyplots.ai
2+
timeline-basic: Event Timeline
3+
Library: plotly 6.5.0 | Python 3.13.11
4+
Quality: 91/100 | Created: 2025-12-29
5+
"""
6+
7+
import pandas as pd
8+
import plotly.graph_objects as go
9+
10+
11+
# Data - Software project milestones with phases
12+
data = {
13+
"date": pd.to_datetime(
14+
[
15+
"2024-01-15",
16+
"2024-02-20",
17+
"2024-03-10",
18+
"2024-04-05",
19+
"2024-05-15",
20+
"2024-06-01",
21+
"2024-07-10",
22+
"2024-08-20",
23+
"2024-09-15",
24+
"2024-10-30",
25+
"2024-11-15",
26+
"2024-12-10",
27+
]
28+
),
29+
"event": [
30+
"Project Kickoff",
31+
"Requirements Complete",
32+
"Design Review",
33+
"Development Start",
34+
"Alpha Release",
35+
"User Testing",
36+
"Beta Release",
37+
"Performance Optimization",
38+
"Security Audit",
39+
"Release Candidate",
40+
"Documentation Complete",
41+
"Production Launch",
42+
],
43+
"category": [
44+
"Planning",
45+
"Planning",
46+
"Planning",
47+
"Development",
48+
"Development",
49+
"Testing",
50+
"Testing",
51+
"Development",
52+
"Testing",
53+
"Release",
54+
"Release",
55+
"Release",
56+
],
57+
}
58+
df = pd.DataFrame(data)
59+
60+
# Color mapping for categories
61+
colors = {
62+
"Planning": "#306998", # Python Blue
63+
"Development": "#FFD43B", # Python Yellow
64+
"Testing": "#4ECDC4", # Teal
65+
"Release": "#E74C3C", # Red-Orange
66+
}
67+
68+
# Alternate positions (above/below axis) to prevent label overlap
69+
positions = [1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1]
70+
df["position"] = positions
71+
72+
# Create figure
73+
fig = go.Figure()
74+
75+
# Add the timeline axis line
76+
fig.add_trace(
77+
go.Scatter(
78+
x=[df["date"].min() - pd.Timedelta(days=15), df["date"].max() + pd.Timedelta(days=15)],
79+
y=[0, 0],
80+
mode="lines",
81+
line=dict(color="#333333", width=3),
82+
hoverinfo="skip",
83+
showlegend=False,
84+
)
85+
)
86+
87+
# Add vertical connector lines for each event
88+
for _, row in df.iterrows():
89+
fig.add_trace(
90+
go.Scatter(
91+
x=[row["date"], row["date"]],
92+
y=[0, row["position"] * 0.4],
93+
mode="lines",
94+
line=dict(color="#888888", width=2, dash="dot"),
95+
hoverinfo="skip",
96+
showlegend=False,
97+
)
98+
)
99+
100+
# Add event markers and labels by category
101+
for category in df["category"].unique():
102+
cat_df = df[df["category"] == category]
103+
104+
fig.add_trace(
105+
go.Scatter(
106+
x=cat_df["date"],
107+
y=[0] * len(cat_df),
108+
mode="markers",
109+
marker=dict(size=20, color=colors[category], line=dict(color="white", width=2)),
110+
name=category,
111+
hovertemplate="<b>%{text}</b><br>%{x|%B %d, %Y}<extra></extra>",
112+
text=cat_df["event"],
113+
)
114+
)
115+
116+
# Add event labels
117+
for _, row in df.iterrows():
118+
y_offset = row["position"] * 0.5
119+
fig.add_annotation(
120+
x=row["date"],
121+
y=y_offset,
122+
text=row["event"],
123+
showarrow=False,
124+
font=dict(size=16, color="#333333"),
125+
xanchor="center",
126+
yanchor="bottom" if row["position"] > 0 else "top",
127+
)
128+
129+
# Add date labels below markers
130+
for _, row in df.iterrows():
131+
fig.add_annotation(
132+
x=row["date"],
133+
y=row["position"] * 0.15,
134+
text=row["date"].strftime("%b %d"),
135+
showarrow=False,
136+
font=dict(size=12, color="#666666"),
137+
xanchor="center",
138+
yanchor="bottom" if row["position"] > 0 else "top",
139+
)
140+
141+
# Layout
142+
fig.update_layout(
143+
title=dict(
144+
text="timeline-basic · plotly · pyplots.ai", font=dict(size=28, color="#333333"), x=0.5, xanchor="center"
145+
),
146+
xaxis=dict(
147+
title=dict(text="Project Timeline (2024)", font=dict(size=22)),
148+
tickfont=dict(size=18),
149+
tickformat="%B",
150+
dtick="M1",
151+
showgrid=True,
152+
gridcolor="rgba(0,0,0,0.1)",
153+
gridwidth=1,
154+
zeroline=False,
155+
),
156+
yaxis=dict(visible=False, range=[-1, 1], fixedrange=True),
157+
template="plotly_white",
158+
showlegend=True,
159+
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5, font=dict(size=16)),
160+
margin=dict(l=80, r=80, t=120, b=80),
161+
plot_bgcolor="white",
162+
paper_bgcolor="white",
163+
)
164+
165+
# Save as PNG and HTML
166+
fig.write_image("plot.png", width=1600, height=900, scale=3)
167+
fig.write_html("plot.html", include_plotlyjs=True, full_html=True)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
library: plotly
2+
specification_id: timeline-basic
3+
created: '2025-12-29T22:47:16Z'
4+
updated: '2025-12-29T22:50:25Z'
5+
generated_by: claude-opus-4-5-20251101
6+
workflow_run: 20584328110
7+
issue: 0
8+
python_version: 3.13.11
9+
library_version: 6.5.0
10+
preview_url: https://storage.googleapis.com/pyplots-images/plots/timeline-basic/plotly/plot.png
11+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/timeline-basic/plotly/plot_thumb.png
12+
preview_html: https://storage.googleapis.com/pyplots-images/plots/timeline-basic/plotly/plot.html
13+
quality_score: 91
14+
review:
15+
strengths:
16+
- Excellent implementation of alternating label positions above/below the axis to
17+
prevent text overlap
18+
- Clean use of Plotly annotation system for event labels and date labels
19+
- Interactive hover templates showing formatted dates enhance usability
20+
- Color scheme effectively distinguishes the four project phases
21+
- Proper use of go.Scatter for both the timeline axis and event markers
22+
weaknesses:
23+
- Yellow markers (#FFD43B) have lower contrast against white background
24+
- Vertical grid lines could be more subtle or removed for cleaner appearance
25+
- Could leverage Plotly interactivity more (e.g., range slider for zooming dense
26+
timelines)

0 commit comments

Comments
 (0)