Files
metabuilder/qml/components/feedback/CProgress.qml
johndoe6345789 5456f7eb4c feat(a11y): add Accessible roles, names, objectNames to all core QML components
Core: CButton, CIconButton, CFab, CChip, CListItem — Button roles, activeFocusOnTab
Forms: CTextField, CSelect, CCheckbox, CSwitch, CRadio, CRating — EditableText, CheckBox, ComboBox, Slider
Feedback: CAlert, CDialog, CSnackbar — AlertMessage, Dialog roles
Navigation: CTabBar — PageTabList + PageTab on delegates
Data: CAvatar, CBadge, CTable, CStatBadge, CStatusBadge — Graphic, StaticText, Table, Row
Surfaces: CCard (Pane), CAccordionItem (Button + expanded), CAppBar (ToolBar)
Progress: CProgress (ProgressBar + value), CSpinner (Animation)
Divider: CDivider (Separator)

28 files, 157 lines of a11y properties added. Zero to full coverage on core library.

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

120 lines
3.7 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
// Accessibility
Accessible.role: Accessible.ProgressBar
Accessible.name: label || "Progress"
Accessible.value: value * 100
// Public properties
property real value: 0 // 0.0 to 1.0
property bool indeterminate: false
// Custom indicator color, uses Theme.primary if empty
property string color: ""
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
}
}