- @hm-design/chart: add --hm-chart-track (radial tracks, horizontal bar hover band; warm neutral light) and --hm-chart-surface (slice / segment gaps, Dot rings, label halos, radial meter center; white by default) - --hm-chart-bar-name-halo stays an optional override and falls back to --hm-chart-surface; official chart.tsx unchanged - Storybook Chart pages (Bar / Line / Area / Donut / Pie / Radar / Radial): open layout without example cards, 2-4 responsive columns, one sample data notice per page, surface token set to the content background - Same sample data, props, tooltip and interaction as the example cards; examples entry and consumer example unchanged - README: surface / track token usage
77 lines
3.8 KiB
TypeScript
77 lines
3.8 KiB
TypeScript
import type { ReactNode } from "react"
|
|
import { sampleDataNotice } from "@hm-design/chart/examples"
|
|
import { StorySection } from "@/components/story-page"
|
|
|
|
// Storybook presentation only (not part of @hm-design/chart): the open Chart page layout (2026-11-12, user request).
|
|
// Charts sit directly on the Storybook content background, without the example card (background, border, padding). Each chart
|
|
// is one StorySection: H2 variant name → description (what the example shows) → thin section divider → optional toolbar → chart.
|
|
// The charts themselves are the public @hm-design/chart components on the @hm-design/chart/examples sample data, with the same
|
|
// props as the matching *Example card, so data, legend, tooltip and interaction are unchanged. No common layout change; the page
|
|
// only sets the chart's own surface token (chartPageClass).
|
|
|
|
/**
|
|
* className of every Chart page's StoryPage. The charts sit on the Storybook content background (--hm-sem-bg-content), so the page
|
|
* sets the chart's public surface token to it (2026-11-12): slice / segment gaps, Dot rings, label halos and the radial meter's
|
|
* center read as background instead of white. Only the token value is set, as a consumer would; no chart internals are overridden.
|
|
*/
|
|
export const chartPageClass = "[--hm-chart-surface:var(--hm-sem-bg-content)]"
|
|
|
|
/** One sample-data notice per page, instead of a badge and a notice under every chart. */
|
|
export function ChartSampleNotice() {
|
|
return (
|
|
<p className="m-0 text-[length:var(--hm-label-font-size)] leading-[var(--hm-label-line-height)] text-[color:var(--hm-sem-fg-secondary)]">
|
|
{sampleDataNotice}
|
|
</p>
|
|
)
|
|
}
|
|
|
|
/**
|
|
* One chart of a Chart page. `toolbar` keeps the example card's control row (Select height, so the charts of a row start at the
|
|
* same height); pass `null` for an empty row of that height next to charts that have one.
|
|
*/
|
|
export function ChartSpecimen({
|
|
title,
|
|
description,
|
|
toolbar,
|
|
children,
|
|
}: {
|
|
title: string
|
|
description?: ReactNode
|
|
toolbar?: ReactNode
|
|
children: ReactNode
|
|
}) {
|
|
return (
|
|
<StorySection title={title} description={description}>
|
|
{toolbar !== undefined ? (
|
|
<div
|
|
data-slot="chart-story-toolbar"
|
|
aria-hidden={toolbar === null ? true : undefined}
|
|
className="mb-3 flex min-h-[34px] items-center text-sm text-muted-foreground"
|
|
>
|
|
{toolbar}
|
|
</div>
|
|
) : null}
|
|
{children}
|
|
</StorySection>
|
|
)
|
|
}
|
|
|
|
// Grid columns (className of StorySectionGrid). Widths are the preview iframe width, which already excludes the Storybook sidebar.
|
|
// A third column only from 1200px, where each column keeps about 340px (Radial needs 320px). Rows align at the top; every
|
|
// chart keeps its own height. Source order is the one-column (mobile) order. All breakpoints are px (min-[…]): Tailwind does not
|
|
// order a rem breakpoint (lg) against a px one, so `lg:grid-cols-2` would win over `min-[1200px]:grid-cols-3`.
|
|
const base = "grid-cols-1 items-start *:min-w-0"
|
|
export const chartGrid = {
|
|
/** Wide charts (Bar): two per row from 1024px. */
|
|
pair: `${base} min-[1024px]:grid-cols-2`,
|
|
/** Compact round charts (Donut, Pie, Radial): two per row from 1024px, three from 1200px. */
|
|
compact: `${base} min-[1024px]:grid-cols-2 min-[1200px]:grid-cols-3`,
|
|
/** Radar (four charts): two per row from 1024px, four in one row from 1600px. */
|
|
quad: `${base} min-[1024px]:grid-cols-2 min-[1600px]:grid-cols-4`,
|
|
/**
|
|
* Plain / labelled pairs (Line, Area): two per row from 1024px (each pair in one row); from 1200px three columns that fill
|
|
* top to bottom, so the plain styles form the first row and their Dot + Label versions the second.
|
|
*/
|
|
pairs: `${base} min-[1024px]:grid-cols-2 min-[1200px]:grid-flow-col min-[1200px]:grid-cols-3 min-[1200px]:grid-rows-2`,
|
|
} as const
|