Voxel cloud
Voxel cloud
| Observation | Value |
|---|---|
| Node 1 | 12 · x: 22 · y: 37 · z: 30 |
| Node 2 | 29 · x: 85 · y: 36 · z: 78 |
| Node 3 | 46 · x: 36 · y: 64 · z: 59 |
| Node 4 | 63 · x: 29 · y: 30 · z: 43 |
| Node 5 | 80 · x: 79 · y: 48 · z: 73 |
| Node 6 | 17 · x: 37 · y: 69 · z: 39 |
| Node 7 | 34 · x: 33 · y: 16 · z: 17 |
| Node 8 | 51 · x: 71 · y: 47 · z: 53 |
| Node 9 | 68 · x: 43 · y: 82 · z: 35 |
| Node 10 | 85 · x: 34 · y: 14 · z: 30 |
| Node 11 | 22 · x: 66 · y: 35 · z: 78 |
| Node 12 | 39 · x: 50 · y: 88 · z: 59 |
| Node 13 | 56 · x: 29 · y: 25 · z: 43 |
| Node 14 | 73 · x: 64 · y: 26 · z: 73 |
| Node 15 | 90 · x: 56 · y: 79 · z: 39 |
| Node 16 | 27 · x: 23 · y: 36 · z: 17 |
| Node 17 | 44 · x: 67 · y: 32 · z: 53 |
| Node 18 | 61 · x: 60 · y: 66 · z: 35 |
| Node 19 | 78 · x: 16 · y: 33 · z: 31 |
| Node 20 | 15 · x: 73 · y: 46 · z: 78 |
| Node 21 | 32 · x: 59 · y: 66 · z: 59 |
| Node 22 | 49 · x: 11 · y: 20 · z: 43 |
| Node 23 | 66 · x: 80 · y: 49 · z: 73 |
| Node 24 | 83 · x: 54 · y: 78 · z: 38 |
| Node 25 | 20 · x: 10 · y: 13 · z: 17 |
| Node 26 | 37 · x: 86 · y: 39 · z: 53 |
| Node 27 | 54 · x: 47 · y: 88 · z: 35 |
| Node 28 | 71 · x: 14 · y: 21 · z: 31 |
| Node 29 | 88 · x: 88 · y: 27 · z: 78 |
| Node 30 | 25 · x: 40 · y: 83 · z: 59 |
Usage
Import the component and the stylesheet once. See Getting started to install the package.
import { VoxelCloudCard } from '@lilt-ui/charts';
import '@lilt-ui/charts/styles.css';<VoxelCloudCard data={spatialCloud} label="name" x="x" y="y" z="z" value="value" group="group" />Omit title to leave out the visible title. Set header={false} to remove the whole header, and use aria-label to name a chart inside your own card. legend={false} removes the legend independently. surface="ghost" controls only the visual frame. See Card composition.
Data
Supply unique labels, XYZ coordinates and nonnegative magnitude. Each coordinate has an independent linear scale and equal-valued axes are centred. Positive cube volume carries magnitude; zero and missing magnitudes use small distinct inspection markers. Slice bounds are inclusive in original z units and do not rescale the camera. All rows remain in the table, including missing and sliced-out positions. The headline counts visible positioned observations.
const spatialCloud = [
{
"name": "Node 1",
"x": 22,
"y": 37,
"z": 30,
"value": 12,
"group": "Platform",
"links": [
"Node 4",
"Node 7"
]
},
{
"name": "Node 2",
"x": 85,
"y": 36,
"z": 78,
"value": 29,
"group": "Experience",
"links": [
"Node 5",
"Node 8"
]
},
{
"name": "Node 3",
"x": 36,
"y": 64,
"z": 59,
"value": 46,
"group": "Growth",
"links": [
"Node 6",
"Node 9"
]
},
{
"name": "Node 4",
"x": 29,
"y": 30,
"z": 43,
"value": 63,
"group": "Platform",
"links": [
"Node 7",
"Node 10"
]
},
{
"name": "Node 5",
"x": 79,
"y": 48,
"z": 73,
"value": 80,
"group": "Experience",
"links": [
"Node 8",
"Node 11"
]
},
{
"name": "Node 6",
"x": 37,
"y": 69,
"z": 39,
"value": 17,
"group": "Growth",
"links": [
"Node 9",
"Node 12"
]
},
{
"name": "Node 7",
"x": 33,
"y": 16,
"z": 17,
"value": 34,
"group": "Platform",
"links": [
"Node 10",
"Node 13"
]
},
{
"name": "Node 8",
"x": 71,
"y": 47,
"z": 53,
"value": 51,
"group": "Experience",
"links": [
"Node 11",
"Node 14"
]
},
{
"name": "Node 9",
"x": 43,
"y": 82,
"z": 35,
"value": 68,
"group": "Growth",
"links": [
"Node 12",
"Node 15"
]
},
{
"name": "Node 10",
"x": 34,
"y": 14,
"z": 30,
"value": 85,
"group": "Platform",
"links": [
"Node 13",
"Node 16"
]
},
{
"name": "Node 11",
"x": 66,
"y": 35,
"z": 78,
"value": 22,
"group": "Experience",
"links": [
"Node 14",
"Node 17"
]
},
{
"name": "Node 12",
"x": 50,
"y": 88,
"z": 59,
"value": 39,
"group": "Growth",
"links": [
"Node 15",
"Node 18"
]
},
{
"name": "Node 13",
"x": 29,
"y": 25,
"z": 43,
"value": 56,
"group": "Platform",
"links": [
"Node 16",
"Node 19"
]
},
{
"name": "Node 14",
"x": 64,
"y": 26,
"z": 73,
"value": 73,
"group": "Experience",
"links": [
"Node 17",
"Node 20"
]
},
{
"name": "Node 15",
"x": 56,
"y": 79,
"z": 39,
"value": 90,
"group": "Growth",
"links": [
"Node 18",
"Node 21"
]
},
{
"name": "Node 16",
"x": 23,
"y": 36,
"z": 17,
"value": 27,
"group": "Platform",
"links": [
"Node 19",
"Node 22"
]
},
{
"name": "Node 17",
"x": 67,
"y": 32,
"z": 53,
"value": 44,
"group": "Experience",
"links": [
"Node 20",
"Node 23"
]
},
{
"name": "Node 18",
"x": 60,
"y": 66,
"z": 35,
"value": 61,
"group": "Growth",
"links": [
"Node 21",
"Node 24"
]
},
{
"name": "Node 19",
"x": 16,
"y": 33,
"z": 31,
"value": 78,
"group": "Platform",
"links": [
"Node 22",
"Node 25"
]
},
{
"name": "Node 20",
"x": 73,
"y": 46,
"z": 78,
"value": 15,
"group": "Experience",
"links": [
"Node 23",
"Node 26"
]
},
{
"name": "Node 21",
"x": 59,
"y": 66,
"z": 59,
"value": 32,
"group": "Growth",
"links": [
"Node 24",
"Node 27"
]
},
{
"name": "Node 22",
"x": 11,
"y": 20,
"z": 43,
"value": 49,
"group": "Platform",
"links": [
"Node 25",
"Node 28"
]
},
{
"name": "Node 23",
"x": 80,
"y": 49,
"z": 73,
"value": 66,
"group": "Experience",
"links": [
"Node 26",
"Node 29"
]
},
{
"name": "Node 24",
"x": 54,
"y": 78,
"z": 38,
"value": 83,
"group": "Growth",
"links": [
"Node 27",
"Node 30"
]
},
{
"name": "Node 25",
"x": 10,
"y": 13,
"z": 17,
"value": 20,
"group": "Platform",
"links": [
"Node 28",
"Node 1"
]
},
{
"name": "Node 26",
"x": 86,
"y": 39,
"z": 53,
"value": 37,
"group": "Experience",
"links": [
"Node 29",
"Node 2"
]
},
{
"name": "Node 27",
"x": 47,
"y": 88,
"z": 35,
"value": 54,
"group": "Growth",
"links": [
"Node 30",
"Node 3"
]
},
{
"name": "Node 28",
"x": 14,
"y": 21,
"z": 31,
"value": 71,
"group": "Platform",
"links": [
"Node 1",
"Node 4"
]
},
{
"name": "Node 29",
"x": 88,
"y": 27,
"z": 78,
"value": 88,
"group": "Experience",
"links": [
"Node 2",
"Node 5"
]
},
{
"name": "Node 30",
"x": 40,
"y": 83,
"z": 59,
"value": 25,
"group": "Growth",
"links": [
"Node 3",
"Node 6"
]
}
];Props
Every prop VoxelCloudCard accepts, in the order you are likely to reach for them.
| Prop | Type | Description |
|---|---|---|
title | string | Optional visible title. Omit to render no title. Also supplies the accessible name unless aria-label is set. |
header | boolean | Defaults to true. False removes the whole header: title, headline, delta and period controls, with no reserved space. Pass data directly when your app owns period selection. |
aria-label | string | Accessible chart name, independent of the visible title. Falls back to title, then a generic chart name. |
data | Row[] | One row per observation. Omit when using ranges. |
height | number | Minimum plot height, default 360px. Dense data may expand within the scrollable viewport. |
depth | boolean | Lit tiles, solid bars, or spheres. Data positions remain exact; loading keeps the same depth treatment. |
color | string | Override the palette with one CSS color. |
headline | number | Override the resting headline. |
delta | number | Fractional change shown alongside the headline. |
deltaTone | 'default' | 'inverse' | 'neutral' | Use inverse when a decrease is good. |
range | string | Static period label. |
ranges | { id, label, data, headline?, delta? }[] | Period choices with their own data. |
defaultRange | string | Initial period id. |
locale | string | Locale for numbers and dates; defaults to en-US. |
formatValue | (value: number) => string | Custom value formatter. |
badge | ReactNode | Content for the glass tab above the card. |
className | string | Class on the card frame. |
style | CSSProperties | ChartStyle | Inline styles and scoped chart variables. |
onSelectionChange | (selection | null) => void | Reports id, original row (or null for an absent day), value, and pinned state. |
renderReadout | (selection | null) => ReactNode | Consumer-owned readout, including when the header is hidden. |
valueFormat | Intl.NumberFormatOptions | Formats the headline, tiles, and axis, e.g. currency. |
surface | 'elevated' | 'outline' | 'ghost' | Card treatment. Ghost removes the visual frame only; header and legend are independent controls. |
palette | 'iris' | 'cobalt' | 'emerald' | Series colors. Iris by default; explicit series colors still win. |
numberStyle | 'count' | 'pop' | 'slide' | 'roll' | 'flow' | 'scramble' | How the headline animates when its value changes. Count (default) counts to the new value. |
loading | boolean | Shows a neutral loading skeleton, not data. |
loadingStyle | 'shimmer' | 'draw' | 'breathe' | Shimmer sweeps a highlight over still shapes; draw reveals them in order; breathe lets them settle. Follows the selected look, including depth, and respects reduced motion. |
empty | 'dots' | 'shape' | ReactElement | null | What the card shows when the period has no data. Dots (default) gathers a quiet dot field around the message; shape lays the chart’s own outline behind it. Pass `<ChartEmpty>` with your own words, any element of your own, or null for nothing. Both looks stay still, so empty never reads as loading, and the headline reads a dash, never zero. |
motion | 'auto' | 'none' | None turns off decorative motion; reduced motion does this automatically. |
label | text key of Row | Unique nonempty observation label, retained through inspection and pinning. |
x | numeric key of Row | First spatial coordinate on an independent linear scale. |
y | numeric key of Row | Second spatial coordinate on an independent linear scale. |
z | numeric key of Row | Third spatial coordinate on an independent linear scale. |
value | numeric key of Row | Nonnegative numeric measurement. Null or undefined is missing. |
group | text key of Row | Optional categorical color key. |
yaw | number | Camera rotation around the vertical axis, in degrees from -180 to 180. Default 35. |
elevation | number | Camera elevation, 10 to 70 degrees. Default 25. |
size | number | Maximum cube half-edge or sphere size as a fraction of the normalized plot, 0.025 to 0.18. Default 0.09. |
slice | readonly [number, number] | Optional inclusive [min, max] filter in original z units. The camera domain remains fixed. |
aggregate | 'sum' | 'mean' | 'max' | Fallback resting summary. A family-defined summary (such as located point count, hierarchy total, or mean signed value) takes precedence. Use headline to override that summary. |
onKeyDown | KeyboardEventHandler<HTMLElement> | Keyboard handler on the card frame. Chart inspection also has its own keyboard handling. |
legendSwatch | 'square' | 'dot' | 'line' | Marker beside each group label, where a group legend is present. Defaults to square. |
legend | false | 'tiles' | 'inline' | 'list' | 'pills' | 'bars' | Layout for the group legend where the data produces groups. False hides it; defaults to tiles. |