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.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right 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 anchors.margins: Tokens.padding.large
nonAnimWidth: root.nonAnimWidth - anchors.margins * 2 nonAnimWidth: root.nonAnimWidth - anchors.margins * 2
@ -198,14 +198,10 @@ Item {
} }
Behavior on implicitWidth { Behavior on implicitWidth {
Anim { Anim {}
type: Anim.EmphasizedLarge
}
} }
Behavior on implicitHeight { Behavior on implicitHeight {
Anim { Anim {}
type: Anim.EmphasizedLarge
}
} }
} }

View file

@ -1,9 +1,9 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Layouts
import QtQuick.Templates
import Quickshell import Quickshell
import Quickshell.Widgets
import Caelestia.Config import Caelestia.Config
import qs.components import qs.components
import qs.components.controls import qs.components.controls
@ -28,10 +28,18 @@ Item {
anchors.top: parent.top anchors.top: parent.top
currentIndex: root.dashState.currentTab currentIndex: root.dashState.currentTab
background: null
onCurrentIndexChanged: root.dashState.currentTab = currentIndex onCurrentIndexChanged: root.dashState.currentTab = currentIndex
implicitHeight: contentHeight
background: null
contentItem: RowLayout {
spacing: 0
Repeater {
model: bar.contentModel
}
}
Repeater { Repeater {
model: ScriptModel { model: ScriptModel {
values: root.tabs values: root.tabs
@ -106,6 +114,10 @@ Item {
required property string iconName required property string iconName
readonly property bool current: TabBar.tabBar.currentItem === this 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 background: null
contentItem: CustomMouseArea { contentItem: CustomMouseArea {
@ -124,92 +136,20 @@ Item {
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onPressed: event => { onPressed: root.dashState.currentTab = tab.TabBar.index
root.dashState.currentTab = tab.TabBar.index;
const stateY = stateWrapper.y; StateLayer {
rippleAnim.x = event.x; id: stateLayer
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
anchors.fill: undefined
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2 implicitHeight: parent.height + Tokens.sizes.dashboard.tabIndicatorSpacing * 2
color: "transparent"
radius: Tokens.rounding.medium radius: Tokens.rounding.medium
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurface
StyledRect { onClicked: root.dashState.currentTab = tab.TabBar.index
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
}
}
} }
MaterialIcon { MaterialIcon {
@ -221,10 +161,12 @@ Item {
text: tab.iconName text: tab.iconName
color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant color: tab.current ? Colours.palette.m3primary : Colours.palette.m3onSurfaceVariant
fill: tab.current ? 1 : 0 fill: tab.current ? 1 : 0
fontStyle: Tokens.font.icon.large fontStyle: Tokens.font.icon.medium
Behavior on fill { Behavior on fill {
Anim {} Anim {
type: Anim.DefaultEffects
}
} }
} }