Skip to content

feat(Layout): add IsExpandOnHover parameter for click-to-expand sidebar - #8349

Open
h2ls wants to merge 2 commits into
dotnetcore:mainfrom
h2ls:lee/feat-layout-sidebar-click-expand
Open

feat(Layout): add IsExpandOnHover parameter for click-to-expand sidebar#8349
h2ls wants to merge 2 commits into
dotnetcore:mainfrom
h2ls:lee/feat-layout-sidebar-click-expand

Conversation

@h2ls

@h2ls h2ls commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Link issues

fixes #8348

Summary By Copilot

Add a new IsExpandOnHover parameter to the Layout component (default true, preserving existing behavior). When set to false, the collapsed sidebar no longer expands on mouse hover; instead it expands on click and collapses again when the mouse leaves the sidebar area.

Changes:

  • Layout.razor.cs: new IsExpandOnHover parameter, is-click-expand / is-expand class logic, click & mouse-leave handlers
  • Layout.razor: bind @onclick / @onmouseleave on the sidebar aside
  • Layout.razor.scss: gate hover-expand rules behind :not(.is-click-expand), add click-expand rules driven by .is-expand; bundle css regenerated
  • LayoutTest.cs: new unit test IsExpandOnHover_OK

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Default value keeps the existing hover behavior; click mode is opt-in only.

Verification

  • Manual (required)
  • Automated

LayoutTest 31/31 passed (including new IsExpandOnHover_OK), UniTest.Sass passed.

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 configurable click-based expansion for collapsed Layout sidebars while preserving hover expansion by default.

New Features:

  • Add an opt-in click-to-expand mode for collapsed sidebars, with automatic collapse when the pointer leaves the sidebar.

Enhancements:

  • Preserve the existing hover-to-expand behavior by default while supporting the new sidebar interaction mode across layout styling and split-bar presentation.

Tests:

  • Add unit coverage for click expansion, mouse-leave collapse, and the default hover behavior.

When IsExpandOnHover is false, the collapsed sidebar no longer expands
on mouse hover. Instead it expands on click and collapses again when
the mouse leaves the sidebar area. Default is true, keeping the
existing hover behavior.
Copilot AI lite review requested due to automatic review settings August 19, 2026 02:00
@bb-auto

bb-auto Bot commented Aug 19, 2026

Copy link
Copy Markdown

Thanks for your PR, @h2ls. Someone from the team will get assigned to your PR shortly and we'll get it reviewed.

@bb-auto
bb-auto Bot requested a review from ArgoZhang August 19, 2026 02:00
@bb-auto bb-auto Bot added the enhancement New feature or request label Aug 19, 2026
@sourcery-ai

sourcery-ai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds a configurable interaction mode for collapsed sidebars on the Layout component by introducing an IsExpandOnHover parameter, wiring click/hover event handlers, adjusting CSS classes and styles, and adding unit tests to cover both behaviors.

Sequence diagram for click-to-expand sidebar interaction when IsExpandOnHover is false

sequenceDiagram
    actor User
    participant Sidebar as layout_side
    participant Layout

    User->>Sidebar: click
    Sidebar->>Layout: OnClickSidebar()
    alt [IsCollapsed && !IsExpandOnHover && !_isSidebarExpand]
        Layout->>Layout: _isSidebarExpand = true
        Layout->>Sidebar: StateHasChanged()
    end

    User->>Sidebar: mouseleave
    Sidebar->>Layout: OnMouseLeaveSidebar()
    alt [_isSidebarExpand]
        Layout->>Layout: _isSidebarExpand = false
        Layout->>Sidebar: StateHasChanged()
    end
Loading

File-Level Changes

Change Details Files
Introduce IsExpandOnHover parameter and internal sidebar expand state to control hover vs click expansion behavior.
  • Add IsExpandOnHover parameter with default true and bilingual XML documentation.
  • Extend root layout CssBuilder to emit is-click-expand when collapsed and hover-expand is disabled.
  • Extend sidebar CssBuilder to emit is-expand based on new internal _isSidebarExpand flag.
  • Reset _isSidebarExpand when toggling collapsed state.
  • Add OnClickSidebar and OnMouseLeaveSidebar handlers to manage _isSidebarExpand and trigger re-render via StateHasChanged.
src/BootstrapBlazor/Components/Layout/Layout.razor.cs
Wire sidebar DOM events to new handlers for click-to-expand behavior.
  • Attach @OnClick to the sidebar to invoke OnClickSidebar.
  • Attach @onmouseleave to the sidebar to invoke OnMouseLeaveSidebar.
src/BootstrapBlazor/Components/Layout/Layout.razor
Split collapsed sidebar styling into hover-expand vs click-expand modes using new CSS classes.
  • Scope existing hover-based collapsed sidebar rules behind .is-collapsed:not(.is-click-expand).
  • Add new .is-collapsed.is-click-expand rules that keep the sidebar visually collapsed unless .layout-side has .is-expand.
  • Ensure .is-expand restores title/menu text opacity in click-expand mode.
  • Preserve existing .is-collapsed layout-main block styling separate from interaction mode.
src/BootstrapBlazor/Components/Layout/Layout.razor.scss
Add a unit test validating IsExpandOnHover behavior and class toggling in both click and hover modes.
  • Render Layout with IsCollapsed=true, Side set, and IsExpandOnHover=false and assert is-click-expand present and is-expand absent.
  • Simulate sidebar click and assert is-expand is applied.
  • Simulate mouse-leave and assert is-expand is removed.
  • Re-render with IsExpandOnHover=true and assert is-click-expand is not present.
test/UnitTest/Components/LayoutTest.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#8348 Add an IsExpandOnHover parameter to the Layout component (default true) that controls whether a collapsed sidebar expands on hover or requires click-to-expand.
#8348 Implement click-to-expand behavior when IsExpandOnHover is false: hovering over a collapsed sidebar does not expand it; clicking the sidebar expands it; moving the mouse out collapses it again.
#8348 Update styles and tests to support and verify the new IsExpandOnHover behavior for the collapsed sidebar.

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

@bb-auto bb-auto Bot added this to the v10.9.0 milestone Aug 19, 2026

@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 1 issue, and left some high level feedback:

  • Consider resetting _isSidebarExpand when IsCollapsed or IsExpandOnHover is updated externally (e.g., in OnParametersSet), to avoid the sidebar remaining visually expanded while the parent considers it collapsed.
  • In OnMouseLeaveSidebar, adding an explicit !IsExpandOnHover check alongside _isSidebarExpand would make the intent clearer and help prevent future changes from accidentally using click-collapse semantics in hover mode.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider resetting `_isSidebarExpand` when `IsCollapsed` or `IsExpandOnHover` is updated externally (e.g., in `OnParametersSet`), to avoid the sidebar remaining visually expanded while the parent considers it collapsed.
- In `OnMouseLeaveSidebar`, adding an explicit `!IsExpandOnHover` check alongside `_isSidebarExpand` would make the intent clearer and help prevent future changes from accidentally using click-collapse semantics in hover mode.

## Individual Comments

### Comment 1
<location path="src/BootstrapBlazor/Components/Layout/Layout.razor.cs" line_range="779-786" />
<code_context>
+    /// <para lang="zh">点击侧边栏回调方法 IsExpandOnHover 为 false 时点击展开侧边栏</para>
+    /// <para lang="en">Callback method when clicking the sidebar. Expands the sidebar when IsExpandOnHover is false</para>
+    /// </summary>
+    private void OnClickSidebar()
+    {
+        if (IsCollapsed && !IsExpandOnHover && !_isSidebarExpand)
+        {
+            _isSidebarExpand = true;
+            StateHasChanged();
+        }
+    }
</code_context>
<issue_to_address>
**suggestion (performance):** Remove explicit StateHasChanged calls from event handlers to avoid redundant renders.

Blazor already calls `StateHasChanged` after UI events such as `@onclick`, so the explicit call in `OnClickSidebar` is redundant and may cause extra render cycles. Unless you have a specific need for an additional render outside the normal event pipeline, you can remove this call and rely on the framework’s default behavior.

```suggestion
    private void OnClickSidebar()
    {
        if (IsCollapsed && !IsExpandOnHover && !_isSidebarExpand)
        {
            _isSidebarExpand = true;
        }
    }
```
</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.

Comment on lines +779 to +786
private void OnClickSidebar()
{
if (IsCollapsed && !IsExpandOnHover && !_isSidebarExpand)
{
_isSidebarExpand = true;
StateHasChanged();
}
}

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.

suggestion (performance): Remove explicit StateHasChanged calls from event handlers to avoid redundant renders.

Blazor already calls StateHasChanged after UI events such as @onclick, so the explicit call in OnClickSidebar is redundant and may cause extra render cycles. Unless you have a specific need for an additional render outside the normal event pipeline, you can remove this call and rely on the framework’s default behavior.

Suggested change
private void OnClickSidebar()
{
if (IsCollapsed && !IsExpandOnHover && !_isSidebarExpand)
{
_isSidebarExpand = true;
StateHasChanged();
}
}
private void OnClickSidebar()
{
if (IsCollapsed && !IsExpandOnHover && !_isSidebarExpand)
{
_isSidebarExpand = true;
}
}

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

Adds an opt-in “click-to-expand” behavior for collapsed Layout sidebars via a new IsExpandOnHover parameter, preserving the existing hover-expand behavior by default.

Changes:

  • Introduces IsExpandOnHover (default true) and click/mouse-leave handlers to support click-to-expand when disabled.
  • Updates sidebar markup and styles to switch between hover-expand and click-expand modes (is-click-expand, is-expand).
  • Adds a unit test covering the new parameter behavior.

Reviewed changes

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

File Description
test/UnitTest/Components/LayoutTest.cs Adds a unit test for IsExpandOnHover click-expand behavior (needs adjustment to validate the intended scenario).
src/BootstrapBlazor/Components/Layout/Layout.razor.scss Gates hover-expand rules behind :not(.is-click-expand) and adds click-expand rules driven by .is-expand.
src/BootstrapBlazor/Components/Layout/Layout.razor.cs Adds IsExpandOnHover, new CSS class logic, and click/mouse-leave handlers with internal _isSidebarExpand state.
src/BootstrapBlazor/Components/Layout/Layout.razor Hooks @onclick / @onmouseleave to the sidebar <aside>.

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

Comment on lines +252 to +255
// 默认悬停展开 不追加 is-click-expand 样式
cut.Render(pb => pb.Add(a => a.IsExpandOnHover, true));
cut.WaitForAssertion(() => Assert.DoesNotContain("is-click-expand", cut.Markup));
}
Comment on lines 510 to 514
private string? SideClassString => CssBuilder.Default("layout-side")
.AddClass("is-fixed-header", IsFixedHeader)
.AddClass("is-fixed-footer", IsFixedFooter)
.AddClass("is-expand", _isSidebarExpand)
.Build();
@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (06ad5c0) to head (3de8616).

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

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(Layout): add click-to-expand mode for collapsed sidebar

3 participants