diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/GroupedVerticalBarChart/GroupedVerticalBarChartDefault.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/GroupedVerticalBarChart/GroupedVerticalBarChartDefault.razor new file mode 100644 index 0000000000..f74e5479f6 --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/GroupedVerticalBarChart/GroupedVerticalBarChartDefault.razor @@ -0,0 +1,10 @@ +@using Microsoft.FluentUI.AspNetCore.Components.Charts + + +@code { + private readonly IReadOnlyList data = new List + { + new GroupedVerticalBarChartDataPoint { Legend = "first", Data = 20000 }, + new GroupedVerticalBarChartDataPoint { Legend = "second", Data = 39000 } + }; +} diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalBarChart/VerticalBarChartDefault.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalBarChart/VerticalBarChartDefault.razor new file mode 100644 index 0000000000..33633d4a9c --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalBarChart/VerticalBarChartDefault.razor @@ -0,0 +1,10 @@ +@using Microsoft.FluentUI.AspNetCore.Components.Charts + +@code { + private readonly IReadOnlyList data = new List + { + new VerticalBarChartDataPoint { Legend = "first", Data = 20000 }, + new VerticalBarChartDataPoint { Legend = "second", Data = 39000 } + }; + +} diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalStackedBarChart/VerticalStackedBarChartDefault.razor b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalStackedBarChart/VerticalStackedBarChartDefault.razor new file mode 100644 index 0000000000..6de14c4f6c --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Examples/VerticalStackedBarChart/VerticalStackedBarChartDefault.razor @@ -0,0 +1,10 @@ +@using Microsoft.FluentUI.AspNetCore.Components.Charts + + +@code { + private readonly IReadOnlyList data = new List + { + new VerticalStackedBarChartDataPoint { Legend = "first", Data = 20000 }, + new VerticalStackedBarChartDataPoint { Legend = "second", Data = 39000 } + }; +} diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentGroupedVerticalBarChart.md b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentGroupedVerticalBarChart.md new file mode 100644 index 0000000000..c8b075c18e --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentGroupedVerticalBarChart.md @@ -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) diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalBarChart.md b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalBarChart.md new file mode 100644 index 0000000000..f31664a6ea --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalBarChart.md @@ -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. diff --git a/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalStackedBarChart.md b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalStackedBarChart.md new file mode 100644 index 0000000000..315b749586 --- /dev/null +++ b/examples/Demo/FluentUI.Demo.Client/Documentation/Components/Charts/Pages/FluentVerticalStackedBarChart.md @@ -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. diff --git a/examples/Demo/FluentUI.Demo/Program.cs b/examples/Demo/FluentUI.Demo/Program.cs index 1802348295..f6ce094e4c 100644 --- a/examples/Demo/FluentUI.Demo/Program.cs +++ b/examples/Demo/FluentUI.Demo/Program.cs @@ -4,6 +4,7 @@ using FluentUI.Demo.Client; using Microsoft.FluentUI.AspNetCore.Components; +using Microsoft.FluentUI.AspNetCore.Components.Charts; var builder = WebApplication.CreateBuilder(args); @@ -27,6 +28,7 @@ // config.DefaultValues.ForAny>().Set(p => p.Width, "100%"); // config.DefaultValues.ForAny>().Set(p => p.Multiple, false); + config.DefaultValues.ForAny().Set(p => p.RoundedCorners, true); // Use a custom localizer config.Localizer = new FluentUI.Demo.MyLocalizer(); }); diff --git a/src/Charts.Scripts/src/chart-legend/chart-legend.definition.ts b/src/Charts.Scripts/src/chart-legend/chart-legend.definition.ts index dd9f1b4e84..48d2f76cc1 100644 --- a/src/Charts.Scripts/src/chart-legend/chart-legend.definition.ts +++ b/src/Charts.Scripts/src/chart-legend/chart-legend.definition.ts @@ -14,3 +14,4 @@ export const definition: PartialFASTElementDefinition = { template, styles, }; + diff --git a/src/Charts/Charts/GroupedVerticalBarChart/FluentGroupedVerticalBarChart.razor b/src/Charts/Charts/GroupedVerticalBarChart/FluentGroupedVerticalBarChart.razor new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Charts/Charts/VerticalBarChart/FluentVerticalBarChart.razor b/src/Charts/Charts/VerticalBarChart/FluentVerticalBarChart.razor new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Charts/Charts/VerticalStackedBarChart/FluentVerticalStackedBarChart.razor b/src/Charts/Charts/VerticalStackedBarChart/FluentVerticalStackedBarChart.razor new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Charts/Infrastructure/ChartJson.cs b/src/Charts/Infrastructure/ChartJson.cs index f6fb1b54bb..28dcb0a062 100644 --- a/src/Charts/Infrastructure/ChartJson.cs +++ b/src/Charts/Infrastructure/ChartJson.cs @@ -76,4 +76,14 @@ public static string Serialize(IReadOnlyList value) => JsonSerializer.Serialize( value, GanttChartDataJsonSerializerContext.Default.IReadOnlyListGanttChartDataPoint); + + /// + /// Serializes vertical bar chart data using the vertical bar chart serializer context. + /// + /// The vertical bar chart series collection. + /// A JSON string suitable for the fluent-vertical-bar-chart component. + public static string Serialize(IReadOnlyList value) => + JsonSerializer.Serialize( + value, + VerticalBarChartDataJsonSerializerContext.Default.IReadOnlyListVerticalBarChartSeries); } diff --git a/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartDataPoint.cs b/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartDataPoint.cs new file mode 100644 index 0000000000..34da6bf847 --- /dev/null +++ b/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartDataPoint.cs @@ -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; + +/// +/// Represents a single data point in a grouped vertical bar chart series. +/// +public sealed record GroupedVerticalBarChartDataPoint +{ + /// + /// Gets the legend text shown for the bar segment. + /// + [JsonPropertyName("legend")] + public string Legend { get; init; } = string.Empty; + + /// + /// Gets the numeric value represented by the bar segment. + /// + [JsonPropertyName("data")] + public double Data { get; init; } + + /// + /// Gets the optional total bar length used for ratio-style rendering. + /// + [JsonPropertyName("total")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public double? Total { get; init; } + + /// + /// Gets the solid color used to render the bar segment. + /// Use and set to supply + /// an exact hex or CSS color string. If not provided, the component falls back to its + /// default palette. + /// + [JsonIgnore] + public DataVizPalette? Color { get; init; } + + /// + /// Custom color value used when is . + /// Accepts an HTML hex color string (e.g. #0099BC) or a CSS variable. + /// + [JsonIgnore] + public string? CustomColor { get; init; } + + /// + /// Gets the serialized color value sent to the web component. + /// Returns when is , + /// otherwise the palette token string, or when no color is set. + /// + [JsonPropertyName("color")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? SerializedColor => Color == DataVizPalette.Custom ? CustomColor : Color?.ToAttributeValue(); + + /// + /// Gets the optional two-color gradient used to render the bar segment. + /// The array should contain exactly two color values: start and end. + /// + [JsonPropertyName("gradient")] + public string[]? Gradient { get; init; } +} diff --git a/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartSeries.cs b/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartSeries.cs new file mode 100644 index 0000000000..ce2f7420ee --- /dev/null +++ b/src/Charts/Models/GroupedVerticalBarChart/GroupedVerticalBarChartSeries.cs @@ -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; + +/// +/// Represents one grouped vertical bar chart series in the data payload. +/// +public sealed record GroupedVerticalBarChartSeries +{ + /// + /// Gets the optional title shown for the data series. + /// + [JsonPropertyName("chartSeriesTitle")] + public string? ChartSeriesTitle { get; init; } + + /// + /// Gets the collection of data points rendered within the series. + /// + [JsonPropertyName("chartData")] + public IReadOnlyList ChartData { get; init; } = []; + + /// + /// Gets the optional benchmark value used to render the benchmark indicator. + /// + [JsonPropertyName("benchmarkData")] + public double? BenchmarkData { get; init; } + + /// + /// Gets optional text displayed alongside the chart data for the series. + /// + [JsonPropertyName("chartDataText")] + public string? ChartDataText { get; init; } +} diff --git a/src/Charts/Models/HorizontalBarChartWithAxis/HorizontalBarChartWithAxisSeries.cs b/src/Charts/Models/HorizontalBarChartWithAxis/HorizontalBarChartWithAxisSeries.cs new file mode 100644 index 0000000000..dedd7c4f92 --- /dev/null +++ b/src/Charts/Models/HorizontalBarChartWithAxis/HorizontalBarChartWithAxisSeries.cs @@ -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; + +/// +/// Represents one horizontal bar chart series in the data payload. +/// +public sealed record HorizontalBarChartWithAxisSeries +{ + /// + /// Gets the optional title shown for the data series. + /// + [JsonPropertyName("chartSeriesTitle")] + public string? ChartSeriesTitle { get; init; } + + /// + /// Gets the collection of data points rendered within the series. + /// + [JsonPropertyName("chartData")] + public IReadOnlyList ChartData { get; init; } = []; + + /// + /// Gets the optional benchmark value used to render the benchmark indicator. + /// + [JsonPropertyName("benchmarkData")] + public double? BenchmarkData { get; init; } + + /// + /// Gets optional text displayed alongside the chart data for the series. + /// + [JsonPropertyName("chartDataText")] + public string? ChartDataText { get; init; } +} diff --git a/src/Charts/Models/VerticalBarChart/VerticalBarChartDataPoint.cs b/src/Charts/Models/VerticalBarChart/VerticalBarChartDataPoint.cs new file mode 100644 index 0000000000..14f4d5ad55 --- /dev/null +++ b/src/Charts/Models/VerticalBarChart/VerticalBarChartDataPoint.cs @@ -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; + +/// +/// Represents a single data point in a vertical bar chart series. +/// +public sealed record VerticalBarChartDataPoint +{ + /// + /// Gets the legend text shown for the bar segment. + /// + [JsonPropertyName("legend")] + public string Legend { get; init; } = string.Empty; + + /// + /// Gets the numeric value represented by the bar segment. + /// + [JsonPropertyName("data")] + public double Data { get; init; } + + /// + /// Gets the optional total bar length used for ratio-style rendering. + /// + [JsonPropertyName("total")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public double? Total { get; init; } + + /// + /// Gets the solid color used to render the bar segment. + /// Use and set to supply + /// an exact hex or CSS color string. If not provided, the component falls back to its + /// default palette. + /// + [JsonIgnore] + public DataVizPalette? Color { get; init; } + + /// + /// Custom color value used when is . + /// Accepts an HTML hex color string (e.g. #0099BC) or a CSS variable. + /// + [JsonIgnore] + public string? CustomColor { get; init; } + + /// + /// Gets the serialized color value sent to the web component. + /// Returns when is , + /// otherwise the palette token string, or when no color is set. + /// + [JsonPropertyName("color")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? SerializedColor => Color == DataVizPalette.Custom ? CustomColor : Color?.ToAttributeValue(); + + /// + /// Gets the optional two-color gradient used to render the bar segment. + /// The array should contain exactly two color values: start and end. + /// + [JsonPropertyName("gradient")] + public string[]? Gradient { get; init; } +} diff --git a/src/Charts/Models/VerticalBarChart/VerticalBarChartSeries.cs b/src/Charts/Models/VerticalBarChart/VerticalBarChartSeries.cs new file mode 100644 index 0000000000..0117457ed9 --- /dev/null +++ b/src/Charts/Models/VerticalBarChart/VerticalBarChartSeries.cs @@ -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; + +/// +/// Represents one vertical bar chart series in the data payload. +/// +public sealed record VerticalBarChartSeries +{ + /// + /// Gets the optional title shown for the data series. + /// + [JsonPropertyName("chartSeriesTitle")] + public string? ChartSeriesTitle { get; init; } + + /// + /// Gets the collection of data points rendered within the series. + /// + [JsonPropertyName("chartData")] + public IReadOnlyList ChartData { get; init; } = []; + + /// + /// Gets the optional benchmark value used to render the benchmark indicator. + /// + [JsonPropertyName("benchmarkData")] + public double? BenchmarkData { get; init; } + + /// + /// Gets optional text displayed alongside the chart data for the series. + /// + [JsonPropertyName("chartDataText")] + public string? ChartDataText { get; init; } +} diff --git a/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartDataPoint.cs b/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartDataPoint.cs new file mode 100644 index 0000000000..aa6f101d4a --- /dev/null +++ b/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartDataPoint.cs @@ -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; + +/// +/// Represents a single data point in a vertical stacked bar chart series. +/// +public sealed record VerticalStackedBarChartDataPoint +{ + /// + /// Gets the legend text shown for the bar segment. + /// + [JsonPropertyName("legend")] + public string Legend { get; init; } = string.Empty; + + /// + /// Gets the numeric value represented by the bar segment. + /// + [JsonPropertyName("data")] + public double Data { get; init; } + + /// + /// Gets the optional total bar length used for ratio-style rendering. + /// + [JsonPropertyName("total")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public double? Total { get; init; } + + /// + /// Gets the solid color used to render the bar segment. + /// Use and set to supply + /// an exact hex or CSS color string. If not provided, the component falls back to its + /// default palette. + /// + [JsonIgnore] + public DataVizPalette? Color { get; init; } + + /// + /// Custom color value used when is . + /// Accepts an HTML hex color string (e.g. #0099BC) or a CSS variable. + /// + [JsonIgnore] + public string? CustomColor { get; init; } + + /// + /// Gets the serialized color value sent to the web component. + /// Returns when is , + /// otherwise the palette token string, or when no color is set. + /// + [JsonPropertyName("color")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? SerializedColor => Color == DataVizPalette.Custom ? CustomColor : Color?.ToAttributeValue(); + + /// + /// Gets the optional two-color gradient used to render the bar segment. + /// The array should contain exactly two color values: start and end. + /// + [JsonPropertyName("gradient")] + public string[]? Gradient { get; init; } +} diff --git a/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartSeries.cs b/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartSeries.cs new file mode 100644 index 0000000000..691d9a42ea --- /dev/null +++ b/src/Charts/Models/VerticalStackedBarChart/VerticalStackedBarChartSeries.cs @@ -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; + +/// +/// Represents one vertical stacked bar chart series in the data payload. +/// +public sealed record VerticalStackedBarChartSeries +{ + /// + /// Gets the optional title shown for the data series. + /// + [JsonPropertyName("chartSeriesTitle")] + public string? ChartSeriesTitle { get; init; } + + /// + /// Gets the collection of data points rendered within the series. + /// + [JsonPropertyName("chartData")] + public IReadOnlyList ChartData { get; init; } = []; + + /// + /// Gets the optional benchmark value used to render the benchmark indicator. + /// + [JsonPropertyName("benchmarkData")] + public double? BenchmarkData { get; init; } + + /// + /// Gets optional text displayed alongside the chart data for the series. + /// + [JsonPropertyName("chartDataText")] + public string? ChartDataText { get; init; } +} diff --git a/src/Charts/Serialization/GroupedVerticalBarChartDataJsonSerializerContext.cs b/src/Charts/Serialization/GroupedVerticalBarChartDataJsonSerializerContext.cs new file mode 100644 index 0000000000..4822419dbc --- /dev/null +++ b/src/Charts/Serialization/GroupedVerticalBarChartDataJsonSerializerContext.cs @@ -0,0 +1,21 @@ +// ------------------------------------------------------------------------ +// This file is licensed to you under the MIT License. +// ------------------------------------------------------------------------ + +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace Microsoft.FluentUI.AspNetCore.Components.Charts; + +/// +/// Provides source-generated JSON serialization metadata for grouped vertical bar chart payloads. +/// +[JsonSerializable(typeof(GroupedVerticalBarChartSeries))] +[JsonSerializable(typeof(GroupedVerticalBarChartDataPoint))] +[JsonSerializable(typeof(IReadOnlyList))] +[JsonSerializable(typeof(IReadOnlyList))] +[ExcludeFromCodeCoverage(Justification = "This class is used for source-generated JSON serialization and does not contain any logic to be tested.")] + +internal sealed partial class GroupedVerticalBarChartDataJsonSerializerContext : JsonSerializerContext +{ +} diff --git a/src/Charts/Serialization/VerticalBarChartDataJsonSerializerContext.cs b/src/Charts/Serialization/VerticalBarChartDataJsonSerializerContext.cs new file mode 100644 index 0000000000..a933143810 --- /dev/null +++ b/src/Charts/Serialization/VerticalBarChartDataJsonSerializerContext.cs @@ -0,0 +1,21 @@ +// ------------------------------------------------------------------------ +// This file is licensed to you under the MIT License. +// ------------------------------------------------------------------------ + +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace Microsoft.FluentUI.AspNetCore.Components.Charts; + +/// +/// Provides source-generated JSON serialization metadata for vertical bar chart payloads. +/// +[JsonSerializable(typeof(VerticalBarChartSeries))] +[JsonSerializable(typeof(VerticalBarChartDataPoint))] +[JsonSerializable(typeof(IReadOnlyList))] +[JsonSerializable(typeof(IReadOnlyList))] +[ExcludeFromCodeCoverage(Justification = "This class is used for source-generated JSON serialization and does not contain any logic to be tested.")] + +internal sealed partial class VerticalBarChartDataJsonSerializerContext : JsonSerializerContext +{ +} diff --git a/src/Charts/Serialization/VerticalStackedBarChartDataJsonSerializerContext.cs b/src/Charts/Serialization/VerticalStackedBarChartDataJsonSerializerContext.cs new file mode 100644 index 0000000000..ccdb974381 --- /dev/null +++ b/src/Charts/Serialization/VerticalStackedBarChartDataJsonSerializerContext.cs @@ -0,0 +1,21 @@ +// ------------------------------------------------------------------------ +// This file is licensed to you under the MIT License. +// ------------------------------------------------------------------------ + +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace Microsoft.FluentUI.AspNetCore.Components.Charts; + +/// +/// Provides source-generated JSON serialization metadata for vertical stacked bar chart payloads. +/// +[JsonSerializable(typeof(VerticalStackedBarChartSeries))] +[JsonSerializable(typeof(VerticalStackedBarChartDataPoint))] +[JsonSerializable(typeof(IReadOnlyList))] +[JsonSerializable(typeof(IReadOnlyList))] +[ExcludeFromCodeCoverage(Justification = "This class is used for source-generated JSON serialization and does not contain any logic to be tested.")] + +internal sealed partial class VerticalStackedBarChartDataJsonSerializerContext : JsonSerializerContext +{ +}