Skip to content
# Chart ## Description A native Blazor charting component: the whole scene - scales, layout, geometry, hit testing - is computed in C# and rendered as plain SVG, so charts work in prerendering and static SSR, need no canvas, and stay crisp at any size. The API mirrors Chart.js: give it a BitChartType plus BitChartData and BitChartOptions (or one BitChartConfig). It draws line, bar, area, pie, doughnut, polar area, radar, scatter, bubble and mixed charts - or a chrome-free sparkline - with multiple axes, stacking, time and log scales, tooltips, data labels, annotations, trendlines, scriptable per-element styling, entry animations and zoom/pan. Refresh() and the visibility API drive it from code for live feeds. Colors follow the bit theme tokens, so every preset and both schemes re-skin it for free; every chart is navigable by keyboard and by touch and ships a visually hidden data table for screen readers, and can hand itself over as SVG, PNG, a data URL or CSV. ## Parameters | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | AriaLabel | `string?` | null | Accessible label for the chart. When null it falls back to the chart title, then to a generated summary. | | Class | `string?` | null | Custom CSS class applied to the root element of the chart. | | Config | `BitChartConfig?` | null | Full configuration (type + data + options). Takes precedence over Type/Data/Options when set. | | Data | `BitChartData?` | null | The chart data: labels and datasets. | | Dir | `BitDir?` | null | Text direction of the chrome around the plot (title, legend, tooltip and the screen-reader table). The plot keeps its own coordinates; mirror it by setting Reverse on the index scale. | | ForceAnimation | `bool` | false | Plays the entry and update animations even when reduced motion is requested (prefers-reduced-motion: reduce). By default the chart honors that preference and draws itself straight in its final state. | | GenerateTable | `bool` | true | Renders a visually-hidden data table for screen readers and points the chart's aria-describedby at it. | | Height | `string?` | null | Optional CSS height of the chart container. When null the height follows the aspect ratio. | | HtmlAttributes | `Dictionary<string, object>` | new() | Additional HTML attributes applied to the root element. | | Id | `string?` | null | The id of the root element of the chart. | | MaxTableColumns | `int` | 100 | Upper bound on the columns the screen-reader table renders. A value series is one row with a cell per category, so a long one is wide rather than tall and the row cap alone would not contain it. Ignored for scatter and bubble data, whose table is three fixed columns. | | MaxTableRows | `int` | 500 | Upper bound on the rows the screen-reader table renders, so a long series does not put tens of thousands of hidden nodes in the DOM. Past the limit the caption says how many rows were left out. | | NavigationHint | `string?` | "Interactive chart. Use the left and right arrow keys..." | A visually hidden sentence telling a screen-reader user how to walk the data, pointed at by aria-describedby alongside the data table. Only rendered when there is data to navigate; set it to null to leave it out. | | NoDataTemplate | `RenderFragment?` | null | Custom content shown in place of the plot when there is nothing to draw. Takes precedence over NoDataText. | | NoDataText | `string` | No data to display | Message shown in place of the plot when the configuration produces nothing to draw. | | OnElementClick | `EventCallback<(int DatasetIndex, int DataIndex)>` | | Callback raised when a data element (point, bar, arc, ...) is clicked, by pointer or with Enter/Space while it is focused. | | OnElementHover | `EventCallback<BitChartTooltipContext?>` | | Callback raised when the active (hovered or keyboard-focused) element set changes. The context is null once nothing is active. | | OnLegendItemClick | `EventCallback<BitChartLegendItemModel>` | | Callback raised when a legend item is clicked, before the default visibility toggle runs. | | OnZoomChange | `EventCallback` | | Callback raised after zoom or pan changes the visible axis ranges. | | Options | `BitChartOptions?` | null | The chart options: scales, plugins (title, legend, tooltip, data labels), interaction, animation, culture and zoom. | | Style | `string?` | null | Custom CSS style applied to the root element of the chart. | | TooltipTemplate | `RenderFragment<BitChartTooltipContext>?` | null | Optional custom tooltip template. When set it replaces the default tooltip body. | | Type | `BitChartType` | BitChartType.Line | The chart type: Line, Bar, Radar, Pie, Doughnut, PolarArea, Bubble or Scatter. | | Width | `string` | 100% | CSS width of the chart container. | ## Public Members | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Refresh | `void Refresh()` | | Rebuilds and redraws the chart from its current data and options. Blazor only re-renders on a parameter change it can see, so mutating the same BitChartData in place - appending to a live series, editing a value - needs this call. The counterpart of Chart.js's chart.update(). | | IsDatasetVisible | `bool IsDatasetVisible(int datasetIndex)` | | Whether a dataset is currently drawn, i.e. hidden neither through the legend nor by BitChartDataset.Hidden. | | SetDatasetVisible | `void SetDatasetVisible(int datasetIndex, bool visible)` | | Shows or hides a dataset, exactly as clicking its legend entry would; the axes re-scale around what is left. | | ToggleDataset | `void ToggleDataset(int datasetIndex)` | | Flips a dataset between shown and hidden. | | IsDataIndexVisible | `bool IsDataIndexVisible(int dataIndex)` | | Whether a data index - a pie, doughnut or polar-area slice - is currently drawn. | | SetDataIndexVisible | `void SetDataIndexVisible(int dataIndex, bool visible)` | | Shows or hides one data index across the chart, the slice-level counterpart of SetDatasetVisible. | | ToggleDataIndex | `void ToggleDataIndex(int dataIndex)` | | Flips one data index between shown and hidden. | | ResetVisibility | `void ResetVisibility()` | | Brings back every dataset and data index hidden through the legend or the API. | | ResetZoom | `void ResetZoom()` | | Clears every zoom/pan override and returns the chart to the full data range. | | ZoomTo | `void ZoomTo(string axisId, double? min, double? max)` | | Zooms an axis to an explicit value range, honoring the configured zoom limits. Pass null bounds to clear that axis's override. | | GetAxisRange | `(double Min, double Max)? GetAxisRange(string axisId)` | | The currently visible range of an axis: its zoomed range when zoomed, otherwise the full data range. | | ExportSvgAsync | `Task<bool> ExportSvgAsync(string? fileName = null, string? backgroundColor = null)` | | Downloads the chart as a standalone .svg file, with the theme tokens it references resolved into the file. | | ExportPngAsync | `Task<bool> ExportPngAsync(string? fileName = null, double scale = 2, string? backgroundColor = "#ffffff")` | | Downloads the chart as a .png image rasterized from the live SVG at the given pixel ratio. | | ExportCsvAsync | `Task<bool> ExportCsvAsync(string? fileName = null)` | | Downloads the chart's data as a .csv file, formatted with the chart's culture. | | ToCsv | `string ToCsv()` | | Returns the chart's data as CSV text: one row per series for value datasets, one row per point for scatter and bubble datasets. | | ToSvgStringAsync | `Task<string?> ToSvgStringAsync(string? backgroundColor = null)` | | Returns the chart as standalone SVG markup instead of downloading it, with the theme tokens it references resolved into the markup. Null when the chart has not been rendered in a browser yet. | | ToBase64ImageAsync | `Task<string?> ToBase64ImageAsync(string mimeType = "image/png", double scale = 2, string? backgroundColor = "#ffffff")` | | Returns the rasterized chart as a data: URL - the same picture ExportPngAsync downloads - ready for an img src or a PDF. Mirrors Chart.js's toBase64Image. | ## Sub Classes ### BitChartConfig Properties A complete chart configuration bundling the type, data and options. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Type | `BitChartType` | BitChartType.Line | The chart type. | | Data | `BitChartData` | new() | The labels and datasets. | | Options | `BitChartOptions` | new() | The scales, plugins, interaction, animation and zoom options. | ### BitChartData Properties The chart data, mirroring Chart.js data: labels + datasets. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Labels | `List<string>` | new() | The category labels shared by the datasets (used by cartesian, radar, pie and polar charts). | | Datasets | `List<BitChartDataset>` | new() | The datasets to render. Each dataset carries either a list of values (Data) or points (Points). | ### BitChartDataset Properties A single dataset, mirroring Chart.js dataset configuration. Colors, radii and styles marked *Fn are scriptable: they receive a BitChartScriptableContext per element and take precedence over the constant beside them. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Label | `string?` | null | Dataset label shown in legends and tooltips. | | Data | `List<double?>` | new() | Per-index values (line, bar, radar, pie, doughnut, polarArea). A null is a gap, not a zero. | | Points | `List<BitChartDataPoint>?` | null | Point data (x, y[, r]) for scatter, bubble and time-based line charts. When set, takes precedence over Data. | | RangeData | `List<(double Low, double High)?>?` | null | Floating-bar ranges per index. When set, bars span low to high instead of growing from the base. | | Type | `BitChartType?` | null | Optional per-dataset type override, used to build mixed charts. | | BackgroundColor | `string?` | null | The fill color of the dataset: bars, arcs, points and the area fill of a filled line. | | BackgroundColors | `List<string>?` | null | One fill color per data index, cycled when shorter than the data. | | BorderColor | `string?` | null | The line/border color. Bars and arcs fall back to their own fill color rather than an unrelated palette entry. | | BorderWidth | `double?` | null | Border/line thickness. When null a per-type default applies: 3 for lines and radar, 2 for arcs, and 0 for bars unless a border color was given. | | Fill | `BitChartFillMode` | BitChartFillMode.None | Area fill mode for line/radar datasets (None, Origin, Start, End, Stack, Dataset, Value). | | FillGradient | `BitChartGradientBase?` | null | A linear or radial gradient used for the area fill, taking precedence over FillColor and BackgroundColor. | | BackgroundPattern | `BitChartFillPattern?` | null | A repeating hatch/grid/dot texture used instead of a solid fill; keeps series distinguishable in print and greyscale. | | Tension | `double` | 0 | Bezier curve tension for line datasets (0 = straight lines). | | Stepped | `BitChartSteppedLine` | BitChartSteppedLine.False | Draws the line as steps (Before, After or Middle) instead of interpolating. | | SpanGaps | `bool` | false | Bridges null values instead of breaking the line at them. | | Segment | `BitChartLineSegmentStyle?` | null | Per-segment color, width and dash callbacks, evaluated from the two endpoints of each segment. | | PointRadius | `double` | 3 | Marker radius. Zero hides the marker but keeps the point hoverable. | | PointStyle | `BitChartPointStyle` | BitChartPointStyle.Circle | Marker shape. BitChartPointStyle.None removes the markers - and their hit targets - entirely. | | Stack | `string?` | null | Stack group id. Datasets sharing an id accumulate together; each group gets its own column. | | Grouped | `bool` | true | When false the bar dataset leaves the side-by-side layout and keeps the whole category band, so it can sit behind the others. | | SkipNull | `bool` | false | Lets the remaining bars of a category widen over the datasets that have no value there, instead of leaving a hole. | | MinBarLength | `double?` | null | Minimum bar length in pixels, so near-zero values stay visible. | | Base | `double?` | null | The value bars grow from. Defaults to zero clamped into the axis range. | | BorderRadius | `double` | 0 | Corner radius. On a bar only the corners away from the skipped (baseline) edge are rounded, and BorderRadiusCorners overrides each corner; on a pie, doughnut or polar-area arc it rounds the arc's own corners, clamped to half the ring's thickness. | | Offset / SpacingArc / HoverOffset | `double` | 0 / 0 / 6 | Arc geometry: how far every slice sits from the center, the gap left between neighbouring slices, and the extra distance the hovered slice pops out. | | Weight | `double` | 1 | Relative thickness of this dataset's ring in a multi-dataset pie or doughnut. The available radius is shared out in proportion to the weights. | | ErrorData | `List<BitChartErrorBar?>?` | null | Per-index uncertainty, drawn as a capped whisker through the value and named in the tooltip. A BitChartErrorBar comes from one number (symmetric) or two (asymmetric); a null entry leaves that value bare. Cartesian charts only. | | ErrorBarColor / ErrorBarWidth / ErrorBarCapWidth | `string? / double / double` | null / 1.5 / 8 | Error-bar styling. A null color follows the primary foreground token; a zero cap width draws a bare whisker. | | HoverBackgroundColor / HoverBorderColor / HoverBorderWidth | `string? / string? / double?` | null | Styling used while a bar or arc is hovered or keyboard-focused. | | XAxisID / YAxisID / RAxisID | `string` | x / y / r | The scales this dataset is bound to. Naming a scale that does not exist yet creates a linear one. | | Order | `int` | 0 | Draw order across datasets; lower draws first. Bars are always drawn before lines and points. | | Hidden | `bool` | false | Hides the dataset without removing it, and marks its legend entry as toggled off. | ### BitChartOptions Properties Top-level chart options, mirroring Chart.js options. The same instance can safely be shared between charts: the renderer completes the missing scales locally instead of writing them back. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | Responsive | `bool` | true | Observes the container and renders at real device pixels, which keeps font sizes constant at any width. | | MaintainAspectRatio / AspectRatio | `bool / double?` | true / null | Whether the height follows the width, and the ratio to use. Defaults to 2 for cartesian charts and 1 for circular and radar ones. | | IndexAxis | `BitChartIndexAxis` | BitChartIndexAxis.X | The axis the data index runs along: X for vertical bars, Y for horizontal ones. | | Sparkline | `bool` | false | Draws the chart as a sparkline: axes, grid, tick labels, legend, title and subtitle are all dropped so the series fills the box. A presentation switch only - tooltips, keyboard navigation and the screen-reader table still describe the full series. | | Scales | `Dictionary<string, BitChartScaleOptions>` | new() | Named scales keyed by id (x, y, r, y2, ...): type, min/max, grid, ticks, title, stacking, time unit and radial options. | | Interaction | `BitChartInteractionOptions` | new() | Mode (Nearest, Index, Dataset, ...) and Intersect. With Intersect false - the default - hit bands make the whole plot hoverable, marked by a crosshair and an axis chip (Crosshair / CrosshairLabel / CrosshairColor). The tooltip inherits Mode and Intersect unless it overrides them. | | Plugins | `BitChartPluginOptions` | new() | Title, Subtitle, Legend, Tooltip, DataLabels and Decimation options, plus Custom for your own IBitChartPlugin drawing plugins. | | Animation | `BitChartAnimationOptions` | new() | Duration, easing, per-element stagger (DelayBetween) and the progressive draw-on for line charts. | | Elements | `BitChartElementOptions` | new() | Per-type defaults used whenever a dataset leaves the matching property unset. | | Layout | `BitChartLayoutOptions` | new() | Padding around the whole chart. | | Zoom | `BitChartZoomOptions` | new() | Wheel zoom, drag pan, drag-to-zoom box, axis mode, speed, and the limits that keep the view inside the data. | | Culture | `CultureInfo?` | null | Culture used for every number and date the chart prints - ticks, tooltips, data labels and the CSV export. Null means the invariant culture. | | CutoutPercentage / CircumferenceDegrees / RotationDegrees | `double` | 50 / 360 / -90 | Doughnut hole size, sweep and starting angle. A 180 degree sweep turns a doughnut into a gauge. | ### BitChartTrendline Properties One fitted line drawn over a dataset by BitChartTrendlinePlugin, which is registered through Options.Plugins.Custom. Cartesian charts only. | Name | Type | Default Value | Description | | :--- | :--- | :------------ | :---------- | | DatasetIndex | `int` | 0 | Index of the dataset the line is fitted to. A dataset hidden through the legend takes its trend line with it. | | Kind | `BitChartTrendlineKind` | BitChartTrendlineKind.Linear | Linear for a least-squares regression, MovingAverage for a trailing average over Period points, or Average for a flat line at the series mean. | | Period | `int` | 5 | Window of the trailing moving average. Ignored by the other kinds. | | Extend | `bool` | false | Projects a straight fit out to both edges of the plot instead of stopping at the first and last data point. Ignored by MovingAverage, which has no meaning outside the data. | | Color / LineWidth / Dash | `string? / double / List<double>?` | null / 2 / [6, 4] | Line styling. A null color follows the dataset's own border color; the dash is what keeps the fit from reading as another measured series - set it to null for a solid line. | | Label / LabelColor / LabelBackground / LabelFont | `string? / string / string? / BitChartFont` | null / #fff / null / 11px bold | An optional pill drawn at the end of the line, pinned inside the plot so it stays readable at the edge. | | DrawBehindDatasets | `bool` | false | Draws the line under the datasets rather than over them. | ## Examples
\n**Smooth line with area fill**: ```razor ``` ```csharp private readonly BitChartOptions _legendBottom = new() { Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } } }; private BitChartData Filled() => new() { Labels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul" }, Datasets = { new BitChartDataset { Label = "Visitors", Data = new() { 120, 190, 160, 250, 220, 300, 280 }, BorderColor = "#36a2eb", Tension = 0.4, Fill = BitChartFillMode.Origin } } }; ``` \n**Dashed border with custom points**: ```razor ``` ```csharp private readonly BitChartOptions _legendBottom = new() { Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } } }; private BitChartData Dashed() => new() { Labels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul" }, Datasets = { new BitChartDataset { Label = "Forecast", Data = new() { 30, 42, null, 55, 48, 67, 70 }, BorderColor = "#9966ff", BorderDash = new() { 6, 4 }, PointStyle = BitChartPointStyle.Star, PointRadius = 6, SpanGaps = true } } }; ``` \n**Logarithmic Y axis**: ```razor ``` ```csharp private readonly BitChartOptions _logOptions = new() { Scales = { ["y"] = new BitChartScaleOptions { Id = "y", Type = BitChartScaleType.Logarithmic } } }; private BitChartData Log() => new() { Labels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul" }, Datasets = { new BitChartDataset { Label = "Growth", Data = new() { 1, 10, 100, 1000, 5000, 20000, 80000 }, BorderColor = "#ff6384", Tension = 0.2 } } }; ``` \n**Per-segment styling**: ```razor ``` ```csharp private readonly BitChartOptions _legendBottom = new() { Plugins = new BitChartPluginOptions { Legend = new BitChartLegendOptions { Position = BitChartPosition.Bottom } } }; private BitChartData Segmented() => new() { Labels = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul" }, Datasets = { new BitChartDataset { Label = "Flow", Data = new() { 40, 55, 48, 70, 62, 80, 72 }, BorderColor = "#36a2eb", BorderWidth = 3, Segment = new BitChartLineSegmentStyle { BorderColor = ctx => ctx.EndValue < ctx.StartValue ? "#ff6384" : "#2ecc71", BorderDash = ctx => ctx.StartIndex >= 4 ? new double[] { 6, 4 } : null } } } }; ``` \n**Sparkline**: ```razor @foreach (var tile in _tiles) {
@tile.Caption
@tile.Value
} ``` ```csharp // Sparkline hides the axes, grid, legend and title; turning off MaintainAspectRatio lets the // chart take the tile's own height instead of one derived from its width. private readonly BitChartOptions _sparkline = new() { Sparkline = true, MaintainAspectRatio = false, Layout = new BitChartLayoutOptions { Padding = 2 } }; private sealed record SparklineTile(string Caption, string Value, BitChartType Type, BitChartData Data); private readonly List _tiles = [ new("Sessions", "12,480", BitChartType.Line, Spark("#36a2eb", true, 30, 34, 31, 40, 44, 41, 52, 58, 55, 64)), new("Signups", "934", BitChartType.Bar, Spark("#4bc0c0", false, 12, 18, 15, 22, 19, 26, 24, 31, 28, 35)), new("Errors", "17", BitChartType.Line, Spark("#ff6384", true, 22, 19, 24, 16, 14, 18, 11, 9, 12, 7)) ]; private static BitChartData Spark(string color, bool line, params double?[] values) => new() { // A category axis spans the labels, so a sparkline still needs one per value - blank, since the // tile shows no axis - or every point lands on the same x. Labels = [.. values.Select(_ => "")], Datasets = { new BitChartDataset { Data = [.. values], BorderColor = color, BackgroundColor = color, PointRadius = 0, BorderWidth = 2, Tension = 0.35, Fill = line ? BitChartFillMode.Origin : BitChartFillMode.None, FillColor = line ? BitChartColorUtil.WithAlpha(color, 0.18) : null, BorderRadius = 2 } } }; ```