diff --git a/Radzen.Blazor.Tests/ChartLegendTests.cs b/Radzen.Blazor.Tests/ChartLegendTests.cs index ad39aaddb..55ade005b 100644 --- a/Radzen.Blazor.Tests/ChartLegendTests.cs +++ b/Radzen.Blazor.Tests/ChartLegendTests.cs @@ -35,6 +35,76 @@ namespace Radzen.Blazor.Tests return double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); } + private static RenderFragment LegendWithSeries(LegendPosition position) => builder => + { + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(RadzenLegend.Position), position); + builder.CloseComponent(); + + builder.OpenComponent>(2); + builder.AddAttribute(3, nameof(RadzenLineSeries.CategoryProperty), nameof(DataItem.Category)); + builder.AddAttribute(4, nameof(RadzenLineSeries.ValueProperty), nameof(DataItem.Value)); + builder.AddAttribute(5, nameof(RadzenLineSeries.Title), "Series"); + builder.AddAttribute(6, nameof(RadzenLineSeries.Data), (IEnumerable)SampleData); + builder.CloseComponent(); + }; + + [Theory] + [InlineData(LegendPosition.Start, "rz-legend-left")] + [InlineData(LegendPosition.End, "rz-legend-right")] + public async Task StartEndLegend_InLtr_ResolvesToPhysicalSide(LegendPosition position, string expectedClass) + { + using var ctx = CreateChartContext(); + + var chart = ctx.RenderComponent(p => p.Add(c => c.ChildContent, LegendWithSeries(position))); + await chart.InvokeAsync(() => chart.Instance.Resize(400, 300)); + + Assert.Contains(expectedClass, chart.Markup); + } + + [Theory] + [InlineData(LegendPosition.Start, "rz-legend-right")] + [InlineData(LegendPosition.End, "rz-legend-left")] + public async Task StartEndLegend_InRtl_FlipsToOppositeSide(LegendPosition position, string expectedClass) + { + using var ctx = CreateChartContext(); + + var chart = ctx.RenderComponent(p => p.Add(c => c.ChildContent, LegendWithSeries(position))); + await chart.InvokeAsync(() => chart.Instance.Resize(400, 300)); + await chart.InvokeAsync(() => chart.Instance.SetRTL(true)); + + Assert.Contains(expectedClass, chart.Markup); + } + + private static RenderFragment DefaultLegendWithSeries() => builder => + { + builder.OpenComponent(0); + builder.CloseComponent(); + + builder.OpenComponent>(1); + builder.AddAttribute(2, nameof(RadzenLineSeries.CategoryProperty), nameof(DataItem.Category)); + builder.AddAttribute(3, nameof(RadzenLineSeries.ValueProperty), nameof(DataItem.Value)); + builder.AddAttribute(4, nameof(RadzenLineSeries.Title), "Series"); + builder.AddAttribute(5, nameof(RadzenLineSeries.Data), (IEnumerable)SampleData); + builder.CloseComponent(); + }; + + [Fact] + public async Task DefaultLegend_RendersOnRightInLtr_AndFlipsToLeftInRtl() + { + using var ctx = CreateChartContext(); + + // No Position set -> defaults to LegendPosition.End. + var chart = ctx.RenderComponent(p => p.Add(c => c.ChildContent, DefaultLegendWithSeries())); + await chart.InvokeAsync(() => chart.Instance.Resize(400, 300)); + + Assert.Contains("rz-legend-right", chart.Markup); + + await chart.InvokeAsync(() => chart.Instance.SetRTL(true)); + + Assert.Contains("rz-legend-left", chart.Markup); + } + [Fact] public async Task TopLegend_WithManyWrappingSeries_ReservesMoreSpaceThanSingleRow() { diff --git a/Radzen.Blazor/LegendPosition.cs b/Radzen.Blazor/LegendPosition.cs index ec9cfc000..3b9ccdb49 100644 --- a/Radzen.Blazor/LegendPosition.cs +++ b/Radzen.Blazor/LegendPosition.cs @@ -20,6 +20,14 @@ namespace Radzen.Blazor /// /// The legend is below the series. /// - Bottom + Bottom, + /// + /// The legend is at the inline-start side of the series — left in left-to-right mode, right in right-to-left mode. + /// + Start, + /// + /// The legend is at the inline-end side of the series — right in left-to-right mode, left in right-to-left mode. + /// + End } } diff --git a/Radzen.Blazor/RadzenChart.razor.cs b/Radzen.Blazor/RadzenChart.razor.cs index a50be087f..e577a87e0 100644 --- a/Radzen.Blazor/RadzenChart.razor.cs +++ b/Radzen.Blazor/RadzenChart.razor.cs @@ -242,6 +242,18 @@ namespace Radzen.Blazor } } + /// + /// Resolves the legend position to a concrete side, mapping the direction-aware + /// / values to + /// / based on . + /// + internal LegendPosition EffectiveLegendPosition => (Legend?.Position ?? LegendPosition.Right) switch + { + LegendPosition.Start => IsRTL ? LegendPosition.Right : LegendPosition.Left, + LegendPosition.End => IsRTL ? LegendPosition.Left : LegendPosition.Right, + var position => position + }; + /// /// Gets or sets the callback invoked when a user clicks on a data point or segment in a chart series. /// Provides information about the clicked series, data item, and value in the event arguments. @@ -717,9 +729,11 @@ namespace Radzen.Blazor if (Legend.Visible) { - if (Legend.Position == LegendPosition.Right || Legend.Position == LegendPosition.Left) + var legendPosition = EffectiveLegendPosition; + + if (legendPosition == LegendPosition.Right || legendPosition == LegendPosition.Left) { - if (Legend.Position == LegendPosition.Right) + if (legendPosition == LegendPosition.Right) { MarginRight = legendSize + 16 + (IsRTL ? valueAxisSize : additionalAxesWidth); } @@ -728,9 +742,9 @@ namespace Radzen.Blazor MarginLeft = legendSize + 16 + (IsRTL ? additionalAxesWidth : valueAxisSize); } } - else if (Legend.Position == LegendPosition.Top || Legend.Position == LegendPosition.Bottom) + else if (legendPosition == LegendPosition.Top || legendPosition == LegendPosition.Bottom) { - if (Legend.Position == LegendPosition.Top) + if (legendPosition == LegendPosition.Top) { MarginTop = legendSize + 16; } diff --git a/Radzen.Blazor/RadzenLegend.cs b/Radzen.Blazor/RadzenLegend.cs index 8aa76b263..c1b30b678 100644 --- a/Radzen.Blazor/RadzenLegend.cs +++ b/Radzen.Blazor/RadzenLegend.cs @@ -11,9 +11,10 @@ namespace Radzen.Blazor /// /// Gets or sets the position. /// - /// The position. + /// The position. Default is , which renders on the right + /// in left-to-right mode and automatically flips to the left in right-to-left mode. [Parameter] - public LegendPosition Position { get; set; } + public LegendPosition Position { get; set; } = LegendPosition.End; /// /// Gets or sets a value indicating whether this is visible. @@ -33,7 +34,8 @@ namespace Radzen.Blazor var size = 16 * 0.875; - if (Position == LegendPosition.Right || Position == LegendPosition.Left) + if (Position == LegendPosition.Right || Position == LegendPosition.Left + || Position == LegendPosition.Start || Position == LegendPosition.End) { if (chart.Series.Any()) { diff --git a/Radzen.Blazor/Rendering/Legend.razor b/Radzen.Blazor/Rendering/Legend.razor index 94e826faf..81d20086d 100644 --- a/Radzen.Blazor/Rendering/Legend.razor +++ b/Radzen.Blazor/Rendering/Legend.razor @@ -21,6 +21,6 @@ public RadzenChart? Chart { get; set; } string Class => ClassList.Create("rz-legend") - .Add($"rz-legend-{Chart?.Legend?.Position ?? LegendPosition.Right}".ToLowerInvariant()) + .Add($"rz-legend-{Chart?.EffectiveLegendPosition ?? LegendPosition.Right}".ToLowerInvariant()) .ToString(); }