﻿---
title: Isomer charts
description: Chart primitives on one shared core, a dashboard grid, and an unsupported placeholder, published for hosts and materializers to build against.
url: https://docs-v3-preview.elastic.dev/isomer/charts
---

# Isomer charts
`@elastic/isomer-primitives-charts` is the published chart pack. It holds separate primitives per chart family over one shared core, a `grid` that lays nodes out as a Kibana dashboard does, and an `unsupported` placeholder for anything that cannot be shown.
A chart node is self-contained: its data is inline and typed, its data colors are concrete for both color schemes, and its formats come from one closed portable set. Whoever builds the node, a Kibana materializer or an agent, resolves everything a renderer would otherwise have to decide. Renderers translate; they never format, pick a data color, sort, or choose ticks.

| Primitive                                                                      | Holds                                                                                                 |
|--------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
| [`metric`](https://docs-v3-preview.elastic.dev/isomer/charts/metric)           | One headline value, or one tile per row, with an optional secondary value, progress bar or trend line |
| [`xyChart`](https://docs-v3-preview.elastic.dev/isomer/charts/xy-chart)        | Lines, areas and bars over a shared x axis, with reference lines and annotations                      |
| [`grid`](https://docs-v3-preview.elastic.dev/isomer/charts/grid)               | Titled panels on a 48-column grid, in optional sections                                               |
| [`unsupported`](https://docs-v3-preview.elastic.dev/isomer/charts/unsupported) | A visible placeholder with a reason and a link                                                        |

Every chart primitive shares the [chart core](https://docs-v3-preview.elastic.dev/isomer/charts/core): `title`, `description`, `data`, `colors`, `source` and `losses`, and declares its [interactions](https://docs-v3-preview.elastic.dev/isomer/charts/interactions).

## Entries


| Entry                                      | Holds                                                                                                                               |
|--------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------|
| `@elastic/isomer-primitives-charts/schema` | The contracts: Zod schemas, node types, catalog entries and named examples. It imports no renderer.                                 |
| `@elastic/isomer-primitives-charts/scene`  | The [Scene](https://docs-v3-preview.elastic.dev/isomer/charts/scene) types every renderer reads, and the `SceneRenderer` interface. |
| `@elastic/isomer-primitives-charts`        | Everything above.                                                                                                                   |

```ts
import {
  metricExamples,
  metricSchema,
  type MetricNode,
} from '@elastic/isomer-primitives-charts/schema';
```

The schemas are object schemas for `definePrimitive`, which adds `id` and `surfaces` and closes each node to unknown keys; `grid` is a container and is bound to a composition's body-node union through `gridSchemaFor`. Validate a node inside a composition with a runtime that registers the pack, so nested nodes are checked against every pack the composition holds.

## Adding a field

A chart node carries everything a faithful rendering needs, and drawing it is the engine's job. When a chart does not match its source, that is a gap in an engine, never missing information in the node. A field belongs on a primitive when:
- **It says what it draws, in Isomer's terms.** Its description gives the values, units and effect a reader can check, never "as Lens does". A name borrowed from a source, such as an Elastic Charts fit or an EUI icon, is fine once the field defines it.
- **It carries what a faithful rendering needs, even if one engine alone can draw it.** An engine that cannot draw a field documents its fallback; the field stays.
- **An agent can choose it from the catalog alone**, without knowing the product a node may come from.
- **Its default is Isomer's.** A materializer states its source's value rather than relying on the default to match.
- **A renderer reads it.** What only a host acts on, such as a saved object id, belongs in opaque `source` meta.


## Rules

`z.toJSONSchema` drops refinements, so each cross-field rule is stated word for word in the description an agent reads, and a test checks that each check states its rule there. The rules are on each primitive's page.