BlazorUI theme improvements ii (#12320)#12369
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
I can’t reliably rebuild the hidden review stack artifact with every provided rangeId exactly once within the constraints of this chat (the <all_range_ids> list is large and must be copied verbatim). Please allow one of the following so I can produce a valid artifact:
✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
|
There was a problem hiding this comment.
Pull request overview
This PR advances the BlazorUI theming system (phase II) by expanding theme tokens (motion/layout/breakpoints), improving accessibility (focus ring tokens + forced-colors), adding runtime system-theme subscription with .NET-side notifications, and updating multiple components/demos to better reflect disabled-state theming.
Changes:
- Add theme change notification pipeline (JS → .NET) and new theme utilities (contrast helpers, density presets, breakpoint defaults, SSR cookie convention, external stylesheet loader).
- Extend theme token surface area (motion + layout + breakpoints) and wire them into CSS variable mapping + Fluent stylesheets (including forced-colors and semantic tokens).
- Update component styling for focus-visible ring consistency and per-role disabled colors; expand demo pages and samples accordingly.
Reviewed changes
Copilot reviewed 111 out of 111 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs | Adds unit tests for WCAG contrast helper. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor | Documents/advertises new advanced theming APIs. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs | Adds disabled-state samples for BitLink. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor | Shows disabled-state rendering for BitLink. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs | Expands color samples (incl. background/foreground/border roles). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor | Visual demo updates for additional icon color roles. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs | Adds disabled-state samples for BitTag. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor | Shows disabled-state rendering for BitTag. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs | Adds disabled-state samples across colors/variants for BitBadge. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor | Shows disabled-state rendering for BitBadge. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs | Adds disabled-state samples for BitPagination. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor | Shows disabled-state rendering for BitPagination. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs | Adds disabled-state samples for BitTimeline item demo. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor | Shows disabled-state rendering for BitTimeline item demo. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs | Adds disabled-state samples for BitTimeline custom demo. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor | Shows disabled-state rendering for BitTimeline custom demo. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs | Expands SearchBox samples across colors + disabled states. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor | Shows expanded SearchBox color/disabled examples. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs | Adds disabled-state samples for ChoiceGroup (item). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor | Shows disabled-state rendering for ChoiceGroup (item). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs | Adds disabled-state samples for ChoiceGroup (custom). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor | Shows disabled-state rendering for ChoiceGroup (custom). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs | Adds disabled-state samples for Checkbox across roles. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor | Shows disabled-state rendering for Checkbox. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs | Adds disabled-state samples for ToggleButton. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor | Shows disabled-state rendering for ToggleButton. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss | Adds layout helper class for demo arrangement. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs | Adds disabled-state samples for ButtonGroup (items). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs | Adds disabled-state samples for ButtonGroup (custom). |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs | Adds disabled-state samples for Button across roles/variants. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor | Shows disabled-state rendering for Button. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs | Adds disabled-state samples for ActionButton. |
| src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor | Shows disabled-state rendering for ActionButton. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs | Adds .NET theme-change event source. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs | Maps/merges new motion/layout/breakpoint tokens to CSS vars. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs | Adds notifier registration, override clearing, and async disposal. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs | Adds JS-invokable receiver for theme-change notifications. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs | Adds JS interop calls for clear/register/unregister notifier. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs | Adds compact density preset overlay helper. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs | Documents SSR cookie name convention for theme preference. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs | Adds optional WCAG-AA text adjustment when deriving colors. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs | Adds WCAG contrast ratio utilities. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs | Adds event args for theme-change notifications. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs | Adds default breakpoint constants for theme layout. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs | Adds theme motion token container. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs | Adds theme layout token container (dir/density/breakpoints). |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs | Adds breakpoint token container. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs | Extends theme model with Motion and Layout. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs | Adds .NET helper to attach/detach external theme stylesheets. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs | Adds JS interop calls for external theme link manipulation. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs | Adds sample accent color presets for branding. |
| src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts | Adds OS theme subscription + .NET notifications + overrides clearing + external theme loader JS. |
| src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss | Adds SCSS vars for disabled/focus tokens and focus-ring shape/shadow tokens. |
| src/BlazorUI/Bit.BlazorUI/Styles/functions.scss | Adds focus ring mixins and imports theme variables. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss | Defines focus-ring CSS variables and focus shadow token. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss | Adds semantic token aliases. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss | Adds motion tokens + reduced-motion overrides. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss | Adds forced-colors + prefers-contrast overrides. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss | Imports new Fluent token files. |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss | Imports new Fluent token files (light). |
| src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss | Imports new Fluent token files (dark). |
| src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss | Switches to importing functions (which imports theme variables) and adds focus utilities. |
| src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs | Registers new theming services in DI. |
| src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss | Adds focus ring + role-based disabled colors. |
| src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss | Adds role-based disabled colors and fixes border-role mapping. |
| src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss | Adds role-based disabled colors across variants. |
| src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss | Adds role-based disabled colors across variants. |
| src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss | Adds focus ring + role-based disabled colors. |
| src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss | Adds role-based disabled colors. |
| src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss | Adds role-based disabled colors. |
| src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss | Adds focus ring styling. |
| src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss | Adds focus ring styling. |
| src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss | Adds role-based disabled colors. |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss | Adds focus ring styling. |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss | Refactors focus visuals to shared focus-ring mixins (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss | Refactors focus visuals to shared focus-ring/underline mixins (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss | Refactors focus visuals to shared focus-ring mixin (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss | Adds consistent thumb focus ring styling. |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss | Adds focus-visible ring styling (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss | Refactors focus visuals to shared focus-ring mixin (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss | Refactors focus visuals to shared focus-ring mixin (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss | Refactors focus visuals to shared focus-ring/underline mixins (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss | Refactors focus visuals to shared focus-ring/underline mixins (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss | Refactors focus visuals to shared focus-ring/underline mixins (+ error focus). |
| src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss | Refactors underlined focus visuals to shared mixin. |
| src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss | Adds focus ring + role-based disabled colors across variants. |
| src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss | Refactors focus ring + role-based disabled colors. |
There was a problem hiding this comment.
Actionable comments posted: 17
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss (1)
49-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix invalid-state selector mismatch (
.bit-dtrp-icpvs.bit-dtrp-icn).Line 50 targets
.bit-dtrp-icp, but the rest of this component’s icon-container styling uses.bit-dtrp-icn(including Line 54). This can break invalid border-color styling.🔧 Proposed fix
- .bit-dtrp-icp { + .bit-dtrp-icn { border-color: $clr-err; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss` around lines 49 - 56, The selector for the invalid state uses the wrong class name: replace the `.bit-dtrp-icp` reference with `.bit-dtrp-icn` so the invalid border-color rule targets the actual icon container used elsewhere; update the rule inside the `&.bit-inv` block (the same block that contains `&.bit-dtrp-foc .bit-dtrp-icn`) so `.bit-dtrp-icn` receives `border-color: $clr-err` consistently with the rest of the DateRangePicker styling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss`:
- Around line 29-30: The SCSS inside BitActionButton.scss violates stylelint
rule declaration-empty-line-before because there is no blank line before the
border-radius declaration in the :focus-visible block; open the :focus-visible
block (where `@include` focus-ring(var(--bit-acb-clr-hover)) is used) and insert a
single empty line before the border-radius: $shp-border-radius; declaration so
the sequence has a blank line separating declarations and satisfies the linter.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss`:
- Line 10: The CSS custom properties use Sass interpolation syntax (e.g.
--bit-chb-ico-clr: #{var(--bit-chb-clr-txt-sec)};) which trips stylelint;
replace all occurrences of "#{var(...)}" with plain "var(...)" for the checkbox
variables (start with --bit-chb-ico-clr and the group referenced in lines 42-53)
so each assignment reads like --bit-chb-ico-clr: var(--bit-chb-clr-txt-sec); and
similarly for the other custom properties to satisfy
custom-property-no-missing-var-function.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss`:
- Around line 21-22: The two invalid comment tokens in BitSlider.scss (the empty
comment "/**/" and the "/*webkit*/" token) break stylelint; replace them with
valid, non-empty comment syntax or remove them entirely—e.g., delete the empty
"/**/" and change "/*webkit*/" to a proper spaced comment like "/* webkit */" or
add the intended vendor-prefixed rule (e.g., "-webkit-..." with a proper
comment), ensuring no empty comments remain so stylelint passes.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss`:
- Around line 27-30: The stylelint violation is caused by missing blank lines
before declaration blocks; update the SCSS so there is an empty line before the
declarations in the selectors &.bit-tgi-fcs .bit-tgi-cnt and the other block
around lines 50-51 (the second selector that triggers the same rule), i.e.,
insert a single blank line immediately before the first property/declaration
inside those selector blocks so they satisfy declaration-empty-line-before.
In `@src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss`:
- Line 1: In src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss the import statement
`@import` "functions.scss"; violates scss/load-partial-extension; remove the .scss
extension so the import reads `@import` "functions"; to reference the partial
correctly and satisfy the stylelint rule.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss`:
- Around line 13-17: In bit.blazorui.fluent-dark.scss the three `@import` lines
reference partials with the .scss extension ("motion.fluent.scss",
"forced-colors.fluent.scss", "semantic-tokens.fluent.scss"); remove the ".scss"
extension from each import so they become `@import` "motion.fluent", `@import`
"forced-colors.fluent", and `@import` "semantic-tokens.fluent" to satisfy the
scss/load-partial-extension rule and avoid stylelint failures.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss`:
- Around line 13-17: Imports in bit.blazorui.fluent-light.scss include the .scss
extension which violates scss/load-partial-extension; update the three `@import`
statements referencing "motion.fluent.scss", "forced-colors.fluent.scss", and
"semantic-tokens.fluent.scss" to omit the .scss extension (e.g. `@import`
"motion.fluent"; `@import` "forced-colors.fluent"; `@import`
"semantic-tokens.fluent";) so they load as SCSS partials and satisfy stylelint.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss`:
- Around line 17-21: The three `@import` statements referencing partials include
the .scss extension which violates scss/load-partial-extension; update the
imports in bit.blazorui.fluent.scss by removing the “.scss” suffix from
"motion.fluent.scss", "forced-colors.fluent.scss", and
"semantic-tokens.fluent.scss" so they become `@import` "motion.fluent", `@import`
"forced-colors.fluent", and `@import` "semantic-tokens.fluent" respectively.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss`:
- Around line 214-218: Add the required blank lines before the comment blocks
around the "req" and "focus (a11y)" comments to satisfy the
scss/double-slash-comment-empty-line-before rule: insert an empty line
immediately before the "//req" comment (the section defining --bit-clr-req) and
before the "//focus (a11y) — color of the focus indicator per role." comment so
the comment blocks preceding the --bit-clr-req variable and the focus
explanation are separated by a blank line.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss`:
- Around line 216-220: The two single-line comments before the variable
declaration violate scss/double-slash-comment-empty-line-before; insert one
blank line immediately above each comment marker (//req and //focus) so there is
an empty line before those comments, keeping the existing comment text and the
--bit-clr-req variable declaration unchanged.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss`:
- Line 24: Add a single blank line above the comment "// Focus must remain
visible in High Contrast — use system Highlight color and a single solid ring."
inside the forced-colors Fluent SCSS block in forced-colors.fluent.scss so it
satisfies the scss/double-slash-comment-empty-line-before rule; locate the
comment text and insert one empty line immediately before it.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss`:
- Around line 19-24: Add a blank line immediately before the comment block that
begins with "//focus ring (a11y) — width is the visible thickness, offset is the
gap between the element and the ring." so the double-slash comment has an empty
line above it (fixes scss/double-slash-comment-empty-line-before); keep the rest
of the block intact including the variable declarations
(--bit-shp-focus-ring-width, --bit-shp-focus-ring-offset, --bit-shd-focus-ring)
and surrounding comments.
In `@src/BlazorUI/Bit.BlazorUI/Styles/functions.scss`:
- Around line 44-49: The focus-ring mixin currently hardcodes a two-layer
box-shadow which ignores the global forced-colors override; update the mixin
(focus-ring) to use the global focus shadow token (CSS variable
--bit-shd-focus-ring) instead of the literal two-layer value so forced-colors
can override it, providing the existing composed value as a fallback (construct
the var(...) with a fallback that uses the current #{$offset},
#{$clr-bg-pri-focus} and #{$color} composition) and keep outline: none
unchanged.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts`:
- Around line 183-185: BitTheme currently registers BitTheme._onSchemeChange
with both addEventListener and the legacy addListener on
BitTheme._schemeMediaQuery which can cause duplicate callbacks; change the
registration to feature-detect and call only one API (use addEventListener if
present, otherwise fall back to addListener) when attaching the handler, and
mirror that logic for removal (use removeEventListener if available, otherwise
removeListener) so BitTheme._schemeMediaQuery and BitTheme._onSchemeChange are
only registered once.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs`:
- Around line 30-36: The current logic in BitThemeColorDerivation.cs (inside the
block that checks adjustTextForWcagAa and variants.Main/Text) simply toggles
variants.Text to black or white based on whether it equals "`#000000`", which can
still fail WCAG on dark backgrounds; instead compute contrast ratios for both
candidate colors ("`#000000`" and "`#FFFFFF`") against variants.Main using
BitThemeColorContrast.GetContrastRatio and choose the candidate with the higher
ratio (and assign it to variants.Text), optionally verifying the chosen color
satisfies BitThemeColorContrast.MeetsWcagAaNormalText and falling back to the
better of the two if only one meets the threshold.
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs`:
- Around line 11-13: Replace the loose threshold assertion for black/white
contrast with a deterministic equality check: call
BitThemeColorContrast.GetContrastRatio("`#000000`", "`#FFFFFF`"), assert the
returned ratio is approximately 21.0 within a small tolerance (e.g., 0.01), and
then use BitThemeColorContrast.MeetsWcagAaNormalText(ratio) to assert
compliance; this makes the test deterministic while still verifying the
MeetsWcagAaNormalText behavior.
---
Outside diff comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss`:
- Around line 49-56: The selector for the invalid state uses the wrong class
name: replace the `.bit-dtrp-icp` reference with `.bit-dtrp-icn` so the invalid
border-color rule targets the actual icon container used elsewhere; update the
rule inside the `&.bit-inv` block (the same block that contains `&.bit-dtrp-foc
.bit-dtrp-icn`) so `.bit-dtrp-icn` receives `border-color: $clr-err`
consistently with the rest of the DateRangePicker styling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: a88c7bf4-5e35-4d3e-acc1-ec9b20c444db
📒 Files selected for processing (111)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 114 out of 114 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts:219
invokeMethodAsyncis fired without handling failures. In Blazor Server (or after a circuit disconnect), the stored .NET reference can become invalid and this will surface as an unhandled promise rejection in the browser console on theme changes (including OS-driven changes). Consider wrappinginvokeMethodAsyncwith a.catch(() => { ... })(and possibly clearing_dotnetNotifier) to avoid noisy errors and improve resilience.
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs (2)
16-18: ⚡ Quick winAdd parameter validation for linkElementId and href.
The method accepts string parameters but doesn't validate them. Adding null/empty checks would provide better error messages and prevent unexpected JS errors. The XML documentation already warns about trusted URLs, so validation here reinforces that guidance.
🛡️ Suggested validation
public ValueTask AttachStylesheetAsync(string linkElementId, string href) { + if (string.IsNullOrWhiteSpace(linkElementId)) + throw new ArgumentException("Link element ID cannot be null or empty.", nameof(linkElementId)); + if (string.IsNullOrWhiteSpace(href)) + throw new ArgumentException("Href cannot be null or empty.", nameof(href)); + return _js.BitExternalThemeAttach(linkElementId, href); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs` around lines 16 - 18, AttachStylesheetAsync currently forwards linkElementId and href to _js.BitExternalThemeAttach without validation; add input checks at the start of BitExternalThemeLoader.AttachStylesheetAsync to throw ArgumentNullException when linkElementId or href is null and ArgumentException (or ArgumentException with nameof()) when either is empty or whitespace, so callers get clear .NET exceptions instead of JS errors, then return the existing _js.BitExternalThemeAttach(linkElementId, href) as before.
21-23: ⚡ Quick winAdd parameter validation for linkElementId.
🛡️ Suggested validation
public ValueTask DetachStylesheetAsync(string linkElementId) { + if (string.IsNullOrWhiteSpace(linkElementId)) + throw new ArgumentException("Link element ID cannot be null or empty.", nameof(linkElementId)); + return _js.BitExternalThemeDetach(linkElementId); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs` around lines 21 - 23, DetachStylesheetAsync currently forwards linkElementId to _js.BitExternalThemeDetach without validation; add parameter validation in DetachStylesheetAsync to throw ArgumentNullException or ArgumentException when linkElementId is null, empty, or whitespace before calling _js.BitExternalThemeDetach, so callers receive a clear exception instead of passing invalid input into the JS interop call.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss`:
- Around line 100-102: The .bit-drp-nbd rule currently removes the focus ring in
the &:focus selector which eliminates a visible keyboard focus cue; update the
.bit-drp-nbd &:focus block to provide a clear, accessible focus treatment
instead of box-shadow: none (for example restore a subtle visible outline or a
2px focus ring using theme focus color and sufficient contrast), ensuring the
selector is `.bit-drp-nbd` and the modified state is `&:focus`, and keep the
styling keyboard-only-friendly (non-invasive) and high-contrast for
accessibility.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss`:
- Around line 22-36: Replace the hardcoded thumb focus box-shadow used in the
input:focus-visible::-webkit-slider-thumb / input:focus::-webkit-slider-thumb
and input:focus-visible::-moz-range-thumb / input:focus::-moz-range-thumb rules
with the global focus-ring shadow token so forced-colors/global theme overrides
apply; specifically remove the manual box-shadow construction and reference the
CSS custom property (e.g. --bit-shd-focus-ring or the project's focus-ring
token) for the thumb focus shadow, preserving the border-color change to
$clr-pri-focus and keeping existing selectors intact.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss`:
- Line 231: The border-focus token --bit-clr-brd-pri-focus is incorrectly
aliased to the primary role --bit-clr-pri; update the alias so the focus token
references the border role instead by changing --bit-clr-brd-pri-focus to use
var(--bit-clr-brd-pri) (so components using border-role focus get the correct
border color). Ensure you update the declaration of --bit-clr-brd-pri-focus in
colors.fluent-dark.scss accordingly.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts`:
- Around line 165-170: The shouldFollowSystem() logic allows an explicitly
persisted theme to be overridden by the presence of the bit-theme-system
attribute; change the checks so a persisted explicit theme blocks
system-following: in BitTheme.shouldFollowSystem() first return false if
BitTheme._persist && BitTheme.getPersisted() !== BitTheme.SYSTEM_THEME (i.e., an
explicit persisted theme exists), then keep the existing checks for
BitTheme._stopFollowingSystem and
document.documentElement.hasAttribute('bit-theme-system'); ensure you still
return true only when persisted value equals BitTheme.SYSTEM_THEME or the
attribute is set and no explicit persisted theme prevents it.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs`:
- Around line 8-12: The BitThemeChangedEventArgs constructor currently assigns
possibly-null parameters to non-nullable properties NewTheme and OldTheme; add
input guards in the BitThemeChangedEventArgs constructor to validate newTheme
and oldTheme and throw ArgumentNullException (or ArgumentException) for null
values before assigning to the NewTheme and OldTheme properties so the
non-nullable contract is preserved.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs`:
- Around line 30-49: The code currently overwrites variants.Text during the WCAG
adjustment even when the caller explicitly provided a non-null text color;
change the logic so adjustments only happen for auto-suggested text (i.e., when
variants.Text was null/unspecified). Concretely, capture the original
variants.Text before the if (adjustTextForWcagAa ...) block (or check at the top
of that block) and only run the contrast calculations/assignments that set
variants.Text when the original variants.Text is null; leave variants.Text
untouched if it was non-null. This touches the adjustTextForWcagAa check and the
assignments to variants.Text (and still uses
BitThemeColorContrast.GetContrastRatio/MeetsWcagAaNormalText with
variants.Main).
---
Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs`:
- Around line 16-18: AttachStylesheetAsync currently forwards linkElementId and
href to _js.BitExternalThemeAttach without validation; add input checks at the
start of BitExternalThemeLoader.AttachStylesheetAsync to throw
ArgumentNullException when linkElementId or href is null and ArgumentException
(or ArgumentException with nameof()) when either is empty or whitespace, so
callers get clear .NET exceptions instead of JS errors, then return the existing
_js.BitExternalThemeAttach(linkElementId, href) as before.
- Around line 21-23: DetachStylesheetAsync currently forwards linkElementId to
_js.BitExternalThemeDetach without validation; add parameter validation in
DetachStylesheetAsync to throw ArgumentNullException or ArgumentException when
linkElementId is null, empty, or whitespace before calling
_js.BitExternalThemeDetach, so callers receive a clear exception instead of
passing invalid input into the JS interop call.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 2ad50f34-04f2-4426-a620-fe354e18d8ee
📒 Files selected for processing (114)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts (1)
59-75:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPersisting resolved light/dark on init breaks system-follow when
persistis enabled.When
systemmode is active with no stored value,initcurrently resolves to a concrete theme (light/dark) and persists it. That makesshouldFollowSystem()immediately stop following OS changes because persisted value is no longer"system".Proposed fix
- if (BitTheme._initOptions.system) { - theme = BitTheme.isSystemDark() ? BitTheme._darkTheme : BitTheme._lightTheme; - } + if (BitTheme._initOptions.system) { + // Persist intent as "system"; set(...) will still apply resolved light/dark to the attribute. + theme = BitTheme.SYSTEM_THEME; + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts` around lines 59 - 75, The init currently resolves a concrete theme when BitTheme._initOptions.system is true and no persisted value exists, then sets BitTheme._persist and writes that resolved theme which makes BitTheme._stopFollowingSystem true; instead, when system mode is enabled and BitTheme.getPersisted() returns null, do not mark _persist true or overwrite persisted state — call BitTheme.set with the resolved theme only for initial display but avoid toggling BitTheme._persist or writing a persisted value (so leave BitTheme._stopFollowingSystem unchanged and keep SYSTEM_THEME as the effective persisted indicator until the user explicitly picks a theme).
🧹 Nitpick comments (1)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs (1)
528-533: ⚡ Quick winMake the disabled primary sample explicit.
Line 528 currently relies on default color resolution. For role-color coverage, set primary explicitly so this sample won’t drift if defaults change.
Proposed tweak
-<BitChoiceGroup IsEnabled="false" Label="Primary (default)" DefaultValue="@("A")" TItem="BitChoiceGroupOption<string>" TValue="string" Horizontal> +<BitChoiceGroup IsEnabled="false" Color="BitColor.Primary" Label="Primary" DefaultValue="@("A")" TItem="BitChoiceGroupOption<string>" TValue="string" Horizontal>🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs` around lines 528 - 533, The sample BitChoiceGroup is relying on implicit/default color resolution; update the BitChoiceGroup markup (the component named BitChoiceGroup in this sample) to explicitly set the primary color by adding a Color="Primary" attribute (so the disabled primary sample remains explicit) while keeping IsEnabled="false" and DefaultValue="@("A")" and the existing BitChoiceGroupOption children unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss`:
- Around line 363-366: The .bit-srb-cnt rule is removing box-shadow
unconditionally which suppresses the focus-ring; update the CSS so the no-border
variant does not clear box-shadow on focus (or focus-visible) — e.g., remove the
global "box-shadow: none" from .bit-srb-cnt and instead only neutralize
box-shadow for non-focused states, ensuring the existing focus-ring mixin (used
for :focus / :focus-visible) can still apply; locate the .bit-srb-cnt selector
and adjust its declarations to preserve the focus state styling.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss`:
- Around line 25-26: Add a blank line immediately before the inline double-slash
comment that begins "Reference the global focus-ring shadow token..." in
BitSlider.scss so it satisfies the Stylelint rule
scss/double-slash-comment-empty-line-before; ensure you keep the same
indentation and do not alter the comment text or surrounding rules/selectors in
the BitSlider.scss file.
In `@src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss`:
- Around line 12-13: Replace bare uses of the CSS variable --bit-nbr-clr-dis
with a fallback value so disabled text won't inherit unpredictably; update
occurrences of color: var(--bit-nbr-clr-dis) in BitNavBar.scss to something like
color: var(--bit-nbr-clr-dis, var(--bit-nbr-clr, currentColor)) or a concrete
fallback (e.g., rgba(...) ) so the disabled color resolves even when the color
class is missing, and apply the same change to the other occurrence of
var(--bit-nbr-clr-dis).
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss`:
- Line 233: Replace the incorrect alias mapping so the border-focus token uses
the border role token instead of the primary palette: update the declaration of
--bit-clr-brd-pri-focus (currently var(--bit-clr-pri)) to reference the border
role token (e.g., var(--bit-clr-brd)) so border-specific focus styling can be
customized independently of --bit-clr-pri.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs`:
- Around line 187-189: Update the disabled "Primary" sample to explicitly set
the color: for the three BitCheckbox usages (the elements with IsEnabled,
Label="Primary", and variations Indeterminate/Value) add
Color="BitColor.Primary" so the disabled color triplet no longer relies on the
default and matches the other color-role samples; target the BitCheckbox
components and the Color property (use BitColor.Primary).
---
Outside diff comments:
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts`:
- Around line 59-75: The init currently resolves a concrete theme when
BitTheme._initOptions.system is true and no persisted value exists, then sets
BitTheme._persist and writes that resolved theme which makes
BitTheme._stopFollowingSystem true; instead, when system mode is enabled and
BitTheme.getPersisted() returns null, do not mark _persist true or overwrite
persisted state — call BitTheme.set with the resolved theme only for initial
display but avoid toggling BitTheme._persist or writing a persisted value (so
leave BitTheme._stopFollowingSystem unchanged and keep SYSTEM_THEME as the
effective persisted indicator until the user explicitly picks a theme).
---
Nitpick comments:
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs`:
- Around line 528-533: The sample BitChoiceGroup is relying on implicit/default
color resolution; update the BitChoiceGroup markup (the component named
BitChoiceGroup in this sample) to explicitly set the primary color by adding a
Color="Primary" attribute (so the disabled primary sample remains explicit)
while keeping IsEnabled="false" and DefaultValue="@("A")" and the existing
BitChoiceGroupOption children unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: adf23b9c-ffbd-4cf6-b580-cf1476b6b7f2
📒 Files selected for processing (114)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss`:
- Around line 322-373: Disabled badges still use the fixed $clr-fg-dis value
instead of the new per-role token; update the badge disabled state (the selector
that sets the disabled text color for .bit-bdg / disabled state) to use the
role-aware CSS variable --bit-bdg-clr-dis-text (e.g., color:
var(--bit-bdg-clr-dis-text)) instead of the hardcoded $clr-fg-dis so each
.bit-bdg-*-role (.bit-bdg-pri, .bit-bdg-sec, etc.) applies its own disabled text
color.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor`:
- Around line 633-653: The three BitPivot instances that set
Color="BitColor.Primary", Color="BitColor.Success" and Color="BitColor.Error"
have BitPivotItem HeaderText values that imply per-item role coloring (e.g.,
"Primary", "Secondary", "Info", "Success", "SevereWarning", "Error") — change
those HeaderText strings in the corresponding BitPivotItem elements to neutral,
non-role labels (for example "File", "Shared", "Recent" or "Tab 1/Tab 2/Tab 3")
so the examples demonstrate a pivot with a colored header rather than implying
per-item role semantics; update each BitPivotItem inside the BitPivot components
referenced above accordingly.
In `@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs`:
- Line 18: The probe render is only checking Theme but can still NRE on nested
properties; update the render in ThemeProbeConsumer so the attribute uses safe
navigation for nested theme fields (e.g., reference Theme?.Color?.Primary?.Main
instead of Theme?.Color.Primary.Main) and fall back to "(none)" when any nested
value is null; locate the usage in the builder.AddAttribute call and apply the
same pattern to any other nested Theme property accesses in the render path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: f3616ba2-d37d-4a00-a01d-ac273a4578eb
📒 Files selected for processing (129)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Bit.BlazorUI.Tests.csprojsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperKeysetTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/bit-theme-css-keys.golden.txt
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts (1)
42-56:⚠️ Potential issue | 🟠 Major | ⚡ Quick winHandle non-literal dark theme names in
onChange.The
newTheme === 'dark'check misses names likefluent-dark(and custom dark names), so the demo can apply light-mode classes/meta color while a dark theme is active.Suggested fix
BitBlazorUI.Theme.init({ system: true, persist: true, onChange: (newTheme: string, oldTheme: string) => { - if (newTheme === 'dark') { + const isDark = newTheme?.toLowerCase().includes('dark') === true; + if (isDark) { document.body.classList.add('bit-blazorui-dark-theme'); document.body.classList.remove('bit-blazorui-light-theme'); document.querySelector("meta[name=theme-color]")?.setAttribute('content', '`#0d1117`'); } else { document.body.classList.add('bit-blazorui-light-theme');🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts` around lines 42 - 56, The onChange handler in BitBlazorUI.Theme.init currently only treats the literal 'dark' as dark; update the condition in the onChange callback (the function with parameters newTheme and oldTheme) to detect dark themes more broadly (e.g., treat as dark if newTheme equals 'dark' or if newTheme contains 'dark' or endsWith '-dark' using a case-insensitive check). Use that boolean to decide when to add/remove 'bit-blazorui-dark-theme' vs 'bit-blazorui-light-theme' and to set the meta[name=theme-color] content accordingly.
♻️ Duplicate comments (2)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss (1)
20-24:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a blank line before the disabled-block comment.
Line [22] still violates
scss/double-slash-comment-empty-line-before, which can fail lint checks.Proposed fix
&.bit-dis { color: var(--bit-btg-clr-dis-text); border-color: var(--bit-btg-clr-dis); + // Resolve through the per-variant `*-dis` tokens so outline/text variants keep transparent // backgrounds and only filled variants render the colored disabled tint. --bit-btg-itm-clr-bg: var(--bit-btg-itm-clr-bg-dis);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss` around lines 20 - 24, The SCSS linter rule scss/double-slash-comment-empty-line-before is violated by the inline comment preceding the disabled-block variable; insert a single blank line immediately before the comment line starting with "// Resolve through the per-variant `*-dis` tokens..." so there is an empty line between the previous property (border-color: var(--bit-btg-clr-dis);) and that comment, ensuring the disabled-block section (affecting --bit-btg-itm-clr-bg) passes linting.src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs (1)
1160-1174:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winKeep
example11RazorCodetab labels aligned with the actual demo markup.Line 1160-Line 1174 still implies per-item role coloring, while the
.razordemo now uses neutral tab labels. This creates a misleading code snippet in docs.💡 Suggested fix
<BitPivot HeaderType=""BitPivotHeaderType.Tab"" Color=""BitColor.Primary""> - <BitPivotItem HeaderText=""Primary""><div>Pivot `#1`: Primary</div></BitPivotItem> - <BitPivotItem HeaderText=""Secondary""><div>Pivot `#2`: Secondary</div></BitPivotItem> - <BitPivotItem HeaderText=""Tertiary""><div>Pivot `#3`: Tertiary</div></BitPivotItem> + <BitPivotItem HeaderText=""File""><div>Pivot `#1`: File</div></BitPivotItem> + <BitPivotItem HeaderText=""Shared""><div>Pivot `#2`: Shared</div></BitPivotItem> + <BitPivotItem HeaderText=""Recent""><div>Pivot `#3`: Recent</div></BitPivotItem> </BitPivot> <BitPivot HeaderType=""BitPivotHeaderType.Tab"" Color=""BitColor.Success""> - <BitPivotItem HeaderText=""Info""><div>Pivot `#1`: Info</div></BitPivotItem> - <BitPivotItem HeaderText=""Success""><div>Pivot `#2`: Success</div></BitPivotItem> - <BitPivotItem HeaderText=""Warning""><div>Pivot `#3`: Warning</div></BitPivotItem> + <BitPivotItem HeaderText=""File""><div>Pivot `#1`: File</div></BitPivotItem> + <BitPivotItem HeaderText=""Shared""><div>Pivot `#2`: Shared</div></BitPivotItem> + <BitPivotItem HeaderText=""Recent""><div>Pivot `#3`: Recent</div></BitPivotItem> </BitPivot> <BitPivot HeaderType=""BitPivotHeaderType.Tab"" Color=""BitColor.Error""> - <BitPivotItem HeaderText=""SevereWarning""><div>Pivot `#1`: SevereWarning</div></BitPivotItem> - <BitPivotItem HeaderText=""Error""><div>Pivot `#2`: Error</div></BitPivotItem> - <BitPivotItem HeaderText=""Info""><div>Pivot `#3`: Info</div></BitPivotItem> + <BitPivotItem HeaderText=""File""><div>Pivot `#1`: File</div></BitPivotItem> + <BitPivotItem HeaderText=""Shared""><div>Pivot `#2`: Shared</div></BitPivotItem> + <BitPivotItem HeaderText=""Recent""><div>Pivot `#3`: Recent</div></BitPivotItem> </BitPivot>";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs` around lines 1160 - 1174, The example11RazorCode snippet is out of sync with the actual .razor demo: it shows per-item role-colored tab labels (BitColor.Info/Success/Error and labels like "Primary"/"Success") while the live demo uses neutral tab labels; update the example11RazorCode content so the BitPivot/BitPivotItem headers match the demo (use neutral, consistent labels for each BitPivot instance and remove role-specific label wording and coloring references in the snippet) so the displayed code matches the rendered .razor markup.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss`:
- Line 1: The import in BitGrid.scss currently includes the .scss extension
which triggers the scss/load-partial-extension lint rule; update the import
statement that references "../../../Styles/functions.scss" to remove the ".scss"
suffix so it imports "../../../Styles/functions" (keep the relative path and
filename but drop the extension) to satisfy stylelint.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs`:
- Around line 68-85: LooksLikeDangerousRelativeScheme currently misses
scheme-relative URLs like "//cdn.example.com/..." which should be rejected;
update LooksLikeDangerousRelativeScheme to also detect and return true for
trimmed strings starting with "//" (in addition to the existing "javascript:",
"data:", and "vbscript:" checks) so that href values with scheme-relative
prefixes are blocked during validation.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs`:
- Around line 42-46: The current WCAG branching calls
BitThemeColorContrast.GetContrastRatio when variants.Main can be non-null but
whitespace, which causes exceptions; update the if-condition around
adjustTextForWcagAa/textWasNull to also require
!string.IsNullOrWhiteSpace(variants.Main) (and optionally
!string.IsNullOrWhiteSpace(variants.Text) if used) before calling
BitThemeColorContrast.GetContrastRatio and
BitThemeColorContrast.MeetsWcagAaNormalText so the code only computes contrast
for valid color strings and avoids exception-driven control flow.
---
Outside diff comments:
In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts`:
- Around line 42-56: The onChange handler in BitBlazorUI.Theme.init currently
only treats the literal 'dark' as dark; update the condition in the onChange
callback (the function with parameters newTheme and oldTheme) to detect dark
themes more broadly (e.g., treat as dark if newTheme equals 'dark' or if
newTheme contains 'dark' or endsWith '-dark' using a case-insensitive check).
Use that boolean to decide when to add/remove 'bit-blazorui-dark-theme' vs
'bit-blazorui-light-theme' and to set the meta[name=theme-color] content
accordingly.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss`:
- Around line 20-24: The SCSS linter rule
scss/double-slash-comment-empty-line-before is violated by the inline comment
preceding the disabled-block variable; insert a single blank line immediately
before the comment line starting with "// Resolve through the per-variant
`*-dis` tokens..." so there is an empty line between the previous property
(border-color: var(--bit-btg-clr-dis);) and that comment, ensuring the
disabled-block section (affecting --bit-btg-itm-clr-bg) passes linting.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs`:
- Around line 1160-1174: The example11RazorCode snippet is out of sync with the
actual .razor demo: it shows per-item role-colored tab labels
(BitColor.Info/Success/Error and labels like "Primary"/"Success") while the live
demo uses neutral tab labels; update the example11RazorCode content so the
BitPivot/BitPivotItem headers match the demo (use neutral, consistent labels for
each BitPivot instance and remove role-specific label wording and coloring
references in the snippet) so the displayed code matches the rendered .razor
markup.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 29d07da8-b992-4d51-a76e-66c264572990
📒 Files selected for processing (130)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/media-queries.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.tssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperKeysetTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss (1)
132-160:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent stacked focus indicators on underlined pickers.
When
.bit-ctp-und.bit-ctp-focis active, both the generic focused selector (lines 133–135) and the underline-focused selector (lines 158–160) match.bit-ctp-icn, causing bothfocus-ringandfocus-underline-ringto apply. Exclude the underlined variant from the generic focus rule to ensure only the underline ring renders.🔧 Proposed fix
-.bit-ctp-foc { +.bit-ctp-foc:not(.bit-ctp-und) { .bit-ctp-icn { `@include` focus-ring; } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss` around lines 132 - 160, The generic focus rule .bit-ctp-foc .bit-ctp-icn must be excluded when the component is the underlined variant to avoid applying both focus-ring and focus-underline-ring; change the selector so the focus-ring only applies when .bit-ctp-foc does not also have .bit-ctp-und (e.g., use .bit-ctp-foc:not(.bit-ctp-und) .bit-ctp-icn) and leave the existing .bit-ctp-und .bit-ctp-foc .bit-ctp-icn rule to apply focus-underline-ring.
♻️ Duplicate comments (5)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss (1)
19-26:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd blank line before comment to satisfy linter.
Line 22 needs an empty line before the
//comment to comply withscss/double-slash-comment-empty-line-before.Proposed fix
&.bit-dis { color: var(--bit-btg-clr-dis-text); border-color: var(--bit-btg-clr-dis); + // Resolve through the per-variant `*-dis` tokens so outline/text variants keep transparent // backgrounds and only filled variants render the colored disabled tint. --bit-btg-itm-clr-bg: var(--bit-btg-itm-clr-bg-dis);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss` around lines 19 - 26, The SCSS rule for the .bit-dis modifier (selector "&.bit-dis") violates scss/double-slash-comment-empty-line-before because there is no blank line before the inline comment starting with "// Resolve..."; fix it by inserting a single empty line immediately before that comment so the comment is separated from the previous declaration and preserves the existing declarations for --bit-btg-itm-clr-bg and --bit-btg-itm-clr-brd.src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss (2)
54-60:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent stacked focus styles for inverted underlined range picker.
When
.bit-inv.bit-dtrp-und.bit-dtrp-focis active, both selectors (lines 54–56 and 58–60) target.bit-dtrp-icn, applying bothfocus-ring($clr-err-focus)andfocus-underline-ring($clr-err-focus)simultaneously. Exclude the underlined variant from the generic focus rule.🔧 Proposed fix
- &.bit-dtrp-foc .bit-dtrp-icn { + &.bit-dtrp-foc:not(.bit-dtrp-und) .bit-dtrp-icn { `@include` focus-ring($clr-err-focus); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss` around lines 54 - 60, The generic focus rule for .bit-dtrp-foc .bit-dtrp-icn is currently also applying to the underlined variant, causing both focus-ring and focus-underline-ring to stack; change the generic selector to exclude the underlined variant (e.g. target .bit-dtrp-foc:not(.bit-dtrp-und) .bit-dtrp-icn) so only the non-underlined state uses `@include` focus-ring($clr-err-focus) while .bit-dtrp-und.bit-dtrp-foc .bit-dtrp-icn continues to use `@include` focus-underline-ring($clr-err-focus).
173-177:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent overlapping focus styles for underlined range picker.
The generic focused selector at lines 174–176 matches all
.bit-dtrp-focstates, including when combined with.bit-dtrp-und, causing bothfocus-ringandfocus-underline-ring(lines 771–773) to apply. Exclude the underlined variant from the generic rule.🔧 Proposed fix
-.bit-dtrp-foc { +.bit-dtrp-foc:not(.bit-dtrp-und) { .bit-dtrp-icn { `@include` focus-ring; } }Also applies to: 771-773
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss` around lines 173 - 177, The generic focus rule .bit-dtrp-foc .bit-dtrp-icn currently matches underlined pickers too, causing both focus-ring and focus-underline-ring to apply; change the selector to exclude the underlined variant (use .bit-dtrp-foc:not(.bit-dtrp-und) .bit-dtrp-icn) so only non-underlined pickers get `@include` focus-ring, and leave the existing .bit-dtrp-foc.bit-dtrp-und .bit-dtrp-icn rule (the focus-underline-ring at the other location) as the sole source of focus styling for underlined pickers.src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss (1)
54-60:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent overlapping focus styles for inverted underlined DatePicker.
When
.bit-inv.bit-dtp-und.bit-dtp-focis present, both selectors (lines 54–56 and 58–60) match.bit-dtp-icn, applying bothfocus-ring($clr-err-focus)andfocus-underline-ring($clr-err-focus). Exclude.bit-dtp-undfrom the first selector to ensure deterministic behavior and avoid stacked focus visuals.🔧 Proposed fix
- &.bit-dtp-foc .bit-dtp-icn { + &.bit-dtp-foc:not(.bit-dtp-und) .bit-dtp-icn { `@include` focus-ring($clr-err-focus); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss` around lines 54 - 60, The two selectors &.bit-dtp-foc .bit-dtp-icn and &.bit-dtp-und.bit-dtp-foc .bit-dtp-icn both match when .bit-inv.bit-dtp-und.bit-dtp-foc is present, causing both focus-ring and focus-underline-ring to stack; update the first selector (&.bit-dtp-foc .bit-dtp-icn) to explicitly exclude .bit-dtp-und (e.g., make it only match focused DatePicker icons that are NOT underlined) so only one focus style applies, leaving the &.bit-dtp-und.bit-dtp-foc .bit-dtp-icn rule unchanged.src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss (1)
48-54:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winPrevent stacked focus indicators on underlined inverted pickers.
When
.bit-inv.bit-ctp-und.bit-ctp-focis active, both selectors (lines 48–50 and 52–54) target.bit-ctp-icn, applying bothfocus-ringandfocus-underline-ringsimultaneously. Exclude the underlined variant from the first selector so only the underline ring renders.🔧 Proposed fix
- &.bit-ctp-foc .bit-ctp-icn { + &.bit-ctp-foc:not(.bit-ctp-und) .bit-ctp-icn { `@include` focus-ring($clr-err-focus); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss` around lines 48 - 54, The first selector (&.bit-ctp-foc .bit-ctp-icn) is applying the focus-ring even when the underlined variant (.bit-ctp-und.bit-ctp-foc .bit-ctp-icn) should only get the underline ring; update the first rule to exclude the underlined variant so only non-underlined focused pickers get `@include` focus-ring (i.e., change the selector to target focused circular time picker elements that do NOT also have .bit-ctp-und), leaving the existing &.bit-ctp-und.bit-ctp-foc .bit-ctp-icn rule intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss`:
- Around line 173-177: The generic focus rule .bit-dtp-foc currently applies to
underlined DatePicker too, causing both focus-ring and focus-underline-ring to
overlap; change the selector that wraps .bit-dtp-icn to exclude the underlined
variant (use .bit-dtp-foc:not(.bit-dtp-und) or equivalent) so only
non-underlined pickers get `@include` focus-ring, and likewise update the
underlined-specific block (the .bit-dtp-und.bit-dtp-foc rule that uses `@include`
focus-underline-ring) to remain targeted so the underline ring is the only focus
style applied.
---
Outside diff comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss`:
- Around line 132-160: The generic focus rule .bit-ctp-foc .bit-ctp-icn must be
excluded when the component is the underlined variant to avoid applying both
focus-ring and focus-underline-ring; change the selector so the focus-ring only
applies when .bit-ctp-foc does not also have .bit-ctp-und (e.g., use
.bit-ctp-foc:not(.bit-ctp-und) .bit-ctp-icn) and leave the existing .bit-ctp-und
.bit-ctp-foc .bit-ctp-icn rule to apply focus-underline-ring.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss`:
- Around line 19-26: The SCSS rule for the .bit-dis modifier (selector
"&.bit-dis") violates scss/double-slash-comment-empty-line-before because there
is no blank line before the inline comment starting with "// Resolve..."; fix it
by inserting a single empty line immediately before that comment so the comment
is separated from the previous declaration and preserves the existing
declarations for --bit-btg-itm-clr-bg and --bit-btg-itm-clr-brd.
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss`:
- Around line 48-54: The first selector (&.bit-ctp-foc .bit-ctp-icn) is applying
the focus-ring even when the underlined variant (.bit-ctp-und.bit-ctp-foc
.bit-ctp-icn) should only get the underline ring; update the first rule to
exclude the underlined variant so only non-underlined focused pickers get
`@include` focus-ring (i.e., change the selector to target focused circular time
picker elements that do NOT also have .bit-ctp-und), leaving the existing
&.bit-ctp-und.bit-ctp-foc .bit-ctp-icn rule intact.
In `@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss`:
- Around line 54-60: The two selectors &.bit-dtp-foc .bit-dtp-icn and
&.bit-dtp-und.bit-dtp-foc .bit-dtp-icn both match when
.bit-inv.bit-dtp-und.bit-dtp-foc is present, causing both focus-ring and
focus-underline-ring to stack; update the first selector (&.bit-dtp-foc
.bit-dtp-icn) to explicitly exclude .bit-dtp-und (e.g., make it only match
focused DatePicker icons that are NOT underlined) so only one focus style
applies, leaving the &.bit-dtp-und.bit-dtp-foc .bit-dtp-icn rule unchanged.
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss`:
- Around line 54-60: The generic focus rule for .bit-dtrp-foc .bit-dtrp-icn is
currently also applying to the underlined variant, causing both focus-ring and
focus-underline-ring to stack; change the generic selector to exclude the
underlined variant (e.g. target .bit-dtrp-foc:not(.bit-dtrp-und) .bit-dtrp-icn)
so only the non-underlined state uses `@include` focus-ring($clr-err-focus) while
.bit-dtrp-und.bit-dtrp-foc .bit-dtrp-icn continues to use `@include`
focus-underline-ring($clr-err-focus).
- Around line 173-177: The generic focus rule .bit-dtrp-foc .bit-dtrp-icn
currently matches underlined pickers too, causing both focus-ring and
focus-underline-ring to apply; change the selector to exclude the underlined
variant (use .bit-dtrp-foc:not(.bit-dtrp-und) .bit-dtrp-icn) so only
non-underlined pickers get `@include` focus-ring, and leave the existing
.bit-dtrp-foc.bit-dtrp-und .bit-dtrp-icn rule (the focus-underline-ring at the
other location) as the sole source of focus styling for underlined pickers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 98a81a8e-2bd2-4f77-b469-c5912aafcaa8
📒 Files selected for processing (129)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/media-queries.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.tssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
|
@coderabbitai re-review |
|
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss (1)
152-167:⚠️ Potential issue | 🟠 Major | ⚡ Quick winDisabled groups still leave checked items on active colors.
.bit-btg.bit-disnow drives disabled styling through--bit-btg-itm-clr-*, but.bit-btg-chkbypasses those variables and hard-codes the checked border/background from active tokens. A preselected item inside anIsEnabled="false"group will still look enabled.Suggested fix
.bit-btg-chk { color: var(--bit-btg-clr-txt); border-color: var(--bit-btg-clr-dark); background-color: var(--bit-btg-clr-dark); @@ &:active { border-color: var(--bit-btg-clr-dark-active); background-color: var(--bit-btg-clr-dark-active); } } + +.bit-btg.bit-dis .bit-btg-chk { + color: var(--bit-btg-clr-dis-text); + border-color: var(--bit-btg-itm-clr-brd-dis, var(--bit-btg-clr-dis)); + background-color: var(--bit-btg-itm-clr-bg-dis); +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss` around lines 152 - 167, The checked-state styles in .bit-btg-chk currently use the dark tokens and bypass the disabled item tokens, causing preselected buttons to appear enabled; update .bit-btg-chk to use the item-level CSS variables instead (replace var(--bit-btg-clr-txt)/--bit-btg-clr-dark/--bit-btg-clr-dark-hover/--bit-btg-clr-dark-active with var(--bit-btg-itm-clr-txt)/var(--bit-btg-itm-clr-dark)/var(--bit-btg-itm-clr-dark-hover)/var(--bit-btg-itm-clr-dark-active)), and ensure the hover and :active rules follow the same variables so a parent .bit-btg.bit-dis will correctly drive the disabled appearance for preselected items.
♻️ Duplicate comments (4)
src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss (1)
1-1:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove
.scssfrom partial import to satisfy stylelint.Line 1 still violates
scss/load-partial-extension, which can fail CI/style checks.Suggested fix
-@import "../../../Styles/functions.scss"; +@import "../../../Styles/functions";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss` at line 1, The import in BitGrid.scss still includes the .scss extension and violates the scss/load-partial-extension rule; update the import statement that currently references functions.scss so it omits the extension (i.e., import the partial "functions" instead of "functions.scss") to satisfy stylelint and CI.src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss (1)
1-1:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRemove
.scssextension from import.The import still includes the
.scssextension, violating thescss/load-partial-extensionstylelint rule flagged in a previous review.🔧 Suggested fix
-@import "theme-variables.scss"; +@import "theme-variables";🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss` at line 1, The import in bit-css.scss currently includes the .scss extension; update the `@import` statement (the line with "`@import` \"theme-variables.scss\";") to remove the extension so it becomes "`@import` \"theme-variables\";" to satisfy the scss/load-partial-extension rule and ensure stylelint no longer flags the file.src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss (1)
28-31:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix stylelint spacing before border-radius declaration.
An empty line is required before the
border-radiusdeclaration at line 31 to satisfy thedeclaration-empty-line-beforerule.💡 Proposed fix
&:focus-visible { `@include` focus-ring(var(--bit-acb-clr-hover)); + border-radius: $shp-border-radius; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss` around lines 28 - 31, In the &:focus-visible block in BitActionButton.scss (the selector that calls `@include` focus-ring(var(--bit-acb-clr-hover))), add a blank line before the border-radius: $shp-border-radius; declaration so the rule declaration-empty-line-before is satisfied; ensure the spacing is a single empty line and keep the `@include` focus-ring and border-radius statements otherwise unchanged.src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss (1)
19-29:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winFix stylelint spacing before focus ring comment.
An empty line is required before the comment at line 20 to satisfy the
scss/double-slash-comment-empty-line-beforerule.💡 Proposed fix
--bit-shp-brd-width: 0.0625rem; --bit-shp-brd-style: solid; + //focus ring (a11y) — width is the visible thickness, offset is the gap between the element and the ring. --bit-shp-focus-ring-width: 0.125rem; //2px🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss` around lines 19 - 29, Add a blank line before the line with the comment starting "//focus ring (a11y) — width is the visible thickness..." so the SCSS rule scss/double-slash-comment-empty-line-before is satisfied; update the block around the CSS variables like --bit-shp-focus-ring-width and --bit-shp-focus-ring-offset in shapes.fluent.scss by inserting a single empty line immediately above that comment (no other changes).
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs (1)
3-16: 💤 Low valueConsider enhancing XML documentation with usage example.
The documentation mentions merging with a baseline
BitThemebut doesn't show how. Adding a brief code example would help developers understand the intended usage pattern.📝 Documentation enhancement suggestion
/// <summary> /// Pre-built density tweaks; merge with a baseline <see cref="BitTheme"/> from your app. +/// <example> +/// <code> +/// var baseTheme = BitTheme.CreateDefault(); +/// var compactTheme = BitThemeMapper.Merge(baseTheme, BitThemeDensityPresets.CreateCompactOverlay()); +/// </code> +/// </example> /// </summary> public static class BitThemeDensityPresets { - /// <summary>Returns a theme overlay that tightens vertical rhythm via <see cref="BitThemeLayout.DensityScale"/> and spacing scale.</summary> + /// <summary> + /// Returns a theme overlay that tightens vertical rhythm via <see cref="BitThemeLayout.DensityScale"/> (0.9 multiplier) and spacing scale (0.95 multiplier). + /// </summary> public static BitTheme CreateCompactOverlay()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs` around lines 3 - 16, Add an XML <example> to BitThemeDensityPresets (or the CreateCompactOverlay method) that demonstrates the intended usage: instantiate a baseline BitTheme, call BitThemeDensityPresets.CreateCompactOverlay(), and then apply/merge the overlay's Layout.DensityScale and Spacing.ScalingFactor into the baseline BitTheme (showing the assignment/merge step so callers know to copy the overlay properties into their BitTheme). Reference BitTheme, BitThemeDensityPresets.CreateCompactOverlay, Layout.DensityScale, and Spacing.ScalingFactor in the example so maintainers can see the exact properties to merge.src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs (1)
120-150: ⚡ Quick winVerify SemaphoreSlim non-disposal pattern is safe.
The comment on lines 156–159 explains that
_jsNotifierRegistrationLockis intentionally not disposed to avoidObjectDisposedExceptionfor callers that passed the_disposedcheck but haven't yet acquired or released the semaphore. While the reasoning is sound (SemaphoreSlim only holds unmanaged resources ifAvailableWaitHandleis accessed), this leaves anIDisposableresource undisposed when the class implementsIAsyncDisposable.Consider an alternative pattern:
Alternative: dispose the semaphore after final release
public async ValueTask DisposeAsync() { await _jsNotifierRegistrationLock.WaitAsync().ConfigureAwait(false); try { if (_disposed) return; _disposed = true; // ... unregister logic ... } finally { _jsNotifierRegistrationLock.Release(); + // Safe to dispose after Release; callers that check _disposed won't reach WaitAsync. + _jsNotifierRegistrationLock.Dispose(); } }In
EnsureJsNotifierRegisteredAsync:private async ValueTask EnsureJsNotifierRegisteredAsync() { if (_jsNotifierRegistered) return; if (_jsNotifierReceiver is null) return; if (_disposed) return; if (_js.IsRuntimeInvalid()) return; + // Callers that reached here before disposal can safely wait; _disposed guards entry. await _jsNotifierRegistrationLock.WaitAsync().ConfigureAwait(false); // ... }Because
_disposedis checked beforeWaitAsync, andDisposeAsyncsets_disposedbefore releasing and disposing the semaphore, no caller should hitObjectDisposedException.If the current pattern is preferred, document why it's safe (callers check
_disposedbeforeWaitAsync, so disposal after the finalReleasewon't race).Also applies to: 152-195
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs` around lines 120 - 150, The SemaphoreSlim _jsNotifierRegistrationLock is intentionally not disposed which leaks an IDisposable; either dispose it safely in DisposeAsync or explicitly document why leaving it undisposed is safe. Fix by either (A) in DisposeAsync set _disposed = true, ensure any waiting EnsureJsNotifierRegisteredAsync callers are not blocked (release if needed) and then call _jsNotifierRegistrationLock.DisposeAsync()/Dispose to clean it up, referencing _jsNotifierRegistrationLock and DisposeAsync; or (B) add a clear comment adjacent to the _jsNotifierRegistrationLock declaration and above EnsureJsNotifierRegisteredAsync explaining the race reasoning: callers check _disposed before WaitAsync, SemaphoreSlim only allocates unmanaged resources when AvailableWaitHandle is used, and so intentional non-disposal is safe—include references to _disposed, EnsureJsNotifierRegisteredAsync, and _jsNotifierRegistrationLock for future maintainers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs`:
- Around line 36-40: The HasNewTheme and HasOldTheme properties currently use
string.IsNullOrWhiteSpace which treats empty string as "missing" but the API
contract treats null as the unknown/unset sentinel and empty string as a
distinct value; update HasNewTheme to check NewTheme != null and HasOldTheme to
check OldTheme != null so only null is considered unset while empty string
remains a valid value.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs`:
- Around line 16-28: GetContrastRatio currently constructs BitInternalColor from
the input strings which silently falls back to white on invalid hex; before
computing RelativeLuminance, validate the input hex formats
(foregroundHex/backgroundHex) or detect when BitInternalColor resulted in white
despite the original input not representing white and throw ArgumentException;
update GetContrastRatio to perform a pre-parse format check (e.g., regex for
`#RGB/`#RRGGBB or named formats) or compare the original trimmed input to a
non-white sentinel after constructing BitInternalColor and throw with a clear
message instead of returning a misleading ratio; reference GetContrastRatio,
BitInternalColor and RelativeLuminance when making the change.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs`:
- Around line 835-857: The sample string example11RazorCode does not include the
styled wrapper used in the live demo, so the three disabled BitChoiceGroup
examples (PrimaryBackground/SecondaryBackground/TertiaryBackground) render
without the same contrast context; update the example11RazorCode content to wrap
those BitChoiceGroup instances with the same CSS wrapper/markup used on the live
demo (the container that sets the background and contrast) so copied code
reproduces the disabled background styles for BitChoiceGroup components.
---
Outside diff comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss`:
- Around line 152-167: The checked-state styles in .bit-btg-chk currently use
the dark tokens and bypass the disabled item tokens, causing preselected buttons
to appear enabled; update .bit-btg-chk to use the item-level CSS variables
instead (replace
var(--bit-btg-clr-txt)/--bit-btg-clr-dark/--bit-btg-clr-dark-hover/--bit-btg-clr-dark-active
with
var(--bit-btg-itm-clr-txt)/var(--bit-btg-itm-clr-dark)/var(--bit-btg-itm-clr-dark-hover)/var(--bit-btg-itm-clr-dark-active)),
and ensure the hover and :active rules follow the same variables so a parent
.bit-btg.bit-dis will correctly drive the disabled appearance for preselected
items.
---
Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss`:
- Around line 28-31: In the &:focus-visible block in BitActionButton.scss (the
selector that calls `@include` focus-ring(var(--bit-acb-clr-hover))), add a blank
line before the border-radius: $shp-border-radius; declaration so the rule
declaration-empty-line-before is satisfied; ensure the spacing is a single empty
line and keep the `@include` focus-ring and border-radius statements otherwise
unchanged.
In `@src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss`:
- Line 1: The import in BitGrid.scss still includes the .scss extension and
violates the scss/load-partial-extension rule; update the import statement that
currently references functions.scss so it omits the extension (i.e., import the
partial "functions" instead of "functions.scss") to satisfy stylelint and CI.
In `@src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss`:
- Line 1: The import in bit-css.scss currently includes the .scss extension;
update the `@import` statement (the line with "`@import` \"theme-variables.scss\";")
to remove the extension so it becomes "`@import` \"theme-variables\";" to satisfy
the scss/load-partial-extension rule and ensure stylelint no longer flags the
file.
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss`:
- Around line 19-29: Add a blank line before the line with the comment starting
"//focus ring (a11y) — width is the visible thickness..." so the SCSS rule
scss/double-slash-comment-empty-line-before is satisfied; update the block
around the CSS variables like --bit-shp-focus-ring-width and
--bit-shp-focus-ring-offset in shapes.fluent.scss by inserting a single empty
line immediately above that comment (no other changes).
---
Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs`:
- Around line 3-16: Add an XML <example> to BitThemeDensityPresets (or the
CreateCompactOverlay method) that demonstrates the intended usage: instantiate a
baseline BitTheme, call BitThemeDensityPresets.CreateCompactOverlay(), and then
apply/merge the overlay's Layout.DensityScale and Spacing.ScalingFactor into the
baseline BitTheme (showing the assignment/merge step so callers know to copy the
overlay properties into their BitTheme). Reference BitTheme,
BitThemeDensityPresets.CreateCompactOverlay, Layout.DensityScale, and
Spacing.ScalingFactor in the example so maintainers can see the exact properties
to merge.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs`:
- Around line 120-150: The SemaphoreSlim _jsNotifierRegistrationLock is
intentionally not disposed which leaks an IDisposable; either dispose it safely
in DisposeAsync or explicitly document why leaving it undisposed is safe. Fix by
either (A) in DisposeAsync set _disposed = true, ensure any waiting
EnsureJsNotifierRegisteredAsync callers are not blocked (release if needed) and
then call _jsNotifierRegistrationLock.DisposeAsync()/Dispose to clean it up,
referencing _jsNotifierRegistrationLock and DisposeAsync; or (B) add a clear
comment adjacent to the _jsNotifierRegistrationLock declaration and above
EnsureJsNotifierRegisteredAsync explaining the race reasoning: callers check
_disposed before WaitAsync, SemaphoreSlim only allocates unmanaged resources
when AvailableWaitHandle is used, and so intentional non-disposal is
safe—include references to _disposed, EnsureJsNotifierRegisteredAsync, and
_jsNotifierRegistrationLock for future maintainers.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 9e31c8ec-cef2-4f8a-917a-c67616d0864e
📒 Files selected for processing (130)
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scsssrc/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scsssrc/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scsssrc/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scsssrc/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scsssrc/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scsssrc/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scsssrc/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scsssrc/BlazorUI/Bit.BlazorUI/Styles/bit-css.scsssrc/BlazorUI/Bit.BlazorUI/Styles/functions.scsssrc/BlazorUI/Bit.BlazorUI/Styles/media-queries.scsssrc/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scsssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.tssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cssrc/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.tssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scsssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cssrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razorsrc/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.tssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razorsrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cssrc/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
💤 Files with no reviewable changes (1)
- src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
| /// <summary>True when <see cref="NewTheme"/> is non-null and non-whitespace.</summary> | ||
| public bool HasNewTheme => !string.IsNullOrWhiteSpace(NewTheme); | ||
|
|
||
| /// <summary>True when <see cref="OldTheme"/> is non-null and non-whitespace.</summary> | ||
| public bool HasOldTheme => !string.IsNullOrWhiteSpace(OldTheme); |
There was a problem hiding this comment.
Make HasNewTheme/HasOldTheme match the new null-based contract.
The remarks say null is the unknown/unset sentinel and explicitly call out empty string as a value callers may need to distinguish. Using IsNullOrWhiteSpace collapses "" back into “missing”, which reintroduces the ambiguity this API is trying to remove.
Suggested fix
- /// <summary>True when <see cref="NewTheme"/> is non-null and non-whitespace.</summary>
- public bool HasNewTheme => !string.IsNullOrWhiteSpace(NewTheme);
+ /// <summary>True when <see cref="NewTheme"/> is not <see langword="null"/>.</summary>
+ public bool HasNewTheme => NewTheme is not null;
- /// <summary>True when <see cref="OldTheme"/> is non-null and non-whitespace.</summary>
- public bool HasOldTheme => !string.IsNullOrWhiteSpace(OldTheme);
+ /// <summary>True when <see cref="OldTheme"/> is not <see langword="null"/>.</summary>
+ public bool HasOldTheme => OldTheme is not null;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /// <summary>True when <see cref="NewTheme"/> is non-null and non-whitespace.</summary> | |
| public bool HasNewTheme => !string.IsNullOrWhiteSpace(NewTheme); | |
| /// <summary>True when <see cref="OldTheme"/> is non-null and non-whitespace.</summary> | |
| public bool HasOldTheme => !string.IsNullOrWhiteSpace(OldTheme); | |
| /// <summary>True when <see cref="NewTheme"/> is not <see langword="null"/>.</summary> | |
| public bool HasNewTheme => NewTheme is not null; | |
| /// <summary>True when <see cref="OldTheme"/> is not <see langword="null"/>.</summary> | |
| public bool HasOldTheme => OldTheme is not null; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs` around
lines 36 - 40, The HasNewTheme and HasOldTheme properties currently use
string.IsNullOrWhiteSpace which treats empty string as "missing" but the API
contract treats null as the unknown/unset sentinel and empty string as a
distinct value; update HasNewTheme to check NewTheme != null and HasOldTheme to
check OldTheme != null so only null is considered unset while empty string
remains a valid value.
| public static double GetContrastRatio(string foregroundHex, string backgroundHex) | ||
| { | ||
| ArgumentException.ThrowIfNullOrWhiteSpace(foregroundHex); | ||
| ArgumentException.ThrowIfNullOrWhiteSpace(backgroundHex); | ||
|
|
||
| var fg = new BitInternalColor(foregroundHex.Trim()); | ||
| var bg = new BitInternalColor(backgroundHex.Trim()); | ||
| var l1 = RelativeLuminance(fg.R, fg.G, fg.B); | ||
| var l2 = RelativeLuminance(bg.R, bg.G, bg.B); | ||
| var lighter = Math.Max(l1, l2); | ||
| var darker = Math.Min(l1, l2); | ||
| return (lighter + 0.05) / (darker + 0.05); | ||
| } |
There was a problem hiding this comment.
Silent fallback to white on invalid hex can produce misleading ratios.
When BitInternalColor receives an invalid hex string (e.g., "not-a-color"), it silently falls back to white. The XML remarks acknowledge this but don't prevent it. Callers who pass malformed strings will receive a plausible-looking ratio that is completely wrong.
Consider adding hex format validation before parsing, or at minimum throwing when the parsed color is suspiciously white (#FFFFFF / rgb(255,255,255)) when the input was something else.
🛡️ Stricter validation option
public static double GetContrastRatio(string foregroundHex, string backgroundHex)
{
ArgumentException.ThrowIfNullOrWhiteSpace(foregroundHex);
ArgumentException.ThrowIfNullOrWhiteSpace(backgroundHex);
+ var fgTrimmed = foregroundHex.Trim();
+ var bgTrimmed = backgroundHex.Trim();
+ if (!IsValidHexColor(fgTrimmed) || !IsValidHexColor(bgTrimmed))
+ {
+ throw new ArgumentException("Invalid hex color format. Expected `#RGB`, `#RRGGBB`, `#RRGGBBAA`, etc.");
+ }
+
- var fg = new BitInternalColor(foregroundHex.Trim());
- var bg = new BitInternalColor(backgroundHex.Trim());
+ var fg = new BitInternalColor(fgTrimmed);
+ var bg = new BitInternalColor(bgTrimmed);
var l1 = RelativeLuminance(fg.R, fg.G, fg.B);
var l2 = RelativeLuminance(bg.R, bg.G, bg.B);
var lighter = Math.Max(l1, l2);
var darker = Math.Min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
+
+private static bool IsValidHexColor(string hex)
+{
+ if (string.IsNullOrWhiteSpace(hex)) return false;
+ var clean = hex.TrimStart('#');
+ return (clean.Length == 3 || clean.Length == 6 || clean.Length == 8)
+ && clean.All(c => (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'));
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static double GetContrastRatio(string foregroundHex, string backgroundHex) | |
| { | |
| ArgumentException.ThrowIfNullOrWhiteSpace(foregroundHex); | |
| ArgumentException.ThrowIfNullOrWhiteSpace(backgroundHex); | |
| var fg = new BitInternalColor(foregroundHex.Trim()); | |
| var bg = new BitInternalColor(backgroundHex.Trim()); | |
| var l1 = RelativeLuminance(fg.R, fg.G, fg.B); | |
| var l2 = RelativeLuminance(bg.R, bg.G, bg.B); | |
| var lighter = Math.Max(l1, l2); | |
| var darker = Math.Min(l1, l2); | |
| return (lighter + 0.05) / (darker + 0.05); | |
| } | |
| public static double GetContrastRatio(string foregroundHex, string backgroundHex) | |
| { | |
| ArgumentException.ThrowIfNullOrWhiteSpace(foregroundHex); | |
| ArgumentException.ThrowIfNullOrWhiteSpace(backgroundHex); | |
| var fgTrimmed = foregroundHex.Trim(); | |
| var bgTrimmed = backgroundHex.Trim(); | |
| if (!IsValidHexColor(fgTrimmed) || !IsValidHexColor(bgTrimmed)) | |
| { | |
| throw new ArgumentException("Invalid hex color format. Expected `#RGB`, `#RRGGBB`, `#RRGGBBAA`, etc."); | |
| } | |
| var fg = new BitInternalColor(fgTrimmed); | |
| var bg = new BitInternalColor(bgTrimmed); | |
| var l1 = RelativeLuminance(fg.R, fg.G, fg.B); | |
| var l2 = RelativeLuminance(bg.R, bg.G, bg.B); | |
| var lighter = Math.Max(l1, l2); | |
| var darker = Math.Min(l1, l2); | |
| return (lighter + 0.05) / (darker + 0.05); | |
| } | |
| private static bool IsValidHexColor(string hex) | |
| { | |
| if (string.IsNullOrWhiteSpace(hex)) return false; | |
| var clean = hex.TrimStart('#'); | |
| return (clean.Length == 3 || clean.Length == 6 || clean.Length == 8) | |
| && clean.All(c => (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs` around lines
16 - 28, GetContrastRatio currently constructs BitInternalColor from the input
strings which silently falls back to white on invalid hex; before computing
RelativeLuminance, validate the input hex formats (foregroundHex/backgroundHex)
or detect when BitInternalColor resulted in white despite the original input not
representing white and throw ArgumentException; update GetContrastRatio to
perform a pre-parse format check (e.g., regex for `#RGB/`#RRGGBB or named formats)
or compare the original trimmed input to a non-white sentinel after constructing
BitInternalColor and throw with a clear message instead of returning a
misleading ratio; reference GetContrastRatio, BitInternalColor and
RelativeLuminance when making the change.
| <BitChoiceGroup IsEnabled=""false"" | ||
| Color=""BitColor.PrimaryBackground"" | ||
| Label=""PrimaryBackground"" | ||
| Horizontal | ||
| Items=""basicCustoms"" | ||
| DefaultValue=""basicCustoms[0].ItemValue"" | ||
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | ||
|
|
||
| <BitChoiceGroup IsEnabled=""false"" | ||
| Color=""BitColor.SecondaryBackground"" | ||
| Label=""SecondaryBackground"" | ||
| Horizontal | ||
| Items=""basicCustoms"" | ||
| DefaultValue=""basicCustoms[0].ItemValue"" | ||
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | ||
|
|
||
| <BitChoiceGroup IsEnabled=""false"" | ||
| Color=""BitColor.TertiaryBackground"" | ||
| Label=""TertiaryBackground"" | ||
| Horizontal | ||
| Items=""basicCustoms"" | ||
| DefaultValue=""basicCustoms[0].ItemValue"" | ||
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> |
There was a problem hiding this comment.
Keep example11RazorCode aligned with the rendered disabled background demo.
This snippet omits the styled wrapper used by the live demo for the disabled PrimaryBackground/SecondaryBackground/TertiaryBackground examples, so copied code won't reproduce the same contrast context users see on the page.
🛠️ Suggested adjustment
+<div style=""background:var(--bit-clr-fg-sec);color:var(--bit-clr-bg-sec);padding:1rem"">
<BitChoiceGroup IsEnabled=""false""
Color=""BitColor.PrimaryBackground""
Label=""PrimaryBackground""
Horizontal
Items=""basicCustoms""
DefaultValue=""basicCustoms[0].ItemValue""
NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" />
<BitChoiceGroup IsEnabled=""false""
Color=""BitColor.SecondaryBackground""
Label=""SecondaryBackground""
Horizontal
Items=""basicCustoms""
DefaultValue=""basicCustoms[0].ItemValue""
NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" />
<BitChoiceGroup IsEnabled=""false""
Color=""BitColor.TertiaryBackground""
Label=""TertiaryBackground""
Horizontal
Items=""basicCustoms""
DefaultValue=""basicCustoms[0].ItemValue""
NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" />
+</div>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.PrimaryBackground"" | |
| Label=""PrimaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.SecondaryBackground"" | |
| Label=""SecondaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.TertiaryBackground"" | |
| Label=""TertiaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| <div style=""background:var(--bit-clr-fg-sec);color:var(--bit-clr-bg-sec);padding:1rem""> | |
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.PrimaryBackground"" | |
| Label=""PrimaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.SecondaryBackground"" | |
| Label=""SecondaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| <BitChoiceGroup IsEnabled=""false"" | |
| Color=""BitColor.TertiaryBackground"" | |
| Label=""TertiaryBackground"" | |
| Horizontal | |
| Items=""basicCustoms"" | |
| DefaultValue=""basicCustoms[0].ItemValue"" | |
| NameSelectors=""@(new() { Text = { Name = nameof(Order.Name) }, Value = { Name = nameof(Order.ItemValue) } })"" /> | |
| </div> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs`
around lines 835 - 857, The sample string example11RazorCode does not include
the styled wrapper used in the live demo, so the three disabled BitChoiceGroup
examples (PrimaryBackground/SecondaryBackground/TertiaryBackground) render
without the same contrast context; update the example11RazorCode content to wrap
those BitChoiceGroup instances with the same CSS wrapper/markup used on the live
demo (the container that sets the background and contrast) so copied code
reproduces the disabled background styles for BitChoiceGroup components.
closes #12320
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests