more hacking friendly widgets

This commit is contained in:
end-4 2025-05-26 11:40:13 +02:00
parent 6c1b27bac9
commit a2ab9d2877
9 changed files with 100 additions and 101 deletions

View file

@ -8,6 +8,9 @@ import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
/**
* A button with ripple effect similar to in Material Design.
*/
Button {
id: root
property bool toggled
@ -19,12 +22,12 @@ Button {
property bool rippleEnabled: true
property var altAction
property color colBackground: ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)
property color colBackgroundHover: Appearance.colors.colLayer1Hover
property color colBackgroundToggled: Appearance.m3colors.m3primary
property color colBackgroundToggledHover: Appearance.colors.colPrimaryHover
property color colRipple: Appearance.colors.colLayer1Active
property color colRippleToggled: Appearance.colors.colPrimaryActive
property color colBackground: ColorUtils.transparentize(Appearance?.colors.colLayer1Hover, 1) || "#00000000"
property color colBackgroundHover: Appearance?.colors.colLayer1Hover ?? "#E5DFED"
property color colBackgroundToggled: Appearance?.m3colors.m3primary ?? "#65558F"
property color colBackgroundToggledHover: Appearance?.colors.colPrimaryHover ?? "#77699C"
property color colRipple: Appearance?.colors.colLayer1Active ?? "#D6CEE2"
property color colRippleToggled: Appearance?.colors.colPrimaryActive ?? "#D6CEE2"
property color buttonColor: root.enabled ? (root.toggled ?
(root.hovered ? colBackgroundToggledHover :
@ -48,8 +51,8 @@ Button {
component RippleAnim: NumberAnimation {
duration: rippleDuration
easing.type: Appearance.animation.elementMoveEnter.type
easing.bezierCurve: Appearance.animationCurves.standardDecel
easing.type: Appearance?.animation.elementMoveEnter.type
easing.bezierCurve: Appearance?.animationCurves.standardDecel
}
MouseArea {
@ -125,7 +128,7 @@ Button {
color: root.buttonColor
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this)
}
layer.enabled: true
@ -140,11 +143,11 @@ Button {
Rectangle {
id: ripple
radius: Appearance.rounding.full
radius: Appearance?.rounding.full ?? 9999
opacity: 0
color: root.rippleColor
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
animation: Appearance?.animation.elementMoveFast.colorAnimation.createObject(this)
}
transform: Translate {

View file

@ -58,11 +58,7 @@ Item {
}
Behavior on size {
NumberAnimation {
duration: root.animationDuration
easing.type: Easing.OutCubic
}
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
}
}

View file

@ -9,7 +9,7 @@ import Quickshell.Io
import Quickshell.Widgets
TabButton {
id: button
id: root
property string buttonText
property string buttonIcon
property bool selected: false
@ -17,6 +17,10 @@ TabButton {
height: buttonBackground.height
property int tabContentWidth: buttonBackground.width - buttonBackground.radius*2
property color colBackground: ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1)
property color colBackgroundHover: Appearance.colors.colLayer1Hover
property color colRipple: Appearance.colors.colLayer1Active
PointingHandInteraction {}
component RippleAnim: NumberAnimation {
@ -42,7 +46,7 @@ TabButton {
rippleAnim.restart();
}
onReleased: (event) => {
button.click() // Because the MouseArea already consumed the event
root.click() // Because the MouseArea already consumed the event
rippleFadeAnim.restart();
}
}
@ -88,9 +92,9 @@ TabButton {
background: Rectangle {
id: buttonBackground
radius: Appearance.rounding.small
radius: Appearance?.rounding.small ?? 7
implicitHeight: 37
color: (button.hovered ? Appearance.colors.colLayer1Hover : ColorUtils.transparentize(Appearance.colors.colLayer1Hover, 1))
color: (root.hovered ? root.colBackgroundHover : root.colBackground)
layer.enabled: true
layer.effect: OpacityMask {
maskSource: Rectangle {
@ -108,7 +112,7 @@ TabButton {
id: ripple
radius: Appearance.rounding.full
color: Appearance.colors.colLayer1Active
color: root.colRipple
opacity: 0
transform: Translate {

View file

@ -9,7 +9,10 @@ import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
ListView { // Scrollable window
/**
* A ListView with animations.
*/
ListView {
id: root
spacing: 5
property real removeOvershoot: 20 // Account for gaps and bouncy animations
@ -23,7 +26,7 @@ ListView { // Scrollable window
add: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
from: 0,
to: 1,
@ -33,10 +36,10 @@ ListView { // Scrollable window
addDisplaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),
@ -45,10 +48,10 @@ ListView { // Scrollable window
displaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),
@ -57,10 +60,10 @@ ListView { // Scrollable window
move: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),
@ -68,10 +71,10 @@ ListView { // Scrollable window
}
moveDisplaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),
@ -80,11 +83,11 @@ ListView { // Scrollable window
remove: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "x",
to: root.width + root.removeOvershoot,
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "opacity",
to: 0,
})
@ -94,10 +97,10 @@ ListView { // Scrollable window
// This is movement when something is removed, not removing animation!
removeDisplaced: Transition {
animations: [
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
property: "y",
}),
Appearance.animation.elementMove.numberAnimation.createObject(this, {
Appearance?.animation.elementMove.numberAnimation.createObject(this, {
properties: "opacity,scale",
to: 1,
}),

View file

@ -8,22 +8,25 @@ import Quickshell
import Quickshell.Widgets
import Qt5Compat.GraphicalEffects
/**
* Material 3 progress bar. See https://m3.material.io/components/progress-indicators/overview
*/
ProgressBar {
id: root
property real valueBarWidth: 120
property real valueBarHeight: 4
property real valueBarGap: 4
property color highlightColor: Appearance.m3colors.m3primary
property color trackColor: Appearance.m3colors.m3secondaryContainer
property color highlightColor: Appearance?.m3colors.m3primary ?? "#685496"
property color trackColor: Appearance?.m3colors.m3secondaryContainer ?? "#F1D3F9"
Behavior on value {
animation: Appearance.animation.elementMoveEnter.numberAnimation.createObject(this)
animation: Appearance?.animation.elementMoveEnter.numberAnimation.createObject(this)
}
background: Rectangle {
anchors.fill: parent
color: "transparent"
radius: Appearance.rounding.full
radius: Appearance?.rounding.full ?? 9999
implicitHeight: valueBarHeight
implicitWidth: valueBarWidth
}
@ -35,21 +38,21 @@ ProgressBar {
Rectangle { // Left progress fill
width: root.visualPosition * parent.width
height: parent.height
radius: Appearance.rounding.full
radius: Appearance?.rounding.full ?? 9999
color: root.highlightColor
}
Rectangle { // Right remaining part fill
anchors.right: parent.right
width: (1 - root.visualPosition) * parent.width - valueBarGap
height: parent.height
radius: Appearance.rounding.full
radius: Appearance?.rounding.full ?? 9999
color: root.trackColor
}
Rectangle { // Stop point
anchors.right: parent.right
width: valueBarGap
height: valueBarGap
radius: Appearance.rounding.full
radius: Appearance?.rounding.full ?? 9999
color: root.highlightColor
}
}

View file

@ -8,22 +8,23 @@ import Quickshell.Widgets
// Material 3 slider. See https://m3.material.io/components/sliders/overview
Slider {
id: slider
id: root
property real scale: 0.85
property real backgroundDotSize: 4 * scale
property real backgroundDotMargins: 4 * scale
// property real handleMargins: 0 * scale
property real handleMargins: (slider.pressed ? 0 : 2) * scale
property real handleWidth: (slider.pressed ? 3 : 5) * scale
property real handleMargins: (root.pressed ? 0 : 2) * scale
property real handleWidth: (root.pressed ? 3 : 5) * scale
property real handleHeight: 44 * scale
property real handleLimit: slider.backgroundDotMargins
property real handleLimit: root.backgroundDotMargins
property real trackHeight: 30 * scale
property color highlightColor: Appearance.m3colors.m3primary
property color trackColor: Appearance.m3colors.m3secondaryContainer
property color handleColor: Appearance.m3colors.m3onSecondaryContainer
property real trackRadius: Appearance.rounding.verysmall * scale
property real unsharpenRadius: Appearance.rounding.unsharpen
property real limitedHandleRangeWidth: (slider.availableWidth - handleWidth - slider.handleLimit * 2)
property real limitedHandleRangeWidth: (root.availableWidth - handleWidth - root.handleLimit * 2)
property string tooltipContent: `${Math.round(value * 100)}%`
Layout.fillWidth: true
from: 0
@ -46,7 +47,7 @@ Slider {
MouseArea {
anchors.fill: parent
onPressed: (mouse) => mouse.accepted = false
cursorShape: slider.pressed ? Qt.ClosedHandCursor : Qt.PointingHandCursor
cursorShape: root.pressed ? Qt.ClosedHandCursor : Qt.PointingHandCursor
}
background: Item {
@ -57,60 +58,56 @@ Slider {
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
width: slider.handleLimit * 2 + slider.visualPosition * slider.limitedHandleRangeWidth - (slider.handleMargins + slider.handleWidth / 2)
width: root.handleLimit * 2 + root.visualPosition * root.limitedHandleRangeWidth - (root.handleMargins + root.handleWidth / 2)
height: trackHeight
color: slider.highlightColor
topLeftRadius: slider.trackRadius
bottomLeftRadius: slider.trackRadius
topRightRadius: Appearance.rounding.unsharpen
bottomRightRadius: Appearance.rounding.unsharpen
color: root.highlightColor
topLeftRadius: root.trackRadius
bottomLeftRadius: root.trackRadius
topRightRadius: root.unsharpenRadius
bottomRightRadius: root.unsharpenRadius
}
// Fill right
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
width: slider.handleLimit * 2 + (1 - slider.visualPosition) * slider.limitedHandleRangeWidth - (slider.handleMargins + slider.handleWidth / 2)
width: root.handleLimit * 2 + (1 - root.visualPosition) * root.limitedHandleRangeWidth - (root.handleMargins + root.handleWidth / 2)
height: trackHeight
color: slider.trackColor
topLeftRadius: Appearance.rounding.unsharpen
bottomLeftRadius: Appearance.rounding.unsharpen
topRightRadius: slider.trackRadius
bottomRightRadius: slider.trackRadius
color: root.trackColor
topLeftRadius: root.unsharpenRadius
bottomLeftRadius: root.unsharpenRadius
topRightRadius: root.trackRadius
bottomRightRadius: root.trackRadius
}
// Dot at the end
Rectangle {
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: slider.backgroundDotMargins
width: slider.backgroundDotSize
height: slider.backgroundDotSize
anchors.rightMargin: root.backgroundDotMargins
width: root.backgroundDotSize
height: root.backgroundDotSize
radius: Appearance.rounding.full
color: slider.handleColor
color: root.handleColor
}
}
handle: Rectangle {
id: handle
x: slider.leftPadding + slider.handleLimit + slider.visualPosition * slider.limitedHandleRangeWidth
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: slider.handleWidth
implicitHeight: slider.handleHeight
x: root.leftPadding + root.handleLimit + root.visualPosition * root.limitedHandleRangeWidth
y: root.topPadding + root.availableHeight / 2 - height / 2
implicitWidth: root.handleWidth
implicitHeight: root.handleHeight
radius: Appearance.rounding.full
color: slider.handleColor
color: root.handleColor
Behavior on implicitWidth {
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
}
StyledToolTip {
extraVisibleCondition: slider.pressed
content: slider.tooltipContent
extraVisibleCondition: root.pressed
content: root.tooltipContent
}
}
}

View file

@ -4,11 +4,16 @@ import QtQuick.Layouts
import QtQuick.Controls
import Qt5Compat.GraphicalEffects
/**
* Material 3 switch. See https://m3.material.io/components/switch/overview
*/
Switch {
id: root
property real scale: 1
implicitHeight: 32 * root.scale
implicitWidth: 52 * root.scale
property color activeColor: Appearance?.m3colors.m3primary ?? "#685496"
property color inactiveColor: Appearance?.m3colors.m3surfaceContainerHighest ?? "#45464F"
PointingHandInteraction {}
@ -16,10 +21,10 @@ Switch {
background: Rectangle {
width: parent.width
height: parent.height
radius: Appearance.rounding.full
color: root.checked ? Appearance.m3colors.m3primary : Appearance.m3colors.m3surfaceContainerHighest
radius: Appearance?.rounding.full ?? 9999
color: root.checked ? root.activeColor : root.inactiveColor
border.width: 2 * root.scale
border.color: root.checked ? Appearance.m3colors.m3primary : Appearance.m3colors.m3outline
border.color: root.checked ? root.activeColor : Appearance.m3colors.m3outline
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)

View file

@ -6,7 +6,7 @@ Text {
renderType: Text.NativeRendering
font.hintingPreference: Font.PreferFullHinting
verticalAlignment: Text.AlignVCenter
font.family: Appearance.font.family.main
font.pixelSize: Appearance.font.pixelSize.small
color: Appearance.m3colors.m3onBackground
font.family: Appearance?.font.family.main ?? "sans-serif"
font.pixelSize: Appearance?.font.pixelSize.small ?? 15
color: Appearance?.m3colors.m3onBackground ?? "black"
}

View file

@ -19,11 +19,7 @@ ToolTip {
visible: opacity > 0
Behavior on opacity {
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
}
background: null
@ -37,34 +33,26 @@ ToolTip {
id: backgroundRectangle
anchors.bottom: contentItemBackground.bottom
anchors.horizontalCenter: contentItemBackground.horizontalCenter
color: Appearance.colors.colTooltip
radius: Appearance.rounding.verysmall
color: Appearance?.colors.colTooltip ?? "#3C4043"
radius: Appearance?.rounding.verysmall ?? 7
width: internalVisibleCondition ? (tooltipTextObject.width + 2 * padding) : 0
height: internalVisibleCondition ? (tooltipTextObject.height + 2 * padding) : 0
clip: true
Behavior on width {
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
}
Behavior on height {
NumberAnimation {
duration: Appearance.animation.elementMoveFast.duration
easing.type: Appearance.animation.elementMoveFast.type
easing.bezierCurve: Appearance.animation.elementMoveFast.bezierCurve
}
animation: Appearance?.animation.elementMoveFast.numberAnimation.createObject(this)
}
StyledText {
id: tooltipTextObject
anchors.centerIn: parent
text: content
font.pixelSize: Appearance.font.pixelSize.smaller
font.pixelSize: Appearance?.font.pixelSize.smaller ?? 14
font.hintingPreference: Font.PreferNoHinting // Prevent shaky text
color: Appearance.colors.colOnTooltip
color: Appearance?.colors.colOnTooltip ?? "#FFFFFF"
wrapMode: Text.Wrap
}
}