@@ -226,6 +226,87 @@ def test_px_templates(backend):
226226 pio .templates .default = "plotly"
227227
228228
229+ def test_px_templates_trace_specific_colors (backend ):
230+ import plotly .graph_objects as go
231+
232+ tips = px .data .tips (return_type = backend )
233+
234+ # read trace-specific colors from template.data.histogram
235+ histogram_template = go .layout .Template ()
236+ histogram_template .data .histogram = [
237+ go .Histogram (marker = dict (color = "orange" )),
238+ go .Histogram (marker = dict (color = "purple" )),
239+ ]
240+ fig = px .histogram (tips , x = "total_bill" , color = "sex" , template = histogram_template )
241+ assert fig .data [0 ].marker .color == "orange"
242+ assert fig .data [1 ].marker .color == "purple"
243+
244+ # scatter uses template.data.scatter colors, not histogram colors
245+ scatter_template = go .layout .Template ()
246+ scatter_template .data .scatter = [
247+ go .Scatter (marker = dict (color = "cyan" )),
248+ go .Scatter (marker = dict (color = "magenta" )),
249+ ]
250+ scatter_template .data .histogram = [
251+ go .Histogram (marker = dict (color = "orange" )),
252+ ]
253+ fig = px .scatter (tips , x = "total_bill" , y = "tip" , color = "sex" , template = scatter_template )
254+ assert fig .data [0 ].marker .color == "cyan"
255+ assert fig .data [1 ].marker .color == "magenta"
256+
257+ # histogram still uses histogram colors even when scatter colors exist
258+ fig = px .histogram (tips , x = "total_bill" , color = "sex" , template = scatter_template )
259+ assert fig .data [0 ].marker .color == "orange"
260+
261+ # fallback to layout.colorway when trace-specific colors don't exist
262+ fig = px .histogram (
263+ tips , x = "total_bill" , color = "sex" , template = dict (layout_colorway = ["yellow" , "green" ])
264+ )
265+ assert fig .data [0 ].marker .color == "yellow"
266+ assert fig .data [1 ].marker .color == "green"
267+
268+ # timeline special case (maps to bar)
269+ timeline_template = go .layout .Template ()
270+ timeline_template .data .bar = [
271+ go .Bar (marker = dict (color = "red" )),
272+ go .Bar (marker = dict (color = "blue" )),
273+ ]
274+ timeline_data = {
275+ "Task" : ["Job A" , "Job B" ],
276+ "Start" : ["2009-01-01" , "2009-03-05" ],
277+ "Finish" : ["2009-02-28" , "2009-04-15" ],
278+ "Resource" : ["Alex" , "Max" ],
279+ }
280+ # Use same backend as tips for consistency
281+ df_timeline = px .data .tips (return_type = backend )
282+ df_timeline = nw .from_native (df_timeline ).with_columns (
283+ nw .lit ("Job A" ).alias ("Task" ),
284+ nw .lit ("2009-01-01" ).alias ("Start" ),
285+ nw .lit ("2009-02-28" ).alias ("Finish" ),
286+ nw .lit ("Alex" ).alias ("Resource" ),
287+ ).head (1 ).to_native ()
288+ # Add second row
289+ df_timeline2 = nw .from_native (df_timeline ).with_columns (
290+ nw .lit ("Job B" ).alias ("Task" ),
291+ nw .lit ("2009-03-05" ).alias ("Start" ),
292+ nw .lit ("2009-04-15" ).alias ("Finish" ),
293+ nw .lit ("Max" ).alias ("Resource" ),
294+ ).head (1 ).to_native ()
295+ # Combine - actually, this is getting too complex. Let me just use a simpler approach
296+ import pandas as pd
297+ df_timeline = pd .DataFrame (timeline_data )
298+ fig = px .timeline (
299+ df_timeline ,
300+ x_start = "Start" ,
301+ x_end = "Finish" ,
302+ y = "Task" ,
303+ color = "Resource" ,
304+ template = timeline_template ,
305+ )
306+ assert fig .data [0 ].marker .color == "red"
307+ assert fig .data [1 ].marker .color == "blue"
308+
309+
229310def test_px_defaults ():
230311 px .defaults .labels = dict (x = "hey x" )
231312 px .defaults .category_orders = dict (color = ["b" , "a" ])
0 commit comments