Skip to main content

XY Container

Basic Configuration​

XY Container is designed as a container that manages multiple XY Components at once, along with optional X and Y axes, tooltip, and crosshair. Here is an example of a common configuration: one XY Component alongside two Axis components:

component.tsx
<VisXYContainer data={data}>
<VisStackedBar x={x} y={y}/>
<VisAxis type="x"/>
<VisAxis type="y"/>
</VisXYContainer>
Loading...

Multiple XY Components​

By providing the container with data, every XY Component within the container will be able to use it. There is no limit to the number of XY Components your container can have.

component.tsx
<VisXYContainer data={data}>
<VisStackedBar x={x} y={y} barWidth={35} color="#72a5ff"/>
<VisLine x={x} y={y}/>
<VisScatter x={x} y={y} shape={shape}/>
</VisXYContainer>
Loading...

Chart Sizing​

Width and Height​

By default, XY Container will try to fit within the bounds of its parent HTML element. If the parent height isn't defined, the default height of 300px will be applied. You can also explicitly define the container's size with the width and height properties, which accepts numeric values.

const width = 200;
const height = 100;
Loading...

Margin​

You can set XY Container's margin to control the spacing between the container and adjacent elements. The margin property accepts a value of type Sizing, where each value represents the corresponding margin size in pixels.

Sizing​

type Sizing = {
top: number;
bottom: number;
left: number;
right: number;
}

Note that the chart's size is affected by this property. Notice how the following chart is affected after setting the margin accordingly.

const margin = { left: 100, right: 100 }

Before:​

Loading...

After:​

Loading...

Padding​

You can configure the padding property of XY Container to change how its children are spaced apart. This property also accepts value of type Sizing. In contrast to margin, the padding property will not affect the overall size of the chart, but rather tha size of the individual components. See how this works using the same example as above:

const padding = { left: 100, right: 100 }
Loading...

Bleed​

Some components need extra space inside the container for their marks to fully fit: half of the point diameter for Scatter, half of the bar width for bar charts at the edges of the domain, and so on. This space is called bleed. Before rendering, the container asks every component how much bleed it needs, combines the values (taking the maximum for each side), and shrinks the scale ranges accordingly. That's why the first and the last points of the scatter chart below are shifted inward from the container's edges instead of being cut in half:

Loading...

The container reports the bleed it used to the onRenderComplete callback, and you can override the calculated values with the bleed property. It accepts a Spacing object, or a function that receives the container's components and returns one. The sides you provide replace the calculated values, the sides left undefined fall back to them. Here is the same chart with the bleed set to zero on every side — the edge points now get clipped:

const bleed = { top: 0, bottom: 0, left: 0, right: 0 }
Loading...

Overriding the bleed is mainly useful for aligning the X values of several charts placed one below another — see the Bleed guide for a complete walkthrough.

Range​

The xRange and yRange determine the screen space your chart contains. By default, an XY Container will fit to its container. Provide xRange with values [xStart, width] and yRange with [yStart, height] to override the default configuration.

Automatic Margins​

By default autoMargin is true: the container measures the X and Y axes and reserves the margin needed so their tick labels and titles aren't clipped. Set it to false when you'd rather control the spacing yourself through the margin property — for example, to line several charts up on a shared left edge:

<VisXYContainer data={data} autoMargin={false} margin={{ left: 60, bottom: 30 }}>
{/* … */}
</VisXYContainer>

Domain​

You can change the domain of your data with the xDomain and yDomain properties to configure which values your XY Component should display. The result will show all data that is in this range- excluding any values that fall outside of the range, and occupying any missing values with white space. See the following example, which looks like this when the domain is not set:

Loading...

xDomain = [4,8]​

Loading...

yDomain = [0,100]​

Loading...

Domain Constraints​

Customizing your domain is helpful in datasets with outliers. When using dynamic data, you may not know which values to constrain your domain values to. With the following constraint properties xDomainMinConstraint, xDomainMaxConstraint, yDomainMinConstraint, and yDomainMaxConstraint, you can define partial domains. For the following examples, consider the following case where the majority of the data is within the ranges [0,10] for all values of x and y. These properties accept a number array in the form [number, number] or more typically [number, undefined] | [undefined, number].

Domain Constraints: None​

Loading...

xDomainMinConstraint: [0, undefined]​

Loading...

yDomainMaxConstraint: [undefined, 10]​

Loading...

Single Data Point​

When the calculated domain is empty (when you have only a single data element and the domain's min and max values are equal), use the preventEmptyDomain property to extend it by +1. This may be useful when you have no data or a single data point and you want to show the empty space. The possible values are:

  • true: automatically extend the domain by +1 when the domain is empty (domain start equals domain end);
  • null: extend the domain, but only when there's no data (default);
  • false: keep the domain as is.

For example, a grouped bar with a single data point at x=1:

Loading...

Scale​

To change the scale of one of your axes in your Container, use the xScale or yScale property and a Scale function (i.e. Scale.scaleLinear()). Currently, only continuous scales are supported. See d3-scale for more information about the meaning behind these functions.

import { Scale } from '@unovis/ts'
const yScale = Scale.scaleLinear()
Loading...
const yScale = Scale.scalePow().exponent(2)

Dynamic Y Scale​

You can also set the yScale domain dynamically based on the current xDomain, meaning that only visible data will be used in the domain calculation. Take a look at the example below. The xDomain configuration property there is not set, the chart displays the whole dataset and the Y axis shows ticks from 0 to 150.

Loading...

Let's set xDomain to [0, 50]. The chart now shows only a portion of the original data but the Y axis still displays the whole data range. Setting scaleByDomain to true will tell the chart to dynamically calculate the domain of yScale based on the data within xDomain. It comes in hand when you're updating xDomain programmatically using, for example, the Brush component to provide some navigation capabilities to a chart with lots of data points.

component.tsx
<VisXYContainer
data={data}
xDomain={[0,50]}
scaleByDomain={true}
>
<VisStackedBar x={x} y={y}/>
<VisAxis type="x"/>
<VisAxis type="y"/>
</VisXYContainer>
Loading...

Y Direction​

You can set yDirection to change the direction of data along the Y axis. Supported values are Direction.North and Direction.South.

component.tsx
<VisXYContainer data={data} yDirection="south">
<VisStackedBar x={x} y={y}/>
<VisAxis type="x"/>
<VisAxis type="y"/>
</VisXYContainer>
Loading...

Color​

Use the colorFunction property to give every component inside the container a single color function of type (key: string | number) => string. Each component resolves its color through this function, passing either a data color key (from the component's colorKeys property) or, as a fallback, the series index. Supplying one colorFunction at the container level — and reusing it across other containers and the BulletLegend — is how you keep a category's color consistent across multiple charts.

import { Scale } from '@unovis/ts'
const color = Scale.scaleOrdinal().range(['#4d8cfd', '#ff6b7e', '#00c19a'])

In the example below the StackedBar's three series are labeled with colorKeys, and the container's colorFunction maps each key to a color:

For the full walkthrough — color keys, building a color function, syncing the legend and tooltip, and overriding the default palette — see Synchronizing Colors Across Charts in the Theming guide.

Animation​

Set duration (in milliseconds) on the container to control how long transitions take when the data or configuration updates. It applies to every component inside the container. The top chart below animates over 1500ms while the bottom one uses duration={0} for instant updates — press the toggle to alternate the data:

Loading...
Loading...

Tooltip​

Attach a Tooltip to show details on hover. Provide a triggers map that pairs a component's selector with a template function returning an HTML string:

See the Tooltip docs for positioning, show/hide delays, and custom rendering.

Crosshair​

A Crosshair renders a vertical line that follows the pointer and marks the nearest value on every series — ideal for line and area charts. Provide a template to show a tooltip alongside it:

Loading...

See the Crosshair docs for custom accessors, show/hide behavior, and styling.

Annotations​

Use Annotations to overlay text labels and callouts. Pass an items array; each item is positioned in data coordinates or with '%' strings and can point at a subject:

Loading...

See the Annotations docs for the full set of AnnotationItem options.

Accessibility​

Pass a descriptive ariaLabel to set an aria-label on the chart's container div, giving screen-reader users a text summary of the visualization:

<VisXYContainer data={data} ariaLabel="Monthly revenue by region, in US dollars">
{/* … */}
</VisXYContainer>

SVG Defs​

You can use the svgDefs property to inject custom SVG definitions — gradients, patterns, clip paths, and filters — that your components can reference by id. See our Theming guide, or the Gradient Fills and SVG Filters sections of the Theming guide, for details.

tip

For ready-made stripe, dot, and hatch fills you don't need custom defs — use a component's pattern accessor or the theme-patterns class. See Patterns in the Theming guide.

Component Props​

NameTypeDescription
* required property