Skip to content

feat(Theme): add Fluent UI theme - #8345

Open
h2ls wants to merge 23 commits into
mainfrom
lee/feat-fluent-ui-theme
Open

feat(Theme): add Fluent UI theme#8345
h2ls wants to merge 23 commits into
mainfrom
lee/feat-fluent-ui-theme

Conversation

@h2ls

@h2ls h2ls commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

Link issues

fixes #8344

Summary By Copilot

新增一套完整的 Fluent UI 主题,主要变更:

  • 主题样式:新增 fluent.css / fluent.min.css,覆盖 Fluent UI 设计令牌(圆角、阴影、色彩、间距)与全部组件样式适配
  • 主题页面:演示站点 Theme.razor 页面新增 Fluent UI 主题入口,并提供组件预览墙(component preview wall)
  • Motronic 主题调整:由全局样式表改为可选主题,避免默认加载
  • 弹层适配:Popover、Dropdown 等 flyout 浮层适配 Fluent UI 风格
  • ThemeChooser 优化:选择主题后自动关闭面板,并改善移动端行为
  • 文档与测试:新增 Fluent UI parity review 报告、主题使用文档,以及 Sass 单元测试 FluentThemeTest.cs 做 CSS 变量回归校验

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Add Fluent UI as a selectable theme and demonstrate its styling across the component library.

New Features:

  • Add a Fluent UI theme with component styling and theme-specific site tokens.
  • Provide a comprehensive theme preview page covering common controls, data display, feedback, navigation, and picker components.

Bug Fixes:

  • Correct theme asset resolution and prevent theme chooser event handlers from persisting across disposal.

Enhancements:

  • Make Motronic an explicitly selectable theme instead of loading it globally.
  • Improve theme chooser responsiveness and interaction behavior, including scrolling, outside-click dismissal, and automatic closing after selection.
  • Adapt site styling and installation guidance for the new theme.

Documentation:

  • Document Fluent UI theme installation and usage in the theme and installation pages.

Copilot AI lite review requested due to automatic review settings August 18, 2026 01:04
@bb-auto
bb-auto Bot requested a review from ArgoZhang August 18, 2026 01:06
@bb-auto bb-auto Bot added the enhancement New feature or request label Aug 18, 2026
@bb-auto bb-auto Bot added this to the v10.9.0 milestone Aug 18, 2026
@sourcery-ai

sourcery-ai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a new Fluent UI theme for BootstrapBlazor, wires it into the demo app as an optional theme alongside Motronic, and updates the theme chooser, documentation, and tests to validate CSS variables and flyout behavior.

Sequence diagram for the updated ThemeChooser behavior

sequenceDiagram
    actor User
    participant ThemeButton as ThemeChooserButton
    participant ThemeList as ThemeListPanel
    participant Document

    User ->> ThemeButton: click
    ThemeButton ->> ThemeList: classList.toggle(is-open)

    alt Close button exists
        User ->> ThemeList: click .btn-close
        ThemeList ->> ThemeList: classList.remove(is-open)
    end

    User ->> ThemeList: click .theme-item
    ThemeList ->> ThemeList: classList.remove(is-open)

    ThemeButton ->> Document: EventHandler.on(click, outsideClick)
    Note over Document,ThemeList: outsideClick handler stored as el.themeOutsideClick

    User ->> Document: click outside ThemeButton & ThemeList
    Document ->> ThemeList: classList.remove(is-open)

    ThemeButton ->> ThemeButton: dispose(id)
    ThemeButton ->> ThemeButton: EventHandler.off(click)
    ThemeButton ->> Document: EventHandler.off(click, el.themeOutsideClick)
    ThemeButton ->> ThemeButton: delete el.themeOutsideClick
    ThemeButton ->> ThemeList: EventHandler.off(click)
Loading

File-Level Changes

Change Details Files
Add Fluent UI theme CSS and integrate it as an optional theme in the server app.
  • Introduce a large Fluent UI theme stylesheet that maps Fluent design tokens to Bootstrap/BootstrapBlazor CSS variables for light and dark modes.
  • Add a minified version of the Fluent theme CSS used by consuming apps, ensuring it is a true minified build with preserved license banner.
  • Add a small site-specific Fluent CSS file to style the demo site's layout controls and theme switcher in Fluent colors.
  • Register the Fluent theme and convert Motronic to an optional theme in appsettings so both are loaded on demand rather than Motronic being global.
  • Remove the always-on Motronic CSS link from App.razor so the default site theme is just the base BootstrapBlazor bundle.
  • Document Fluent CSS usage in the Install page for both CDN-like and Assets-based setups, including Fluent alongside Bootstrap and Motronic.
  • Update localization resources to include new Fluent-related strings for the Theme and Install pages.
src/BootstrapBlazor/wwwroot/css/fluent.css
src/BootstrapBlazor/wwwroot/css/fluent.min.css
src/BootstrapBlazor.Server/wwwroot/css/fluent.css
src/BootstrapBlazor.Server/appsettings.json
src/BootstrapBlazor.Server/Components/App.razor
src/BootstrapBlazor.Server/Components/Pages/Install.razor
src/BootstrapBlazor.Server/Locales/en-US.json
src/BootstrapBlazor.Server/Locales/zh-CN.json
Extend the Theme page with Fluent usage instructions and a comprehensive component preview wall.
  • Inject MessageService and ToastService into the Theme page to drive feedback samples.
  • Update the textual guidance to explain how to include bootstrap.blazor.bundle.min.css, fluent.min.css, and motronic.min.css, with localized text keys for new content.
  • Add a large component preview section exercising buttons, form controls, table, tags/badges, cards, progress indicators, skeletons, alerts, modal, tooltip/popover, messages/toasts, tabs, breadcrumb/pagination, menu, and pickers, all wired to simple demo data.
  • Implement backing C# code for the preview page, including Select items, breadcrumb/menu models, table data, modal reference, and handlers to show modal, message, and toast.
  • Add a small CSS override so the embedded table preview uses auto height instead of stretching the full page via .table-container defaults.
src/BootstrapBlazor.Server/Components/Pages/Theme.razor
src/BootstrapBlazor.Server/Components/Pages/Theme.razor.css
Improve ThemeChooser behavior and responsiveness, especially on mobile and when interacting outside the panel.
  • Guard against missing .theme-list elements in init to avoid null reference errors when the theme chooser is not present.
  • Ensure the close button is looked up relative to the theme list and only wired when present.
  • Close the theme list when a theme-item is clicked, so selecting a theme collapses the panel automatically.
  • Add a document-level click handler that closes the theme list when clicking outside the trigger and panel, storing a reference on the trigger element for cleanup.
  • Clean up event handlers on dispose, including the outside-click handler, theme-list click handlers, and close button events for proper teardown.
  • Change the theme list height animation from a fixed height to max-height with a capped viewport percentage and enable vertical scrolling with overscroll-behavior, improving mobile usability.
  • Allow the theme list to be responsive with max-width relative to viewport and update header to be sticky so the header stays visible when scrolling theme items.
  • Increase theme-item padding and tweak spacing for better touch targets.
src/BootstrapBlazor.Server/Components/Components/ThemeChooser.razor.js
src/BootstrapBlazor.Server/Components/Components/ThemeChooser.razor.css
Add documentation and tests to validate the Fluent theme and prevent regressions in CSS variables.
  • Introduce a detailed Fluent UI parity review markdown document describing component-level mapping, theme token alignment, and flyout differences between BootstrapBlazor and Fluent UI.
  • Add a dedicated test class that asserts the Fluent theme CSS has balanced braces, defines required semantic variables for light/dark, does not reference undefined CSS variables, and avoids legacy Motronic/Bootstrap color literals.
  • Validate that key component sections (dropdown, popover, tooltip, modal, switch, table) are present in the theme CSS.
  • Verify that the minified fluent.min.css exists, is actually smaller than the source, keeps only a single long body line (true minification), preserves the header banner, and has the same set of CSS variable definitions as the non-minified file.
docs/fluentui-parity-review.md
test/UniTest.Sass/FluentThemeTest.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#8344 Add a complete Fluent UI theme to the library, including fluent.css/fluent.min.css implementing Fluent design tokens for light/dark modes and provide documentation and regression tests for the theme.
#8344 Integrate the Fluent UI theme into the demo site, including adding a Fluent entry and component preview wall on Theme.razor, updating Install.razor and locale texts, and changing Motronic from a globally loaded stylesheet to a selectable theme via configuration.
#8344 Adjust flyout-style components and the theme chooser behavior to align with Fluent UI, including CSS adaptations for dropdowns/popovers/tooltips and improving ThemeChooser (auto close on selection, outside-click handling, better mobile behavior).

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 adds a new Fluent UI theme to BootstrapBlazor (including light/dark tokens and component-specific variable overrides), wires it into the demo site’s theme switching flow, and introduces regression tests to guard theme CSS variable integrity and minified asset quality.

Changes:

  • Add Fluent UI theme assets (fluent.css + fluent.min.css) with broad Bootstrap/BootstrapBlazor token + component coverage.
  • Update the demo site to treat themes as optional (Motronic no longer globally loaded), register Fluent as a selectable theme, and expand the Theme page with a component preview wall.
  • Add Sass/unit tests validating Fluent theme semantic variables, var() references, minified banner preservation, and minified/source variable-set parity.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/UniTest.Sass/FluentThemeTest.cs Adds automated checks for Fluent theme CSS correctness and minified asset expectations
src/BootstrapBlazor/wwwroot/css/fluent.css Adds readable Fluent UI theme source (tokens + component overrides)
src/BootstrapBlazor/wwwroot/css/fluent.min.css Adds minified Fluent UI theme with preserved banner header
src/BootstrapBlazor.Server/wwwroot/css/fluent.css Adds demo-site-only Fluent styling variables (site appearance overrides)
src/BootstrapBlazor.Server/Locales/zh-CN.json Adds/updates localized strings for Install/Theme pages to reference Fluent theme
src/BootstrapBlazor.Server/Locales/en-US.json Adds/updates localized strings for Install/Theme pages to reference Fluent theme
src/BootstrapBlazor.Server/Components/Pages/Theme.razor.css Fixes Table preview sizing inside the new preview wall
src/BootstrapBlazor.Server/Components/Pages/Theme.razor Updates theme docs and adds a large component preview wall
src/BootstrapBlazor.Server/Components/Pages/Install.razor Adds Fluent theme link snippet to install instructions
src/BootstrapBlazor.Server/Components/Components/ThemeChooser.razor.js Improves chooser UX: close-on-select, outside-click close, safer element checks
src/BootstrapBlazor.Server/Components/Components/ThemeChooser.razor.css Improves chooser mobile behavior (max-height, scrolling, sticky header)
src/BootstrapBlazor.Server/Components/App.razor Stops globally loading Motronic theme CSS
src/BootstrapBlazor.Server/appsettings.json Registers Fluent and Motronic as optional selectable themes
docs/fluentui-parity-review.md Adds a Fluent parity review/report and execution notes
Files not reviewed (1)
  • src/BootstrapBlazor/wwwroot/css/fluent.min.css: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread test/UniTest.Sass/FluentThemeTest.cs Outdated
Comment on lines +146 to +148
var banner = BannerRegex().Match(source).Value;
var body = min[banner.Length..];

Comment thread test/UniTest.Sass/FluentThemeTest.cs Outdated
Comment on lines +149 to +152
// 正文为单行(不存在多行规则)且平均行长远超可读版本
var bodyLines = body.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
Assert.Single(bodyLines);
Assert.True(bodyLines[0].Length > 10000, "压缩文件正文疑似未被压缩");
Comment on lines +37 to +41
<h4>Component preview</h4>

<p>Sections below exercise the core components with minimal parameters. Use the theme button at the bottom-right corner of this site to switch between Fluent UI, Motronic and Bootstrap in light or dark mode and eyeball the result in one place.</p>

<h4>Buttons</h4>
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (00ce3eb) to head (bfc7532).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8345   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          771       771           
  Lines        34575     34575           
=========================================
  Hits         34575     34575           
Flag Coverage Δ
BB 100.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've found 2 issues, and left some high level feedback:

  • Theme.razor introduces a large amount of hardcoded English UI text (e.g. section titles and descriptions) alongside localized strings; consider moving these into the existing localization resources to keep the page fully localizable.
  • ThemeChooser.razor.js dispose still queries .theme-list .btn-close but does not detach its handler anymore; either remove the unused close lookup or consistently unregister any remaining listeners to keep the cleanup logic straightforward.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Theme.razor introduces a large amount of hardcoded English UI text (e.g. section titles and descriptions) alongside localized strings; consider moving these into the existing localization resources to keep the page fully localizable.
- ThemeChooser.razor.js dispose still queries `.theme-list .btn-close` but does not detach its handler anymore; either remove the unused `close` lookup or consistently unregister any remaining listeners to keep the cleanup logic straightforward.

## Individual Comments

### Comment 1
<location path="src/BootstrapBlazor.Server/Components/Pages/Theme.razor" line_range="251" />
<code_context>
+
+<div class="row g-3">
+    <div class="col-12 col-md-4">
+        <DateTimePicker TValue="DateTime" Value="DateTime.Today" />
+    </div>
+    <div class="col-12 col-md-4">
</code_context>
<issue_to_address>
**issue (bug_risk):** Bind the DateTimePicker Value as a C# expression rather than a string literal.

`Value="DateTime.Today"` is treated as a string, not a `DateTime`. Use `Value="@DateTime.Today"` (or bind to a `DateTime` property) so the picker receives the correct type and avoids compile/runtime binding errors.
</issue_to_address>

### Comment 2
<location path="docs/fluentui-parity-review.md" line_range="176" />
<code_context>
+|---|---|---|---|
+| Icon / SvgIcon / BootstrapBlazorIcon | FluentIcon | ✅ | Fluent 图标体系(Fluent System Icons)是独立资产包 |
+| ThemeProvider | FluentDesignTheme / FluentDesignSystemProvider | 🟡 | 都能切明暗主题;Fluent 的设计令牌体系更完整 |
+| Dropzone(DragDrap) | FluentDragContainer / FluentDropZone | 🟡 | 都是拖放容器,交互模型不同 |
+| Logout / LogoutLink | FluentProfileMenu | 🟡 | |
+| FullScreen / GoTop / Affix / Transition | — | ❌ | |
</code_context>
<issue_to_address>
**issue (typo):** Typo in the term "DragDrap" — should likely be "DragDrop".

In the Dropzone row, correct the label from "DragDrap" to "DragDrop" to match the drag-and-drop terminology and avoid confusion.

```suggestion
| Dropzone(DragDrop) | FluentDragContainer / FluentDropZone | 🟡 | 都是拖放容器,交互模型不同 |
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


<div class="row g-3">
<div class="col-12 col-md-4">
<DateTimePicker TValue="DateTime" Value="DateTime.Today" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): Bind the DateTimePicker Value as a C# expression rather than a string literal.

Value="DateTime.Today" is treated as a string, not a DateTime. Use Value="@DateTime.Today" (or bind to a DateTime property) so the picker receives the correct type and avoids compile/runtime binding errors.

Comment thread docs/fluentui-parity-review.md Outdated
|---|---|---|---|
| Icon / SvgIcon / BootstrapBlazorIcon | FluentIcon | ✅ | Fluent 图标体系(Fluent System Icons)是独立资产包 |
| ThemeProvider | FluentDesignTheme / FluentDesignSystemProvider | 🟡 | 都能切明暗主题;Fluent 的设计令牌体系更完整 |
| Dropzone(DragDrap) | FluentDragContainer / FluentDropZone | 🟡 | 都是拖放容器,交互模型不同 |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

issue (typo): Typo in the term "DragDrap" — should likely be "DragDrop".

In the Dropzone row, correct the label from "DragDrap" to "DragDrop" to match the drag-and-drop terminology and avoid confusion.

Suggested change
| Dropzone(DragDrap| FluentDragContainer / FluentDropZone | 🟡 | 都是拖放容器,交互模型不同 |
| Dropzone(DragDrop| FluentDragContainer / FluentDropZone | 🟡 | 都是拖放容器,交互模型不同 |

ArgoZhang and others added 10 commits August 21, 2026 10:11
…yles

- remove global .navbar foreground override: the later-loaded theme won
  equal-specificity ties and painted dark text on brand-colored navbars
- define explicit --bs-btn-color on .btn-primary/.btn-success/.btn-danger/
  .btn-dark so a consumer re-pointing the foreground cannot end up
  stranded on the theme's brand fill
- DemoBlock: replace hard-coded #d3dce6/#409eff with theme tokens
- Header: invert fill-less repo svg icons to white on the colored header
- regenerate fluent.min.css
…cing tokens

- base typography 14px/20px (fontSizeBase300/lineHeightBase300)
- button/input/select 32px medium density (small 24px, large 40px)
- checkbox/radio 16px indicator with Fluent label gap
- dialog 24px surface padding, card 12px, alert 36px row height
- pagination/list-group/dropdown density aligned to spacing scale
- route .form-control padding through --bb-form-control-padding and add
  min-height 32/24/40 so the 32px control target is actually reached
- rework checkbox/radio metrics with specificity-free :where() exclusions
  (size variants, form-check-reverse, is-label, table-excel cells stay intact)
- drive pagination via --bb-pagination-link-padding with breakpoint mirrors
  and re-point the active page from legacy blue to brand
- give SweetAlert popup a themed surface (dark white-on-white fix)
- add the dark outline button family, dark primary/secondary recipes and
  brand100 accents for checked/interactive states across components
- set modal header/footer padding directly and re-calibrate form-footer
- mirror the bundle exclusion chain on input hover; honor reduced-motion
- sync --bb-height/select/multi-select triggers to the 32px rhythm
- fix secondary-surface invisibility in ClockPicker/Circle/Checkbox and
  assorted token-ramp/comment corrections; extend FluentThemeTest contract
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(Theme): 新增 Fluent UI 主题

3 participants