You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
apps/ui/src/routes/explorer.tsx's CallMixSection (lines 137-223) renders the top-10 call-module counts as hand-rolled <li> rows with an inline percentage bar (lines 158-196) instead of using the shared Donut/DonutLegend primitives from components/metagraphed/charts/donut.tsx. Every other "N labeled categories with counts" panel in the app — providers.index.tsx's kind/status breakdowns, status.tsx, health.tsx, subnet-profile-panel.tsx, economics-mini.tsx — already uses Donut + DonutLegend with a var(--chart-1)..var(--chart-6) palette for this exact shape, so CallMixSection's module list is the outlier.
Requirement
Replace the module-count list inside CallMixSection with the shared Donut (+ DonutLegend) component, following the same donut-plus-legend layout and --chart-N palette convention used in providers.index.tsx's ProviderOverview. The function-level drill-down sub-chart (the BarMini rendered at lines 203-208 for functions.slice(0, 10)) is a separate concern and stays as BarMini — do not convert it.
Deliverable
File to change: apps/ui/src/routes/explorer.tsx — specifically the CallMixSection function (lines 137-223).
Anchor: the <ul className="space-y-1.5"> module list at lines 158-196, which currently derives cap/pct per row and paints a <span> bar manually. This block is what gets replaced; the modules selection (calls.calls.slice(0, 10), line 138) and the click-to-select/drill-down state (selected/setSelected, active, lines 139, 143, 162, 167, 169) must be preserved so clicking a module still filters functions and drives the "Tap a module to drill into its functions" copy below it.
Import Donut and DonutLegend from @/components/metagraphed/charts/donut (mirroring the import in apps/ui/src/routes/providers.index.tsx); the existing import { BarMini } from "@/components/metagraphed/charts/bar-mini" (line 15) stays, since the drill-down chart still needs it.
Build DonutSegment[] from modules, mapping call_module → label, count → value, and a var(--chart-N) palette cycled by index (same pattern as kindPalette/kindSegs in providers.index.tsx lines 541-551). ChainCallEntry.share (already computed server-side, see apps/ui/src/lib/metagraphed/types.ts) may be used for percentage display in the legend if convenient, but is not required.
Render <Donut segments={...} centerLabel={formatNumber(calls.total_extrinsics)} centerSub="calls" /> beside a <DonutLegend segments={...} />, with each legend row remaining clickable to drive setSelected (the current active/aria-pressed toggle behavior must survive the swap — DonutLegend as it stands is not interactive, so the legend rows will need to become buttons, or the selection affordance needs to move onto the donut segments/legend wrapper).
No backend/schema change — ChainCallEntry/ChainCalls (apps/ui/src/lib/metagraphed/types.ts) already carry everything needed.
apps/ui/src/routes/explorer.tsx no longer renders the hand-rolled module-count <ul>/bar markup inside CallMixSection; that block is replaced by <Donut> + <DonutLegend> (or an equivalent clickable-legend variant) fed from modules
Donut/DonutLegend are imported from @/components/metagraphed/charts/donut in explorer.tsx
The module list still supports click-to-select drill-down: clicking a module (segment or legend row) sets selected, filters functions to that module, and highlights the active module, exactly as the current active/aria-pressed button did
The function-level breakdown (functions.slice(0, 10) rendered via <BarMini ... />, currently lines 203-208) is untouched and still renders BarMini, not Donut
formatNumber(calls.total_extrinsics) (or equivalent) still surfaces as a total, now via Donut's centerLabel/centerSub rather than the removed header <span>
No changes outside apps/ui/src/routes/explorer.tsx (no edits to donut.tsx, bar-mini.tsx, or backend/schema files)
npm run lint / npm run typecheck (or the repo's apps/ui equivalents) pass with no new errors
Non-goals
Do not touch the function-level drill-down chart (functions.slice(0, 10) → BarMini, lines 203-208) — it stays BarMini; this issue is scoped to the top-level module-count list only.
Do not modify components/metagraphed/charts/donut.tsx or bar-mini.tsx themselves — this is a call-site swap in explorer.tsx, not a chart-primitive change.
Do not touch any other BarMini call site (status-diagnostics.tsx, validators-panel.tsx, metagraph-panel.tsx, integrability-board.tsx, concentration-panel.tsx, analytics/registry-depth.tsx, accounts.$ss58.tsx) — those are unrelated, separately-tracked usages.
No backend/API/schema change — this is frontend-only.
Size
Size: XS — keep this PR small (aim for ≤10 files / ≤1000 LOC).
Context
apps/ui/src/routes/explorer.tsx'sCallMixSection(lines 137-223) renders the top-10 call-module counts as hand-rolled<li>rows with an inline percentage bar (lines 158-196) instead of using the sharedDonut/DonutLegendprimitives fromcomponents/metagraphed/charts/donut.tsx. Every other "N labeled categories with counts" panel in the app —providers.index.tsx's kind/status breakdowns,status.tsx,health.tsx,subnet-profile-panel.tsx,economics-mini.tsx— already usesDonut+DonutLegendwith avar(--chart-1)..var(--chart-6)palette for this exact shape, soCallMixSection's module list is the outlier.Requirement
Replace the module-count list inside
CallMixSectionwith the sharedDonut(+DonutLegend) component, following the same donut-plus-legend layout and--chart-Npalette convention used inproviders.index.tsx'sProviderOverview. The function-level drill-down sub-chart (theBarMinirendered at lines 203-208 forfunctions.slice(0, 10)) is a separate concern and stays asBarMini— do not convert it.Deliverable
apps/ui/src/routes/explorer.tsx— specifically theCallMixSectionfunction (lines 137-223).<ul className="space-y-1.5">module list at lines 158-196, which currently derivescap/pctper row and paints a<span>bar manually. This block is what gets replaced; themodulesselection (calls.calls.slice(0, 10), line 138) and the click-to-select/drill-down state (selected/setSelected,active, lines 139, 143, 162, 167, 169) must be preserved so clicking a module still filtersfunctionsand drives the "Tap a module to drill into its functions" copy below it.DonutandDonutLegendfrom@/components/metagraphed/charts/donut(mirroring the import inapps/ui/src/routes/providers.index.tsx); the existingimport { BarMini } from "@/components/metagraphed/charts/bar-mini"(line 15) stays, since the drill-down chart still needs it.DonutSegment[]frommodules, mappingcall_module→label,count→value, and avar(--chart-N)palette cycled by index (same pattern askindPalette/kindSegsinproviders.index.tsxlines 541-551).ChainCallEntry.share(already computed server-side, seeapps/ui/src/lib/metagraphed/types.ts) may be used for percentage display in the legend if convenient, but is not required.<Donut segments={...} centerLabel={formatNumber(calls.total_extrinsics)} centerSub="calls" />beside a<DonutLegend segments={...} />, with each legend row remaining clickable to drivesetSelected(the currentactive/aria-pressedtoggle behavior must survive the swap —DonutLegendas it stands is not interactive, so the legend rows will need to become buttons, or the selection affordance needs to move onto the donut segments/legend wrapper).ChainCallEntry/ChainCalls(apps/ui/src/lib/metagraphed/types.ts) already carry everything needed.explorer.tsx.Acceptance criteria
apps/ui/src/routes/explorer.tsxno longer renders the hand-rolled module-count<ul>/bar markup insideCallMixSection; that block is replaced by<Donut>+<DonutLegend>(or an equivalent clickable-legend variant) fed frommodulesDonut/DonutLegendare imported from@/components/metagraphed/charts/donutinexplorer.tsxselected, filtersfunctionsto that module, and highlights the active module, exactly as the currentactive/aria-pressedbutton didfunctions.slice(0, 10)rendered via<BarMini ... />, currently lines 203-208) is untouched and still rendersBarMini, notDonutformatNumber(calls.total_extrinsics)(or equivalent) still surfaces as a total, now viaDonut'scenterLabel/centerSubrather than the removed header<span>apps/ui/src/routes/explorer.tsx(no edits todonut.tsx,bar-mini.tsx, or backend/schema files)npm run lint/npm run typecheck(or the repo'sapps/uiequivalents) pass with no new errorsNon-goals
functions.slice(0, 10)→BarMini, lines 203-208) — it staysBarMini; this issue is scoped to the top-level module-count list only.components/metagraphed/charts/donut.tsxorbar-mini.tsxthemselves — this is a call-site swap inexplorer.tsx, not a chart-primitive change.BarMinicall site (status-diagnostics.tsx,validators-panel.tsx,metagraph-panel.tsx,integrability-board.tsx,concentration-panel.tsx,analytics/registry-depth.tsx,accounts.$ss58.tsx) — those are unrelated, separately-tracked usages.Size
Size: XS — keep this PR small (aim for ≤10 files / ≤1000 LOC).
Part of #2542.