fix: pixel align dash tabs + use smaller icons

Also use state layer instead of custom impl
This commit is contained in:
2 * r + 2 * t 2026-04-23 02:38:51 +10:00
parent 6897f0629a
commit e653ed1cdf
2 changed files with 29 additions and 91 deletions

View file

@ -66,7 +66,7 @@ Item {
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.topMargin: Tokens.padding.medium
anchors.topMargin: Math.min(anchors.margins, Math.max(0, anchors.margins - Config.border.thickness))
anchors.margins: Tokens.padding.large
nonAnimWidth: root.nonAnimWidth - anchors.margins * 2
@ -198,14 +198,10 @@ Item {
}
Behavior on implicitWidth {
Anim {
type: Anim.EmphasizedLarge
}
Anim {}
}
Behavior on implicitHeight {
Anim {
type: Anim.EmphasizedLarge
}
Anim {}
}
}

View file

@ -1,9 +1,9 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Templates
import Quickshell
import Quickshell.Widgets
import Caelestia.Config
import qs.components
import qs.components.controls
@ -28,10 +28,18 @@ Item {
anchors.top: parent.top
currentIndex: root.dashState.currentTab
background: null
onCurrentIndexChanged: root.dashState.currentTab = currentIndex
implicitHeight: contentHeight
background: null
contentItem: RowLayout {
spacing: 0
Repeater {
model: bar.contentModel
}
}
Repeater {
model: ScriptModel {
values: root.tabs
@ -106,6 +114,10 @@ Item {
required property string iconName
readonly property bool current: TabBar.tabBar.currentItem === this
Layout.fillWidth: true
Layout.preferredWidth: 1 // Uniform width across all tabs
implicitWidth: implicitContentWidth
implicitHeight: implicitContentHeight
background: null
contentItem: CustomMouseArea {
@ -124,92 +136,20 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onPressed: event => {
root.dashState.currentTab = tab.TabBar.index;
onPressed: root.dashState.currentTab = tab.TabBar.index
const stateY = stateWrapper.y;
rippleAnim.x = event.x;
rippleAnim.y = event.y - stateY;
const dist = (ox, oy) => ox * ox + oy * oy;
rippleAnim.radius = Math.sqrt(Math.max(dist(event.x, event.y + stateY), dist(event.x, stateWrapper.height - event.y), dist(width - event.x, event.y + stateY), dist(width - event.x, stateWrapper.height - event.y)));
rippleAnim.restart();
}
SequentialAnimation {
id: rippleAnim
property real x
property real y
property real radius
PropertyAction {
target: ripple
property: "x"
value: rippleAnim.x
}
PropertyAction {
target: ripple
property: "y"
value: rippleAnim.y
}
PropertyAction {
target: ripple
property: "opacity"
value: 0.08
}
Anim {
target: ripple
properties: "implicitWidth,implicitHeight"
from: 0
to: rippleAnim.radius * 2
duration: Tokens.anim.durations.normal
easing: Tokens.anim.standardDecel
}
Anim {
target: ripple
property: "opacity"
to: 0
}
}
ClippingRectangle {
id: stateWrapper
StateLayer {
id: stateLayer
anchors.fill: undefined
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2
color: "transparent"
radius: Tokens.rounding.medium
StyledRect {
id: stateLayer
anchors.fill: parent
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
opacity: mouse.pressed ? 0.1 : mouse.containsMouse ? 0.08 : 0
Behavior on opacity {
Anim {}
}
}
StyledRect {
id: ripple
radius: Tokens.rounding.full
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
opacity: 0
transform: Translate {
x: -ripple.width / 2
y: -ripple.height / 2
}
}
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
onClicked: root.dashState.currentTab = tab.TabBar.index
}
MaterialIcon {
@ -221,10 +161,12 @@ Item {
text: tab.iconName
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
fill: tab.current ? 1 : 0
fontStyle: Tokens.font.icon.large
fontStyle: Tokens.font.icon.medium
Behavior on fill {
Anim {}
Anim {
type: Anim.DefaultEffects
}
}
}