Files
metabuilder/qml/components/feedback/CProgress.qml
T
git 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

110 lines
3.5 KiB
QML

import QtQuick
import QmlComponents 1.0
/**
* CProgress.qml - Material Design 3 Linear Progress Indicator
*
* MD3 spec: 4px track with rounded ends, primary indicator, indeterminate sliding animation
*
* Usage:
* CProgress { value: 0.5 } // 50% determinate
* CProgress { indeterminate: true } // Animated indeterminate
* CProgress { value: 0.75; label: "75%" } // With label
*/
Item {
id: root
// Public properties
property real value: 0 // 0.0 to 1.0
property bool indeterminate: false
property string color: "" // Custom indicator color, uses Theme.primary if empty
property string trackColor: "" // Custom track color
property string size: "md" // sm, md, lg (track thickness)
property string label: "" // Optional label below track
// Computed colors (MD3: primary for indicator, surfaceContainerHighest for track)
readonly property color _indicatorColor: color || Theme.primary
readonly property color _trackColor: trackColor || Qt.rgba(Theme.surface.r, Theme.surface.g, Theme.surface.b, 0.38)
// MD3 track height: 4px standard
readonly property int _trackHeight: {
switch (size) {
case "sm": return 2
case "lg": return 6
default: return 4
}
}
implicitWidth: 200
implicitHeight: label ? _trackHeight + Theme.fontSizeXs + Theme.spacingXs : _trackHeight
// Track background (MD3: rounded, surfaceContainerHighest)
Rectangle {
id: track
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: root._trackHeight
radius: root._trackHeight / 2
color: root._trackColor
clip: true
// Determinate indicator
Rectangle {
id: determinateBar
visible: !root.indeterminate
anchors.left: parent.left
anchors.top: parent.top
height: parent.height
width: parent.width * Math.max(0, Math.min(1, root.value))
radius: root._trackHeight / 2
color: root._indicatorColor
Behavior on width {
NumberAnimation {
duration: Theme.transitionStandard
easing.type: Easing.OutCubic
}
}
}
// Indeterminate indicator (MD3: sliding bar that traverses the track)
Rectangle {
id: indeterminateBar
visible: root.indeterminate
anchors.top: parent.top
height: parent.height
width: parent.width * 0.4
radius: root._trackHeight / 2
color: root._indicatorColor
SequentialAnimation {
running: root.indeterminate && root.visible
loops: Animation.Infinite
// Slide right, accelerating
NumberAnimation {
target: indeterminateBar
property: "x"
from: -indeterminateBar.width
to: track.width
duration: 1500
easing.type: Easing.InOutQuad
}
}
}
}
// Optional label
Text {
visible: root.label !== ""
anchors.top: track.bottom
anchors.topMargin: Theme.spacingXs
anchors.horizontalCenter: parent.horizontalCenter
text: root.label
font.pixelSize: Theme.fontSizeXs
font.family: Theme.fontFamily
color: Theme.textSecondary
}
}