Legend components for displaying chart keys and visual guides that help users understand chart data mappings and categories.
SVG-based legend component that displays color-coded keys for chart data series or categories.
/**
* Create an SVG-based Legend
* @param {String|node|d3.selection} parent - DOM selector, element, or d3 selection
* @param {String} [chartGroup] - Chart group name for coordinated interactions
*/
class Legend extends BaseMixin {
constructor(parent: string | Element | d3.Selection, chartGroup?: string);
/** Set/get legend items */
legendItems(items?: LegendItem[]): LegendItem[] | Legend;
/** Set/get legend width */
legendWidth(width?: number): number | Legend;
/** Set/get legend item height */
itemHeight(height?: number): number | Legend;
/** Set/get gap between legend items */
gap(gap?: number): number | Legend;
/** Set/get horizontal gap between legend items */
horizontal(horizontal?: boolean): boolean | Legend;
/** Set/get legend text accessor */
legendText(textFunction?: Function): Function | Legend;
/** Set/get maximum items per row */
maxItems(maxItems?: number): number | Legend;
/** Set/get whether legend is autoItemWidth */
autoItemWidth(auto?: boolean): boolean | Legend;
}
/** Factory function for creating Legend instances */
function legend(parent: string | Element | d3.Selection, chartGroup?: string): Legend;Usage Example:
import { Legend } from 'dc';
const chartLegend = new Legend('#legend')
.legendWidth(200)
.itemHeight(20)
.gap(5)
.horizontal(false)
.legendText(d => d.name)
.legendItems([
{ name: 'Series 1', color: '#1f77b4' },
{ name: 'Series 2', color: '#ff7f0e' },
{ name: 'Series 3', color: '#2ca02c' }
]);
chartLegend.render();HTML-based legend component with more flexible styling and interaction capabilities.
/**
* Create an HTML-based Legend
* @param {String|node|d3.selection} parent - DOM selector, element, or d3 selection
* @param {String} [chartGroup] - Chart group name for coordinated interactions
*/
class HtmlLegend extends BaseMixin {
constructor(parent: string | Element | d3.Selection, chartGroup?: string);
/** Set/get legend container element */
container(container?: string | Element | d3.Selection): any | HtmlLegend;
/** Set/get maximum items displayed */
maxItems(maxItems?: number): number | HtmlLegend;
/** Set/get legend item class */
legendItemClass(className?: string): string | HtmlLegend;
/** Set/get highlighted class */
highlightedClass(className?: string): string | HtmlLegend;
/** Set/get hidden class */
hiddenClass(className?: string): string | HtmlLegend;
/** Set/get legend text function */
legendText(textFunction?: Function): Function | HtmlLegend;
/** Set/get whether items are highlightable */
highlightable(highlightable?: boolean): boolean | HtmlLegend;
/** Set/get whether items are hidable */
hidable(hidable?: boolean): boolean | HtmlLegend;
/** Set/get reset button text */
resetText(text?: string): string | HtmlLegend;
/** Set/get legend items */
legendItems(items?: LegendItem[]): LegendItem[] | HtmlLegend;
}
/** Factory function for creating HtmlLegend instances */
function htmlLegend(parent: string | Element | d3.Selection, chartGroup?: string): HtmlLegend;Usage Example:
import { HtmlLegend } from 'dc';
const htmlLegend = new HtmlLegend('#html-legend')
.container('#legend-container')
.maxItems(10)
.legendItemClass('legend-item')
.highlightedClass('highlighted')
.hiddenClass('hidden')
.highlightable(true)
.hidable(true)
.resetText('Reset filters')
.legendText(d => `${d.name} (${d.value})`)
.legendItems([
{ name: 'Category A', value: 150, color: '#FF6B6B' },
{ name: 'Category B', value: 230, color: '#4ECDC4' },
{ name: 'Category C', value: 180, color: '#45B7D1' }
]);
htmlLegend.render();Legends can automatically generate items based on chart data:
import { PieChart, HtmlLegend } from 'dc';
const pie = new PieChart('#pie-chart')
.dimension(categoryDimension)
.group(categoryGroup);
const legend = new HtmlLegend('#legend')
.legendItems(() => {
// Generate legend items from pie chart data
return pie.data().map(d => ({
name: d.key,
value: d.value,
color: pie.getColor(d, 0)
}));
})
.legendText(d => `${d.name}: ${d.value}`);
// Render both chart and legend
pie.render();
legend.render();HTML legends support interactive filtering:
import { BarChart, HtmlLegend } from 'dc';
const chart = new BarChart('#chart')
.dimension(categoryDimension)
.group(categoryGroup);
const legend = new HtmlLegend('#legend')
.dimension(categoryDimension) // Connect to same dimension
.group(categoryGroup)
.highlightable(true)
.hidable(true)
.on('filtered', function(legend, filter) {
// Legend filtering affects connected chart
chart.redraw();
});
chart.render();
legend.render();HTML legends provide flexible styling options:
/* Custom legend styles */
.legend-item {
display: flex;
align-items: center;
padding: 5px;
cursor: pointer;
border-radius: 3px;
margin: 2px 0;
}
.legend-item:hover {
background-color: #f0f0f0;
}
.legend-item.highlighted {
background-color: #e3f2fd;
font-weight: bold;
}
.legend-item.hidden {
opacity: 0.3;
text-decoration: line-through;
}
.legend-item::before {
content: '';
width: 12px;
height: 12px;
margin-right: 8px;
border-radius: 50%;
background-color: var(--item-color);
}const legend = new HtmlLegend('#legend')
.legendItemClass('legend-item')
.highlightedClass('highlighted')
.hiddenClass('hidden')
.legendText(d => {
// Set CSS custom property for color
return `<span style="--item-color: ${d.color}">${d.name}</span>`;
});Coordinate legends across multiple charts:
import { BarChart, LineChart, HtmlLegend } from 'dc';
const barChart = new BarChart('#bar-chart', 'main')
.dimension(categoryDimension)
.group(categoryGroup);
const lineChart = new LineChart('#line-chart', 'main')
.dimension(timeDimension)
.group(timeGroup);
// Single legend coordinating both charts
const legend = new HtmlLegend('#shared-legend', 'main')
.legendItems([
{ name: 'Bar Chart', color: barChart.colors()(0) },
{ name: 'Line Chart', color: lineChart.colors()(0) }
])
.on('filtered', function(legend, filter) {
// Custom logic to coordinate multiple charts
});Standard structure for legend items:
interface LegendItem {
/** Display name for the legend item */
name: string;
/** Color associated with the item */
color: string;
/** Optional numeric value */
value?: number;
/** Optional additional data */
data?: any;
/** Whether item is visible */
visible?: boolean;
/** Whether item is highlighted */
highlighted?: boolean;
}Update legend items based on data changes:
import { HtmlLegend } from 'dc';
const legend = new HtmlLegend('#legend');
function updateLegend(newData) {
const items = newData.map((d, i) => ({
name: d.category,
value: d.total,
color: d3.schemeCategory10[i % 10],
data: d
}));
legend.legendItems(items).redraw();
}
// Update legend when data changes
chart.on('filtered', function() {
const filteredData = chart.group().all();
updateLegend(filteredData);
});SVG Legend (Legend class):
HTML Legend (HtmlLegend class):
// Limit legend items for performance
const legend = new HtmlLegend('#legend')
.maxItems(20) // Cap at 20 items
.legendItems(data.slice(0, 20)); // Pre-filter data
// Use efficient update patterns
legend.on('preRender', function() {
// Batch DOM operations
});
legend.on('postRender', function() {
// Apply final styling after rendering
});Make legends accessible to screen readers:
const legend = new HtmlLegend('#legend')
.legendText(d => `${d.name}, value: ${d.value}`)
.on('postRender', function() {
// Add ARIA labels
d3.select('#legend').selectAll('.legend-item')
.attr('role', 'button')
.attr('aria-label', d => `Filter by ${d.name}`)
.attr('tabindex', 0);
});Enable keyboard navigation for interactive legends:
legend.on('postRender', function() {
d3.select('#legend').selectAll('.legend-item')
.on('keydown', function(event, d) {
if (event.key === 'Enter' || event.key === ' ') {
// Trigger click behavior
d3.select(this).dispatch('click');
event.preventDefault();
}
});
});interface LegendItem {
name: string;
color: string;
value?: number;
data?: any;
visible?: boolean;
highlighted?: boolean;
}
interface Legend extends BaseMixin {
legendItems(items?: LegendItem[]): LegendItem[] | Legend;
legendWidth(width?: number): number | Legend;
itemHeight(height?: number): number | Legend;
gap(gap?: number): number | Legend;
horizontal(horizontal?: boolean): boolean | Legend;
legendText(textFunction?: Function): Function | Legend;
maxItems(maxItems?: number): number | Legend;
autoItemWidth(auto?: boolean): boolean | Legend;
}
interface HtmlLegend extends BaseMixin {
container(container?: string | Element | d3.Selection): any | HtmlLegend;
maxItems(maxItems?: number): number | HtmlLegend;
legendItemClass(className?: string): string | HtmlLegend;
highlightedClass(className?: string): string | HtmlLegend;
hiddenClass(className?: string): string | HtmlLegend;
legendText(textFunction?: Function): Function | HtmlLegend;
highlightable(highlightable?: boolean): boolean | HtmlLegend;
hidable(hidable?: boolean): boolean | HtmlLegend;
resetText(text?: string): string | HtmlLegend;
legendItems(items?: LegendItem[]): LegendItem[] | HtmlLegend;
}
type LegendFactory = (parent: string | Element | d3.Selection, chartGroup?: string) => Legend;
type HtmlLegendFactory = (parent: string | Element | d3.Selection, chartGroup?: string) => HtmlLegend;