Skip to content

Commit c9d11e7

Browse files
strickvlclaude
andcommitted
Refactor CSS to shared styles and utility functions
- Created shared CSS file at assets/styles.css consolidating all common styles - Added CSS utility functions in utils/css_utils.py for consistent styling - Updated all materializers to use shared CSS instead of inline styles - Updated report template in prompts.py to use shared CSS - Fixed unused 'question' variable in approval_decision_materializer.py - Reduced code duplication across all visualization components This refactoring improves maintainability by centralizing style definitions and provides consistent visual styling across all materializers. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 19eb71a commit c9d11e7

12 files changed

+1938
-1512
lines changed

deep_research/assets/styles.css

Lines changed: 672 additions & 0 deletions
Large diffs are not rendered by default.

deep_research/materializers/analysis_data_materializer.py

Lines changed: 45 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
import os
44
from typing import Dict
55

6+
from utils.css_utils import (
7+
get_card_class,
8+
get_section_class,
9+
get_shared_css_tag,
10+
)
611
from utils.pydantic_models import AnalysisData
712
from zenml.enums import ArtifactType, VisualizationType
813
from zenml.io import fileio
@@ -51,7 +56,7 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
5156
# Points of agreement
5257
agreement_html = ""
5358
if va.main_points_of_agreement:
54-
agreement_html = "<div class='agreement-points'><h3>Main Points of Agreement</h3><ul>"
59+
agreement_html = "<div class='dr-section dr-section--success'><h3>Main Points of Agreement</h3><ul class='dr-list'>"
5560
for point in va.main_points_of_agreement:
5661
agreement_html += f"<li>{point}</li>"
5762
agreement_html += "</ul></div>"
@@ -60,13 +65,13 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
6065
tensions_html = ""
6166
if va.areas_of_tension:
6267
tensions_html = (
63-
"<div class='tensions'><h3>Areas of Tension</h3>"
68+
"<div class='tensions-section'><h3>Areas of Tension</h3>"
6469
)
6570
for tension in va.areas_of_tension:
6671
viewpoints_html = ""
6772
for perspective, view in tension.viewpoints.items():
6873
viewpoints_html += f"""
69-
<div class="viewpoint">
74+
<div class="viewpoint-item">
7075
<div class="viewpoint-label">{perspective}</div>
7176
<div class="viewpoint-text">{view}</div>
7277
</div>
@@ -86,7 +91,7 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
8691
gaps_html = ""
8792
if va.perspective_gaps:
8893
gaps_html = f"""
89-
<div class='perspective-gaps'>
94+
<div class='{get_section_class("warning")}'>
9095
<h3>Perspective Gaps</h3>
9196
<p>{va.perspective_gaps}</p>
9297
</div>
@@ -96,14 +101,14 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
96101
insights_html = ""
97102
if va.integrative_insights:
98103
insights_html = f"""
99-
<div class='integrative-insights'>
104+
<div class='{get_section_class("info")}'>
100105
<h3>Integrative Insights</h3>
101106
<p>{va.integrative_insights}</p>
102107
</div>
103108
"""
104109

105110
viewpoint_html = f"""
106-
<div class="viewpoint-section">
111+
<div class="{get_card_class()}">
107112
<h2>Viewpoint Analysis</h2>
108113
{agreement_html}
109114
{tensions_html}
@@ -120,23 +125,23 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
120125
# Critique summary
121126
critique_html = ""
122127
if rm.critique_summary:
123-
critique_html = "<div class='critique-summary'><h3>Critique Summary</h3><ul>"
128+
critique_html = "<div class='dr-section dr-section--danger'><h3>Critique Summary</h3><ul class='dr-list'>"
124129
for critique in rm.critique_summary:
125130
critique_html += f"<li>{critique}</li>"
126131
critique_html += "</ul></div>"
127132

128133
# Additional questions
129134
questions_html = ""
130135
if rm.additional_questions_identified:
131-
questions_html = "<div class='additional-questions'><h3>Additional Questions Identified</h3><ul>"
136+
questions_html = "<div class='dr-section dr-section--info'><h3>Additional Questions Identified</h3><ul class='dr-list'>"
132137
for question in rm.additional_questions_identified:
133138
questions_html += f"<li>{question}</li>"
134139
questions_html += "</ul></div>"
135140

136141
# Searches performed
137142
searches_html = ""
138143
if rm.searches_performed:
139-
searches_html = "<div class='searches-performed'><h3>Searches Performed</h3><ul>"
144+
searches_html = "<div class='dr-section dr-section--success'><h3>Searches Performed</h3><ul class='dr-list'>"
140145
for search in rm.searches_performed:
141146
searches_html += f"<li>{search}</li>"
142147
searches_html += "</ul></div>"
@@ -145,18 +150,18 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
145150
error_html = ""
146151
if rm.error:
147152
error_html = f"""
148-
<div class='error-message'>
153+
<div class='dr-notice dr-notice--warning'>
149154
<h3>Error Encountered</h3>
150155
<p>{rm.error}</p>
151156
</div>
152157
"""
153158

154159
reflection_html = f"""
155-
<div class="reflection-section">
160+
<div class="{get_card_class()}">
156161
<h2>Reflection Metadata</h2>
157-
<div class="improvements-count">
158-
<span class="count">{int(rm.improvements_made)}</span>
159-
<span class="label">Improvements Made</span>
162+
<div class="improvements-counter">
163+
<span class="count-value">{int(rm.improvements_made)}</span>
164+
<span class="count-label">Improvements Made</span>
160165
</div>
161166
{critique_html}
162167
{questions_html}
@@ -168,7 +173,7 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
168173
# Handle empty state
169174
if not viewpoint_html and not reflection_html:
170175
content_html = (
171-
'<div class="no-analysis">No analysis data available yet</div>'
176+
'<div class="dr-empty">No analysis data available yet</div>'
172177
)
173178
else:
174179
content_html = viewpoint_html + reflection_html
@@ -178,79 +183,23 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
178183
<html>
179184
<head>
180185
<title>Analysis Data Visualization</title>
186+
{get_shared_css_tag()}
181187
<style>
188+
/* Component-specific styles */
182189
body {{
183-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
184-
margin: 0;
185-
padding: 20px;
186190
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
187191
min-height: 100vh;
188-
color: #333;
189192
}}
190193
191-
.container {{
192-
max-width: 1200px;
193-
margin: 0 auto;
194-
}}
195-
196-
.header {{
197-
background: white;
198-
border-radius: 15px;
199-
padding: 30px;
200-
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
201-
margin-bottom: 30px;
202-
text-align: center;
203-
}}
204-
205-
h1 {{
206-
margin: 0;
207-
color: #2c3e50;
208-
font-size: 36px;
209-
}}
210-
211-
.viewpoint-section,
212-
.reflection-section {{
213-
background: white;
214-
border-radius: 15px;
215-
padding: 30px;
216-
margin-bottom: 30px;
217-
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
218-
}}
219-
220-
h2 {{
221-
color: #2c3e50;
222-
margin: 0 0 25px 0;
223-
padding-bottom: 15px;
224-
border-bottom: 2px solid #e9ecef;
225-
}}
226-
227-
h3 {{
228-
color: #495057;
229-
margin: 25px 0 15px 0;
230-
}}
231-
232-
h4 {{
233-
color: #6c757d;
234-
margin: 15px 0 10px 0;
235-
}}
236-
237-
.agreement-points {{
238-
background: #f0f9ff;
239-
border-radius: 10px;
240-
padding: 20px;
241-
margin-bottom: 20px;
242-
border-left: 4px solid #2dce89;
243-
}}
244-
245-
.tensions {{
246-
margin-top: 25px;
194+
.tensions-section {{
195+
margin-top: var(--spacing-lg);
247196
}}
248197
249198
.tension-card {{
250199
background: #fff5f5;
251-
border-radius: 10px;
252-
padding: 20px;
253-
margin-bottom: 20px;
200+
border-radius: var(--radius-md);
201+
padding: var(--spacing-md);
202+
margin-bottom: var(--spacing-md);
254203
border: 1px solid #ffe0e0;
255204
}}
256205
@@ -261,129 +210,53 @@ def _generate_visualization_html(self, data: AnalysisData) -> str:
261210
margin-top: 15px;
262211
}}
263212
264-
.viewpoint {{
265-
background: #f8f9fa;
266-
border-radius: 8px;
213+
.viewpoint-item {{
214+
background: var(--color-bg-secondary);
215+
border-radius: var(--radius-md);
267216
padding: 15px;
268-
border: 1px solid #e9ecef;
217+
border: 1px solid var(--color-border);
269218
}}
270219
271220
.viewpoint-label {{
272221
font-weight: bold;
273-
color: #495057;
222+
color: var(--color-text-secondary);
274223
margin-bottom: 8px;
275224
text-transform: uppercase;
276-
font-size: 12px;
225+
font-size: 0.75rem;
277226
letter-spacing: 0.5px;
278227
}}
279228
280229
.viewpoint-text {{
281-
color: #666;
230+
color: var(--color-text-secondary);
282231
line-height: 1.6;
283232
}}
284233
285-
.perspective-gaps,
286-
.integrative-insights {{
287-
background: #f8f9fa;
288-
border-radius: 10px;
289-
padding: 20px;
290-
margin-top: 20px;
291-
}}
292-
293-
.perspective-gaps {{
294-
border-left: 4px solid #ffd600;
295-
}}
296-
297-
.integrative-insights {{
298-
border-left: 4px solid #5e72e4;
299-
background: #f0f5ff;
300-
}}
301-
302-
.improvements-count {{
303-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
234+
.improvements-counter {{
235+
background: linear-gradient(135deg, var(--color-secondary) 0%, var(--color-accent) 100%);
304236
color: white;
305-
border-radius: 10px;
306-
padding: 20px;
237+
border-radius: var(--radius-md);
238+
padding: var(--spacing-md);
307239
text-align: center;
308-
margin-bottom: 25px;
240+
margin-bottom: var(--spacing-lg);
309241
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
310242
}}
311243
312-
.improvements-count .count {{
244+
.count-value {{
313245
display: block;
314-
font-size: 48px;
246+
font-size: 3rem;
315247
font-weight: bold;
316248
margin-bottom: 5px;
317249
}}
318250
319-
.improvements-count .label {{
320-
font-size: 16px;
251+
.count-label {{
252+
font-size: 1rem;
321253
opacity: 0.9;
322254
}}
323-
324-
.critique-summary,
325-
.additional-questions,
326-
.searches-performed {{
327-
background: #f8f9fa;
328-
border-radius: 10px;
329-
padding: 20px;
330-
margin-bottom: 20px;
331-
}}
332-
333-
.critique-summary {{
334-
border-left: 4px solid #f5365c;
335-
background: #fff5f5;
336-
}}
337-
338-
.additional-questions {{
339-
border-left: 4px solid #11cdef;
340-
background: #f0fbff;
341-
}}
342-
343-
.searches-performed {{
344-
border-left: 4px solid #2dce89;
345-
background: #f0fff5;
346-
}}
347-
348-
ul {{
349-
margin: 10px 0;
350-
padding-left: 25px;
351-
}}
352-
353-
li {{
354-
margin: 8px 0;
355-
line-height: 1.6;
356-
}}
357-
358-
.error-message {{
359-
background: #ffe0e0;
360-
border: 1px solid #ffb0b0;
361-
border-radius: 10px;
362-
padding: 20px;
363-
margin-top: 20px;
364-
color: #d32f2f;
365-
}}
366-
367-
.no-analysis {{
368-
text-align: center;
369-
color: #999;
370-
font-style: italic;
371-
padding: 60px;
372-
background: white;
373-
border-radius: 15px;
374-
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
375-
}}
376-
377-
p {{
378-
line-height: 1.8;
379-
color: #666;
380-
margin: 10px 0;
381-
}}
382255
</style>
383256
</head>
384257
<body>
385-
<div class="container">
386-
<div class="header">
258+
<div class="dr-container">
259+
<div class="dr-header-card dr-text-center">
387260
<h1>Research Analysis</h1>
388261
</div>
389262

0 commit comments

Comments
 (0)