Skip to content

Commit 61c9f13

Browse files
feat(muix): implement bar-stacked-labeled (#10807)
## Implementation: `bar-stacked-labeled` - javascript/muix Implements the **javascript/muix** version of `bar-stacked-labeled`. **File:** `plots/bar-stacked-labeled/implementations/javascript/muix.tsx` **Parent Issue:** #3504 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/anyplot/actions/runs/33003514982)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com>
1 parent cd8e31e commit 61c9f13

2 files changed

Lines changed: 372 additions & 0 deletions

File tree

  • plots/bar-stacked-labeled
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// anyplot.ai
2+
// bar-stacked-labeled: Stacked Bar Chart with Total Labels
3+
// Library: muix 7.29.1 | JavaScript 22.23.2
4+
// Quality: 88/100 | Created: 2026-08-26
5+
import { BarChart } from "@mui/x-charts/BarChart";
6+
import { useXScale, useYScale } from "@mui/x-charts/hooks";
7+
import Box from "@mui/material/Box";
8+
import Typography from "@mui/material/Typography";
9+
10+
const t = window.ANYPLOT_TOKENS;
11+
12+
// --- Data (in-memory, deterministic) ----------------------------------------
13+
// Project budget breakdown by phase, three stacked cost types (Imprint palette 1-3).
14+
const phases = ["Planning", "Design", "Development", "Testing", "Deployment"];
15+
const costTypes = ["Labor", "Materials", "Equipment"];
16+
const labor = [18, 32, 58, 34, 22];
17+
const materials = [6, 14, 20, 10, 8];
18+
const equipment = [4, 10, 16, 6, 12];
19+
const totals = phases.map((_, i) => labor[i] + materials[i] + equipment[i]);
20+
const maxTotal = Math.max(...totals);
21+
22+
const TITLE = "bar-stacked-labeled · javascript · muix · anyplot.ai";
23+
const TITLE_H = 56;
24+
25+
// --- Total labels (custom overlay, positioned via chart scales) -------------
26+
function TotalLabels() {
27+
const xScale = useXScale();
28+
const yScale = useYScale();
29+
return (
30+
<g>
31+
{phases.map((phase, i) => (
32+
<text
33+
key={phase}
34+
x={xScale(phase) + xScale.bandwidth() / 2}
35+
y={yScale(totals[i]) - 16}
36+
textAnchor="middle"
37+
fontSize={20}
38+
fontWeight={700}
39+
fill={t.ink}
40+
>
41+
{`$${totals[i]}k`}
42+
</text>
43+
))}
44+
</g>
45+
);
46+
}
47+
48+
// --- Chart (default-exported component — the harness mounts it) -------------
49+
export default function Chart() {
50+
const { width, height } = window.ANYPLOT_SIZE;
51+
52+
return (
53+
<Box
54+
sx={{
55+
width,
56+
height,
57+
bgcolor: t.pageBg,
58+
display: "flex",
59+
flexDirection: "column",
60+
}}
61+
>
62+
<Box
63+
sx={{
64+
height: TITLE_H,
65+
display: "flex",
66+
alignItems: "center",
67+
px: "40px",
68+
pt: "10px",
69+
}}
70+
>
71+
<Typography
72+
sx={{
73+
color: t.ink,
74+
fontSize: "22px",
75+
fontWeight: 600,
76+
letterSpacing: "0.02em",
77+
lineHeight: 1,
78+
}}
79+
>
80+
{TITLE}
81+
</Typography>
82+
</Box>
83+
84+
<BarChart
85+
width={width}
86+
height={height - TITLE_H}
87+
colors={t.palette}
88+
skipAnimation
89+
borderRadius={4}
90+
grid={{ horizontal: true }}
91+
xAxis={[
92+
{
93+
scaleType: "band",
94+
data: phases,
95+
label: "Project Phase",
96+
},
97+
]}
98+
yAxis={[
99+
{
100+
label: "Cost ($ thousands)",
101+
max: Math.ceil((maxTotal * 1.18) / 10) * 10,
102+
tickFontSize: 14,
103+
labelFontSize: 16,
104+
tickSize: 8,
105+
},
106+
]}
107+
series={[
108+
{ data: labor, label: costTypes[0], stack: "total" },
109+
{ data: materials, label: costTypes[1], stack: "total" },
110+
{ data: equipment, label: costTypes[2], stack: "total" },
111+
]}
112+
margin={{ top: 30, right: 32, bottom: 90, left: 90 }}
113+
sx={{
114+
"& .MuiChartsAxis-tickLabel": { fontSize: "14px" },
115+
"& .MuiChartsAxis-label": { fontSize: "16px", fontWeight: 600 },
116+
"& .MuiChartsLegend-label": { fontSize: "15px" },
117+
"& .MuiChartsGrid-line": { stroke: t.grid, strokeWidth: 1 },
118+
"& .MuiBarElement-root": { stroke: t.pageBg, strokeWidth: 1.5 },
119+
}}
120+
slotProps={{
121+
legend: { position: { vertical: "bottom", horizontal: "middle" } },
122+
}}
123+
>
124+
<TotalLabels />
125+
</BarChart>
126+
</Box>
127+
);
128+
}
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
library: muix
2+
language: javascript
3+
specification_id: bar-stacked-labeled
4+
created: '2026-08-26T19:14:45Z'
5+
updated: '2026-08-26T19:28:32Z'
6+
generated_by: claude-sonnet
7+
workflow_run: 33003514982
8+
issue: 3504
9+
language_version: 22.23.2
10+
library_version: 7.29.1
11+
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/bar-stacked-labeled/javascript/muix/plot-light.png
12+
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/bar-stacked-labeled/javascript/muix/plot-dark.png
13+
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/bar-stacked-labeled/javascript/muix/plot-light.html
14+
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/bar-stacked-labeled/javascript/muix/plot-dark.html
15+
quality_score: 88
16+
review:
17+
strengths:
18+
- Correct use of MUI X's useXScale/useYScale hooks to render dynamic, scale-accurate
19+
total labels above each stack — an idiomatic, distinctive solution to the spec's
20+
core requirement.
21+
- Repair pass added a subtle 1.5px pageBg-colored edge stroke and 4px border radius
22+
to bar segments, giving clearer segment definition without breaking the Imprint
23+
palette.
24+
- Imprint palette applied correctly and identically across both themes (green →
25+
lavender → blue canonical order), with fully theme-adaptive chrome (title, axes,
26+
legend, total labels all flip correctly).
27+
- Y-axis max computed with deliberate headroom (Math.ceil((maxTotal * 1.18) / 10)
28+
* 10) specifically to leave room for total labels — directly satisfies the spec's
29+
headroom note.
30+
- Deterministic hardcoded data, skipAnimation set, clean imports — no extraneous
31+
dependencies or fake functionality.
32+
weaknesses:
33+
- Design still reads close to a well-configured MUI X BarChart default beyond the
34+
total-label overlay and the new edge/border-radius touches — no differentiating
35+
typographic treatment, accent, or additional polish.
36+
- No further visual hierarchy within each stack (e.g. optional per-segment value
37+
labels for the dominant Labor segment) to reinforce the data story beyond the
38+
total labels.
39+
- Element visibility is good but unremarkable — bar widths and segment proportions
40+
rely on library defaults rather than a deliberately tuned density-aware sizing.
41+
image_description: |-
42+
Light render (plot-light.png):
43+
Background: Warm off-white, matches #FAF8F1 — not pure white.
44+
Chrome: Bold dark title "bar-stacked-labeled · javascript · muix · anyplot.ai" top-left, clearly readable. Y-axis label "Cost ($ thousands)" and X-axis label "Project Phase" both dark, legible, and similarly sized/weighted (bolded in this attempt). Tick labels dark and legible. Horizontal gridlines subtle and light. Legend ("Labor", "Materials", "Equipment") centered below the plot, dark text, readable.
45+
Data: Stacks use brand green (Labor, #009E73), lavender (Materials), and blue (Equipment) — canonical Imprint order, first series is #009E73 as required. Bars now show a thin cream-colored (pageBg) edge stroke and slight border radius separating segments, and each bar. Bold black total labels ("$28k", "$56k", "$94k", "$50k", "$42k") sit directly above each stack with clear headroom below the y=120 axis max.
46+
Legibility verdict: PASS
47+
48+
Dark render (plot-dark.png):
49+
Background: Warm near-black, matches #1A1A17 — not pure black.
50+
Chrome: Title, axis labels, and tick labels flip to white/light text and remain clearly legible — no dark-on-dark issues anywhere. Legend text is white and readable. Gridlines remain subtle.
51+
Data: Colors (green/lavender/blue) are pixel-identical to the light render, confirming only chrome flipped. The bar edge stroke now reads as a thin near-black (pageBg) separator between segments, consistent with the theme. Total labels flip to white text, clearly readable above each stack.
52+
Legibility verdict: PASS
53+
criteria_checklist:
54+
visual_quality:
55+
score: 28
56+
max: 30
57+
items:
58+
- id: VQ-01
59+
name: Text Legibility
60+
score: 7
61+
max: 8
62+
passed: true
63+
comment: All font sizes explicitly set, readable in both themes; title fits
64+
without clipping
65+
- id: VQ-02
66+
name: No Overlap
67+
score: 6
68+
max: 6
69+
passed: true
70+
comment: No collisions between text, data, or legend
71+
- id: VQ-03
72+
name: Element Visibility
73+
score: 5
74+
max: 6
75+
passed: true
76+
comment: Bars clearly visible with new edge stroke + border radius, but sizing
77+
still relies on library defaults
78+
- id: VQ-04
79+
name: Color Accessibility
80+
score: 2
81+
max: 2
82+
passed: true
83+
comment: Good contrast, CVD-safe; edge strokes aid segment distinction beyond
84+
hue alone
85+
- id: VQ-05
86+
name: Layout & Canvas
87+
score: 4
88+
max: 4
89+
passed: true
90+
comment: Chart fills the canvas well, balanced margins, nothing cut off
91+
- id: VQ-06
92+
name: Axis Labels & Title
93+
score: 2
94+
max: 2
95+
passed: true
96+
comment: Descriptive axis labels with units (Cost ($ thousands))
97+
- id: VQ-07
98+
name: Palette Compliance
99+
score: 2
100+
max: 2
101+
passed: true
102+
comment: 'Canonical Imprint order, first series #009E73, theme-correct chrome
103+
in both renders'
104+
design_excellence:
105+
score: 12
106+
max: 20
107+
items:
108+
- id: DE-01
109+
name: Aesthetic Sophistication
110+
score: 5
111+
max: 8
112+
passed: false
113+
comment: Border radius, edge strokes, and letter-spacing add polish above
114+
a stock default, but overall still close to a well-configured MUI X chart
115+
- id: DE-02
116+
name: Visual Refinement
117+
score: 4
118+
max: 6
119+
passed: false
120+
comment: New pageBg edge stroke and border radius on bars give visible refinement;
121+
grid subtle, spines minimal
122+
- id: DE-03
123+
name: Data Storytelling
124+
score: 3
125+
max: 6
126+
passed: false
127+
comment: Bold total labels create a clear focal point on the Development peak,
128+
but segments aren't further differentiated for storytelling
129+
spec_compliance:
130+
score: 15
131+
max: 15
132+
items:
133+
- id: SC-01
134+
name: Plot Type
135+
score: 5
136+
max: 5
137+
passed: true
138+
comment: Correct stacked bar chart
139+
- id: SC-02
140+
name: Required Features
141+
score: 4
142+
max: 4
143+
passed: true
144+
comment: Total labels above each stack, adequate headroom, all spec features
145+
present
146+
- id: SC-03
147+
name: Data Mapping
148+
score: 3
149+
max: 3
150+
passed: true
151+
comment: Category on x-axis, value stacked by component on y-axis
152+
- id: SC-04
153+
name: Title & Legend
154+
score: 3
155+
max: 3
156+
passed: true
157+
comment: Title format correct; legend labels match cost-type series
158+
data_quality:
159+
score: 15
160+
max: 15
161+
items:
162+
- id: DQ-01
163+
name: Feature Coverage
164+
score: 6
165+
max: 6
166+
passed: true
167+
comment: Segment proportions vary meaningfully across phases (Development
168+
dominated by Labor, Planning more balanced)
169+
- id: DQ-02
170+
name: Realistic Context
171+
score: 5
172+
max: 5
173+
passed: true
174+
comment: Neutral, realistic project-budget-by-phase scenario
175+
- id: DQ-03
176+
name: Appropriate Scale
177+
score: 4
178+
max: 4
179+
passed: true
180+
comment: Plausible cost figures and proportions for a project budget in $
181+
thousands
182+
code_quality:
183+
score: 10
184+
max: 10
185+
items:
186+
- id: CQ-01
187+
name: KISS Structure
188+
score: 3
189+
max: 3
190+
passed: true
191+
comment: Straightforward data → overlay component → chart; TotalLabels component
192+
is required for the hooks pattern, not over-engineering
193+
- id: CQ-02
194+
name: Reproducibility
195+
score: 2
196+
max: 2
197+
passed: true
198+
comment: Deterministic hardcoded arrays
199+
- id: CQ-03
200+
name: Clean Imports
201+
score: 2
202+
max: 2
203+
passed: true
204+
comment: Only used imports (BarChart, hooks, Box, Typography)
205+
- id: CQ-04
206+
name: Code Elegance
207+
score: 2
208+
max: 2
209+
passed: true
210+
comment: Appropriate complexity, no fake functionality
211+
- id: CQ-05
212+
name: Output & API
213+
score: 1
214+
max: 1
215+
passed: true
216+
comment: Harness-mounted component, current MUI X API
217+
library_mastery:
218+
score: 8
219+
max: 10
220+
items:
221+
- id: LM-01
222+
name: Idiomatic Usage
223+
score: 4
224+
max: 5
225+
passed: true
226+
comment: Correct high-level BarChart API usage, stack config, sx/slotProps
227+
overrides
228+
- id: LM-02
229+
name: Distinctive Features
230+
score: 4
231+
max: 5
232+
passed: true
233+
comment: useXScale/useYScale hooks drive a scale-accurate custom overlay —
234+
distinctive to MUI X
235+
verdict: APPROVED
236+
impl_tags:
237+
dependencies: []
238+
techniques:
239+
- annotations
240+
patterns:
241+
- data-generation
242+
dataprep: []
243+
styling:
244+
- edge-highlighting

0 commit comments

Comments
 (0)