Professional chart and diagram creation skill. Covers all types of visual data representation and structural diagrams: - **Data charts**: bar charts, line charts, pie charts, scatter plots, heatmaps, radar charts, candlestick charts, boxplots, histograms, area charts, waterfall charts, regression plots, distribution plots, and statistical visualizations. - **Structural diagrams**: flowcharts, mind maps, tree diagrams, org charts, architecture diagrams, network/relationship graphs, ER diagrams, class diagrams, Gantt charts, swimlane diagrams, and sequence diagrams. - **Dashboards**: data dashboards, KPI panels, multi-chart compositions, and interactive visualizations. - **Design quality**: professional color systems, anti-overlap rules, layout optimization, scene-based framework routing (matplotlib, seaborn, ECharts, D3.js, Mermaid, Playwright+CSS), and publication-ready output. Applies when the user wants to create, generate, draw, plot, visualize, or improve any chart, graph, diagram, or dashboard. Also appl
Each template file contains its own framework-specific rules (spacing, connectors, color details). This file contains only routing decisions and universal rules that apply to ALL charts.
Part 1: Routing
⚠️ Format Constraint Rule (HIGHEST PRIORITY)
When the user specifies an output format/tool, you MUST comply. Never substitute.
① Output Mermaid code block (mermaid ... ) ② Also provide a rendered image preview
❌ Cannot only give image without code; ❌ Cannot screenshot raw code text as image
"use markdown code"
Output markdown-formatted hierarchy
❌ Cannot switch to HTML/CSS
"via mermaid or markdown code"
Choose one of the two, output code text
❌ Cannot switch to any non-specified format
"flowchart" / "mind map" (no format specified)
Free to choose the best approach
-
"use echarts/d3"
Must use the specified framework
❌ Cannot switch
🚫 FORBIDDEN: Mermaid Code Screenshot
NEVER take a screenshot of raw Mermaid source code and deliver it as the "diagram image". This is the worst possible outcome — the user gets neither usable code nor a visual diagram. When the user requests Mermaid format:
MUST output the Mermaid code in a fenced code block (````mermaid`)
SHOULD also render the code into a visual diagram image (via mermaid-cli or Playwright + mermaid.js)
If rendering fails, deliver the code block and tell the user to paste it into mermaid.live
Format Specified vs Auto-Upgrade Conflict
When the user specifies Mermaid but content triggers auto-upgrade conditions (>8 nodes, CJK-heavy, etc.):
User choice wins — still use Mermaid, deliver code block + rendered image
Proactively guide — after delivery, suggest the user try without specifying Mermaid for better layout quality
Never silently switch to Playwright+CSS when user explicitly asked for Mermaid
When a specified tool hits rendering difficulties (e.g., mermaid CDN fails):
✅ Output raw mermaid code text, tell user to view at mermaid.live
When the user asks to "generate/create a XXX flowchart/流程图" without specifying format, the DEFAULT layout is Phased Vertical (Layout C in references/playwright-css.md).
This is because nearly all real-world processes (manufacturing, legal proceedings, project management, business operations, cooking recipes, etc.) have natural phases/stages. Layout C produces the most professional, readable result.
Flowchart routing priority:
User specified Mermaid/markdown → follow user choice (Format Constraint Rule)
≤6 nodes AND no phases AND short text → Mermaid (simple flowchart)
Standard bar/line/scatter/heatmap/radar/pie: matplotlib
Regression/distribution/boxplot: Seaborn
3. Interactive Charts / Dashboards
Data dashboard / candlestick / real-time: ECharts
Fully custom interactive: D3.js
Default Strategy
One scene, one tool — don't hesitate:
Scene
Tool
Template
Data chart (bar/line/scatter/pie/radar)
matplotlib
references/matplotlib.md
Statistical (regression/box/dist)
Seaborn
references/seaborn.md
Mind map / tree / org chart
Playwright + CSS
references/mindmap-css.md
Center-radial (SWOT/BSC/PEST/Five Forces)
Playwright + CSS
references/radial-grid.md
Any flowchart (default)
Playwright + CSS Layout C
references/playwright-css.md
Simple flowchart (≤6 nodes, truly flat)
Mermaid
references/mermaid.md
Relationship / force-directed
ECharts graph
references/echarts.md
Data dashboard
ECharts
references/echarts.md
Academic paper figures
matplotlib
references/matplotlib.md
Mermaid Auto-Upgrade Rules
Mermaid's dagre/elk layout estimates CJK widths incorrectly. Auto-switch to Playwright+CSS when ANY condition is met:
Trigger
Action
Total nodes > 6
→ CSS flowchart (Layout C)
Any node text > 12 Chinese characters
→ CSS flowchart
More than 3 parallel branches
→ CSS flowchart
Nested subgraphs > 2 levels
→ CSS flowchart
Connector crossings > 2
→ CSS flowchart
Side annotations / dashed note boxes
→ CSS flowchart
Loop-back / cycle arrows
→ CSS flowchart
Process has identifiable phases/stages
→ CSS flowchart (Layout C)
If staying with Mermaid: padding: 32, nodeSpacing: 80, rankSpacing: 80. Node text ≤ 10 CJK chars/line, wrap with <br>, quote all text A["text"].
Large Dataset Rendering
Data Size
Approach
< 1,000 points
matplotlib / any
1,000 - 10,000
matplotlib (no markers) or ECharts
10,000 - 100,000
ECharts (Canvas mode)
> 100,000
ECharts (large: true) or WebGL
Part 2: Universal Rules
These rules apply to ALL charts regardless of framework. Framework-specific rules live in each template file.
7 Core Rules
Zero overlap. No element may cover another's text. Overlap = information loss = task failure. Post-generation: verify every element has clear separation.
Hierarchy over uniformity. Primary nodes larger/bolder than secondary. Annotation nodes smaller/muted. Spacing between groups > within groups. If every box looks identical, the layout has failed.
Low-saturation palette. 70% background/neutral, 20% secondary, 10% accent (one highlight only). No high-saturation large fills. Saturated colors only on borders (2px), text, and small elements.
Insight first. Titles express conclusions, not field names. Remove non-essential elements: top/right borders, grid lines, tick marks, legend box borders. If removing it doesn't reduce understanding, it shouldn't exist.
Label clarity over label method. The goal is zero overlap — choose the method that achieves it for each chart type. Direct labels, legends, and leader lines are all valid; what matters is that nothing overlaps.
🚫 FORBIDDEN: Any Text Overlapping Any Other Element
No label, legend, annotation, or title may overlap any other visual element. This is the single most common matplotlib defect. Both direct labels AND legends can cause overlap — neither is inherently safe.
Anti-overlap decision tree:
Check if direct labels fit — if all labels have enough space (bar tops, line endpoints, large pie slices), label directly. No legend needed.
If some labels would collide (small pie slices, dense scatter points, clustered bars) → use legend outside plot area instead of forcing labels into tight spaces.
Mixed approach — label the major items directly, group small items into "其他" or use leader lines + legend for the small ones.
Pie chart specific (the worst offender):
Slices < 5%: MUST use leader lines (wedgeprops + texts manual repositioning, or matplotlib.patches.ConnectionPatch) to pull labels outside. Do NOT rely on autopct alone — it places text inside/near the slice.
Multiple small adjacent slices: use bbox_to_anchor legend outside, NOT direct labels
labeldistance=1.25 minimum to keep labels outside the pie
When >2 slices are < 5%, consider grouping all < 3% into "其他(X项)"
Use adjustText library to auto-resolve label collisions when available
Legend placement (when legend is needed):
Place legend outside the plot area using bbox_to_anchor
Suggested starting positions:
Bar/line/scatter: right side outside (bbox_to_anchor=(1.02, 1), loc='upper left')
Pie: right side outside (bbox_to_anchor=(1.1, 0.5), loc='center left')
🔧 Mandatory: auto-adjust legend to prevent overlap. Copy this snippet after placing any legend:
# ── Auto-adjust legend position to prevent overlap ──
fig.canvas.draw() # must render first to get bboxes
legend = ax.get_legend()
if legend:
renderer = fig.canvas.get_renderer()
# Try shifting up to 5 times to resolve overlap
for _ in range(5):
leg_bb = legend.get_window_extent(renderer).transformed(ax.transAxes.inverted())
has_overlap = False
for text in ax.texts + [ax.title] + ax.get_xticklabels() + ax.get_yticklabels():
if not text.get_text():
continue
txt_bb = text.get_window_extent(renderer).transformed(ax.transAxes.inverted())
if leg_bb.overlaps(txt_bb):
has_overlap = True
break
if not has_overlap:
break
# Move legend further outside (direction depends on current loc)
bbox = legend.get_bbox_to_anchor().transformed(ax.transAxes.inverted())
x0, y0 = bbox.x0, bbox.y0
# Heuristic: if legend is below center, move down; if right of center, move right
if y0 < 0.5:
legend.set_bbox_to_anchor((x0, y0 - 0.08), transform=ax.transAxes)
else:
legend.set_bbox_to_anchor((x0 + 0.08, y0), transform=ax.transAxes)
fig.canvas.draw()
After placing legend: always call plt.tight_layout() or fig.subplots_adjust() to ensure legend is not clipped
🚫 FORBIDDEN:
loc='best' — matplotlib's "best" frequently overlaps data
loc='upper right' / loc='lower right' on line/bar charts — high collision risk
Direct labels on pie slices < 5% without leader lines
Any text placement without verifying zero overlap
Font discipline. Max 2 fonts. Chinese: SimHei/PingFang SC. Always explicitly set fonts in code. Font size follows hierarchy (title 18-24px → body 13-15px → annotation 11-13px). Never go below 10px floor. When text overflows: condense text → enlarge canvas → last resort: shrink font (but never below floor).
Whitespace is design. Chart area 60-70% of canvas, margins 15-20%. At least 16pt between title and chart. Crowded ≠ information-rich.
Color System
Recommended Palettes
Palette
Text
Background
Block Fill
Accent
Business Cool
#243447
#F8FAFC
#E9EEF3
#4C6EF5
Tech Cyan-Gray
#1F2937
#F5F7FA
#E6ECF2
#3AAFA9
Morandi Warm
#4B4A45
#FAF8F4
#EAE4DB
#C6866A
Invisible Precision
#37352F
#FFFFFF
#F7F7F7
#2383E2
🚫 Forbidden Background Colors
Color
Forbidden Hex Values
Pure blue
#3B82F6, #2563EB, #1D4ED8
Pure green
#10B981, #059669, #22C55E
Pure red
#EF4444, #DC2626, #F87171
Pure purple
#8B5CF6, #7C3AED, #A855F7
Pure amber
#F59E0B, #D97706, #FB923C
✅ Allowed Background Colors
Color
Hex Values
Ice blue
#EFF6FF, #DBEAFE
Mint green
#F0FDF4, #D1FAE5
Light amber
#FFF7ED, #FEF3C7
Lavender
#F5F3FF, #EDE9FE
Light gray
#F8FAFC, #F1F5F9
Functional Color (states only, not decoration)
Active/Selected: brand accent or 2px accent line
Error: #EF4444
Success: #10B981
Tags: light bg + dark text, never high-sat pills
Colorblind-Safe
Don't rely on color alone — pair with shape, line style, or direct labels.
Paul Tol palette: ['#0077BB', '#33BBEE', '#009988', '#EE7733', '#CC3311', '#EE3377']
Bar chart Y-axis starts at 0 (line charts may truncate)
Never use 3D (distorts proportions)
Playwright Screenshot
Default device_scale_factor=2. Large mind maps (3000px+): 1.5. PDF embed: 1-1.5. Print: 3.
After render, read bounding_box() and resize viewport to fit. Min viewport: 800px single-col, 1200px multi-col.
🚫 FORBIDDEN: max-width on Mermaid/SVG Containers
Mermaid's dagre engine produces SVGs with unpredictable width (especially with subgraphs, CJK text, or parallel branches). NEVER set max-width on the Mermaid container element. Use width: fit-content; min-width: 800px; instead.
Root cause: Mermaid SVGs overflow their CSS container silently. bounding_box() (Playwright) returns the CSS box model size, NOT the SVG's actual rendered size. So auto-resize viewport based on bounding_box() alone will still produce clipped screenshots.
Fix: Always read the SVG element's own getBoundingClientRect() via page.evaluate(), then use max(css_size, svg_size) + padding for viewport dimensions. See references/mermaid.md for the corrected screenshot script.
Aspect Ratio Preservation (embedding)
MUST read actual image dimensions and calculate height proportionally. NEVER hardcode both width and height.
matplotlib-Specific Rules
These apply when routing to matplotlib/seaborn:
Layout & Overlap
Prefer constrained_layout=True over tight_layout()
Use adjustText library for automatic label repositioning — this is the most reliable anti-overlap tool for matplotlib. Install: pip install adjustText. Usage: from adjustText import adjust_text; adjust_text(texts)
Max 4 subplots per canvas. More → split images or figsize=(20, 16) minimum
Multi-subplot: GridSpec with wspace/hspace ≥ 0.3
Colorbar: shrink=0.8 + pad=0.08
Data labels: Y-axis upper limit with 15-20% headroom (ylim(0, max_val * 1.18))
Long X labels → horizontal bar chart or show every N-th label
Radar / Spider Charts
Every fill() MUST have alpha=0.25 (max 0.3). Omitting alpha = opaque = hides underlying series.
Legend: place outside chart with bbox_to_anchor, start with (0.5, -0.15), loc='upper center'. If dimension labels are long or dimensions > 8, increase offset (e.g., -0.25 or -0.3). Also FORBIDDEN: loc='lower right' (collides with radar dimension labels).
1---2name: charts3description: Professional chart and diagram creation skill. Covers all types of visual data representation and structural diagrams: - **Data charts**: bar charts, line charts, pie charts, scatter plots, heatmaps, radar charts, candlestick charts, boxplots, histograms, area charts, waterfall charts, regression plots, distribution plots, and statistical visualizations. - **Structural diagrams**: flowcharts, mind maps, tree diagrams, org charts, architecture diagrams, network/relationship graphs, ER diagrams, class diagrams, Gantt charts, swimlane diagrams, and sequence diagrams. - **Dashboards**: data dashboards, KPI panels, multi-chart compositions, and interactive visualizations. - **Design quality**: professional color systems, anti-overlap rules, layout optimization, scene-based framework routing (matplotlib, seaborn, ECharts, D3.js, Mermaid, Playwright+CSS), and publication-ready output. Applies when the user wants to create, generate, draw, plot, visualize, or improve any chart, graph, diagram, or dashboard. Also appl4license: Proprietary. LICENSE.txt has complete terms5---67# Beautiful Charts89## Quick Setup1011```bash12bash "$SKILL_DIR/setup.sh" # Interactive environment check + install13```1415Make every chart and diagram look professionally designed, not AI-generated.1617## Architecture1819| Module | File | When to Load |20|--------|------|-------------|21| **Routing + Core Rules** | This file | Always read first |22| **Framework Templates** | `references/` by framework | After choosing framework, read the corresponding file |2324**Loading order: Read this file → choose framework → read template file → start coding.**2526Each template file contains its own framework-specific rules (spacing, connectors, color details). This file contains only routing decisions and universal rules that apply to ALL charts.2728---2930# Part 1: Routing3132## ⚠️ Format Constraint Rule (HIGHEST PRIORITY)3334**When the user specifies an output format/tool, you MUST comply. Never substitute.**3536| User Says | You Must Do | Forbidden |37|-----------|------------|-----------|38| "use mermaid code" / "用Mermaid格式输出" / "转化为mermaid" / "mermaid流程" | ① Output Mermaid code block (```mermaid ... ```) ② Also provide a rendered image preview | ❌ Cannot only give image without code; ❌ Cannot screenshot raw code text as image |39| "use markdown code" | Output markdown-formatted hierarchy | ❌ Cannot switch to HTML/CSS |40| "via mermaid or markdown code" | Choose one of the two, output code text | ❌ Cannot switch to any non-specified format |41| "flowchart" / "mind map" (no format specified) | Free to choose the best approach | - |42| "use echarts/d3" | Must use the specified framework | ❌ Cannot switch |4344### 🚫 FORBIDDEN: Mermaid Code Screenshot45**NEVER take a screenshot of raw Mermaid source code and deliver it as the "diagram image".** This is the worst possible outcome — the user gets neither usable code nor a visual diagram. When the user requests Mermaid format:461. **MUST** output the Mermaid code in a fenced code block (````mermaid`)472. **SHOULD** also render the code into a visual diagram image (via mermaid-cli or Playwright + mermaid.js)483. If rendering fails, deliver the code block and tell the user to paste it into mermaid.live4950### Format Specified vs Auto-Upgrade Conflict51When the user specifies Mermaid but content triggers auto-upgrade conditions (>8 nodes, CJK-heavy, etc.):521. **User choice wins** — still use Mermaid, deliver code block + rendered image532. **Proactively guide** — after delivery, suggest the user try without specifying Mermaid for better layout quality543. **Never silently switch** to Playwright+CSS when user explicitly asked for Mermaid5556When a specified tool hits rendering difficulties (e.g., mermaid CDN fails):57- ✅ Output raw mermaid code text, tell user to view at mermaid.live58- ❌ Secretly switch to another framework59- ❌ Screenshot the code text as an "image"6061---6263## Routing Decision Tree6465### 1. Structural Diagrams6667#### 🔴 Flowchart Default: Phased Vertical (HIGHEST PRIORITY)6869**When the user asks to "generate/create a XXX flowchart/流程图" without specifying format, the DEFAULT layout is Phased Vertical (Layout C in `references/playwright-css.md`).**7071This is because nearly all real-world processes (manufacturing, legal proceedings, project management, business operations, cooking recipes, etc.) have natural phases/stages. Layout C produces the most professional, readable result.7273**Flowchart routing priority:**741. **User specified Mermaid/markdown** → follow user choice (Format Constraint Rule)752. **≤6 nodes AND no phases AND short text** → Mermaid (simple flowchart)763. **Everything else** → **Playwright + CSS, Layout C (Phased Vertical)** → `references/playwright-css.md`7778**Phase detection — treat as "has phases" when ANY is true:**79- Content has numbered sections (一、二、三 or 1. 2. 3. or Phase 1/Stage 1)80- Process can be grouped by time/stage/role (e.g., "preparation → execution → review")81- Total steps ≥ 5 (almost always groupable into 2+ phases)82- Process involves multiple roles/departments83- Process has clear start/end with intermediate stages8485**⚠️ When in doubt, default to Layout C.** A phased layout with only 1 phase still looks professional. A Grid layout with phases looks like a mess.8687#### Other Structural Diagrams88- Simple flowchart (≤6 nodes, truly flat, no phases): **Mermaid**89- Complex flowchart (>6 nodes / CJK-heavy / branches / phases): **Playwright + CSS Layout C** → `references/playwright-css.md`90- Mind map / tree / org chart: **Playwright + CSS** → `references/mindmap-css.md`91- Relationship / network diagram: **ECharts graph**92- Center-radial analysis (SWOT / BSC / Porter's Five Forces / PEST): **Playwright + CSS** → `references/radial-grid.md`9394### 2. Data Charts (matplotlib / seaborn)95- Standard bar/line/scatter/heatmap/radar/pie: **matplotlib**96- Regression/distribution/boxplot: **Seaborn**9798### 3. Interactive Charts / Dashboards99- Data dashboard / candlestick / real-time: **ECharts**100- Fully custom interactive: **D3.js**101102### Default Strategy103**One scene, one tool — don't hesitate:**104105| Scene | Tool | Template |106|-------|------|----------|107| Data chart (bar/line/scatter/pie/radar) | matplotlib | `references/matplotlib.md` |108| Statistical (regression/box/dist) | Seaborn | `references/seaborn.md` |109| Mind map / tree / org chart | Playwright + CSS | `references/mindmap-css.md` |110| Center-radial (SWOT/BSC/PEST/Five Forces) | Playwright + CSS | `references/radial-grid.md` |111| **Any flowchart (default)** | **Playwright + CSS Layout C** | **`references/playwright-css.md`** |112| Simple flowchart (≤6 nodes, truly flat) | Mermaid | `references/mermaid.md` |113| Relationship / force-directed | ECharts graph | `references/echarts.md` |114| Data dashboard | ECharts | `references/echarts.md` |115| Academic paper figures | matplotlib | `references/matplotlib.md` |116117---118119## Mermaid Auto-Upgrade Rules120121Mermaid's dagre/elk layout estimates CJK widths incorrectly. **Auto-switch to Playwright+CSS when ANY condition is met:**122123| Trigger | Action |124|---------|--------|125| Total nodes > **6** | → CSS flowchart (Layout C) |126| Any node text > **12 Chinese characters** | → CSS flowchart |127| More than **3 parallel branches** | → CSS flowchart |128| Nested subgraphs > **2 levels** | → CSS flowchart |129| Connector crossings > **2** | → CSS flowchart |130| **Side annotations / dashed note boxes** | → CSS flowchart |131| **Loop-back / cycle arrows** | → CSS flowchart |132| **Process has identifiable phases/stages** | → CSS flowchart (Layout C) |133134**If staying with Mermaid**: `padding: 32`, `nodeSpacing: 80`, `rankSpacing: 80`. Node text ≤ 10 CJK chars/line, wrap with `<br>`, quote all text `A["text"]`.135136---137138## Large Dataset Rendering139140| Data Size | Approach |141|-----------|----------|142| < 1,000 points | matplotlib / any |143| 1,000 - 10,000 | matplotlib (no markers) or ECharts |144| 10,000 - 100,000 | ECharts (Canvas mode) |145| > 100,000 | ECharts (`large: true`) or WebGL |146147---148149# Part 2: Universal Rules150151These rules apply to ALL charts regardless of framework. Framework-specific rules live in each template file.152153## 7 Core Rules1541551. **Zero overlap.** No element may cover another's text. Overlap = information loss = task failure. Post-generation: verify every element has clear separation.1561572. **Hierarchy over uniformity.** Primary nodes larger/bolder than secondary. Annotation nodes smaller/muted. Spacing between groups > within groups. If every box looks identical, the layout has failed.1581593. **Low-saturation palette.** 70% background/neutral, 20% secondary, 10% accent (one highlight only). No high-saturation large fills. Saturated colors only on borders (2px), text, and small elements.1601614. **Insight first.** Titles express conclusions, not field names. Remove non-essential elements: top/right borders, grid lines, tick marks, legend box borders. If removing it doesn't reduce understanding, it shouldn't exist.1621635. **Label clarity over label method.** The goal is zero overlap — choose the method that achieves it for each chart type. Direct labels, legends, and leader lines are all valid; what matters is that nothing overlaps.164165### 🚫 FORBIDDEN: Any Text Overlapping Any Other Element166**No label, legend, annotation, or title may overlap any other visual element.** This is the single most common matplotlib defect. Both direct labels AND legends can cause overlap — neither is inherently safe.167168**Anti-overlap decision tree:**1691. **Check if direct labels fit** — if all labels have enough space (bar tops, line endpoints, large pie slices), label directly. No legend needed.1702. **If some labels would collide** (small pie slices, dense scatter points, clustered bars) → use legend outside plot area instead of forcing labels into tight spaces.1713. **Mixed approach** — label the major items directly, group small items into "其他" or use leader lines + legend for the small ones.172173**Pie chart specific (the worst offender):**174- Slices < 5%: MUST use leader lines (`wedgeprops + texts` manual repositioning, or `matplotlib.patches.ConnectionPatch`) to pull labels outside. Do NOT rely on `autopct` alone — it places text inside/near the slice.175- Multiple small adjacent slices: use `bbox_to_anchor` legend outside, NOT direct labels176- `labeldistance=1.25` minimum to keep labels outside the pie177- When >2 slices are < 5%, consider grouping all < 3% into "其他(X项)"178- Use `adjustText` library to auto-resolve label collisions when available179180**Legend placement (when legend is needed):**181- Place legend **outside** the plot area using `bbox_to_anchor`182- Suggested starting positions:183 - Bar/line/scatter: right side outside (`bbox_to_anchor=(1.02, 1), loc='upper left'`)184 - Pie: right side outside (`bbox_to_anchor=(1.1, 0.5), loc='center left'`)185 - Radar: below chart (`bbox_to_anchor=(0.5, -0.15), loc='upper center'`)186 - Heatmap: no legend needed (colorbar suffices)187188**🔧 Mandatory: auto-adjust legend to prevent overlap.** Copy this snippet after placing any legend:189```python190# ── Auto-adjust legend position to prevent overlap ──191fig.canvas.draw() # must render first to get bboxes192legend = ax.get_legend()193if legend:194 renderer = fig.canvas.get_renderer()195 # Try shifting up to 5 times to resolve overlap196 for _ in range(5):197 leg_bb = legend.get_window_extent(renderer).transformed(ax.transAxes.inverted())198 has_overlap = False199 for text in ax.texts + [ax.title] + ax.get_xticklabels() + ax.get_yticklabels():200 if not text.get_text():201 continue202 txt_bb = text.get_window_extent(renderer).transformed(ax.transAxes.inverted())203 if leg_bb.overlaps(txt_bb):204 has_overlap = True205 break206 if not has_overlap:207 break208 # Move legend further outside (direction depends on current loc)209 bbox = legend.get_bbox_to_anchor().transformed(ax.transAxes.inverted())210 x0, y0 = bbox.x0, bbox.y0211 # Heuristic: if legend is below center, move down; if right of center, move right212 if y0 < 0.5:213 legend.set_bbox_to_anchor((x0, y0 - 0.08), transform=ax.transAxes)214 else:215 legend.set_bbox_to_anchor((x0 + 0.08, y0), transform=ax.transAxes)216 fig.canvas.draw()217```218- **After placing legend**: always call `plt.tight_layout()` or `fig.subplots_adjust()` to ensure legend is not clipped219220🚫 FORBIDDEN:221- `loc='best'` — matplotlib's "best" frequently overlaps data222- `loc='upper right'` / `loc='lower right'` on line/bar charts — high collision risk223- Direct labels on pie slices < 5% without leader lines224- Any text placement without verifying zero overlap2252266. **Font discipline.** Max 2 fonts. Chinese: SimHei/PingFang SC. Always explicitly set fonts in code. Font size follows hierarchy (title 18-24px → body 13-15px → annotation 11-13px). Never go below 10px floor. When text overflows: condense text → enlarge canvas → last resort: shrink font (but never below floor).2272287. **Whitespace is design.** Chart area 60-70% of canvas, margins 15-20%. At least 16pt between title and chart. Crowded ≠ information-rich.229230---231232## Color System233234### Recommended Palettes235236| Palette | Text | Background | Block Fill | Accent |237|---------|------|------------|------------|--------|238| Business Cool | `#243447` | `#F8FAFC` | `#E9EEF3` | `#4C6EF5` |239| Tech Cyan-Gray | `#1F2937` | `#F5F7FA` | `#E6ECF2` | `#3AAFA9` |240| Morandi Warm | `#4B4A45` | `#FAF8F4` | `#EAE4DB` | `#C6866A` |241| Invisible Precision | `#37352F` | `#FFFFFF` | `#F7F7F7` | `#2383E2` |242243### 🚫 Forbidden Background Colors244245| Color | Forbidden Hex Values |246|-------|---------------------|247| Pure blue | `#3B82F6`, `#2563EB`, `#1D4ED8` |248| Pure green | `#10B981`, `#059669`, `#22C55E` |249| Pure red | `#EF4444`, `#DC2626`, `#F87171` |250| Pure purple | `#8B5CF6`, `#7C3AED`, `#A855F7` |251| Pure amber | `#F59E0B`, `#D97706`, `#FB923C` |252253### ✅ Allowed Background Colors254255| Color | Hex Values |256|-------|------------|257| Ice blue | `#EFF6FF`, `#DBEAFE` |258| Mint green | `#F0FDF4`, `#D1FAE5` |259| Light amber | `#FFF7ED`, `#FEF3C7` |260| Lavender | `#F5F3FF`, `#EDE9FE` |261| Light gray | `#F8FAFC`, `#F1F5F9` |262263### Functional Color (states only, not decoration)264- Active/Selected: brand accent or `2px` accent line265- Error: `#EF4444`266- Success: `#10B981`267- Tags: light bg + dark text, never high-sat pills268269### Colorblind-Safe270Don't rely on color alone — pair with shape, line style, or direct labels.271Paul Tol palette: `['#0077BB', '#33BBEE', '#009988', '#EE7733', '#CC3311', '#EE3377']`272273### Dark Theme274- Background: `#0F172A` (not pure black)275- Text: `#F1F5F9` (not pure white)276- Grid: `#1E293B`, low alpha277- Export: `savefig(facecolor='#0F172A')`278279---280281## Export Rules282283- Static charts: minimum 200 DPI, recommended 300 DPI284- Pie/radar: **square `figsize=(8, 8)`** — non-square = elliptical285- No more than 6 colors per chart (split if more)286- Bar chart Y-axis starts at 0 (line charts may truncate)287- Never use 3D (distorts proportions)288289### Playwright Screenshot290Default `device_scale_factor=2`. Large mind maps (3000px+): 1.5. PDF embed: 1-1.5. Print: 3.291After render, read `bounding_box()` and resize viewport to fit. Min viewport: 800px single-col, 1200px multi-col.292293### 🚫 FORBIDDEN: `max-width` on Mermaid/SVG Containers294Mermaid's dagre engine produces SVGs with unpredictable width (especially with subgraphs, CJK text, or parallel branches). **NEVER set `max-width` on the Mermaid container element.** Use `width: fit-content; min-width: 800px;` instead.295296**Root cause**: Mermaid SVGs overflow their CSS container silently. `bounding_box()` (Playwright) returns the CSS box model size, NOT the SVG's actual rendered size. So auto-resize viewport based on `bounding_box()` alone will still produce clipped screenshots.297298**Fix**: Always read the **SVG element's own `getBoundingClientRect()`** via `page.evaluate()`, then use `max(css_size, svg_size) + padding` for viewport dimensions. See `references/mermaid.md` for the corrected screenshot script.299300### Aspect Ratio Preservation (embedding)301**MUST read actual image dimensions and calculate height proportionally. NEVER hardcode both width and height.**302303---304305## matplotlib-Specific Rules306307These apply when routing to matplotlib/seaborn:308309### Layout & Overlap310- Prefer `constrained_layout=True` over `tight_layout()`311- Use `adjustText` library for automatic label repositioning — **this is the most reliable anti-overlap tool for matplotlib.** Install: `pip install adjustText`. Usage: `from adjustText import adjust_text; adjust_text(texts)`312- Max 4 subplots per canvas. More → split images or `figsize=(20, 16)` minimum313- Multi-subplot: `GridSpec` with `wspace/hspace` ≥ 0.3314- Colorbar: `shrink=0.8` + `pad=0.08`315- Data labels: Y-axis upper limit with 15-20% headroom (`ylim(0, max_val * 1.18)`)316- Long X labels → horizontal bar chart or show every N-th label317318### Radar / Spider Charts319- **Every `fill()` MUST have `alpha=0.25`** (max 0.3). Omitting alpha = opaque = hides underlying series.320- Legend: place outside chart with `bbox_to_anchor`, start with `(0.5, -0.15), loc='upper center'`. If dimension labels are long or dimensions > 8, increase offset (e.g., `-0.25` or `-0.3`). Also FORBIDDEN: `loc='lower right'` (collides with radar dimension labels).321- Dimension label padding: `set_rlim(0, max_value * 1.2)`322- Labels with >4 CJK chars: rotate to follow angle or abbreviate323- `figsize=(8, 8)` mandatory (square)324325### One Color, Gray the Rest3265 lines → color only the key one, others `#D1D5DB`. 8 bars → accent only the highlight, rest `#E5E7EB`.327328---329330## Connector Rules (structural diagrams)331332- Attach to node edges, not through centers333- Prefer orthogonal polylines or clean curves334- Main paths avoid crossing335- Never pass through text areas336- Start/end points at same level must align (no staggering)337- Same-level connectors follow same direction338- Bend angles consistent (all right-angles or all curves, no mixing)339- Label positions uniform (all above line or all centered)340341---342343## Pre-Output Checklist344345Before delivery, verify:346347- [ ] Zero overlap (nodes, connectors, labels, legends — **especially check legend vs data, and adjacent pie/bar labels**)348- [ ] No connectors pass through text boxes349- [ ] Clear hierarchy (primary/secondary/annotation visually distinct)350- [ ] Low-saturation palette (no forbidden background colors)351- [ ] Text readable at final size (standalone: ≥12px body, ≥10px annotation; PDF embed: ≥10pt/8pt/7pt)352- [ ] Legend fully visible, not clipped, not overlapping any chart element353- [ ] Canvas wide/tall enough (check bounding box before screenshot)354- [ ] **If mind map**: each level distinct (≥3 property changes), connectors visible (≥ `#94A3B8`), left-right balanced355- [ ] **If flowchart**: phase titles distinct from steps, arrows only between phases, **using Layout C by default**356- [ ] **If flowchart**: phase colors are same-hue family (blue-gray progression), **NOT rainbow** (blue→green→amber→purple)357- [ ] **If flowchart looks scattered**: STOP — you're using the wrong layout, switch to Layout C358- [ ] **If Mermaid looked rigid**: already switched to Playwright+CSS359360---361362## Anti-Pattern Quick Reference363364| ❌ Don't | ✅ Do This Instead |365|----------|-------------------|366| matplotlib default blue `#1f77b4` | Use this skill's palette |367| 3D bar/pie | Always 2D |368| Rainbow colormap (jet/rainbow) | Single-hue gradient or diverging |369| Thick black grid lines | `alpha=0.08` or remove |370| Different color per bar | Same series same color, highlight only key |371| 45° tilted X labels | Horizontal bar chart or shorten |372| 8+ subplots in one canvas | Split to 2-3 images, max 4 each |373| `tight_layout()` alone | `constrained_layout=True` or `GridSpec` |374| Labels overflowing chart | `ylim` with 18-25% headroom |375| Mind map: all levels same style | Root+L1 get boxes, leaves plain text |376| Mind map: image too tall | Left-right layout for ≥5 branches |377| Mind map: invisible connectors | Lines ≥ `#94A3B8`, root→L1 `#64748B` 2.5px |378| Mind map: unbalanced sides | Alternate large/small branches across sides |379| Flowchart: high-sat node fills | Low-sat bg (`#EFF6FF`) + sat border (`#3B82F6`) |380| Flowchart: dark bg + dark text | Dark bg → white text. Light bg → dark text |381| Flowchart: arrows between every step | Arrows ONLY between phases, steps use indent |382| Flowchart: cross-layer lines through nodes | Connect adjacent layers only |383| Flowchart: Grid layout for phased process | **Always use Layout C (Phased Vertical)** |384| Flowchart: phase titles as floating labels | Phase titles MUST be inside group cards |385| Flowchart: nodes scattered without grouping | Group nodes into phase cards with `.phase-group` |386| Flowchart: rainbow phase colors (blue→green→amber→purple) | Same-hue blue-gray progression for all phases |387| Multiple arrows to same entry point | Merge-then-enter pattern |388| Legend inside plot obscuring data | `bbox_to_anchor` outside plot area |389| Radar fill without alpha | `alpha=0.25` mandatory |390| Decorative icons/emoji | Let the data speak |391| Grid lines where whitespace suffices | Background contrast or spacing instead |392393---394395## UI Aesthetics (dashboards / card layouts)396397When building UI-style outputs (dashboards, panels), apply "Invisible Precision":398399- **Boundaries**: Subtle bg shifts (`#F7F7F7` on `#FFFFFF`), not border lines. Reserve `1px` dividers for absolute logical breaks only.400- **Actions**: Primary CTA in dark neutral (`#1A1A1B`). Secondary: ghost/gray. Hover: 5% darker, no size change.401- **Quiet UI**: Action buttons `opacity: 0` by default, `1` on hover. Only active elements get visual indicators.402- **Numbers**: `font-variant-numeric: tabular-nums` for strict vertical alignment.403- **Spacing**: `line-height: 1.625`, generous paragraph spacing.
Run npx skillmds@latest add hongmaple0820/charts in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Professional chart and diagram creation skill. Covers all types of visual data representation and structural diagrams: - **Data charts**: bar charts, line charts, pie charts, scatter plots, heatmaps, radar charts, candlestick charts, boxplots, histograms, area charts, waterfall charts, regression plots, distribution plots, and statistical visualizations. - **Structural diagrams**: flowcharts, mind maps, tree diagrams, org charts, architecture diagrams, network/relationship graphs, ER diagrams, class diagrams, Gantt charts, swimlane diagrams, and sequence diagrams. - **Dashboards**: data dashboards, KPI panels, multi-chart compositions, and interactive visualizations. - **Design quality**: professional color systems, anti-overlap rules, layout optimization, scene-based framework routing (matplotlib, seaborn, ECharts, D3.js, Mermaid, Playwright+CSS), and publication-ready output. Applies when the user wants to create, generate, draw, plot, visualize, or improve any chart, graph, diagram, or dashboard. Also appl It is listed under Web & Frontend on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free. This skill is licensed under Proprietary.
hongmaple0820 (@hongmaple0820) published this skill. Their other Agent Skills are listed on their SkillMD profile.