Skip to content

ToolButton: 深色模式 hover/pressed 毛玻璃效果 + checked 状态样式重构 - #672

Merged
18202781743 merged 1 commit into
linuxdeepin:v25-flowstylefrom
zqq-dora:feat/toolbutton-dark-hover-pressed
Sep 7, 2026
Merged

ToolButton: 深色模式 hover/pressed 毛玻璃效果 + checked 状态样式重构#672
18202781743 merged 1 commit into
linuxdeepin:v25-flowstylefrom
zqq-dora:feat/toolbutton-dark-hover-pressed

Conversation

@zqq-dora

@zqq-dora zqq-dora commented Aug 26, 2026

Copy link
Copy Markdown

ToolButton: 深色模式 hover/pressed 毛玻璃效果 + checked 状态样式重构

背景

ToolButton 在深色模式下的 hover/pressed 样式效果不理想:hover 时使用的是浅灰色 tint(rgba(1,1,1,0.15)),缺乏层次感和质感;checked 状态复用了 Button 的 accent 填充样式,视觉上与 ToolButton 的轻量风格不匹配。

本 PR 重新设计了 ToolButton 的深色模式 hover/pressed 样式,并重构了 checked 状态的独立样式。

修改内容

1. 深色模式 hover 效果(毛玻璃)

深色模式 hover 新增了背景模糊(backdrop blur)效果,模拟设计稿中的磨砂玻璃质感:

  • 背景模糊 radius: 15saturation: 100%
  • 背景色 rgba(20, 20, 20, 0.2) 半透明深色 tint
  • 顶部 1px 白色内阴影 rgba(255, 255, 255, 0.1)(高光)
  • 底部 1px 黑色内阴影 rgba(0, 0, 0, 0.5)(暗角)
  • 圆角 6px

模糊效果通过 D.InWindowBlur 实现,使用 D.ItemViewport 裁剪到圆角形状。模糊功能受平台限制(valid 属性门控),在不支持的平台仅显示 tint + 内阴影。

2. 深色模式 pressed 效果

深色模式 pressed 使用纯色 tint rgba(0, 0, 0, 0.15),不叠加模糊和内阴影,保持简洁。

3. checked 状态样式重构

checked 状态不再复用 Button 的 accent 填充样式,改为独立的 overlay chip 样式:

  • 背景:浅色模式 rgba(0, 0, 0, 0.1~0.15),深色模式 rgba(0, 0, 0, 0.3~0.35)
  • 文字/图标:统一使用 Highlight 强调色
  • 底部 1px 内阴影:浅色 rgba(0, 0, 0, 0.1),深色 rgba(0, 0, 0, 0.5)

4. InWindowBlur 组件增强

InWindowBlur.qml 新增 saturation 属性别名,暴露 MultiEffect 的饱和度参数,使 ToolButton 的深色 hover 可以设置 100% 饱和度。

涉及文件

文件 改动
qt6/src/qml/overridable/InWindowBlur.qml 新增 saturation 属性别名
qt6/src/qml/FlowStyle.qml toolButton QtObject 新增 radiuscheckedBackgroundcheckedTextcheckedShadowhoverBackground 属性
qt6/src/qml/ToolButton.qml 重构 textColorbackground 的 Binding 逻辑,新增深色 hover 毛玻璃和内阴影、checked 状态独立样式

已知限制

  • 背景模糊(backdrop blur)依赖平台 GPU 支持,在软件渲染或不支持 InWindowBlur 的环境下会降级为纯 tint + 内阴影(仅去掉模糊,视觉效果保持一致)
  • ButtonBox 有自己的 backgroundPanel 动画覆盖层,与本 PR 的 ToolButton hover 样式独立,不在本次修改范围内

Summary by Sourcery

Redesign ToolButton state styling to provide polished dark-theme hover feedback and a lightweight checked appearance.

New Features:

  • Add a dark-theme frosted-glass hover treatment for non-checked ToolButtons with platform-gated blur and inset highlights/shadows.

Enhancements:

  • Refactor ToolButton checked styling into a lightweight overlay chip with consistent accent-colored text and state-aware shadows.
  • Expose saturation configuration through InWindowBlur and centralize ToolButton state palettes and sizing in FlowStyle.

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

Hi @zqq-dora. Thanks for your PR. 😃

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

Hi @zqq-dora. Thanks for your PR.

I'm waiting for a linuxdeepin member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@sourcery-ai

sourcery-ai Bot commented Aug 26, 2026

Copy link
Copy Markdown

Reviewer's Guide

Redesigns ToolButton interaction and checked-state rendering by centralizing state palettes, adding a platform-gated dark frosted-glass hover treatment with inset highlights/shadows, and replacing the shared accent-fill checked style with a lightweight overlay chip.

State diagram for ToolButton rendering

stateDiagram-v2
    [*] --> Normal
    Normal --> Hovered : hover
    Hovered --> Pressed : press
    Pressed --> Hovered : release
    Normal --> Checked : checked
    Hovered --> Checked : checked
    Pressed --> Checked : checked
    Checked --> Normal : unchecked

    state Hovered {
        [*] --> LightTint
        LightTint --> DarkFrostedGlass : dark theme
        DarkFrostedGlass --> DarkTintFallback : InWindowBlur.valid is false
    }
    state Pressed {
        [*] --> PressedTint
    }
    state Checked {
        [*] --> OverlayChip
        OverlayChip --> AccentContent
        OverlayChip --> InsetShadow
    }
Loading

File-Level Changes

Change Details Files
Centralize ToolButton state palettes and dimensions in FlowStyle.
  • Add radius, normal/hover/pressed backgrounds, checked-state backgrounds, accent text, and inset-shadow palettes.
  • Define separate light and dark values for checked and interaction states.
qt6/src/qml/FlowStyle.qml
Implement independent checked styling and dark-mode interaction visuals for ToolButton.
  • Bind checked and non-checked states to their dedicated palettes instead of the shared checked Button style.
  • Add dark hover backdrop blur with rounded clipping and platform-gated fallback behavior.
  • Add hover bevel shadows, checked-state bottom inset shadow, and consistent accent-colored checked content.
  • Use the palette state selector for hover and pressed tint selection.
qt6/src/qml/ToolButton.qml
Expose saturation control for in-window blur effects.
  • Add an alias from InWindowBlur to MultiEffect saturation and configure the ToolButton hover blur to full saturation.
qt6/src/qml/overridable/InWindowBlur.qml

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

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="qt6/src/qml/FlowStyle.qml" line_range="822-823" />
<code_context>
         // the highlight color of main menu item, when submenu is opened.
</code_context>
<issue_to_address>
**issue (bug_risk):** FlowStyle.qml ends with an incomplete `property D.Palette submenuOpenedItemHigh` declaration after deleting the remainder of the style object. QML parsing fails, so the style module cannot be loaded and every component importing `DS.Style` fails to instantiate.

**Suggested fix:** Restore the deleted FlowStyle contents and complete the `submenuOpenedItemHighlight` declaration and closing braces.
</issue_to_address>

### Comment 2
<location path="qt6/src/qml/FlowStyle.qml" line_range="822-823" />
<code_context>
         // the highlight color of main menu item, when submenu is opened.
</code_context>
<issue_to_address>
**issue (broader_impact):** The change removes the existing style objects after the toolButton section, including `highlightPanel`, `behindWindowBlur`, `arrowRectangleBlur`, `itemDelegate`, `scrollBar`, `progressBar`, `titleBar`, and related properties that remain referenced by QML components. Those references resolve to undefined style objects at runtime even if the truncated FlowStyle declaration is repaired.

**Triggers:** When any component using one of the removed DS.Style properties is loaded.

**Suggested fix:** Keep all unrelated FlowStyle properties and only add the new toolButton properties.
</issue_to_address>

### Comment 3
<location path="qt6/src/qml/ToolButton.qml" line_range="205" />
<code_context>
+            visible: control.checked
+            z: D.DTK.AboveOrder
+            cornerRadius: buttonPanel.radius
+            shadowColor: control.D.ColorSelector.checkedShadow
+            shadowOffsetX: 0
+            shadowOffsetY: -1
</code_context>
<issue_to_address>
**issue (bug_risk):** `D.ColorSelector` exposes palette colors using the `...Color` naming convention, but the checked shadow is read as `control.D.ColorSelector.checkedShadow`. That attached property is undefined, so the checked chip's `shadowColor` does not receive the configured palette color and can produce an invalid binding/runtime warning.

**Triggers:** When a ToolButton is checked and the checked shadow is evaluated.

**Suggested fix:** Use the ColorSelector-exposed checked shadow color property, such as `control.D.ColorSelector.checkedShadowColor`, or bind directly to the `checkedShadow` palette through a supported selector API.
</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 thread qt6/src/qml/FlowStyle.qml Outdated
Comment thread qt6/src/qml/FlowStyle.qml Outdated
Comment thread qt6/src/qml/ToolButton.qml
@hudeng-go

Copy link
Copy Markdown

/ok-to-test

Comment thread qt6/src/qml/FlowStyle.qml
Comment thread qt6/src/qml/ToolButton.qml
Comment thread qt6/src/qml/FlowStyle.qml Outdated
@zqq-dora

zqq-dora commented Sep 3, 2026

Copy link
Copy Markdown
Author

关于内阴影在 QWidget 端的实现问题,已在 dtkwidget 中新增了 DDrawUtils::drawInsetShadow(),接口与现有的 drawShadow() 平行,使用同样的 qt_blurImage 做内阴影渲染,可以在 QWidget 的 ToolButton 样式中调用以实现一致的视觉效果。

dtkwidget PR: linuxdeepin/dtkwidget#779

关于性能问题,深色 hover 的模糊和内阴影只在鼠标悬停时触发(__darkHover 条件门控),且 ToolButton 通常只有少量同时显示,实际开销可控。在不支持 InWindowBlur 的平台上会自动降级为纯 tint + 内阴影,不会触发模糊。

另外,之前的两个问题也已修复:

  1. FlowStyle.qml 被误删的样式对象已全部恢复
  2. hoverBackground 已改名为 background,利用 Palette 内建的状态切换机制,不再手动判断 controlState

@18202781743

Copy link
Copy Markdown
Contributor

这一个pr只需要一个commit,

Comment thread qt6/src/qml/ToolButton.qml
Comment thread qt6/src/qml/ToolButton.qml Outdated
Binding on visible {
when: D.DTK.hasAnimation
value: control.hovered && !control.checked
when: control.checked

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.

when: D.DTK.hasAnimation
value: control.hovered && !control.checked
这个逻辑不需要了么?如果直接为true,直接绑定就好了,应该不需要这个Binding,

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

这里我已经删掉了。ButtonPanel 默认的 visible 逻辑本身就覆盖了 button.checked,checked 态仍然会正常显示,所以这个额外的 Binding 确实是冗余的。

@18202781743

Copy link
Copy Markdown
Contributor

需要修下ci报错的问题,

@zqq-dora
zqq-dora force-pushed the feat/toolbutton-dark-hover-pressed branch from 00a3b43 to 2f31602 Compare September 4, 2026 02:43
@zqq-dora

zqq-dora commented Sep 4, 2026

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA.

@zqq-dora

zqq-dora commented Sep 4, 2026

Copy link
Copy Markdown
Author

recheck

@18202781743
18202781743 force-pushed the feat/toolbutton-dark-hover-pressed branch from 2f31602 to 10704de Compare September 7, 2026 01:33
@zqq-dora
zqq-dora force-pushed the feat/toolbutton-dark-hover-pressed branch from 10704de to 22126b7 Compare September 7, 2026 02:13
@zqq-dora

zqq-dora commented Sep 7, 2026

Copy link
Copy Markdown
Author

recheck

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, zqq-dora

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@18202781743 18202781743 closed this Sep 7, 2026
@18202781743 18202781743 reopened this Sep 7, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

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

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="qt6/src/qml/ToolButton.qml" line_range="200" />
<code_context>
+            visible: control.checked
+            z: D.DTK.AboveOrder
+            cornerRadius: buttonPanel.radius
+            shadowColor: control.D.ColorSelector.checkedShadow
+            shadowOffsetX: 0
+            shadowOffsetY: -1
</code_context>
<issue_to_address>
**issue (bug_risk):** The checked-chip shadow reads `control.D.ColorSelector.checkedShadow`, but `checkedShadow` is declared on `control`, not exposed by the `D.ColorSelector` attached object. QML fails to resolve this non-existent attached property when loading `ToolButton.qml`, so ToolButton creation/import fails.

**Triggers:** When a checked ToolButton is loaded and the binding is evaluated.

**Suggested fix:** Use the declared `control.checkedShadow` palette and explicitly select its state, or expose `checkedShadow` as a supported `ColorSelector` property.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

visible: control.checked
z: D.DTK.AboveOrder
cornerRadius: buttonPanel.radius
shadowColor: control.D.ColorSelector.checkedShadow

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): The checked-chip shadow reads control.D.ColorSelector.checkedShadow, but checkedShadow is declared on control, not exposed by the D.ColorSelector attached object. QML fails to resolve this non-existent attached property when loading ToolButton.qml, so ToolButton creation/import fails.

Triggers: When a checked ToolButton is loaded and the binding is evaluated.

Suggested fix: Use the declared control.checkedShadow palette and explicitly select its state, or expose checkedShadow as a supported ColorSelector property.

- 深色 hover: backdrop blur(radius=15, saturation=100%) + rgba(20,20,20,0.2) tint + 白色顶部/黑色底部内阴影
- 深色 pressed: rgba(0,0,0,0.15) 纯色 tint
- checked 状态: 独立 overlay chip 样式(checkedBackground/checkedText/checkedShadow)
- InWindowBlur: 新增 saturation 属性别名
- FlowStyle toolButton: 新增 radius/checkedBackground/checkedText/checkedShadow/background
- textColor 改为统一使用 toolButton.checkedText,不再按 hasAnimation 切换旧 checkedButton 文本样式
- 移除冗余的 checked visible Binding,复用 ButtonPanel 默认可见性
- 更新 ToolButton SPDX 版权年份到 2026
@zqq-dora
zqq-dora force-pushed the feat/toolbutton-dark-hover-pressed branch from 22126b7 to 4ffe48d Compare September 7, 2026 02:39
@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 98 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 98 分,大于 70 分通过阈值,代码质量符合要求。本次 PR 为 ToolButton 深色模式 hover/pressed 毛玻璃效果及 checked 状态样式重构,实现清晰、注释完善,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 语法正确,逻辑清晰。QML 属性声明、Binding 元素、组件嵌套均符合规范。__darkHover 条件判断逻辑正确,通过 readonly property 组合多个条件判断(非 checked + 深色主题 + HoveredState),确保毛玻璃效果仅在正确的场景下触发。


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. qt6/src/qml/FlowStyle.qml:42 - checkedText 调色板所有 6 个状态值完全相同,存在冗余定义
  2. qt6/src/qml/FlowStyle.qml:15 - checkedBackground 和 background 调色板中 common 和 crystal 主题值完全相同,存在重复

建议: 代码结构清晰,注释完整。建议考虑简化 checkedText 调色板的冗余状态定义,如果 DTK Palette API 支持通配状态或默认值继承机制,可减少重复代码。


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理。InWindowBlur 使用 offscreen: true 优化渲染性能,且仅在深色模式 hover 且非 checked 状态下激活(通过 __darkHover 条件门控)。BoxInsetShadow 元素轻量级,不会造成性能瓶颈。


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: 存在0个安全漏洞。本次修改为纯 QML UI 样式代码,不涉及用户输入处理、网络操作、文件系统访问、命令执行等安全敏感操作,无安全风险。


💡 改进建议代码示例

// FlowStyle.qml - checkedText 可简化为单一状态
// 当前所有 6 个状态均为相同值,可考虑简化
property D.Palette checkedText: D.Palette {
    normal: D.DTK.makeColor(D.Color.Highlight)
    normalDark: D.DTK.makeColor(D.Color.Highlight)
    hovered: D.DTK.makeColor(D.Color.Highlight)
    hoveredDark: D.DTK.makeColor(D.Color.Highlight)
    pressed: D.DTK.makeColor(D.Color.Highlight)
    pressedDark: D.DTK.makeColor(D.Color.Highlight)
}
// 如果 DTK Palette 支持通配状态,可简化为:
// property D.Palette checkedText: D.DTK.makeColor(D.Color.Highlight)

本报告由 AI 代码审查工具自动生成

@18202781743
18202781743 merged commit 7070383 into linuxdeepin:v25-flowstyle Sep 7, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants