From 17e924e35f19ab80be1d0ff1b1fecf4fb8e0b7f3 Mon Sep 17 00:00:00 2001 From: Saleh Yusefnejad Date: Wed, 24 Dec 2025 21:49:40 +0330 Subject: [PATCH] fix culture-related number issues in BitColorPicker #11920 --- .../Inputs/ColorPicker/BitColorPicker.razor | 22 ++++---- .../ColorPicker/BitColorPicker.razor.cs | 52 +++++++++++++------ 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor index 20d6e39245..8f5fd05bae 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor @@ -1,6 +1,13 @@ -@namespace Bit.BlazorUI +@namespace Bit.BlazorUI @inherits BitComponentBase +@{ + var thumbStyle = FormattableString.Invariant($"top:{_saturationPickerThumbPosition?.Top}px;left:{_saturationPickerThumbPosition?.Left}px;background-color:{Rgb}"); + + var alphaSliderBg = "url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJUlEQVQYV2N89erVfwY0ICYmxoguxjgUFKI7GsTH5m4M3w1ChQC1/Ca8i2n1WgAAAABJRU5ErkJggg==)"; + var alphaSliderStyle = $"background:linear-gradient(to left,{Rgb} 0%, transparent 100%), {alphaSliderBg};"; +} +
-
-
+
@@ -46,8 +51,7 @@ @if (ShowAlphaSlider) { -
+
+ value="@(FormattableString.Invariant($"{_color.A}"))" + aria-valuenow="@(FormattableString.Invariant($"{_color.A}"))" + aria-valuetext="@(FormattableString.Invariant($"{_color.A}"))">
}
diff --git a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor.cs b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor.cs index 60f7a55a16..638e91e4c4 100644 --- a/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor.cs +++ b/src/BlazorUI/Bit.BlazorUI/Components/Inputs/ColorPicker/BitColorPicker.razor.cs @@ -1,7 +1,11 @@ -namespace Bit.BlazorUI; +using System.Globalization; + +namespace Bit.BlazorUI; /// -/// The color picker (ColorPicker) is used to browse through and select colors. By default, it lets people navigate through colors on a color spectrum, or specify a color in either Red-Green-Blue (RGB), or alpha color code; or Hexadecimal textboxes. +/// The color picker (ColorPicker) is used to browse through and select colors. +/// By default, it lets people navigate through colors on a color spectrum, +/// or specify a color in either Red-Green-Blue (RGB), or alpha color code; or Hexadecimal textboxes. /// public partial class BitColorPicker : BitComponentBase { @@ -35,6 +39,7 @@ public double Alpha if (_color.A == value) return; _color.A = value; + AlphaChanged.InvokeAsync(value); } } @@ -48,7 +53,7 @@ public string Color get => _colorType == BitInternalColorType.Hex ? _color.Hex! : _color.Rgb!; set { - _colorType = value.HasValue() && value.StartsWith("#", StringComparison.InvariantCultureIgnoreCase) + _colorType = value.HasValue() && value.StartsWith('#') ? BitInternalColorType.Hex : BitInternalColorType.Rgb; @@ -85,10 +90,15 @@ public string Color public string? Hex => _color.Hex; + public string? Rgb => FormattableString.Invariant($"rgb({_color.R},{_color.G},{_color.B})"); + public string? Rgba => FormattableString.Invariant($"rgba({_color.R},{_color.G},{_color.B},{_color.A})"); + public (double Hue, double Saturation, double Value) Hsv => _color.Hsv; + + [JSInvokable(nameof(HandlePointerUp))] public void HandlePointerUp(MouseEventArgs e) { @@ -132,6 +142,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender) private async Task SetSaturationPickerThumbPositionAsync() { var (_, saturation, value) = _color.Hsv; + var saturationPickerRect = await _js.BitUtilsGetBoundingClientRect(_saturationPickerRef); var width = saturationPickerRect?.Width ?? 0; @@ -145,6 +156,7 @@ private async Task SetSaturationPickerThumbPositionAsync() private void SetSaturationPickerStyle() { var rgb = BitInternalColor.ToRgb(_selectedHue, 1, 1).ToString(); + _saturationPickerStyle = $"background-color:rgb{rgb}"; } @@ -153,14 +165,17 @@ private async Task UpdateColor(MouseEventArgs e) if (ColorHasBeenSet && ColorChanged.HasDelegate is false) return; var pickerRect = await _js.BitUtilsGetBoundingClientRect(_saturationPickerRef); - var left = e.ClientX < pickerRect.Left ? 0 + + var left = e.ClientX < pickerRect.Left + ? 0 : e.ClientX > pickerRect.Left + pickerRect.Width - ? pickerRect.Width - : (e.ClientX - pickerRect.Left); - var top = e.ClientY < pickerRect.Top ? 0 + ? pickerRect.Width + : (e.ClientX - pickerRect.Left); + var top = e.ClientY < pickerRect.Top + ? 0 : e.ClientY > pickerRect.Top + pickerRect.Height - ? pickerRect.Height - : (e.ClientY - pickerRect.Top); + ? pickerRect.Height + : (e.ClientY - pickerRect.Top); _saturationPickerThumbPosition = new(left, top); @@ -168,6 +183,7 @@ private async Task UpdateColor(MouseEventArgs e) _selectedValue = Math.Clamp((pickerRect.Height - e.ClientY + pickerRect.Top) / pickerRect.Height, 0, 1); _color.Update(_selectedHue, _selectedSaturation, _selectedValue, _color.A); + var colorValue = _colorType == BitInternalColorType.Hex ? _color.Hex : _color.Rgb; SetSaturationPickerStyle(); @@ -183,7 +199,8 @@ private async Task HandleOnHueInput(ChangeEventArgs args) { if (ColorHasBeenSet && ColorChanged.HasDelegate is false) return; - _selectedHue = Convert.ToDouble(args.Value); + _selectedHue = Convert.ToDouble(args.Value, CultureInfo.InvariantCulture); + _color.Update(_selectedHue, _selectedSaturation, _selectedValue, _color.A); var colorValue = _colorType == BitInternalColorType.Hex ? _color.Hex : _color.Rgb; @@ -199,7 +216,8 @@ private async Task HandleOnAlphaInput(ChangeEventArgs args) { if (AlphaHasBeenSet && AlphaChanged.HasDelegate is false) return; - _color.A = Convert.ToDouble(args.Value); + _color.A = Convert.ToDouble(args.Value, CultureInfo.InvariantCulture); + var colorValue = _colorType == BitInternalColorType.Hex ? _color.Hex : _color.Rgb; await ColorChanged.InvokeAsync(colorValue); @@ -210,20 +228,20 @@ private async Task HandleOnAlphaInput(ChangeEventArgs args) private async Task HandleOnSaturationPickerPointerDown(MouseEventArgs e) { _saturationPickerPointerDown = true; + await UpdateColor(e); } private string GetRootElAriaLabel() { - var ariaLabel = $"Color picker, Red {_color.R} Green {_color.G} Blue {_color.B} "; + var ariaLabel = $"Color picker, Red {_color.R} Green {_color.G} Blue {_color.B}"; + if (ShowAlphaSlider) { - ariaLabel += $"Alpha {_color.A * 100}% selected."; - } - else - { - ariaLabel += "selected."; + ariaLabel += FormattableString.Invariant($" and Alpha {_color.A * 100}%"); } + + ariaLabel += " selected."; return ariaLabel; }