Add semanticGradient, downward hist, nodeStyle#961
Conversation
Introduce semanticGradient support and related conversions for AreaChart, add downward histogram direction handling, and expose a per-node nodeStyle overlay for Treemap.
- AreaChart: add SemanticGradientStop type and conversion (semanticGradientToColorStops) that maps user-facing percentages to renderer colorStops; semanticGradient takes precedence over gradientFill and is passed to the renderer.
- RealtimeHistogram: add direction prop ("up"|"down"); implement logic to resolve a flipped value extent for downward histograms (including category bin-summing and padding); wire resolved extent into yExtent and add test.
- Treemap: add nodeStyle prop and compose it with frameProps.nodeStyle and built-in color encoding; ensure primitive stroke/opacity props are applied after composition; pass remaining frameProps through; add test covering composed styles.
- Shared types/hooks: add HoverHighlightMode (boolean | "series") and propagate the type through hooks and streamPropsHelpers; add test for hoverHighlight alias behavior.
- Specs/validation/schema: update CHART_SPECS, VALIDATION_MAP and ai/schema.json with gradientFill, semanticGradient, direction, and nodeStyle metadata.
Also include tests for the new behaviors and small import/utility additions (color opacity helper). These changes enable semantic gradients, mirrored histogram layouts, and more flexible Treemap styling.
There was a problem hiding this comment.
Pull request overview
This PR expands Semiotic’s chart customization surface by introducing semantic gradient stops for AreaChart, a "down" direction option for RealtimeHistogram (mirrored histograms), and a composable nodeStyle overlay for Treemap, along with accompanying validation/spec/schema updates and tests.
Changes:
AreaChart: addsemanticGradient(user-percent stops) → converted to renderergradientFill.colorStopswith precedence overgradientFill.RealtimeHistogram: adddirection: "up" | "down"and compute a flippedyExtent(including stacked/bin-summed max) for downward histograms.Treemap: addnodeStylecomposition (built-in color encoding + user +frameProps.nodeStyle+ primitive props) and update specs/validation/tests.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/components/charts/xy/AreaChart.tsx | Adds semanticGradient API and conversion to renderer gradientFill.colorStops. |
| src/components/charts/xy/AreaChart.test.tsx | Tests semanticGradient-to-colorStops conversion and precedence over gradientFill. |
| src/components/charts/shared/validationMap.ts | Extends validation metadata for gradientFill, semanticGradient, direction, and nodeStyle. |
| src/components/charts/shared/useChartSetup.ts | Propagates widened hoverHighlight typing into chart setup. |
| src/components/charts/shared/types.ts | Introduces `HoverHighlightMode = boolean |
| src/components/charts/shared/streamPropsHelpers.ts | Propagates widened hoverHighlight typing through stream prop helpers. |
| src/components/charts/shared/hooks.ts | Updates useChartSelection typing to accept HoverHighlightMode. |
| src/components/charts/shared/hooks.test.ts | Adds coverage for hoverHighlight="series" alias behavior. |
| src/components/charts/shared/chartSpecs.ts | Documents new props in CHART_SPECS (including Treemap nodeStyle metadata). |
| src/components/charts/realtime/RealtimeHistogram.tsx | Adds direction support and downward-domain resolution logic. |
| src/components/charts/realtime/RealtimeHistogram.test.tsx | Adds test ensuring downward histograms flip the y-domain. |
| src/components/charts/network/Treemap.tsx | Adds nodeStyle overlay composition and ensures primitive props apply after composition. |
| src/components/charts/network/Treemap.test.tsx | Adds test covering composed Treemap styling behavior. |
| ai/schema.json | Updates JSON schema for gradientFill, semanticGradient, and histogram direction. |
Make readNumericValue more robust: treat null/undefined as null, convert Date to timestamp, and treat whitespace-only strings as null. Also narrow raw to unknown before coercion. Update tests to cover a blank time string and a null value to ensure the component handles these edge cases in RealtimeHistogram.
Introduce a TemporalHistogram (static-data temporal histogram) and wire it into exports, chart specs, AI schema, and validation map. Normalize partial margin handling across chart components and hooks (use normalizePartialMargin, treat "auto"/null as explicit auto-reservation) and document margin behavior in types and schema. Add a theme CSS variable --semiotic-cell-border (fallback to border) and use it as the Treemap tile stroke default. Improve tooltip handling by normalizing bucket-array hover data for custom tooltips. Also add several tests and small behavior changes: AreaChart/LineChart fallback to areaBy/lineBy when colorBy is omitted, update hooks/tests for legend margin reservation, and various export/index updates.
Change Treemap composition so public top-level `nodeStyle` wins over `frameProps.nodeStyle` for overlapping keys (frame styles are applied first, then user styles). Add nullish coalescing guards when merging style objects and update the explanatory comment. Update the Treemap test to declare a GroupedNode type and call <Treemap<GroupedNode>> so colorBy (a leaf-only field) is correctly typed against the union of root/leaf nodes. In AreaChart, semanticGradientToColorStops now filters out stops with non-finite `at` values before mapping to offsets (avoiding invalid offsets), removing the prior sort step.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 30 out of 30 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/components/stream/hoverUtils.ts:46
buildHoverDatais documented (and covered by existing tests) as preserving the raw datum onhover.data, but it now normalizes array-shaped datums torawDatum[0]. This is a behavior change for hover/click callbacks and can break consumers that rely on bucket/array-shaped hover data. Tooltip-specific normalization can happen at the tooltip layer without changing the core HoverData contract.
return {
data: normalizeHoverDatum(rawDatum),
x,
y,
__semioticHoverData: true,
...extra,
Update hoverUtils test to reflect that buildHoverData normalizes array-shaped datums to the first entry for tooltip consumers. The test name, inline comment and assertion were changed to document bucket-style scenes (histogram bins) and confirm hover.data is the first datum rather than the full array, while leaving the full array available via scene-level lookups.
Export the SemanticGradientStop type from AreaChart and re-export it via semiotic-xy and semiotic. Simplify and correct RealtimeHistogram.resolveDownwardHistogramExtent: remove the unused categoryAccessor parameter, return undefined when no data is present (allowing auto-scaling), always compute bin sums (so bar heights are summed per bin), and adjust the memo dependency list accordingly. These changes add the gradient-stop type to public APIs and make downward streaming histogram extents correct and more robust for empty/push-mode data.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 32 out of 32 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/components/stream/hoverUtils.ts:46
buildHoverDatanow normalizes array-shaped datums to their first entry. This breaks StreamOrdinalFrame’s built-in tooltip behavior for summary charts (boxplot/violin/ridgeline), which relies onhover.databeing an array to show item counts / stats (seeStreamOrdinalFrame.tsxDefaultOrdinalTooltip’sArray.isArray(d)branch).
Consider keeping hover.data as the raw datum and performing any “array → first datum” normalization only at the HOC tooltip-unwrapping layer (e.g. in Tooltip.normalizeTooltip) so stream-frame consumers that expect arrays keep working.
| * custom borders, or per-depth opacity without re-implementing color | ||
| * encoding. | ||
| */ | ||
| nodeStyle?: (d: Datum) => Datum | ||
| enableHover?: boolean |
Introduce a new TemporalHistogram entry to ai/capabilities.json (category: realtime; supportsLegend: true; supportsSelection: true; supportsLinkedHover: true; supportsPush: false; supportsSSR: false; colorModel: categorical; layoutMode: plugin; specialFeatures: ["brush"]). Regenerate docs/capabilities.md to include the new chart (Last regen updated to 2026-05-21), add the table row for TemporalHistogram, and update aggregate counts (chart total increased from 45 to 46).
Introduce TemporalHistogram as a static-data sibling to RealtimeHistogram: export it from the semiotic AI barrel, add it to the component registry, and mark it renderable in component metadata (exempting push-only Realtime charts). Update docs and examples (CLAUDE.md, ai/examples.md, API surface files) to document the new component and its usage. Adjust the parity checker to exclude TemporalHistogram from server-only exclusions, and update tests/test baseline and RealtimeHistogram test to assert the static frame/canvas rendering.
Document a new TemporalHistogram (static-data sibling of RealtimeHistogram) and add `direction` to RealtimeHistogram docs across rule and docs files; update public docs and .github instructions accordingly. Add API surface entries for function TemporalHistogram and interface SemanticGradientStop. Adjust scatter-50k benchmark to increase measurement/warmup time with a comment explaining the CI noise mitigation.
Introduce semanticGradient support and related conversions for AreaChart, add downward histogram direction handling, and expose a per-node nodeStyle overlay for Treemap.
Also include tests for the new behaviors and small import/utility additions (color opacity helper). These changes enable semantic gradients, mirrored histogram layouts, and more flexible Treemap styling.
This pull request introduces new customization options for chart components, focusing on improved styling and control for Treemap and RealtimeHistogram charts. It adds new props and schema definitions to support per-node styling in Treemap, directional bar growth in RealtimeHistogram (including downward/mirrored histograms), and more flexible hover highlighting. The changes are covered by new and updated tests, and documentation/spec updates are included to reflect the new features.
Add TemporalHistogram; normalize margins & cell-border
Introduce a TemporalHistogram (static-data temporal histogram) and wire it into exports, chart specs, AI schema, and validation map. Normalize partial margin handling across chart components and hooks (use normalizePartialMargin, treat "auto"/null as explicit auto-reservation) and document margin behavior in types and schema. Add a theme CSS variable --semiotic-cell-border (fallback to border) and use it as the Treemap tile stroke default. Improve tooltip handling by normalizing bucket-array hover data for custom tooltips. Also add several tests and small behavior changes: AreaChart/LineChart fallback to areaBy/lineBy when colorBy is omitted, update hooks/tests for legend margin reservation, and various export/index updates.
cbf9b12
ai/componentMetadata.cjs
Key changes:
Treemap Customization:
nodeStyleprop toTreemap, allowing users to overlay custom styles on top of built-in color encoding for individual nodes. This enables features like hiding the root node or customizing borders without losing default color resolution. [1] [2]nodeStylefunctions together, merging them with built-in styles. [1] [2]nodeStylecorrectly composes with color encoding.nodeStyleprop.RealtimeHistogram Directional Bars:
directionprop ("up" or "down") toRealtimeHistogram, allowing bars to grow downward for mirrored histogram layouts. When set to "down", the value domain is reversed, and explicitvalueExtentis also reversed. [1] [2] [3] [4] [5]directionprop. [1] [2]Area/Line Chart Gradient Fills:
gradientFillandsemanticGradientproperties to the area/line chart schema and chart specs, supporting both renderer-space and user-facing gradient fills. [1] [2]Hover Highlighting Improvements:
hoverHighlightprop to accept"series"as an alias for per-series highlighting, improving compatibility with wrapper libraries. [1] [2] [3] [4]"series"works as expected for hover highlighting.Documentation & Spec Updates:
These changes collectively provide more flexibility and control for users customizing chart appearance and behavior.