Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
0f3f1fb
Add DonutChart and HorizontalBarChart Web Component wrappers, docs an…
vnbaaij Apr 13, 2026
ac10e6a
Merge branch 'dev-v5' into charts
vnbaaij Apr 13, 2026
7d5edce
Process review comments
vnbaaij Apr 14, 2026
8cf21ba
More review comments processed
vnbaaij Apr 14, 2026
4aadb4c
Merge branch 'dev-v5' into charts
vnbaaij Apr 14, 2026
d4cb02c
Introduce separate Charts package. This uses a new Charts.Scripts pac…
vnbaaij Apr 16, 2026
5ae31d5
Add project reference to esproj, remove wrong using statement
vnbaaij Apr 16, 2026
4d1e401
Use .editorconfig instead of surpression file
vnbaaij Apr 16, 2026
e83fba7
Internalize the chart code. Devlopement is STILL done in the chart-we…
vnbaaij Apr 19, 2026
2f5bc1e
Improve and finalize(?) donut chart, improve bar charts. Add more dem…
vnbaaij Apr 23, 2026
561259d
- Update charts ts code
vnbaaij May 5, 2026
faa6425
merge
vnbaaij May 5, 2026
016fc47
- Add coercion step for parsing axis values
vnbaaij May 6, 2026
8ba166c
Ignore generated chart-comments.json
vnbaaij May 11, 2026
28e7249
- Enhance DataVizPalette
vnbaaij May 11, 2026
e7e08ab
Addd missing parameters on the Blazor side
vnbaaij May 11, 2026
f2acc8d
Add more examples
vnbaaij May 11, 2026
2d514d4
- Introduce FluentChartBase
vnbaaij May 11, 2026
e8d894f
Merge branch 'dev-v5' into charts
vnbaaij May 11, 2026
e3a5e06
Use charts comments for docs
vnbaaij May 11, 2026
d6b9beb
Update docs
vnbaaij May 11, 2026
da276d8
Merge dev-v5
vnbaaij May 12, 2026
e79a22a
Update package-lock
vnbaaij May 12, 2026
4bcbbb2
Update package-lock.json to use secure package URLs and update versions
dvoituron May 12, 2026
90403ef
Update .npmrc to use secure Azure DevOps package registry
dvoituron May 12, 2026
bb84c06
Remove unnecessary esbuild platform-specific packages from package-lo…
dvoituron May 12, 2026
68302e8
Update package-lock.json to upgrade dependencies and add new platform…
dvoituron May 12, 2026
e7280c7
Add Charts csproj to build-core-lib
vnbaaij May 12, 2026
1868118
Merge branch 'dev-v5' into charts
vnbaaij May 12, 2026
957e2d4
- Update Microsoft.VisualStudio.JavaScript.Sdk
vnbaaij May 12, 2026
1413d2f
Merge branch 'charts' of https://github.com/microsoft/fluentui-blazor…
vnbaaij May 12, 2026
71e3851
Fix path
vnbaaij May 12, 2026
afdc3c2
Add charts to DocApiGen
vnbaaij May 12, 2026
397f048
Update mcp server proj to include charts docs
vnbaaij May 12, 2026
1828993
Chart WC optimizations
vnbaaij May 12, 2026
0e23826
Use the new fluent-chart-legend compnent
vnbaaij May 13, 2026
229650a
Centralize tooltip code and styles
vnbaaij May 14, 2026
a4ef2cd
Remove style="width: 100%;" from examples
vnbaaij May 14, 2026
b0770a9
Add FunnelChart, simplyfy Donut data model, Title/Legend positioning
vnbaaij May 15, 2026
217a42b
- Add FunnelChart pages
vnbaaij May 16, 2026
4543ebb
Use DataVizPalette in all chart models and examples
vnbaaij May 16, 2026
5c8e9e5
Fix some a11y data transfer issues
vnbaaij May 16, 2026
ffbb16d
- Add roving tabindex where applicable
vnbaaij May 17, 2026
fb6d428
A11y improvements
vnbaaij May 18, 2026
0b9b386
Enhance legend selection and visibility features
vnbaaij May 18, 2026
377143c
Merge branch 'dev-v5' into charts
vnbaaij May 19, 2026
e3fa760
- Update docs
vnbaaij May 19, 2026
394229c
- Add FluentCartesianChartBase on the Blazor side
vnbaaij May 19, 2026
2cb1fcf
- Add FluentGanttChart (WIP)
vnbaaij May 19, 2026
9864498
Update package-lock.json with new d3 dependencies
dvoituron May 19, 2026
5e91768
Add Gantt chart component and axis/tick enhancements
vnbaaij May 19, 2026
448f317
Small fixes
vnbaaij May 20, 2026
c8c67d6
- Remove always-auth from .npmrc
vnbaaij May 20, 2026
09d3362
feat: add the Blazor parts of tooltipRenderer support so chart compon…
vnbaaij May 22, 2026
56ccad8
Update spaces and aligns
dvoituron May 25, 2026
1f3e2b9
Merge branch 'dev-v5' into charts
dvoituron May 25, 2026
50d48c2
Fix compiler warnings
vnbaaij May 25, 2026
ca90c13
Merge branch 'charts' of https://github.com/microsoft/fluentui-blazor…
vnbaaij May 25, 2026
fad58a5
Process review comments
vnbaaij May 26, 2026
e51129e
Update chart script code
vnbaaij Jul 7, 2026
3bcb93f
Initial add AreaChart work
vnbaaij Jul 7, 2026
49a2d7f
- Update WC Chart code
vnbaaij Jul 27, 2026
51706fc
Add unit tests for FluentAreaChart
vnbaaij Jul 27, 2026
30b1760
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/add-areachart
vnbaaij Jul 27, 2026
e4e4e83
- Add AreaChart examples
vnbaaij Jul 28, 2026
38a84d7
Merge branch 'dev-v5' into users/vnbaaij/dev-v5/add-areachart
vnbaaij Jul 28, 2026
74915c6
Undo project change
vnbaaij Jul 28, 2026
f453dc2
Merge branch 'users/vnbaaij/dev-v5/add-areachart' of https://github.c…
vnbaaij Jul 28, 2026
a91101b
Undo project file change
vnbaaij Jul 28, 2026
e401003
Merge area-chart
vnbaaij Jul 28, 2026
475010d
- Make sample order consistent
vnbaaij Jul 29, 2026
6ea5645
Initial work to add GroupedVerticalBarChart, VerticalBarChart and Ver…
vnbaaij Jul 29, 2026
5ccf620
Merge dev-v5
vnbaaij Aug 3, 2026
7a79f5a
Merge branch 'charts' into add-vbccharts
vnbaaij Aug 3, 2026
d122481
Fix merge issue
vnbaaij Aug 3, 2026
66661b0
Merge branch 'dev-v5' into add-vbccharts
vnbaaij Aug 4, 2026
e54336d
Fix Copilor remarks
vnbaaij Aug 4, 2026
f020b5a
Merge branch 'add-vbccharts' of https://github.com/microsoft/fluentui…
vnbaaij Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@using Microsoft.FluentUI.AspNetCore.Components.Charts


@code {
private readonly IReadOnlyList<GroupedVerticalBarChartDataPoint> data = new List<GroupedVerticalBarChartDataPoint>
{
new GroupedVerticalBarChartDataPoint { Legend = "first", Data = 20000 },
new GroupedVerticalBarChartDataPoint { Legend = "second", Data = 39000 }
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@using Microsoft.FluentUI.AspNetCore.Components.Charts

@code {
private readonly IReadOnlyList<VerticalBarChartDataPoint> data = new List<VerticalBarChartDataPoint>
{
new VerticalBarChartDataPoint { Legend = "first", Data = 20000 },
new VerticalBarChartDataPoint { Legend = "second", Data = 39000 }
};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@using Microsoft.FluentUI.AspNetCore.Components.Charts


@code {
private readonly IReadOnlyList<VerticalStackedBarChartDataPoint> data = new List<VerticalStackedBarChartDataPoint>
{
new VerticalStackedBarChartDataPoint { Legend = "first", Data = 20000 },
new VerticalStackedBarChartDataPoint { Legend = "second", Data = 39000 }
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: Grouped Vertical Bar Chart
route: /Charts/GroupedVerticalBarChart
---

# Grouped Vertical Bar Chart

A grouped vertical bar chart displays multiple series of data as a group of bars, with each bar
denoting a category. The bars are grouped together side by side, with each group denoting a
different series.

Effectively, a grouped vertical bar chart can slice data across 2 dimensions - (1) A dimension
along the x axis and (2) Groups within the first dimension. And the y-axis plots the values of
each category. Each bar in a group is colored differently to differentiate among categories within
the group.

## Layout

A stacked bar chart is used to emphasize the composition of a category and how individual
components contribute to it. On the other hand, a grouped bar chart is used to compare distinct
values across various categories or groups separately.

Refer to Vertical Bar Chart page for common layout guidance.

## Content

Refer to Vertical Bar Chart page for common content guidance.

## Accessibility

Refer to Vertical Bar Chart page for common accessibility guidance.

## Customizing the chart

- Use the BarWidth prop to customize the width of each bar in the chart. When set to undefined
or 'default', the bar width defaults to 16px, which may decrease to prevent overlap. When set to
'auto', the bar width is calculated from padding values. For a fixed bar width, specify an
absolute pixel value like 40.

- Use the MaxBarWidth prop to limit the width of bars to a specified number of pixels.

- Use the XAxisInnerPadding and XAxisOuterPadding props to adjust the padding between groups and
the padding before the first group and after the last group, respectively. These props accept
values between 0 and 1, representing a fraction of the step, which is the interval between the
start of a group and the start of the next group. These props are particularly relevant when using
a string x-axis. By default, the inner padding is set to 2 / (2 + groupWidthInTermsOfBarWidth),
maintaining a 2:1 spacing ratio. This default value is calculated at runtime using the formula:
> innerPadding = spaceBetweenGroups / (spaceBetweenGroups + groupWidth)
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: Vertical Bar Chart
route: /Charts/VerticalBarChart
---

# Vertical Bar Chart

A vertical bar chart displays data as a series of vertical bars, with each bar representing a category and the height of the bar representing the value of that category. It is commonly used to show comparisons between categories of one or more data sets, usually over a period of time. Categories are shown on the horizontal axis, while the data values are shown along the vertical axis. They could present data over time or in relationship to a whole.

## Layout

The default bar width is 16px. For dense data, it can be as thin as 8px wide. Always consider the visual weight of the bars in relationship to the rest of the app before choosing this type of chart.

The padding around the bar chart is a default of 8px from the x and y-axis container. This gives enough room for additional content like label values to display properly without overlapping on to the X-axis ticks. A 2:1 spacing is maintained between all the bars in the graph so that space between two bars is always two times the bar width. This helps to ensure that the graph is not overpowering other data visualizations.

For charts that display monetary values, the dollar symbol should be displayed as part of the total value. Also call out the currency in the chart title to provide additional context. Chart title can be used to communicate currency when the total labels are hidden.

## Content

- **Bar segment** Bar segments make up a bar chart. Standard size options are: 8px, 16px, and 24px with 16px being the default.
- **Value labels** (Optional - Off by default) with the option to toggle on in case the data visualization needs to communicate label values to users.

## Accessibility

Bar graphs should be flexible to their containers. They will change widths to fit their environment. This also means that bar labels will rotate or truncate to best fit the available space in the chart (Auto adjusting labels coming soon).

Type truncation should happen when the total value exceeds one thousand including 1 decimal place for the hundreds. For example, display full value for 600, 983, or 19.53. Truncate 6,000 to 6.0K, 9,801 to 9.8K, and 100,900 to 100.9K.

## Customizing the chart

- The chart provides an option to select a color scale based on the range of y values. Similar y values will end up having similar colors. Use the colors attribute to define the color scale.

- Use `UseSingleColor` to use a single color for all bars.

- Use `LineLegendText` and `LineLegendColor` to specify the text and color for legends of lines in the chart.

- The bar labels are shown by default. Set the `HideLabels` prop to hide them.

- Use the `BarWidth` prop to customize the width of each bar in the chart. When set to undefined or 'default', the bar width defaults to 16px, which may decrease to prevent overlap. When set to 'auto', the bar width is calculated from padding values. For a fixed bar width, specify an absolute pixel value like 40.

- Use the `MaxBarWidth` prop to limit the width of bars to a specified number of pixels.

- Use the `XAxisInnerPadding` and `XAxisOuterPadding` props to adjust the padding between bars and the padding before the first bar and after the last bar, respectively. These props accept values between 0 and 1, representing a fraction of the step, which is the interval between the start of a bar and the start of the next bar. These props are particularly relevant when using a string x-axis. By default, the inner padding is set to 2/3, maintaining a 2:1 spacing ratio. This default value is calculated using the formula:
> innerPadding = spaceBetweenBars / (spaceBetweenBars + barWidth)

## Do's

Try to keep the number of bars in the chart between 3 and 20 to maximize readability.

## Don'ts

Don't use very long labels in vertical bar chart. Long labels use unnecessary space and make the chart skewed. For long labels use horizontal bar chart with axis.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
title: Vertical Stacked Bar Chart
route: /Charts/VerticalStackedBarChart
---

# Vertical Stacked Bar Chart

Vertical stacked bar chart displays multiple series of data as stacked bars, with each bar representing a category. The bars are stacked on top of each other, with the height of each bar representing the value of the category of the series.

Categories and their count are shown on the horizontal axis.

## Layout

Stacked bar charts are ideal for comparing values across two or more categories. They can easily show multiple categories on the same chart.

Refer to Vertical Bar Chart page for common layout guidance.

## Content

Refer to Vertical Bar Chart page for common content guidance.

## Accessibility

Refer to Vertical Bar Chart page for common accessibility guidance.

## Customizing the chart

Here are some commonly used properties to customize the bar chart.

- `BarGapMax` sets the maximum gap between bars in a stack. See the prop for more details.

- `BarCornerRadius` sets the corner radius of the bars.

- `BarMinimumHeight` provides the minimum height of a bar. Bars below this height will be displayed at this height.

- Use `IsCalloutForStack` to configure callout to be at stack level or individual datapoint level.

- Define a custom callout rendered per datapoint using `OnRenderCalloutPerDataPoint` and per stack using `OnRenderCalloutPerStack`

- Use `OnBarClick` handler for callback on click of bars

- The bar labels are shown by default. Set the `HideLabels` prop to hide them.

- Use the `BarWidth` prop to customize the width of each bar in the chart. When set to undefined or 'default', the bar width defaults to 16px, which may decrease to prevent overlap. When set to 'auto', the bar width is calculated from padding values. For a fixed bar width, specify an absolute pixel value like 40.

- Use the `MaxBarWidth` prop to limit the width of bars to a specified number of pixels.

- Use the `XAxisInnerPadding` and `XAxisOuterPadding` props to adjust the padding between bars and the padding before the first bar and after the last bar, respectively. These props accept values between 0 and 1, representing a fraction of the step, which is the interval between the start of a bar and the start of the next bar. These props are particularly relevant when using a string x-axis. By default, the inner padding is set to 2/3, maintaining a 2:1 spacing ratio. This default value is calculated using the formula:

> `innerPadding = spaceBetweenBars / (spaceBetweenBars + barWidth)`

## Do's

Refer to Vertical Bar Chart page for common dos.

## Don'ts

Refer to Vertical Bar Chart page for common don'ts.
2 changes: 2 additions & 0 deletions examples/Demo/FluentUI.Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using FluentUI.Demo.Client;
using Microsoft.FluentUI.AspNetCore.Components;
using Microsoft.FluentUI.AspNetCore.Components.Charts;

var builder = WebApplication.CreateBuilder(args);

Expand All @@ -27,6 +28,7 @@
// config.DefaultValues.ForAny<FluentAutocomplete<object, object>>().Set(p => p.Width, "100%");
// config.DefaultValues.ForAny<FluentAutocomplete<object, object>>().Set(p => p.Multiple, false);

config.DefaultValues.ForAny<FluentChartBase>().Set(p => p.RoundedCorners, true);
// Use a custom localizer
config.Localizer = new FluentUI.Demo.MyLocalizer();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ export const definition: PartialFASTElementDefinition = {
template,
styles,
};

Empty file.
10 changes: 10 additions & 0 deletions src/Charts/Infrastructure/ChartJson.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,14 @@ public static string Serialize(IReadOnlyList<GanttChartDataPoint> value) =>
JsonSerializer.Serialize(
value,
GanttChartDataJsonSerializerContext.Default.IReadOnlyListGanttChartDataPoint);

/// <summary>
/// Serializes vertical bar chart data using the vertical bar chart serializer context.
/// </summary>
/// <param name="value">The vertical bar chart series collection.</param>
/// <returns>A JSON string suitable for the <c>fluent-vertical-bar-chart</c> component.</returns>
public static string Serialize(IReadOnlyList<VerticalBarChartSeries> value) =>
JsonSerializer.Serialize(
value,
VerticalBarChartDataJsonSerializerContext.Default.IReadOnlyListVerticalBarChartSeries);
Comment thread
vnbaaij marked this conversation as resolved.
}
Comment on lines +80 to 89
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using System.Text.Json.Serialization;
using Microsoft.FluentUI.AspNetCore.Components.Extensions;

namespace Microsoft.FluentUI.AspNetCore.Components.Charts;

/// <summary>
/// Represents a single data point in a grouped vertical bar chart series.
/// </summary>
public sealed record GroupedVerticalBarChartDataPoint
{
/// <summary>
/// Gets the legend text shown for the bar segment.
/// </summary>
[JsonPropertyName("legend")]
public string Legend { get; init; } = string.Empty;

/// <summary>
/// Gets the numeric value represented by the bar segment.
/// </summary>
[JsonPropertyName("data")]
public double Data { get; init; }

/// <summary>
/// Gets the optional total bar length used for ratio-style rendering.
/// </summary>
[JsonPropertyName("total")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public double? Total { get; init; }

/// <summary>
/// Gets the solid color used to render the bar segment.
/// Use <see cref="DataVizPalette.Custom"/> and set <see cref="CustomColor"/> to supply
/// an exact hex or CSS color string. If not provided, the component falls back to its
/// default palette.
/// </summary>
[JsonIgnore]
public DataVizPalette? Color { get; init; }

/// <summary>
/// Custom color value used when <see cref="Color"/> is <see cref="DataVizPalette.Custom"/>.
/// Accepts an HTML hex color string (e.g. <c>#0099BC</c>) or a CSS variable.
/// </summary>
[JsonIgnore]
public string? CustomColor { get; init; }

/// <summary>
/// Gets the serialized color value sent to the web component.
/// Returns <see cref="CustomColor"/> when <see cref="Color"/> is <see cref="DataVizPalette.Custom"/>,
/// otherwise the palette token string, or <see langword="null"/> when no color is set.
/// </summary>
[JsonPropertyName("color")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? SerializedColor => Color == DataVizPalette.Custom ? CustomColor : Color?.ToAttributeValue();

/// <summary>
/// Gets the optional two-color gradient used to render the bar segment.
/// The array should contain exactly two color values: start and end.
/// </summary>
[JsonPropertyName("gradient")]
public string[]? Gradient { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using System.Text.Json.Serialization;

namespace Microsoft.FluentUI.AspNetCore.Components.Charts;

/// <summary>
/// Represents one grouped vertical bar chart series in the data payload.
/// </summary>
public sealed record GroupedVerticalBarChartSeries
{
/// <summary>
/// Gets the optional title shown for the data series.
/// </summary>
[JsonPropertyName("chartSeriesTitle")]
public string? ChartSeriesTitle { get; init; }

/// <summary>
/// Gets the collection of data points rendered within the series.
/// </summary>
[JsonPropertyName("chartData")]
public IReadOnlyList<GroupedVerticalBarChartDataPoint> ChartData { get; init; } = [];

/// <summary>
/// Gets the optional benchmark value used to render the benchmark indicator.
/// </summary>
[JsonPropertyName("benchmarkData")]
public double? BenchmarkData { get; init; }

/// <summary>
/// Gets optional text displayed alongside the chart data for the series.
/// </summary>
[JsonPropertyName("chartDataText")]
public string? ChartDataText { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using System.Text.Json.Serialization;

namespace Microsoft.FluentUI.AspNetCore.Components.Charts;

/// <summary>
/// Represents one horizontal bar chart series in the data payload.
/// </summary>
public sealed record HorizontalBarChartWithAxisSeries
{
/// <summary>
/// Gets the optional title shown for the data series.
/// </summary>
[JsonPropertyName("chartSeriesTitle")]
public string? ChartSeriesTitle { get; init; }

/// <summary>
/// Gets the collection of data points rendered within the series.
/// </summary>
[JsonPropertyName("chartData")]
public IReadOnlyList<HorizontalBarChartWithAxisDataPoint> ChartData { get; init; } = [];

/// <summary>
/// Gets the optional benchmark value used to render the benchmark indicator.
/// </summary>
[JsonPropertyName("benchmarkData")]
public double? BenchmarkData { get; init; }

/// <summary>
/// Gets optional text displayed alongside the chart data for the series.
/// </summary>
[JsonPropertyName("chartDataText")]
public string? ChartDataText { get; init; }
}
Loading
Loading