@@ -193,31 +193,24 @@ def _categorize(label):
193193 _opts = [o for o in _ECOSYSTEMS if o in _states ]
194194 _djs_safe = _json .dumps (_states ).replace ('</' , '<\\ /' )
195195 _opts_js = _json .dumps (_opts )
196- _btn_html = '' . join ( f'<button class="tab-btn" data-idx=" { i } ">{ o } </button >' for i , o in enumerate (_opts ))
196+ _sel_html = '<div style="margin-bottom:8px"><span style="font-size:11px;color:#6b7280;display:block;margin-bottom:2px">Ecosystem</span><select id="sel" style="padding:4px 8px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;color:#374151;background:#fff;cursor:pointer">' + '' . join ( f'<option value=" { i } ">{ o } </option >' for i , o in enumerate (_opts )) + '</select></div>'
197197
198198 _inner = (
199199 '<!DOCTYPE html><html><head><meta charset="utf-8">'
200200 '<script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>'
201201 '<style>'
202202 '*{box-sizing:border-box;margin:0;padding:0}'
203203 'body{font-family:Arial,sans-serif;font-size:13px;padding:4px}'
204- '.tab-btn{padding:6px 14px;border:none;background:none;border-radius:6px;font-size:13px;cursor:pointer;color:#6b7280}'
205- '.tab-btn:hover{background:#f3f4f6;color:#111}'
206- '.tab-btn.active{background:#eff6ff;color:#2563eb;font-weight:600}'
207- '.tab-bar{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:12px;border-bottom:1px solid #e5e7eb;padding-bottom:8px}'
208204 '</style></head><body>'
209- f'<div class="tab-bar"> { _btn_html } </div> '
205+ f'{ _sel_html } '
210206 '<div id="stats" style="margin-bottom:12px"></div>'
211207 '<div id="chart"></div>'
212208 f'<script>var D={ _djs_safe } ;var O={ _opts_js } ;'
213- 'document.querySelectorAll(".tab-btn").forEach(function(btn,i){'
214- 'btn.addEventListener("click",function(){'
215- 'document.querySelectorAll(".tab-btn").forEach(function(b){b.classList.remove("active")});'
216- 'btn.classList.add("active");'
217- 'document.getElementById("stats").innerHTML=D[O[i]].stats||"";'
218- 'Plotly.react("chart",D[O[i]].chart.data,D[O[i]].chart.layout,{responsive:true});'
219- '});});'
220- 'var _b=document.querySelectorAll(".tab-btn");if(_b.length)_b[0].click();'
209+ 'var sel=document.getElementById("sel");'
210+ 'function show(i){document.getElementById("stats").innerHTML=D[O[i]].stats||"";'
211+ 'Plotly.react("chart",D[O[i]].chart.data,D[O[i]].chart.layout,{responsive:true});}'
212+ 'sel.addEventListener("change",function(){show(parseInt(this.value))});'
213+ 'show(0);'
221214 '</script></body></html>'
222215 )
223216 _src = _html_mod .escape (_inner , quote = True )
@@ -297,29 +290,22 @@ def ecosystem_comparison_tabs(ACTIVE_LABELS, CHURNED_LABELS, DORMANT_LABELS, FT_
297290 _opts = [m for m in _METRICS if m in _states ]
298291 _djs_safe = _json .dumps (_states ).replace ('</' , '<\\ /' )
299292 _opts_js = _json .dumps (_opts )
300- _btn_html = '' . join ( f'<button class="tab-btn" data-idx=" { i } ">{ o } </button >' for i , o in enumerate (_opts ))
293+ _sel_html = '<div style="margin-bottom:8px"><span style="font-size:11px;color:#6b7280;display:block;margin-bottom:2px">Metric</span><select id="sel" style="padding:4px 8px;border:1px solid #d1d5db;border-radius:6px;font-size:13px;color:#374151;background:#fff;cursor:pointer">' + '' . join ( f'<option value=" { i } ">{ o } </option >' for i , o in enumerate (_opts )) + '</select></div>'
301294
302295 _inner = (
303296 '<!DOCTYPE html><html><head><meta charset="utf-8">'
304297 '<script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>'
305298 '<style>'
306299 '*{box-sizing:border-box;margin:0;padding:0}'
307300 'body{font-family:Arial,sans-serif;font-size:13px;padding:4px}'
308- '.tab-btn{padding:6px 14px;border:none;background:none;border-radius:6px;font-size:13px;cursor:pointer;color:#6b7280}'
309- '.tab-btn:hover{background:#f3f4f6;color:#111}'
310- '.tab-btn.active{background:#eff6ff;color:#2563eb;font-weight:600}'
311- '.tab-bar{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:12px;border-bottom:1px solid #e5e7eb;padding-bottom:8px}'
312301 '</style></head><body>'
313- f'<div class="tab-bar"> { _btn_html } </div> '
302+ f'{ _sel_html } '
314303 '<div id="chart"></div>'
315304 f'<script>var D={ _djs_safe } ;var O={ _opts_js } ;'
316- 'document.querySelectorAll(".tab-btn").forEach(function(btn,i){'
317- 'btn.addEventListener("click",function(){'
318- 'document.querySelectorAll(".tab-btn").forEach(function(b){b.classList.remove("active")});'
319- 'btn.classList.add("active");'
320- 'Plotly.react("chart",D[O[i]].chart.data,D[O[i]].chart.layout,{responsive:true});'
321- '});});'
322- 'var _b=document.querySelectorAll(".tab-btn");if(_b.length)_b[0].click();'
305+ 'var sel=document.getElementById("sel");'
306+ 'function show(i){Plotly.react("chart",D[O[i]].chart.data,D[O[i]].chart.layout,{responsive:true});}'
307+ 'sel.addEventListener("change",function(){show(parseInt(this.value))});'
308+ 'show(0);'
323309 '</script></body></html>'
324310 )
325311 _src = _html_mod .escape (_inner , quote = True )
0 commit comments