feat(chart): add @hm-design/chart package with Bar, Line, Donut, Pie, Radar, Area and Radial charts
- new workspace package packages/chart (shadcn/ui Chart + Recharts, HM Theme tokens), examples entry with sample data - Storybook Chart group (src/chart), consumer example (examples/chart), build:chart / build:chart-example scripts - README rewritten as the AI usage guide (install, CSS wiring, chart selection, data rules, verification) - docs: package count/list, Submodule guide (chart workspace, React dedupe), shared AI_GUIDE row, MAINTAINING, story inventory
This commit is contained in:
1 parent
228944a06b
commit
dc9258599c
56 files changed
+3979
-28
No files matched your search
@@ -0,0 +1,152 @@
|
||||
/* Chart mapping: the shadcn/ui Chart (Recharts) wired to the HM Theme. HM has no separate chart spec yet, so series colors are
|
||||
derived from existing HM palette Semantic tokens (green / brown / warm neutral); no HEX value is defined here.
|
||||
Requires @hm-design/ui/theme.css (the --hm-sem-* tokens). Runtime Theme overrides of the palette flow through these aliases. */
|
||||
:root, [data-hm-theme] {
|
||||
/* Series order alternates green and brown so neighbouring series stay distinguishable (bar, line and donut slices). */
|
||||
--hm-chart-1: var(--hm-sem-palette-green-light-2);
|
||||
--hm-chart-2: var(--hm-sem-palette-brown-light-2);
|
||||
--hm-chart-3: var(--hm-sem-palette-green-light-3);
|
||||
--hm-chart-4: var(--hm-sem-palette-brown-light-4);
|
||||
--hm-chart-5: var(--hm-sem-palette-warm-neutral-mid);
|
||||
|
||||
/* Light end of a stacked segment: the next palette step(s) lighter in the same family as the series color.
|
||||
Brown Light 4 is the lightest brown token, so series 4 keeps its own color (a flat segment) instead of borrowing another family. */
|
||||
--hm-chart-1-light: var(--hm-sem-palette-green-light-3);
|
||||
--hm-chart-2-light: var(--hm-sem-palette-brown-light-3);
|
||||
--hm-chart-3-light: var(--hm-sem-palette-green-light-4);
|
||||
--hm-chart-4-light: var(--hm-sem-palette-brown-light-4);
|
||||
--hm-chart-5-light: var(--hm-sem-palette-warm-neutral-light);
|
||||
|
||||
--hm-chart-tooltip-background: var(--hm-sem-bg-surface);
|
||||
--hm-chart-tooltip-border-color: var(--hm-sem-stroke-default);
|
||||
--hm-chart-tooltip-radius: var(--hm-radius-container);
|
||||
--hm-chart-tooltip-shadow: var(--hm-sem-floating-shadow);
|
||||
--hm-chart-tooltip-text: var(--hm-sem-fg-primary);
|
||||
--hm-chart-tooltip-label: var(--hm-sem-fg-secondary);
|
||||
--hm-chart-grid-color: var(--hm-sem-stroke-default);
|
||||
--hm-chart-axis-text: var(--hm-sem-fg-secondary);
|
||||
--hm-chart-center-value: var(--hm-sem-fg-primary);
|
||||
--hm-chart-font-family: var(--hm-font-family-base);
|
||||
}
|
||||
|
||||
[data-slot="chart"] {
|
||||
font-family: var(--hm-chart-font-family);
|
||||
/* The container may sit in a flex row or a narrow card: let it shrink instead of overflowing. */
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
[data-slot="chart"] .recharts-cartesian-axis-tick text {
|
||||
fill: var(--hm-chart-axis-text);
|
||||
}
|
||||
[data-slot="chart"] .recharts-cartesian-grid line {
|
||||
stroke: var(--hm-chart-grid-color);
|
||||
stroke-opacity: 0.6;
|
||||
}
|
||||
|
||||
[data-slot="chart-tooltip-content"] {
|
||||
border: 1px solid var(--hm-chart-tooltip-border-color);
|
||||
border-radius: var(--hm-chart-tooltip-radius);
|
||||
background: var(--hm-chart-tooltip-background);
|
||||
color: var(--hm-chart-tooltip-text);
|
||||
box-shadow: var(--hm-chart-tooltip-shadow);
|
||||
}
|
||||
[data-slot="chart-tooltip-content"] .text-muted-foreground {
|
||||
color: var(--hm-chart-tooltip-label);
|
||||
}
|
||||
|
||||
[data-slot="chart-legend-content"] {
|
||||
color: var(--hm-chart-tooltip-label);
|
||||
}
|
||||
|
||||
/* Donut center total. */
|
||||
[data-slot="chart-center-value"] {
|
||||
fill: var(--hm-chart-center-value);
|
||||
font-size: 24px;
|
||||
font-weight: var(--hm-font-weight-bold);
|
||||
}
|
||||
[data-slot="chart-center-label"] {
|
||||
fill: var(--hm-chart-axis-text);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* "Sample data" marker used by the @hm-design/chart/examples entry. */
|
||||
[data-slot="chart-sample-notice"] {
|
||||
color: var(--hm-chart-axis-text);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Horizontal bar chart labels. The item name sits on a gradient that starts at 30% of the series color, so the dark text gets
|
||||
a light halo (the card surface) to stay readable from the faint left end to the opaque right end. */
|
||||
:root, [data-hm-theme] {
|
||||
--hm-chart-bar-name-text: var(--hm-sem-fg-primary);
|
||||
--hm-chart-bar-name-halo: var(--hm-sem-bg-surface);
|
||||
--hm-chart-bar-value-text: var(--hm-sem-fg-primary);
|
||||
}
|
||||
[data-slot="chart-bar-name"],
|
||||
[data-slot="chart-bar-value"] {
|
||||
font-size: 12px;
|
||||
font-weight: var(--hm-font-weight-medium);
|
||||
pointer-events: none;
|
||||
}
|
||||
[data-slot="chart-bar-name"] {
|
||||
fill: var(--hm-chart-bar-name-text);
|
||||
stroke: var(--hm-chart-bar-name-halo);
|
||||
stroke-width: 3px;
|
||||
stroke-linejoin: round;
|
||||
paint-order: stroke;
|
||||
}
|
||||
[data-slot="chart-bar-value"] {
|
||||
fill: var(--hm-chart-bar-value-text);
|
||||
}
|
||||
/* Name of a bar too short to hold it: shown after the value on the card surface, so it uses the secondary text color. */
|
||||
[data-slot="chart-bar-outside-name"] {
|
||||
fill: var(--hm-chart-axis-text);
|
||||
font-size: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 0 line of the positive / negative bar chart: clearly darker than the regular gridlines. */
|
||||
:root, [data-hm-theme] {
|
||||
--hm-chart-zero-line: var(--hm-sem-fg-secondary);
|
||||
}
|
||||
|
||||
/* Value label above a line chart Dot; its color is set per point (series color or the point's own color). */
|
||||
[data-slot="chart-point-label"] {
|
||||
font-size: 12px;
|
||||
font-weight: var(--hm-font-weight-medium);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Pie: outside "name value" labels, value labels inside slices, and the ring key of the stacked pie. */
|
||||
[data-slot="chart-pie-label"] {
|
||||
fill: var(--hm-chart-axis-text);
|
||||
font-size: 12px;
|
||||
pointer-events: none;
|
||||
}
|
||||
[data-slot="chart-slice-label"] {
|
||||
fill: var(--hm-chart-bar-name-text);
|
||||
stroke: var(--hm-chart-bar-name-halo);
|
||||
stroke-width: 3px;
|
||||
stroke-linejoin: round;
|
||||
paint-order: stroke;
|
||||
font-size: 12px;
|
||||
font-weight: var(--hm-font-weight-medium);
|
||||
pointer-events: none;
|
||||
}
|
||||
/* Radar: custom axis names. */
|
||||
[data-slot="chart-axis-label"] {
|
||||
fill: var(--hm-chart-axis-text);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Radial: item names curved along the start of each bar. The halo keeps the text readable on pale bar colors. */
|
||||
.hm-radial-name {
|
||||
fill: var(--hm-chart-bar-name-text);
|
||||
stroke: var(--hm-chart-bar-name-halo);
|
||||
stroke-width: 2px;
|
||||
stroke-linejoin: round;
|
||||
paint-order: stroke;
|
||||
font-size: 11px;
|
||||
font-weight: var(--hm-font-weight-medium);
|
||||
pointer-events: none;
|
||||
}
|
||||
Reference in new issue
Block a user