Files
metabuilder/qml/components/form/CSwitch.qml
johndoe6345789 eecaac8634 feat(qml): MD3 rework batch 1 — 20 components rewritten
Core: CButton (pill variants), CFab (radius 16 tonal), CIconButton (circle state layers)
Cards: CCard (filled/outlined/elevated, radius 12), CAccordionItem (smooth expand), CPaper
Chips: CChip (8px radius, filter/assist/input), CBadge (6px dot/16px pill), CStatBadge, CStatusBadge
Forms: CTextField (floating label, outlined), CSelect (styled popup), CTextarea (scrollable)
Toggles: CCheckbox (Canvas checkmark), CSwitch (52x32 pill track), CRadio (scale dot), CRating (hover stars)
Feedback: CProgress (4px track, indeterminate slide), CSpinner (Canvas arc sweep), CErrorState (tonal container)

All components: theme-aware, dark/light mode, hover/press state layers, preserved public API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 04:03:18 +00:00

108 lines
3.7 KiB
QML

import QtQuick
import QtQuick.Controls
import QmlComponents 1.0
/**
* CSwitch.qml - Material Design 3 styled toggle switch
*
* MD3 spec: 52x32 pill track, 24px thumb (28px when pressed),
* animated slide and color transitions.
*/
Rectangle {
id: root
property bool checked: false
property alias text: label.text
property bool enabled: true
signal toggled(bool checked)
width: row.implicitWidth
height: 40
color: "transparent"
Row {
id: row
spacing: StyleVariables.spacingSm
anchors.verticalCenter: parent.verticalCenter
// Track + thumb container
Item {
width: 52; height: 32
anchors.verticalCenter: parent.verticalCenter
// Track
Rectangle {
id: track
anchors.fill: parent
radius: 16
color: root.checked ? Theme.primary : Theme.surface
border.color: root.checked ? "transparent" : Theme.border
border.width: root.checked ? 0 : 2
opacity: root.enabled ? 1.0 : 0.38
Behavior on color { ColorAnimation { duration: 200; easing.type: Easing.OutCubic } }
Behavior on border.color { ColorAnimation { duration: 200; easing.type: Easing.OutCubic } }
}
// Thumb
Rectangle {
id: thumb
property int thumbSize: mouseArea.pressed ? 28 : 24
width: thumbSize; height: thumbSize
radius: thumbSize / 2
color: root.checked ? "#ffffff" : Theme.border
y: (parent.height - height) / 2
x: root.checked ? (parent.width - width - 4) : 4
opacity: root.enabled ? 1.0 : 0.38
// Elevation shadow for thumb
layer.enabled: true
layer.effect: null
Behavior on x { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
Behavior on width { NumberAnimation { duration: 100; easing.type: Easing.OutCubic } }
Behavior on height { NumberAnimation { duration: 100; easing.type: Easing.OutCubic } }
Behavior on color { ColorAnimation { duration: 200; easing.type: Easing.OutCubic } }
}
// Hover state circle around thumb
Rectangle {
id: hoverIndicator
width: 40; height: 40
radius: 20
color: root.checked ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
: Qt.rgba(Theme.text.r, Theme.text.g, Theme.text.b, 0.08)
opacity: mouseArea.containsMouse || mouseArea.pressed ? 1 : 0
x: thumb.x + (thumb.width / 2) - (width / 2)
y: thumb.y + (thumb.height / 2) - (height / 2)
Behavior on opacity { NumberAnimation { duration: 150 } }
Behavior on x { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
enabled: root.enabled
cursorShape: Qt.PointingHandCursor
onClicked: {
root.checked = !root.checked;
root.toggled(root.checked);
}
}
}
Text {
id: label
text: ""
color: root.enabled ? Theme.text : Theme.textDisabled
font.pixelSize: StyleVariables.fontSizeSm
font.family: Theme.fontFamily
anchors.verticalCenter: parent.verticalCenter
visible: text.length > 0
}
}
}