Skip to content

BlazorUI theme improvements ii (#12320)#12369

Open
msynk wants to merge 29 commits into
bitfoundation:developfrom
msynk:12320-blazorui-theme-improvements-ii
Open

BlazorUI theme improvements ii (#12320)#12369
msynk wants to merge 29 commits into
bitfoundation:developfrom
msynk:12320-blazorui-theme-improvements-ii

Conversation

@msynk
Copy link
Copy Markdown
Member

@msynk msynk commented May 22, 2026

closes #12320

Summary by CodeRabbit

  • New Features
    • Improved keyboard focus/underline visuals, added focus/focus-underline mixins, motion & layout tokens, breakpoint updates, safer external stylesheet attach/detach, new theme APIs and helpers (theme names, providers, SSR script, external loader) and expanded demo coverage for disabled states.
  • Bug Fixes
    • Consistent, theme-driven disabled styling across components and better high-contrast/forced-colors support.
  • Documentation
    • Comprehensive theming guide rewrite with SSR, persistence, API usage, and recipes.
  • Tests
    • New tests for contrast, theme mapping drift, SSR/provider behavior, and color-derivation.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Coordinated theming overhaul: add focus-ring/underline mixins and focus tokens; introduce per-variant disabled CSS variables; replace pseudo-element focus with mixins in components; add JS Theme runtime and C# notifier lifecycle; update DI, demos, and tests.

Changes

Theming & runtime

Layer / File(s) Summary
Theme tokens, mixins, and media
src/BlazorUI/Bit.BlazorUI/Styles/functions.scss, src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss, src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss, src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss, src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss, src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss, src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
Adds focus-ring and focus-underline-ring mixins, focus/disabled/focus-ring tokens, motion and layout tokens, forced-colors high-contrast overrides, semantic aliases, and breakpoint refactors.
Theme mapper & utilities
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
Emit/merge additional CSS variables (disabled/focus/motion/layout), skip whitespace vars, and replace reflection-based ensure with explicit initializer.
JS theme runtime & SSR
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts, (removed) src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs, src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
Adds BitBlazorUI.Theme module (init/set/get/apply/clear/ExternalTheme), removes old TS file, provides SSR inline script builder with nonce support and attribute constants.
C# theme runtime & APIs
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
Converts manager to notifier lifecycle, adds notifier registration/unregistration, nullable theme returns, notification service and event args, attribute name constants, and a type-safe theme name wrapper.
Theme DTOs & helpers
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/*.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
Adds Motion/Layout sections, breakpoints DTO/defaults, focus ring shape tokens, disabled/focus properties on color variants, accent/density presets, and cookie constant.

Components & styles

Layer / File(s) Summary
Global utilities & focus classes
src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss, src/BlazorUI/Bit.BlazorUI/Styles/functions.scss, src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
Adds focus-visible utility classes and focus mixins plus global focus-ring shadow token.
Inputs / Controls focus refactor
multiple src/BlazorUI/Bit.BlazorUI/Components/Inputs/*
Replace ::after focus/underline with focus-ring/focus-underline-ring, add :focus-visible where appropriate, and wire focus tokens.
Buttons, links, icons — disabled & focus
src/BlazorUI/Bit.BlazorUI/Components/Buttons/*, src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss, src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss, src/BlazorUI/Bit.BlazorUI/Components/Notifications/*
Introduce per-variant --*-clr-dis / --*-clr-dis-text, refactor disabled selectors to use CSS vars, add :focus-visible mixin usage, correct transparent disabled backgrounds.
ChoiceGroup/Checkbox/Toggle/Timeline/Pagination/Pivot/Breadcrumb/Navs
relevant component SCSS files
Add border-radius, :focus-visible focus rings, and per-theme disabled CSS variable wiring.
Grid & media queries
src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss, src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
Rename breakpoint variables and update responsive mixins to new $mq-* values.

Interop, DI, demos & tests

Layer / File(s) Summary
DI and external CSS loader
src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs, src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
Register notifications, notifier receiver, manager factory, and external stylesheet loader with defensive URL validation and JS interop helpers.
BitThemeProvider
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
Sealed provider, AdditionalAttributes capture, caching merged theme and computed CSS-variable inline style, conditional wrapper rendering and efficient style reuse.
Demos updated
src/BlazorUI/Demo/Client/...
Add extensive “Disabled” demo sections for many components; fix sample snippets and markup.
Tests added/updated
src/BlazorUI/Tests/...
Add contrast tests, color-derivation WCAG tests, mapper merge-drift tests, SSR script tests, BitThemeProvider tests, and helper probes.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

"A rabbit in a patch of code,
nibbling tokens, hop by node.
Focus rings like moonlit lace,
disabled hues in every place.
I hop, I sketch, the theme's in bloom. 🐇"

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Fix invalid-state selector mismatch (.bit-dtrp-icp vs .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

📥 Commits

Reviewing files that changed from the base of the PR and between a074040 and 4d4e8e0.

📒 Files selected for processing (111)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
@msynk msynk requested a review from Copilot May 22, 2026 15:15
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 22, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

@msynk: Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  • invokeMethodAsync is 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 wrapping invokeMethodAsync with a .catch(() => { ... }) (and possibly clearing _dotnetNotifier) to avoid noisy errors and improve resilience.

Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs (2)

16-18: ⚡ Quick win

Add 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 win

Add 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

📥 Commits

Reviewing files that changed from the base of the PR and between a074040 and 530329a.

📒 Files selected for processing (114)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs Outdated
@msynk msynk requested a review from Copilot May 23, 2026 03:56
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 23, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

@msynk: Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 114 out of 114 changed files in this pull request and generated 2 comments.

Comment thread src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Persisting resolved light/dark on init breaks system-follow when persist is enabled.

When system mode is active with no stored value, init currently resolves to a concrete theme (light/dark) and persists it. That makes shouldFollowSystem() 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 win

Make 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

📥 Commits

Reviewing files that changed from the base of the PR and between a074040 and 6a96955.

📒 Files selected for processing (114)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss Outdated
@msynk msynk requested a review from Copilot May 24, 2026 15:36
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Prevent stacked focus indicators on underlined pickers.

When .bit-ctp-und.bit-ctp-foc is active, both the generic focused selector (lines 133–135) and the underline-focused selector (lines 158–160) match .bit-ctp-icn, causing both focus-ring and focus-underline-ring to 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 win

Add blank line before comment to satisfy linter.

Line 22 needs an empty line before the // comment to comply with scss/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 win

Prevent stacked focus styles for inverted underlined range picker.

When .bit-inv.bit-dtrp-und.bit-dtrp-foc is active, both selectors (lines 54–56 and 58–60) target .bit-dtrp-icn, applying both focus-ring($clr-err-focus) and focus-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 win

Prevent overlapping focus styles for underlined range picker.

The generic focused selector at lines 174–176 matches all .bit-dtrp-foc states, including when combined with .bit-dtrp-und, causing both focus-ring and focus-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 win

Prevent overlapping focus styles for inverted underlined DatePicker.

When .bit-inv.bit-dtp-und.bit-dtp-foc is present, both selectors (lines 54–56 and 58–60) match .bit-dtp-icn, applying both focus-ring($clr-err-focus) and focus-underline-ring($clr-err-focus). Exclude .bit-dtp-und from 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 win

Prevent stacked focus indicators on underlined inverted pickers.

When .bit-inv.bit-ctp-und.bit-ctp-foc is active, both selectors (lines 48–50 and 52–54) target .bit-ctp-icn, applying both focus-ring and focus-underline-ring simultaneously. 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

📥 Commits

Reviewing files that changed from the base of the PR and between aef9d8e and d304174.

📒 Files selected for processing (129)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss Outdated
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 29, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

@msynk Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 130 out of 130 changed files in this pull request and generated 1 comment.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Disabled groups still leave checked items on active colors.

.bit-btg.bit-dis now drives disabled styling through --bit-btg-itm-clr-*, but .bit-btg-chk bypasses those variables and hard-codes the checked border/background from active tokens. A preselected item inside an IsEnabled="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 win

Remove .scss from 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 win

Remove .scss extension from import.

The import still includes the .scss extension, violating the scss/load-partial-extension stylelint 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 win

Fix stylelint spacing before border-radius declaration.

An empty line is required before the border-radius declaration at line 31 to satisfy the declaration-empty-line-before rule.

💡 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 win

Fix 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-before rule.

💡 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 value

Consider enhancing XML documentation with usage example.

The documentation mentions merging with a baseline BitTheme but 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 win

Verify SemaphoreSlim non-disposal pattern is safe.

The comment on lines 156–159 explains that _jsNotifierRegistrationLock is intentionally not disposed to avoid ObjectDisposedException for callers that passed the _disposed check but haven't yet acquired or released the semaphore. While the reasoning is sound (SemaphoreSlim only holds unmanaged resources if AvailableWaitHandle is accessed), this leaves an IDisposable resource undisposed when the class implements IAsyncDisposable.

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 _disposed is checked before WaitAsync, and DisposeAsync sets _disposed before releasing and disposing the semaphore, no caller should hit ObjectDisposedException.

If the current pattern is preferred, document why it's safe (callers check _disposed before WaitAsync, so disposal after the final Release won'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

📥 Commits

Reviewing files that changed from the base of the PR and between aef9d8e and f9411e9.

📒 Files selected for processing (130)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
💤 Files with no reviewable changes (1)
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts

Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
@msynk msynk requested a review from Copilot May 30, 2026 18:47
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 30, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 30, 2026

@msynk Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 130 out of 130 changed files in this pull request and generated 2 comments.

Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs Outdated
Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

♻️ Duplicate comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss (1)

49-60: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep the error underline visible for invalid underlined pickers.

In underline mode, .bit-dtrp-icn has border: none later in the file, so Line 50's border-color: $clr-err never renders for the unfocused invalid state. Right now the red invalid indicator only appears once the control is focused.

💡 Minimal fix
     &.bit-inv {
         .bit-dtrp-icn {
             border-color: $clr-err;
         }
+
+        &.bit-dtrp-und .bit-dtrp-wrp {
+            border-bottom-color: $clr-err;
+        }
 
         &.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 49 - 60, The invalid-but-unfocused underline isn't visible because
`.bit-dtrp-icn` gets `border: none` later, so setting `border-color` in
`.bit-inv` doesn't show; update the `.bit-inv` rules to explicitly style the
underline mode by targeting the `.bit-dtrp-und` state (e.g. selector involving
`.bit-inv.bit-dtrp-und .bit-dtrp-icn`) and apply a visible underline style such
as `border-bottom` or a 0 1px box-shadow using `$clr-err` so the red indicator
appears when invalid and unfocused; keep the existing focus rules
(`&.bit-dtrp-foc:not(.bit-dtrp-und)`, `&.bit-dtrp-und.bit-dtrp-foc`) unchanged.
🧹 Nitpick comments (1)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs (1)

102-112: 💤 Low value

Activator.CreateInstance(pt) can throw, not just return null.

The val is null guard only covers the nullable-overload returning null; for a reference type lacking a public parameterless constructor, Activator.CreateInstance(pt) throws MissingMethodException. The current theme graph is all simple POCOs so this is fine today, but a future model type without a default ctor would crash this drift test instead of degrading gracefully.

♻️ Optional hardening
-                    var val = prop.GetValue(obj);
-                    if (val is null)
-                    {
-                        val = Activator.CreateInstance(pt);
-                        if (val is null) continue;
-                        prop.SetValue(obj, val);
-                    }
+                    var val = prop.GetValue(obj);
+                    if (val is null)
+                    {
+                        try
+                        {
+                            val = Activator.CreateInstance(pt);
+                        }
+                        catch (MissingMethodException)
+                        {
+                            continue;
+                        }
+                        if (val is null) continue;
+                        prop.SetValue(obj, val);
+                    }
🤖 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/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs`
around lines 102 - 112, The code calls Activator.CreateInstance(pt) inside the
Walk method without guarding against exceptions; for types without a public
parameterless ctor this will throw (e.g., MissingMethodException) and crash the
test. Wrap the Activator.CreateInstance(pt) call in a try/catch (catch
Exception) and treat any exception the same as a null return — skip setting the
property and continue walking — so replace the direct call with a guarded
attempt that on exception continues without mutating the object (affecting the
prop.SetValue(obj, val) and subsequent Walk(val, visited, ref counter) paths).
🤖 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/Button/BitButton.scss`:
- Around line 22-24: BitButton.scss currently calls
focus-ring(var(--bit-btn-clr)) which ignores the new per-role focus tokens
published by BitThemeMapper; change the focus-ring call to use the matching
per-variant focus CSS variable (the new *-focus vars) instead of --bit-btn-clr
(e.g., replace usages in BitButton.scss where focus-ring(var(--bit-btn-clr))
appears with focus-ring(var(--bit-btn-<role>-focus)) for the default and for
each color variant), and replicate that pattern across the other color variant
blocks (lines ~189-356) so each variant uses its own --bit-btn-<variant>-focus
token.

In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss`:
- Around line 16-19: The focus ring in the MenuButton SCSS currently uses the
role-specific CSS variable --bit-mnb-clr inside the &:focus-visible,
&:focus-within block with `@include` focus-ring(var(--bit-mnb-clr)); change this
to use the dedicated theme focus token (the same focus-token mapping pattern
used for other components) by replacing var(--bit-mnb-clr) with the new token
variable (e.g., var(--bit-<component>-focus) or the project's focus token name)
wherever `@include` focus-ring is invoked for the MenuButton; apply the same
mapping update to all other color-specific classes in this file (see other
`@include` focus-ring occurrences in the 239-390 region) so the component follows
the theme's focus-token override path.

In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss`:
- Around line 20-22: The focus-ring currently uses the legacy token
var(--bit-tgb-clr) in BitToggleButton.scss (&:focus-visible) so theme mapper
Color.*.Focus values are ignored; change the focus-ring to use the new focus
palette token (e.g., replace var(--bit-tgb-clr) with the corresponding focus
token like var(--bit-<variant>-focus) or the component-level focus token your
theme emits) and update each variant block to define and use its own
--bit-*-focus token (mirror this change for all variant blocks in the file,
including the ranges noted) so the focus style reads from the new Color.*.Focus
tokens.

In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss`:
- Around line 220-233: Add the missing focus-token aliases for secondary and
tertiary semantic colors so theme-level focus surfaces are available for those
roles: create --bit-clr-fg-sec-focus, --bit-clr-bg-sec-focus,
--bit-clr-brd-sec-focus and their tertiary counterparts --bit-clr-fg-ter-focus,
--bit-clr-bg-ter-focus, --bit-clr-brd-ter-focus (following the existing pattern
used for primary: e.g. --bit-clr-fg-pri-focus, --bit-clr-bg-pri-focus,
--bit-clr-brd-pri-focus) and initialize them to their respective base tokens
(e.g. var(--bit-clr-fg-sec), var(--bit-clr-bg-sec), var(--bit-clr-brd-sec),
etc.) so SecondaryBackground/TertiaryBackground,
SecondaryForeground/TertiaryForeground, and SecondaryBorder/TertiaryBorder can
bind to dedicated focus tokens.

In `@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts`:
- Around line 46-47: The dark-theme detection is too broad because
name.includes('dark') treats any theme containing the substring as dark; update
the logic in app.ts (variables newTheme, name, isDark) to detect dark only when
name === 'dark' or it ends with '-dark' (or matches a pattern like /^.+-dark$/)
and remove the generic includes('dark') check so only explicit "dark" or
explicit "-dark" suffixed theme names flip the body classes and meta
theme-color.

---

Duplicate comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss`:
- Around line 49-60: The invalid-but-unfocused underline isn't visible because
`.bit-dtrp-icn` gets `border: none` later, so setting `border-color` in
`.bit-inv` doesn't show; update the `.bit-inv` rules to explicitly style the
underline mode by targeting the `.bit-dtrp-und` state (e.g. selector involving
`.bit-inv.bit-dtrp-und .bit-dtrp-icn`) and apply a visible underline style such
as `border-bottom` or a 0 1px box-shadow using `$clr-err` so the red indicator
appears when invalid and unfocused; keep the existing focus rules
(`&.bit-dtrp-foc:not(.bit-dtrp-und)`, `&.bit-dtrp-und.bit-dtrp-foc`) unchanged.

---

Nitpick comments:
In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs`:
- Around line 102-112: The code calls Activator.CreateInstance(pt) inside the
Walk method without guarding against exceptions; for types without a public
parameterless ctor this will throw (e.g., MissingMethodException) and crash the
test. Wrap the Activator.CreateInstance(pt) call in a try/catch (catch
Exception) and treat any exception the same as a null return — skip setting the
property and continue walking — so replace the direct call with a guarded
attempt that on exception continues without mutating the object (affecting the
prop.SetValue(obj, val) and subsequent Walk(val, visited, ref counter) paths).
🪄 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: 28fbd9ca-de79-4f21-b749-601cc9189a60

📥 Commits

Reviewing files that changed from the base of the PR and between beb2c47 and 8058ae1.

📒 Files selected for processing (130)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
💤 Files with no reviewable changes (1)
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts

Comment thread src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
Comment thread src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
Comment thread src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts Outdated
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 31, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

@msynk Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 130 out of 130 changed files in this pull request and generated 2 comments.

Comment thread src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (6)
src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss (1)

1-1: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Drop .scss extension in the import path.

The import violates scss/load-partial-extension.

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 SCSS import
currently uses a file extension in the import string ("`@import`
\"theme-variables.scss\";") which violates scss/load-partial-extension; update
the import in bit-css.scss to drop the .scss extension so it reads "`@import`
\"theme-variables\";" (keep the same quoted name so the partial
_theme-variables.scss will be resolved).
src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss (1)

16-19: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bind the MenuButton focus ring to a dedicated focus token.

The focus ring at line 18 still uses var(--bit-mnb-clr), so role-level *-focus theme overrides cannot affect MenuButton. Add a dedicated --bit-mnb-clr-focus variable and map it in each color class (lines 239-390) following the same pattern used for --bit-mnb-clr-dis and --bit-mnb-clr-dis-text.

🔧 Proposed fix
     &:focus-visible,
     &:focus-within {
-        `@include` focus-ring(var(--bit-mnb-clr));
+        `@include` focus-ring(var(--bit-mnb-clr-focus));
     }

Then add the focus token to each color class. For example, in .bit-mnb-pri:

 .bit-mnb-pri {
     --bit-mnb-clr: #{$clr-pri};
     --bit-mnb-clr-txt: #{$clr-pri-text};
     --bit-mnb-clr-hover: #{$clr-pri-hover};
     --bit-mnb-clr-active: #{$clr-pri-active};
+    --bit-mnb-clr-focus: #{$clr-pri-focus};
     --bit-mnb-clr-dis: #{$clr-pri-dis};
     --bit-mnb-clr-dis-text: #{$clr-pri-dis-text};
 }

Apply the same mapping to all color classes (.bit-mnb-sec, .bit-mnb-ter, .bit-mnb-inf, .bit-mnb-suc, .bit-mnb-wrn, .bit-mnb-swr, .bit-mnb-err, .bit-mnb-pbg, .bit-mnb-sbg, .bit-mnb-tbg, .bit-mnb-pfg, .bit-mnb-sfg, .bit-mnb-tfg, .bit-mnb-pbr, .bit-mnb-sbr, .bit-mnb-tbr).

🤖 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/MenuButton/BitMenuButton.scss`
around lines 16 - 19, The focus-ring include in BitMenuButton.scss currently
hardcodes var(--bit-mnb-clr); change it to use a dedicated focus token
--bit-mnb-clr-focus (i.e. `@include` focus-ring(var(--bit-mnb-clr-focus))); then
add mapping for --bit-mnb-clr-focus inside every MenuButton color class (e.g.
.bit-mnb-pri, .bit-mnb-sec, .bit-mnb-ter, .bit-mnb-inf, .bit-mnb-suc,
.bit-mnb-wrn, .bit-mnb-swr, .bit-mnb-err, .bit-mnb-pbg, .bit-mnb-sbg,
.bit-mnb-tbg, .bit-mnb-pfg, .bit-mnb-sfg, .bit-mnb-tfg, .bit-mnb-pbr,
.bit-mnb-sbr, .bit-mnb-tbr) following the same pattern used for
--bit-mnb-clr-dis and --bit-mnb-clr-dis-text so role-level *-focus overrides can
control the MenuButton focus color.
src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss (1)

22-24: 🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Focus ring should use the new per-role focus tokens.

The :focus-visible rule uses var(--bit-btn-clr) but BitThemeMapper now publishes per-role *-focus tokens. Define and reference --bit-btn-clr-focus (or a fallback var(--bit-btn-clr-focus, var(--bit-btn-clr))) so theme overrides for focus colors take effect.

🔧 Suggested approach
  1. Update the focus-visible rule:
 &:focus-visible {
-    `@include` focus-ring(var(--bit-btn-clr));
+    `@include` focus-ring(var(--bit-btn-clr-focus, var(--bit-btn-clr)));
 }
  1. Define --bit-btn-clr-focus for each color variant (lines 189-357), e.g.:
 .bit-btn-pri {
     --bit-btn-clr: #{$clr-pri};
+    --bit-btn-clr-focus: #{$clr-pri-focus};
     --bit-btn-clr-txt: #{$clr-pri-text};
     ...
 }

Repeat for all variants (sec, ter, inf, suc, wrn, swr, err, pbg, sbg, tbg, pfg, sfg, tfg, pbr, sbr, tbr).

🤖 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/Button/BitButton.scss` around
lines 22 - 24, The :focus-visible rule in BitButton.scss currently calls
`@include` focus-ring(var(--bit-btn-clr)) and must be updated to use the new
per-role focus token; change the argument to use --bit-btn-clr-focus with a
fallback (e.g. var(--bit-btn-clr-focus, var(--bit-btn-clr))) so theme overrides
apply, and then add definitions for --bit-btn-clr-focus for each color variant
(primary/secondary/tertiary/info/success/warn/swear/error and the p/s/t
background/foreground/border variants) alongside the existing --bit-btn-clr
declarations so BitThemeMapper’s per-role focus tokens are honored by BitButton.
src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss (1)

20-22: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Wire ToggleButton focus ring to focus tokens, not base color token.

Current focus style still uses var(--bit-tgb-clr), so Color.*.Focus values won’t affect BitToggleButton. Add a dedicated --bit-tgb-clr-focus per variant and consume it with fallback.

Suggested minimal change
 .bit-tgb {
     &:focus-visible {
-        `@include` focus-ring(var(--bit-tgb-clr));
+        `@include` focus-ring(var(--bit-tgb-clr-focus, var(--bit-tgb-clr)));
     }
 }

 .bit-tgb-pri {
+    --bit-tgb-clr-focus: #{$clr-pri-focus};
     --bit-tgb-clr-txt: #{$clr-pri-text};
     --bit-tgb-clr: #{$clr-pri};
     ...
 }

(Apply similarly to other variant blocks.)

Also applies to: 134-336

🤖 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/ToggleButton/BitToggleButton.scss`
around lines 20 - 22, The focus-ring currently uses var(--bit-tgb-clr) so
Color.*.Focus tokens are ignored; update BitToggleButton styles to introduce and
use a per-variant focus token (e.g., add a --bit-tgb-clr-focus fallback for each
variant block) and change the &:focus-visible rule to call `@include`
focus-ring(var(--bit-tgb-clr-focus, var(--bit-tgb-clr))); apply the same change
to all variant blocks where --bit-tgb-clr is defined so the focus color honors
Color.*.Focus.
src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss (1)

220-234: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add missing secondary and tertiary focus tokens for foreground, background, and border roles.

Components using SecondaryBackground, TertiaryBackground, SecondaryForeground, TertiaryForeground, SecondaryBorder, or TertiaryBorder cannot bind to dedicated focus tokens because only primary variants exist (--bit-clr-fg-pri-focus, --bit-clr-bg-pri-focus, --bit-clr-brd-pri-focus). This forces secondary/tertiary components to fall back to their base role colors instead of dedicated focus colors, breaking the theming contract.

🔧 Proposed fix
     --bit-clr-fg-pri-focus: var(--bit-clr-fg-pri);
+    --bit-clr-fg-sec-focus: var(--bit-clr-fg-sec);
+    --bit-clr-fg-ter-focus: var(--bit-clr-fg-ter);
     --bit-clr-bg-pri-focus: var(--bit-clr-bg-pri);
+    --bit-clr-bg-sec-focus: var(--bit-clr-bg-sec);
+    --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter);
     --bit-clr-brd-pri-focus: var(--bit-clr-brd-pri);
+    --bit-clr-brd-sec-focus: var(--bit-clr-brd-sec);
+    --bit-clr-brd-ter-focus: var(--bit-clr-brd-ter);
🤖 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/colors.fluent-light.scss` around
lines 220 - 234, The focus token set is incomplete: only primary
foreground/background/border focus tokens exist (--bit-clr-fg-pri-focus,
--bit-clr-bg-pri-focus, --bit-clr-brd-pri-focus), so secondary/tertiary
components cannot use dedicated focus values; add the missing focus tokens
--bit-clr-fg-sec-focus, --bit-clr-fg-ter-focus, --bit-clr-bg-sec-focus,
--bit-clr-bg-ter-focus, --bit-clr-brd-sec-focus, and --bit-clr-brd-ter-focus and
initialize each to the corresponding base role (e.g. --bit-clr-fg-sec-focus:
var(--bit-clr-fg-sec), --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter), etc.),
placing them alongside the existing primary focus declarations so
Secondary/TertiaryForeground, Secondary/TertiaryBackground, and
Secondary/TertiaryBorder can bind to dedicated focus tokens.
src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss (1)

218-232: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add missing secondary and tertiary focus tokens for foreground, background, and border roles.

Components using SecondaryBackground, TertiaryBackground, SecondaryForeground, TertiaryForeground, SecondaryBorder, or TertiaryBorder cannot bind to dedicated focus tokens because only primary variants exist. This creates an incomplete theming surface for secondary/tertiary component variants.

🔧 Proposed fix
     --bit-clr-fg-pri-focus: var(--bit-clr-fg-pri);
+    --bit-clr-fg-sec-focus: var(--bit-clr-fg-sec);
+    --bit-clr-fg-ter-focus: var(--bit-clr-fg-ter);
     --bit-clr-bg-pri-focus: var(--bit-clr-bg-pri);
+    --bit-clr-bg-sec-focus: var(--bit-clr-bg-sec);
+    --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter);
     --bit-clr-brd-pri-focus: var(--bit-clr-brd-pri);
+    --bit-clr-brd-sec-focus: var(--bit-clr-brd-sec);
+    --bit-clr-brd-ter-focus: var(--bit-clr-brd-ter);
🤖 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/colors.fluent-dark.scss` around lines
218 - 232, Missing focus tokens for secondary and tertiary roles: add focus CSS
custom properties for foreground, background, and border by declaring
--bit-clr-fg-sec-focus, --bit-clr-bg-sec-focus, --bit-clr-brd-sec-focus and
--bit-clr-fg-ter-focus, --bit-clr-bg-ter-focus, --bit-clr-brd-ter-focus and
alias them to their corresponding base tokens (e.g. set --bit-clr-fg-sec-focus:
var(--bit-clr-fg-sec); --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter); etc.)
alongside the existing primary focus tokens so components like
SecondaryForeground/SecondaryBackground/SecondaryBorder and Tertiary* can bind
to dedicated focus tokens.
🧹 Nitpick comments (2)
src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs (1)

18-18: ⚡ Quick win

Note: const to static readonly is a minor breaking change.

The field was changed from const to static readonly to support dynamic initialization. This prevents compile-time constant usage, though such usage for a script body is unlikely. The change improves maintainability by centralizing attribute names.

🤖 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/BitThemeSsr.cs` at line 18, The public
field InlineHeadScriptBody in BitThemeSsr was changed from a compile-time const
to static readonly (declared as public static readonly string
InlineHeadScriptBody = BuildInlineScriptBody()), which is a breaking change for
any consumers relying on a const; either revert it back to a public const string
InlineHeadScriptBody with a literal value if dynamic initialization is not
strictly required, or if dynamic initialization is required keep the static
readonly but restore a compile-time constant by adding a new public const string
InlineHeadScriptBodyConst with the literal value and leave public static
readonly string InlineHeadScriptBody = BuildInlineScriptBody(); also add XML
docs on BitThemeSsr/InlineHeadScriptBody documenting the change so callers know
to migrate.
src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss (1)

171-173: ⚡ Quick win

Use dedicated focus tokens for Pivot focus-ring.

focus-ring(var(--bit-pvt-clr)) ignores the new role-specific *.Focus theme contract and keeps focus color coupled to base color. Add a --bit-pvt-clr-focus token per variant and use it with fallback.

Suggested minimal change
 .bit-pvti {
     &:focus-visible {
-        `@include` focus-ring(var(--bit-pvt-clr));
+        `@include` focus-ring(var(--bit-pvt-clr-focus, var(--bit-pvt-clr)));
     }
 }

 .bit-pvti-sel {
     &:focus-visible {
-        `@include` focus-ring(var(--bit-pvt-clr));
+        `@include` focus-ring(var(--bit-pvt-clr-focus, var(--bit-pvt-clr)));
     }
 }

 .bit-pvt-pri {
+    --bit-pvt-clr-focus: #{$clr-pri-focus};
     --bit-pvt-clr: #{$clr-pri};
     ...
 }

Also applies to: 214-216, 257-392

🤖 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/Navs/Pivot/BitPivot.scss` around lines
171 - 173, Replace uses of focus-ring(var(--bit-pvt-clr)) with a role-specific
focus token that falls back to the base color: change calls to
focus-ring(var(--bit-pvt-clr-focus, var(--bit-pvt-clr))). Add corresponding
--bit-pvt-clr-focus CSS variables for each pivot variant where --bit-pvt-clr is
defined (so the new token can be themed independently), and update every
occurrence (e.g., the &:focus-visible blocks and the other ranges noted) to use
the new fallback pattern to preserve current color if a focused token isn’t
provided.
🤖 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/Styles/media-queries.scss`:
- Around line 3-21: The breakpoint boundary is inconsistent: update the
media-query logic in BitMediaQuery (class/file BitMediaQuery.razor.cs) and
BitScreenQuery (class/file BitScreenQuery.cs) to match the SCSS variables (xs
max = 599px, sm min = 600px) by changing any hardcoded "(max-width: 600px)" to
"(max-width: 599px)" and any "(min-width: 601px)" to "(min-width: 600px)" (or
equivalent constants used there), then update the tests in BitMediaQueryTests
(src/.../BitMediaQueryTests.cs) to expect "(max-width: 599px)" and "(min-width:
600px)" accordingly; treat this as a breaking change for downstream consumers.

---

Duplicate comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss`:
- Around line 22-24: The :focus-visible rule in BitButton.scss currently calls
`@include` focus-ring(var(--bit-btn-clr)) and must be updated to use the new
per-role focus token; change the argument to use --bit-btn-clr-focus with a
fallback (e.g. var(--bit-btn-clr-focus, var(--bit-btn-clr))) so theme overrides
apply, and then add definitions for --bit-btn-clr-focus for each color variant
(primary/secondary/tertiary/info/success/warn/swear/error and the p/s/t
background/foreground/border variants) alongside the existing --bit-btn-clr
declarations so BitThemeMapper’s per-role focus tokens are honored by BitButton.

In `@src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss`:
- Around line 16-19: The focus-ring include in BitMenuButton.scss currently
hardcodes var(--bit-mnb-clr); change it to use a dedicated focus token
--bit-mnb-clr-focus (i.e. `@include` focus-ring(var(--bit-mnb-clr-focus))); then
add mapping for --bit-mnb-clr-focus inside every MenuButton color class (e.g.
.bit-mnb-pri, .bit-mnb-sec, .bit-mnb-ter, .bit-mnb-inf, .bit-mnb-suc,
.bit-mnb-wrn, .bit-mnb-swr, .bit-mnb-err, .bit-mnb-pbg, .bit-mnb-sbg,
.bit-mnb-tbg, .bit-mnb-pfg, .bit-mnb-sfg, .bit-mnb-tfg, .bit-mnb-pbr,
.bit-mnb-sbr, .bit-mnb-tbr) following the same pattern used for
--bit-mnb-clr-dis and --bit-mnb-clr-dis-text so role-level *-focus overrides can
control the MenuButton focus color.

In
`@src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss`:
- Around line 20-22: The focus-ring currently uses var(--bit-tgb-clr) so
Color.*.Focus tokens are ignored; update BitToggleButton styles to introduce and
use a per-variant focus token (e.g., add a --bit-tgb-clr-focus fallback for each
variant block) and change the &:focus-visible rule to call `@include`
focus-ring(var(--bit-tgb-clr-focus, var(--bit-tgb-clr))); apply the same change
to all variant blocks where --bit-tgb-clr is defined so the focus color honors
Color.*.Focus.

In `@src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss`:
- Line 1: The SCSS import currently uses a file extension in the import string
("`@import` \"theme-variables.scss\";") which violates
scss/load-partial-extension; update the import in bit-css.scss to drop the .scss
extension so it reads "`@import` \"theme-variables\";" (keep the same quoted name
so the partial _theme-variables.scss will be resolved).

In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss`:
- Around line 218-232: Missing focus tokens for secondary and tertiary roles:
add focus CSS custom properties for foreground, background, and border by
declaring --bit-clr-fg-sec-focus, --bit-clr-bg-sec-focus,
--bit-clr-brd-sec-focus and --bit-clr-fg-ter-focus, --bit-clr-bg-ter-focus,
--bit-clr-brd-ter-focus and alias them to their corresponding base tokens (e.g.
set --bit-clr-fg-sec-focus: var(--bit-clr-fg-sec); --bit-clr-bg-ter-focus:
var(--bit-clr-bg-ter); etc.) alongside the existing primary focus tokens so
components like SecondaryForeground/SecondaryBackground/SecondaryBorder and
Tertiary* can bind to dedicated focus tokens.

In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss`:
- Around line 220-234: The focus token set is incomplete: only primary
foreground/background/border focus tokens exist (--bit-clr-fg-pri-focus,
--bit-clr-bg-pri-focus, --bit-clr-brd-pri-focus), so secondary/tertiary
components cannot use dedicated focus values; add the missing focus tokens
--bit-clr-fg-sec-focus, --bit-clr-fg-ter-focus, --bit-clr-bg-sec-focus,
--bit-clr-bg-ter-focus, --bit-clr-brd-sec-focus, and --bit-clr-brd-ter-focus and
initialize each to the corresponding base role (e.g. --bit-clr-fg-sec-focus:
var(--bit-clr-fg-sec), --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter), etc.),
placing them alongside the existing primary focus declarations so
Secondary/TertiaryForeground, Secondary/TertiaryBackground, and
Secondary/TertiaryBorder can bind to dedicated focus tokens.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss`:
- Around line 171-173: Replace uses of focus-ring(var(--bit-pvt-clr)) with a
role-specific focus token that falls back to the base color: change calls to
focus-ring(var(--bit-pvt-clr-focus, var(--bit-pvt-clr))). Add corresponding
--bit-pvt-clr-focus CSS variables for each pivot variant where --bit-pvt-clr is
defined (so the new token can be themed independently), and update every
occurrence (e.g., the &:focus-visible blocks and the other ranges noted) to use
the new fallback pattern to preserve current color if a focused token isn’t
provided.

In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs`:
- Line 18: The public field InlineHeadScriptBody in BitThemeSsr was changed from
a compile-time const to static readonly (declared as public static readonly
string InlineHeadScriptBody = BuildInlineScriptBody()), which is a breaking
change for any consumers relying on a const; either revert it back to a public
const string InlineHeadScriptBody with a literal value if dynamic initialization
is not strictly required, or if dynamic initialization is required keep the
static readonly but restore a compile-time constant by adding a new public const
string InlineHeadScriptBodyConst with the literal value and leave public static
readonly string InlineHeadScriptBody = BuildInlineScriptBody(); also add XML
docs on BitThemeSsr/InlineHeadScriptBody documenting the change so callers know
to migrate.
🪄 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: 78c90892-e14b-473f-a62e-7f753a0a6f64

📥 Commits

Reviewing files that changed from the base of the PR and between beb2c47 and 8058ae1.

📒 Files selected for processing (130)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
💤 Files with no reviewable changes (1)
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts

Comment thread src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
@msynk
Copy link
Copy Markdown
Member Author

msynk commented May 31, 2026

@coderabbitai re-review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 31, 2026

@msynk Sure! I'll re-review the PR now.

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 131 out of 131 changed files in this pull request and generated 2 comments.

internal static ValueTask<string?> BitThemeGetCurrentTheme(this IJSRuntime js)
{
return js.Invoke<string>("BitTheme.get");
return js.Invoke<string?>("BitBlazorUI.Theme.get");
/// derivation is still a usable theme branch. The outer <c>try/catch</c> below is defense-in-depth
/// for unforeseen exceptions; nothing currently throws past <c>BitInternalColor</c>.
/// </remarks>
public static void FillColorRoleFromMain(BitThemeColorVariants? variants, string? mainHex, bool adjustTextForWcagAa = false)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (3)
src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs (1)

12-12: ⚡ Quick win

Consider tightening the tolerance for consistency.

The tolerance of 0.01 allows the ratio to vary between 20.99 and 21.01. The same-color test at line 20 uses a tighter tolerance of 0.001. For an exact mathematical constant like the black-on-white contrast ratio (21:1), using the same tighter tolerance would improve the test's ability to detect calculation errors.

🔧 Proposed consistency improvement
-        Assert.AreEqual(21.0, ratio, 0.01);
+        Assert.AreEqual(21.0, ratio, 0.001);
🤖 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/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs`
at line 12, The test assertion for the black-on-white contrast uses
Assert.AreEqual(21.0, ratio, 0.01) with a 0.01 tolerance; tighten this to 0.001
to match the same-color test's precision and better catch calculation
errors—locate the assertion in BitThemeColorContrastTests.cs (the
Assert.AreEqual call comparing 21.0 and ratio) and change the tolerance argument
from 0.01 to 0.001 while keeping the expected value 21.0.
src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs (1)

317-326: ⚡ Quick win

Set foreground color in disabled background wrapper for consistent contrast.

The disabled *Background examples are wrapped in a <div style="background:var(--bit-clr-fg-sec);padding:1rem">, but unlike the ChoiceGroup demo (which sets both background and color), this wrapper omits the color property. Adding color:var(--bit-clr-bg-sec) would ensure proper text contrast and align with the pattern established in other component demos.

♻️ Suggested fix
-<div style="background:var(--bit-clr-fg-sec);padding:1rem">
+<div style=""background:var(--bit-clr-fg-sec);color:var(--bit-clr-bg-sec);padding:1rem"">
🤖 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/SearchBox/BitSearchBoxDemo.razor.samples.cs`
around lines 317 - 326, The wrapper DIV around the disabled BitSearchBox
examples lacks a foreground color, causing contrast inconsistencies; update the
DIV's inline style (the element containing the BitSearchBox samples) to include
color:var(--bit-clr-bg-sec) in addition to the existing
background:var(--bit-clr-fg-sec);padding:1rem so the BitSearchBox examples
(components named BitSearchBox with Placeholder values like
"PrimaryBackground"/"SecondaryBackground"/"TertiaryBackground") render with the
same text/background contrast pattern used in other demos.
src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss (1)

218-231: ⚡ Quick win

Add secondary/tertiary focus aliases for the surface roles.

Only the primary fg/bg/brd focus aliases were added here. SecondaryForeground, TertiaryForeground, SecondaryBackground, TertiaryBackground, SecondaryBorder, and TertiaryBorder still have no dedicated *-focus tokens, so those variants can't be themed independently for focus states.

💡 Suggested direction
     --bit-clr-fg-pri-focus: var(--bit-clr-fg-pri);
+    --bit-clr-fg-sec-focus: var(--bit-clr-fg-sec);
+    --bit-clr-fg-ter-focus: var(--bit-clr-fg-ter);
     --bit-clr-bg-pri-focus: var(--bit-clr-bg-pri);
+    --bit-clr-bg-sec-focus: var(--bit-clr-bg-sec);
+    --bit-clr-bg-ter-focus: var(--bit-clr-bg-ter);
     --bit-clr-brd-pri-focus: var(--bit-clr-brd-pri);
+    --bit-clr-brd-sec-focus: var(--bit-clr-brd-sec);
+    --bit-clr-brd-ter-focus: var(--bit-clr-brd-ter);
🤖 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/colors.fluent-dark.scss` around lines
218 - 231, The file defines focus aliases only for primary surface roles (e.g.,
--bit-clr-fg-pri-focus, --bit-clr-bg-pri-focus, --bit-clr-brd-pri-focus) but
missing secondary/tertiary equivalents; add focus aliases for
SecondaryForeground, TertiaryForeground, SecondaryBackground,
TertiaryBackground, SecondaryBorder, and TertiaryBorder by declaring tokens like
--bit-clr-fg-sec-focus, --bit-clr-fg-ter-focus, --bit-clr-bg-sec-focus,
--bit-clr-bg-ter-focus, --bit-clr-brd-sec-focus, and --bit-clr-brd-ter-focus and
point each to the corresponding base token (e.g., var(--bit-clr-fg-sec),
var(--bit-clr-bg-ter), var(--bit-clr-brd-sec)) so those surface roles can be
themed independently for focus states.
🤖 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/Utilities/Link/BitLink.scss`:
- Around line 22-24: The :focus-visible block in BitLink.scss calls `@include`
focus-ring(var(--bit-lnk-clr)) but BitButton now uses per-variant focus tokens;
update BitLink to define --bit-lnk-clr-focus inside each variant block (e.g.,
.bit-lnk-pri, .bit-lnk-sec, .bit-lnk-ter and any other variants currently
defined) and change the mixin invocation in the &:focus-visible rule to `@include`
focus-ring(var(--bit-lnk-clr-focus)); ensure each variant block sets an
appropriate focus color value for --bit-lnk-clr-focus.

In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss`:
- Around line 9-15: The current reduced-motion rule sets --bit-mot-duration,
--bit-mot-duration-short, and --bit-mot-duration-long to 0.01ms which is
effectively a hack; update the `@media` (prefers-reduced-motion: reduce) :root
block so those CSS custom properties are set to 0ms (or set
animations/transitions to none where used) to fully honor the user's preference;
specifically change the values for --bit-mot-duration, --bit-mot-duration-short,
and --bit-mot-duration-long used by your motion/animation code paths (and ensure
any code reading these vars treats "0ms" as disabled).

In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts`:
- Around line 78-82: The current logic always overrides any explicit
Theme._initOptions.theme or Theme._initOptions.default when
Theme._initOptions.system is true; change it so OS resolution (using
Theme.isSystemDark() to set Theme._darkTheme or Theme._lightTheme) only runs
when the chosen value is explicitly 'system' or when neither theme nor default
were supplied (i.e., Theme._initOptions.theme === 'system' OR
(!Theme._initOptions.theme && !Theme._initOptions.default &&
Theme._initOptions.system)); otherwise leave the initially selected theme (from
Theme._initOptions.theme or Theme._initOptions.default) intact.
- Around line 312-327: The attach method currently writes any href into the DOM;
update BitTheme.attach to validate href before creating/updating the <link>:
parse the href with new URL(href, document.baseURI), ensure url.protocol is
'http:' or 'https:' and url.origin === location.origin (mirroring the C#
loader’s same‑origin + http(s) rules), and if validation fails do not set
link.href (log/throw as appropriate). Apply this validation at the start of
public static attach(linkId: string, href: string) before creating or assigning
to the link element so both create and update paths are protected.
- Around line 192-198: applyTheme currently unions historic CSS variable keys
(Theme._appliedVarKeys) and never removes keys that are omitted in a later
theme, leaving stale vars on the element; change applyTheme (the method in
BitTheme/Theme) to compute removed keys as those in prev but not in keys, call
el.style.removeProperty for each removed key, then set the new keys (and update
Theme._appliedVarKeys for the element to exactly the current keys) so applyTheme
behaves as a replace operation whether element is the provided HTMLElement or
document.body.

In `@src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs`:
- Around line 8-18: Update the XML example in
BitThemeDensityPresets.CreateCompactOverlay's doc comment to clarify the
ThemeManager identifier: explicitly reference a BitThemeManager instance (e.g.,
name the variable bitThemeManager or state it is injected/created) and call its
ApplyBitThemeAsync(theme) method so the example matches the actual API signature
(BitThemeManager.ApplyBitThemeAsync(BitTheme? bitTheme, ElementReference?
element = null)); keep the rest of the example unchanged.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs`:
- Around line 1394-1490: The disabled Primary/Secondary/Tertiary background
BitMenuButton examples (the BitMenuButton elements with
Text="PrimaryBackground"/"SecondaryBackground"/"TertiaryBackground" and
IsEnabled="false") are missing the contrast container used elsewhere, so they
render against the default page background; wrap each group of these disabled
samples (including both Split and non-Split variants) in the same contrast
container/component used by other background demos in this PR so they display
the correct disabled appearance.

---

Nitpick comments:
In `@src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss`:
- Around line 218-231: The file defines focus aliases only for primary surface
roles (e.g., --bit-clr-fg-pri-focus, --bit-clr-bg-pri-focus,
--bit-clr-brd-pri-focus) but missing secondary/tertiary equivalents; add focus
aliases for SecondaryForeground, TertiaryForeground, SecondaryBackground,
TertiaryBackground, SecondaryBorder, and TertiaryBorder by declaring tokens like
--bit-clr-fg-sec-focus, --bit-clr-fg-ter-focus, --bit-clr-bg-sec-focus,
--bit-clr-bg-ter-focus, --bit-clr-brd-sec-focus, and --bit-clr-brd-ter-focus and
point each to the corresponding base token (e.g., var(--bit-clr-fg-sec),
var(--bit-clr-bg-ter), var(--bit-clr-brd-sec)) so those surface roles can be
themed independently for focus states.

In
`@src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs`:
- Around line 317-326: The wrapper DIV around the disabled BitSearchBox examples
lacks a foreground color, causing contrast inconsistencies; update the DIV's
inline style (the element containing the BitSearchBox samples) to include
color:var(--bit-clr-bg-sec) in addition to the existing
background:var(--bit-clr-fg-sec);padding:1rem so the BitSearchBox examples
(components named BitSearchBox with Placeholder values like
"PrimaryBackground"/"SecondaryBackground"/"TertiaryBackground") render with the
same text/background contrast pattern used in other demos.

In
`@src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs`:
- Line 12: The test assertion for the black-on-white contrast uses
Assert.AreEqual(21.0, ratio, 0.01) with a 0.01 tolerance; tighten this to 0.001
to match the same-color test's precision and better catch calculation
errors—locate the assertion in BitThemeColorContrastTests.cs (the
Assert.AreEqual call comparing 21.0 and ratio) and change the tolerance argument
from 0.01 to 0.001 while keeping the expected value 21.0.
🪄 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: b98d8739-bc76-4791-ba94-9306a09b764a

📥 Commits

Reviewing files that changed from the base of the PR and between beb2c47 and fab1c3c.

📒 Files selected for processing (131)
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ActionButton/BitActionButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/Button/BitButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ButtonGroup/BitButtonGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/MenuButton/BitMenuButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Buttons/ToggleButton/BitToggleButton.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Calendar/BitCalendar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Checkbox/BitCheckbox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/ChoiceGroup/BitChoiceGroup.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/CircularTimePicker/BitCircularTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DateRangePicker/BitDateRangePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Dropdown/BitDropdown.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/NumberField/BitNumberField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/OtpInput/BitOtpInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/SearchBox/BitSearchBox.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Slider/BitSlider.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TagsInput/BitTagsInput.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TextField/BitTextField.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/TimePicker/BitTimePicker.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/Toggle/BitToggle.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Layouts/Grid/BitGrid.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Lists/Timeline/BitTimeline.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Breadcrumb/BitBreadcrumb.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/DropMenu/BitDropMenu.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/NavBar/BitNavBar.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pagination/BitPagination.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Navs/Pivot/BitPivot.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Badge/BitBadge.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Notifications/Tag/BitTag.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Icon/BitIcon.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/Link/BitLink.scss
  • src/BlazorUI/Bit.BlazorUI/Components/Utilities/MediaQuery/BitMediaQuery.razor.cs
  • src/BlazorUI/Bit.BlazorUI/Extensions/IBitBlazorUIServiceCollectionExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/bit.blazorui.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-dark.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-light.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/forced-colors.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/semantic-tokens.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/Fluent/shapes.fluent.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/bit-css.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/functions.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/media-queries.scss
  • src/BlazorUI/Bit.BlazorUI/Styles/theme-variables.scss
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitAccentColorPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitExternalThemeLoader.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme.ts
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitTheme.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBoxShadows.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeBreakpoints.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeColors.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeLayout.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeMotion.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitTheme/BitThemeShapes.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeAttributeNames.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeBreakpointDefaults.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeChangedEventArgs.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorContrast.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeColorDerivation.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeCookie.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeDensityPresets.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsExtensions.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeJsNotifierReceiver.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeManager.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeMapper.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeName.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeNotifications.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeProvider.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSerialization.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeSsr.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/BitThemeUtilities.cs
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ActionButton/BitActionButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/Button/BitButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/BitButtonGroupDemo.razor.scss
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ButtonGroup/_BitButtonGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Buttons/ToggleButton/BitToggleButtonDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/Checkbox/BitCheckboxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/ChoiceGroup/_BitChoiceGroupOptionDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Inputs/SearchBox/BitSearchBoxDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineCustomDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineItemDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Lists/Timeline/_BitTimelineOptionDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pagination/BitPaginationDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Navs/Pivot/BitPivotDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Badge/BitBadgeDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Notifications/Tag/BitTagDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Icon/BitIconDemo.razor.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/Components/Utilities/Link/BitLinkDemo.razor.samples.cs
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Pages/ThemingPage.razor
  • src/BlazorUI/Demo/Client/Bit.BlazorUI.Demo.Client.Core/Scripts/app.ts
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorContrastTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeColorDerivationTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeMapperMergeDriftTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderHtmlAttributesTest.razor
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeProviderTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/BitThemeSsrTests.cs
  • src/BlazorUI/Tests/Bit.BlazorUI.Tests/Utils/Theme/ThemeProbeConsumer.cs
💤 Files with no reviewable changes (1)
  • src/BlazorUI/Bit.BlazorUI/Utils/Theme/bit-theme.ts

Comment on lines +22 to +24
&:focus-visible {
@include focus-ring(var(--bit-lnk-clr));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Wire focus ring to per-variant focus tokens.

BitButton now defines --bit-btn-clr-focus for each variant and uses it in focus-ring(), but BitLink still uses the base --bit-lnk-clr. To maintain consistency with the new focus-token pattern and fully realize the "improve focus state handling" objective, define --bit-lnk-clr-focus in each variant block (lines 82–182) and update the mixin call.

♻️ Example for .bit-lnk-pri
+&:focus-visible {
+    `@include` focus-ring(var(--bit-lnk-clr-focus));
+}

 .bit-lnk-pri {
     --bit-lnk-clr: #{$clr-pri};
     --bit-lnk-clr-hover: #{$clr-pri-hover};
+    --bit-lnk-clr-focus: #{$clr-pri-focus};
     --bit-lnk-clr-dis: #{$clr-pri-dis-text};
 }

Apply the same pattern to .bit-lnk-sec, .bit-lnk-ter, and all other variants.

🤖 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/Utilities/Link/BitLink.scss` around
lines 22 - 24, The :focus-visible block in BitLink.scss calls `@include`
focus-ring(var(--bit-lnk-clr)) but BitButton now uses per-variant focus tokens;
update BitLink to define --bit-lnk-clr-focus inside each variant block (e.g.,
.bit-lnk-pri, .bit-lnk-sec, .bit-lnk-ter and any other variants currently
defined) and change the mixin invocation in the &:focus-visible rule to `@include`
focus-ring(var(--bit-lnk-clr-focus)); ensure each variant block sets an
appropriate focus color value for --bit-lnk-clr-focus.

Comment on lines +9 to +15
@media (prefers-reduced-motion: reduce) {
:root {
--bit-mot-duration: 0.01ms;
--bit-mot-duration-short: 0.01ms;
--bit-mot-duration-long: 0.01ms;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the recommended duration value for prefers-reduced-motion in CSS - should it be 0.01ms, 1ms, or 0s?

💡 Result:

Recommended duration value for prefers-reduced-motion: use 0s (or 0ms) / ideally disable motion rather than “almost zero”. In practice, the most accessible/robust approach is to set animation: none !important; and transition: none !important; inside @media (prefers-reduced-motion: reduce) [1][2]. This directly removes non-essential motion, matching the intent of the reduce preference (“preferably to the point where all non-essential movement is removed”) [1][3]. The “tiny non-zero” durations you’ll see in the wild (commonly 0.01ms, sometimes 0.001ms) are hacks used when you need the animation/transition to still technically start (e.g., for code relying on events) instead of being fully disabled [1][2]. They are not described by the official docs as the standard recommended value; they’re specifically presented as a fallback/less-radical technique when none could break behavior on some sites [1]. Therefore: choose 0s/0ms (or none) as the recommended target; only consider 0.01ms (or 0.001ms) as a compatibility workaround when fully disabling breaks required functionality [1].

Citations:


Use an accessibility-safe reduced-motion value (avoid 0.01ms “almost zero”)

In @media (prefers-reduced-motion: reduce), setting durations to 0.01ms is generally a hack; the recommended behavior is to effectively disable non-essential motion (e.g., 0s/0ms or animation/transition: none) so the “reduce” preference is honored reliably.

File: src/BlazorUI/Bit.BlazorUI/Styles/Fluent/motion.fluent.scss (lines 9-15)

🤖 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/motion.fluent.scss` around lines 9 -
15, The current reduced-motion rule sets --bit-mot-duration,
--bit-mot-duration-short, and --bit-mot-duration-long to 0.01ms which is
effectively a hack; update the `@media` (prefers-reduced-motion: reduce) :root
block so those CSS custom properties are set to 0ms (or set
animations/transitions to none where used) to fully honor the user's preference;
specifically change the values for --bit-mot-duration, --bit-mot-duration-short,
and --bit-mot-duration-long used by your motion/animation code paths (and ensure
any code reading these vars treats "0ms" as disabled).

Comment on lines +78 to +82
let theme = Theme._initOptions.theme || Theme._initOptions.default || Theme._lightTheme;

if (Theme._initOptions.system) {
theme = Theme.isSystemDark() ? Theme._darkTheme : Theme._lightTheme;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Honor explicit theme/default before system resolution.

When system is enabled, this block overwrites any explicit theme or default value. That makes <html bit-theme="fluent-dark" bit-theme-system> resolve to the OS theme instead of the explicit preset, which contradicts the documented precedence and removes the escape hatch for hosts that keep bit-theme-system present as a fallback. Restrict OS resolution to the cases where the selected value is actually system or no explicit/default theme was supplied.

🤖 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/BitTheme.ts` around lines 78 - 82, The
current logic always overrides any explicit Theme._initOptions.theme or
Theme._initOptions.default when Theme._initOptions.system is true; change it so
OS resolution (using Theme.isSystemDark() to set Theme._darkTheme or
Theme._lightTheme) only runs when the chosen value is explicitly 'system' or
when neither theme nor default were supplied (i.e., Theme._initOptions.theme ===
'system' OR (!Theme._initOptions.theme && !Theme._initOptions.default &&
Theme._initOptions.system)); otherwise leave the initially selected theme (from
Theme._initOptions.theme or Theme._initOptions.default) intact.

Comment on lines +192 to +198
public static applyTheme(theme: Record<string, string>, element?: HTMLElement) {
const el = element || document.body;
const keys = Object.keys(theme);
const prev = Theme._appliedVarKeys.get(el) || [];
keys.forEach(key => el.style.setProperty(key, theme[key]));
Theme._appliedVarKeys.set(el, [...new Set([...prev, ...keys])]);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Remove previously applied vars that disappear from the next theme.

applyTheme only sets the new keys and keeps a union of all historic keys. If a later call applies a smaller theme object, omitted variables stay stuck on the element and ApplyBitThemeAsync no longer behaves like a replace operation.

💡 Proposed fix
         public static applyTheme(theme: Record<string, string>, element?: HTMLElement) {
             const el = element || document.body;
             const keys = Object.keys(theme);
             const prev = Theme._appliedVarKeys.get(el) || [];
+            prev
+                .filter(key => !keys.includes(key))
+                .forEach(key => el.style.removeProperty(key));
             keys.forEach(key => el.style.setProperty(key, theme[key]));
-            Theme._appliedVarKeys.set(el, [...new Set([...prev, ...keys])]);
+            Theme._appliedVarKeys.set(el, keys);
         }
🤖 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/BitTheme.ts` around lines 192 - 198,
applyTheme currently unions historic CSS variable keys (Theme._appliedVarKeys)
and never removes keys that are omitted in a later theme, leaving stale vars on
the element; change applyTheme (the method in BitTheme/Theme) to compute removed
keys as those in prev but not in keys, call el.style.removeProperty for each
removed key, then set the new keys (and update Theme._appliedVarKeys for the
element to exactly the current keys) so applyTheme behaves as a replace
operation whether element is the provided HTMLElement or document.body.

Comment on lines +312 to +327
public static attach(linkId: string, href: string) {
const existing = document.getElementById(linkId);
let link: HTMLLinkElement;
if (existing && existing.tagName === 'LINK') {
link = existing as HTMLLinkElement;
} else {
// No element, or an element with the same id but a different tag (e.g. a stale
// <style> or <meta>): replace/insert a fresh <link> rather than blindly mutating
// an unrelated node which would break attach/detach invariants.
existing?.remove();
link = document.createElement('link');
link.id = linkId;
link.rel = 'stylesheet';
document.head.appendChild(link);
}
link.href = href;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate stylesheet URLs in the JS loader as well.

ExternalTheme.attach accepts any href and writes it straight into the DOM. That bypasses the same-origin / http(s) safety rules documented for this feature and weakens the boundary for any caller that forwards tenant-controlled values here. Mirror the C# loader’s URL validation before creating or updating the <link>.

🤖 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/BitTheme.ts` around lines 312 - 327,
The attach method currently writes any href into the DOM; update BitTheme.attach
to validate href before creating/updating the <link>: parse the href with new
URL(href, document.baseURI), ensure url.protocol is 'http:' or 'https:' and
url.origin === location.origin (mirroring the C# loader’s same‑origin + http(s)
rules), and if validation fails do not set link.href (log/throw as appropriate).
Apply this validation at the start of public static attach(linkId: string, href:
string) before creating or assigning to the link element so both create and
update paths are protected.

Comment on lines +8 to +18
/// <summary>Returns a theme overlay that tightens vertical rhythm via <see cref="BitThemeLayout.DensityScale"/> and spacing scale.</summary>
/// <example>
/// Merge the overlay's density-affecting properties into your baseline <see cref="BitTheme"/>:
/// <code>
/// var theme = new BitTheme(); // your app baseline
/// var overlay = BitThemeDensityPresets.CreateCompactOverlay();
/// theme.Layout.DensityScale = overlay.Layout.DensityScale;
/// theme.Spacing.ScalingFactor = overlay.Spacing.ScalingFactor;
/// await ThemeManager.ApplyBitThemeAsync(theme);
/// </code>
/// </example>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for theme application methods in the Utils/Theme directory
rg -n --type=cs -C3 'ApplyBitThemeAsync|ApplyThemeAsync|SetTheme' src/BlazorUI/Bit.BlazorUI/Utils/Theme/

Repository: bitfoundation/bitplatform

Length of output: 9537


Clarify the XML example’s theme manager identifier

BitThemeManager exposes ApplyBitThemeAsync(BitTheme? bitTheme, ElementReference? element = null), so the ApplyBitThemeAsync(theme) call matches the actual API. The XML example’s ThemeManager identifier is the only ambiguous part—clarify it’s a BitThemeManager instance (e.g., rename to bitThemeManager or make the injection/variable origin explicit).

🤖 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
8 - 18, Update the XML example in BitThemeDensityPresets.CreateCompactOverlay's
doc comment to clarify the ThemeManager identifier: explicitly reference a
BitThemeManager instance (e.g., name the variable bitThemeManager or state it is
injected/created) and call its ApplyBitThemeAsync(theme) method so the example
matches the actual API signature (BitThemeManager.ApplyBitThemeAsync(BitTheme?
bitTheme, ElementReference? element = null)); keep the rest of the example
unchanged.

Comment on lines +1394 to +1490
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>

<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>


<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>

<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>


<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>

<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Wrap the disabled *Background samples in the same contrast container.

These copied snippets render PrimaryBackground/SecondaryBackground/TertiaryBackground against the default page background, so they won't reproduce the same disabled appearance shown by the live demos elsewhere in this PR.

Suggested fix
+<div style=""background:var(--bit-clr-fg-sec);padding:1rem"">
 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>

 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>

 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>

 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>

 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>

 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
 <BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
     <BitMenuButtonOption Text=""Option A"" Key=""A"" />
     <BitMenuButtonOption Text=""Option B"" Key=""B"" />
     <BitMenuButtonOption Text=""Option C"" Key=""C"" />
 </BitMenuButton>
+</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.

Suggested change
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""PrimaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.PrimaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""SecondaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.SecondaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"">
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Fill"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Outline"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<BitMenuButton Text=""TertiaryBackground"" TItem=""BitMenuButtonOption"" Variant=""BitVariant.Text"" Color=""BitColor.TertiaryBackground"" IsEnabled=""false"" Split>
<BitMenuButtonOption Text=""Option A"" Key=""A"" />
<BitMenuButtonOption Text=""Option B"" Key=""B"" />
<BitMenuButtonOption Text=""Option C"" Key=""C"" />
</BitMenuButton>
<div style="background:var(--bit-clr-fg-sec);padding:1rem">
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.PrimaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.PrimaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.PrimaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.PrimaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.PrimaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="PrimaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.PrimaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.SecondaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.SecondaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.SecondaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.SecondaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.SecondaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="SecondaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.SecondaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.TertiaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.TertiaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.TertiaryBackground" IsEnabled="false">
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Fill" Color="BitColor.TertiaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Outline" Color="BitColor.TertiaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
<BitMenuButton Text="TertiaryBackground" TItem="BitMenuButtonOption" Variant="BitVariant.Text" Color="BitColor.TertiaryBackground" IsEnabled="false" Split>
<BitMenuButtonOption Text="Option A" Key="A" />
<BitMenuButtonOption Text="Option B" Key="B" />
<BitMenuButtonOption Text="Option C" Key="C" />
</BitMenuButton>
</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/Buttons/MenuButton/_BitMenuButtonOptionDemo.razor.cs`
around lines 1394 - 1490, The disabled Primary/Secondary/Tertiary background
BitMenuButton examples (the BitMenuButton elements with
Text="PrimaryBackground"/"SecondaryBackground"/"TertiaryBackground" and
IsEnabled="false") are missing the contrast container used elsewhere, so they
render against the default page background; wrap each group of these disabled
samples (including both Split and non-Split variants) in the same contrast
container/component used by other background demos in this PR so they display
the correct disabled appearance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BlazorUI theme system improvements - phase II

2 participants