Skip to content

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

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

feat(Theme): add Fluent UI theme#8345
h2ls wants to merge 10 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 an optional Fluent UI theme with complete light and dark styling, demo coverage, documentation, and regression validation.

New Features:

  • Add a Fluent UI theme with light and dark mode styling across BootstrapBlazor components.
  • Add Fluent UI theme selection and installation examples to the demo site.
  • Add a comprehensive component preview wall for evaluating the Fluent UI theme.

Bug Fixes:

  • Prevent Motronic styles from being loaded globally when another theme is selected.
  • Improve theme chooser behavior for selection, outside clicks, disposal, and constrained mobile layouts.

Enhancements:

  • Align flyouts, popovers, tooltips, dialogs, forms, navigation, feedback, and data components with Fluent UI visual tokens and interaction states.

Documentation:

  • Add Fluent UI theme usage guidance and a parity review covering component coverage and flyout differences.

Tests:

  • Add Sass regression tests validating Fluent theme variables, CSS structure, minified output, and legacy color removal.

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 on lines +146 to +148
var banner = BannerRegex().Match(source).Value;
var body = min[banner.Length..];

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 (fa2cb1d) to head (1308797).

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #8345   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          771       771           
  Lines        34546     34546           
=========================================
  Hits         34546     34546           
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.

|---|---|---|---|
| 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 | 🟡 | 都是拖放容器,交互模型不同 |

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