From 5c1158018be6013a8dba4942483ee6379feb53ce Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Sat, 2 May 2026 18:50:28 +1000 Subject: [PATCH] feat: add button base component --- components/controls/ButtonBase.qml | 85 ++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 components/controls/ButtonBase.qml diff --git a/components/controls/ButtonBase.qml b/components/controls/ButtonBase.qml new file mode 100644 index 00000000..43d2156c --- /dev/null +++ b/components/controls/ButtonBase.qml @@ -0,0 +1,85 @@ +//@ pragma Internal + +import QtQuick +import Caelestia.Config +import qs.components +import qs.services + +StyledRect { + id: root + + enum ButtonType { + Filled, + Tonal, + Text + } + + property bool checked + property alias disabled: stateLayer.disabled + property bool isToggle + property bool isRound + + property bool radiusMorph + property alias shapeMorph: stateLayer.shapeMorph + + property font font + property int type: ButtonBase.Filled + + property real padding + property real horizontalPadding: padding + property real verticalPadding: padding + + readonly property alias pressed: stateLayer.pressed + readonly property alias hovered: stateLayer.containsMouse + readonly property alias stateLayer: stateLayer + readonly property alias radiusAnim: radiusAnim + + required property color activeColour + required property color inactiveColour + required property color activeOnColour + required property color inactiveOnColour + property color disabledColour: Qt.alpha(Colours.palette.m3onSurface, 0.1) + property color disabledOnColour: Qt.alpha(Colours.palette.m3onSurface, 0.38) + + property bool internalChecked + readonly property color onColour: disabled ? disabledOnColour : internalChecked ? activeOnColour : inactiveOnColour + + signal clicked + + onCheckedChanged: internalChecked = checked + + radius: { + if (radiusMorph && pressed) + return Tokens.rounding.small; + if (internalChecked) + return Tokens.rounding.medium; + if (isRound) + return implicitHeight / 2 * Math.min(1, Tokens.rounding.scale); + return Tokens.rounding.large; + } + color: type === ButtonBase.Text ? "transparent" : disabled ? disabledColour : internalChecked ? activeColour : inactiveColour + + // Make size required so we don't forget to set it + required implicitWidth + required implicitHeight + + StateLayer { + id: stateLayer + + color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour + disabled: root.disabled + onClicked: { + if (root.isToggle) + root.internalChecked = !root.internalChecked; + root.clicked(); + } + } + + Behavior on radius { + Anim { + id: radiusAnim + + type: Anim.DefaultEffects + } + } +}