XYLabels
The XYLabels component allows you to add text labels directly onto your XY charts at specific data coordinates.
Basic Configuration​
Get started with just two required properties - x, y accessors and an optional label function.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.9)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
color: "#374151",
backgroundColor: "rgba(255, 255, 255, 0.9)"
})
// Basic configuration
const xyLabels = new XYLabels({
x: d => d.x,
y: d => d.y,
label: d => d.label
})
Label Content​
The label property accepts a string accessor function that determines what text to display for each data point.
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.95)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
color="#374151"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
color: "#374151",
backgroundColor: "rgba(255, 255, 255, 0.95)"
})
// Custom label content
label: d => `${d.label}: ${d.y}`
Positioning​
XYLabels supports three different positioning modes through the xPositioning and yPositioning properties:
Data Space Positioning (Default)​
By default, labels are positioned in data space, meaning their coordinates correspond to data values. This is ideal when you want labels to move with your data:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="data_space"
yPositioning="data_space"
color="#0F172A"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
xPositioning="data_space"
yPositioning="data_space"
color="#0F172A"
backgroundColor="rgba(255, 255, 255, 0.9)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
xPositioning="data_space"
yPositioning="data_space"
color="#0F172A"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
xPositioning="data_space"
yPositioning="data_space"
color="#0F172A"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="data_space"
yPositioning="data_space"
color="#0F172A"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
xPositioning: "data_space",
yPositioning: "data_space",
color: "#0F172A",
backgroundColor: "rgba(255, 255, 255, 0.9)"
})
// Data space positioning (default)
xPositioning: XYLabelPositioning.DataSpace,
yPositioning: XYLabelPositioning.DataSpace
Absolute Pixel Positioning​
Position labels using absolute pixel coordinates from the top-left corner of the chart area:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="absolute_px"
yPositioning="absolute_px"
color="#065F46"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
xPositioning="absolute_px"
yPositioning="absolute_px"
color="#065F46"
backgroundColor="rgba(255, 255, 255, 0.95)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
xPositioning="absolute_px"
yPositioning="absolute_px"
color="#065F46"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
xPositioning="absolute_px"
yPositioning="absolute_px"
color="#065F46"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="absolute_px"
yPositioning="absolute_px"
color="#065F46"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
xPositioning: "absolute_px",
yPositioning: "absolute_px",
color: "#065F46",
backgroundColor: "rgba(255, 255, 255, 0.95)"
})
// Absolute pixel positioning
xPositioning: XYLabelPositioning.AbsolutePx,
yPositioning: XYLabelPositioning.AbsolutePx,
x: 100, // 100 pixels from left
y: 50 // 50 pixels from top
Absolute Percentage Positioning​
Position labels using percentage coordinates (0-100) relative to the chart container dimensions:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="absolute_percentage"
yPositioning="absolute_percentage"
color="#92400E"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
xPositioning="absolute_percentage"
yPositioning="absolute_percentage"
color="#92400E"
backgroundColor="rgba(255, 255, 255, 0.95)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
xPositioning="absolute_percentage"
yPositioning="absolute_percentage"
color="#92400E"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
xPositioning="absolute_percentage"
yPositioning="absolute_percentage"
color="#92400E"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
xPositioning="absolute_percentage"
yPositioning="absolute_percentage"
color="#92400E"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
xPositioning: "absolute_percentage",
yPositioning: "absolute_percentage",
color: "#92400E",
backgroundColor: "rgba(255, 255, 255, 0.95)"
})
// Absolute percentage positioning
xPositioning: XYLabelPositioning.AbsolutePercentage,
yPositioning: XYLabelPositioning.AbsolutePercentage,
x: 75, // 75% from left edge
y: 25 // 25% from top edge
Mixed Positioning​
You can mix different positioning modes for x and y coordinates:
// Mix data space with screen space
xPositioning: XYLabelPositioning.DataSpace, // Follow data horizontally
yPositioning: XYLabelPositioning.AbsolutePx, // Fixed vertical position
y: 20 // Always 20px from top
Styling​
Label Color​
Control label text color with the color property. You can use dynamic colors based on your data:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
color={color}
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
[color]="color"
backgroundColor="rgba(255, 255, 255, 0.9)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
{color}
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
:color="color"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
color={color}
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
color,
backgroundColor: "rgba(255, 255, 255, 0.9)"
})
Background Color​
Add background colors to make labels more readable, especially over complex visualizations:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
backgroundColor="rgba(255, 255, 255, 0.95)"
color="#374151"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
backgroundColor="rgba(255, 255, 255, 0.95)"
color="#374151"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
backgroundColor="rgba(255, 255, 255, 0.95)"
color="#374151"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
backgroundColor="rgba(255, 255, 255, 0.95)"
color="#374151"
/>
<VisXYLabels
x={x}
y={y}
label={label}
backgroundColor="rgba(255, 255, 255, 0.95)"
color="#374151"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
backgroundColor: "rgba(255, 255, 255, 0.95)",
color: "#374151"
})
Font Size​
Customize label font size with the labelFontSize property. You can make it dynamic based on data values:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
labelFontSize={labelFontSize}
color="#831843"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
[labelFontSize]="labelFontSize"
color="#831843"
backgroundColor="rgba(255, 255, 255, 0.9)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
{labelFontSize}
color="#831843"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
:labelFontSize="labelFontSize"
color="#831843"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
labelFontSize={labelFontSize}
color="#831843"
backgroundColor="rgba(255, 255, 255, 0.9)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
labelFontSize,
color: "#831843",
backgroundColor: "rgba(255, 255, 255, 0.9)"
})
Label Clustering​
When labels overlap, XYLabels can automatically cluster them to reduce visual clutter. This feature is enabled by default and is particularly useful for dense datasets.
Enabling/Disabling Clustering​
Control clustering with the clustering property. When enabled, overlapping labels are automatically grouped together to reduce visual clutter. Toggle the checkbox below to see the difference:
// Enable/disable clustering programmatically
const xyLabels = new XYLabels({
x: d => d.x,
y: d => d.y,
label: d => d.label,
clustering: true, // Set to false to disable clustering
// Optional: Customize cluster appearance when clustering is enabled
clusterLabel: (records) => `${records.length} items`,
clusterBackgroundColor: 'rgba(132, 204, 22, 0.2)',
clusterLabelColor: '#365314'
})
Cluster Customization​
Customize cluster appearance with cluster-specific properties:
// Cluster configuration
clusterLabel: (records) => `${records.length} items`,
clusterFontSize: 14,
clusterBackgroundColor: 'rgba(59, 130, 246, 0.1)',
clusterLabelColor: '#1E40AF'
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
clustering={true}
clusterLabel={clusterLabel}
clusterBackgroundColor="rgba(59, 130, 246, 0.1)"
clusterLabelColor="#1E40AF"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
[clustering]="true"
[clusterLabel]="clusterLabel"
clusterBackgroundColor="rgba(59, 130, 246, 0.1)"
clusterLabelColor="#1E40AF"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
clustering={true}
{clusterLabel}
clusterBackgroundColor="rgba(59, 130, 246, 0.1)"
clusterLabelColor="#1E40AF"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
:clustering="true"
:clusterLabel="clusterLabel"
clusterBackgroundColor="rgba(59, 130, 246, 0.1)"
clusterLabelColor="#1E40AF"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
<VisXYLabels
x={x}
y={y}
label={label}
clustering={true}
clusterLabel={clusterLabel}
clusterBackgroundColor="rgba(59, 130, 246, 0.1)"
clusterLabelColor="#1E40AF"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
clustering: true,
clusterLabel,
clusterBackgroundColor: "rgba(59, 130, 246, 0.1)",
clusterLabelColor: "#1E40AF",
color: "#1E40AF",
backgroundColor: "rgba(255, 255, 255, 0.95)"
})
Events​
The XYLabels component supports interactive events on both individual labels and clusters. Available selectors:
XYLabels.selectors.label- Events for individual labelsXYLabels.selectors.cluster- Events for label clusters (when clustering is enabled)
import { XYLabels } from '@unovis/ts'
const events = {
[XYLabels.selectors.label]: {
click: (d: Datum) => alert(`Clicked: ${d.label}`),
mouseover: (d: Datum) => console.log('Label hovered:', d),
mouseleave: (d: Datum) => console.log('Label unhovered:', d)
},
[XYLabels.selectors.cluster]: {
click: (cluster: XYLabel<Datum>[]) => {
const labels = cluster.map(d => d.label).join(', ')
alert(`Cluster clicked! Contains: ${labels}`)
},
mouseover: (cluster: XYLabel<Datum>[]) => {
console.log('Cluster hovered:', cluster.length, 'labels')
}
}
}
Interactive Labels​
Click on any label below to see event handling in action:
- React
- Angular
- Svelte
- Vue
- Solid
- TypeScript
<VisXYLabels
x={x}
y={y}
label={label}
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
cursor="pointer"
events={events}
/>
<vis-xy-labels
[x]="x"
[y]="y"
[label]="label"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
cursor="pointer"
[events]="events"
></vis-xy-labels>
<VisXYLabels
{x}
{y}
{label}
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
cursor="pointer"
{events}
/>
<VisXYLabels
:x="x"
:y="y"
:label="label"
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
cursor="pointer"
:events="events"
/>
<VisXYLabels
x={x}
y={y}
label={label}
color="#1E40AF"
backgroundColor="rgba(255, 255, 255, 0.95)"
cursor="pointer"
events={events}
/>
const xYLabels = new XYLabels<DataRecord>({
x,
y,
label,
color: "#1E40AF",
backgroundColor: "rgba(255, 255, 255, 0.95)",
cursor: "pointer",
events
})
CSS Variables​
The following CSS variables can be used to customize the default appearance:
/* Label styling */
--vis-xy-label-font-size: 12px;
--vis-xy-label-font-family: var(--vis-font-family);
--vis-xy-label-text-color: #000;
--vis-xy-label-background-fill-color: none;
--vis-xy-label-background-stroke-color: none;
--vis-xy-label-background-stroke-width: 0;
--vis-xy-label-padding: 4px;
/* Cluster styling */
--vis-xy-label-cluster-font-size: 14px;
--vis-xy-label-cluster-text-color: #000;
--vis-xy-label-cluster-background-fill-color: #f0f0f0;
--vis-xy-label-cluster-background-stroke-color: #ccc;
--vis-xy-label-cluster-background-stroke-width: 1px;
--vis-xy-label-cluster-padding: 6px;
/* Dark theme overrides */
--vis-dark-xy-label-text-color: #fff;
--vis-dark-xy-label-cluster-text-color: #fff;
--vis-dark-xy-label-cluster-background-fill-color: #333;
--vis-dark-xy-label-cluster-background-stroke-color: #666;
Component Props​
| Name | Type | Description |
|---|---|---|
| * required property |