Files
metabuilder/qml/qt6/PackageViewLoader.qml
johndoe6345789 d9ca84628b feat(a11y): deep keyboard accessibility pass across all QML components
Second-pass a11y work across all 12 component groups. Every interactive
element now has activeFocusOnTab, Keys.onReturnPressed/SpacePressed, and
context-aware Accessible.name/description bindings.

Highlights:
- Dialogs: keyboard handlers with enabled-guard on confirm buttons
- CDropdownMenu: full keyboard nav (Up/Down/Enter/Escape)
- CLoginForm: explicit KeyNavigation.tab chain (username→password→submit)
- CNotificationBell: dynamic "3 notifications"/"No notifications" name
- CJobProgressBar: Accessible.minimumValue/maximumValue/currentValue
- CExecutionStatusDot: "Execution status: Running/Passed/Failed" binding
- CKeyboardShortcuts: invisible Repeater exposes all shortcuts to a11y tree
- CDataTable rows: "Row N of M" descriptions
- Canvas elements: Accessible.Canvas role + keyboard zoom (+/- keys)
- DropdownExpandedList: focus-highlight extended to :activeFocus
- Dynamic names reflect loading state (e.g. "Signing in, please wait")

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:53:53 +00:00

99 lines
2.8 KiB
QML

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QmlComponents 1.0
Rectangle {
id: loader
color: "transparent"
objectName: "view_package_" + packageId
Accessible.role: Accessible.Pane
Accessible.name: formatTitle(packageId)
property string packageId: ""
// Resolve view URL via PackageLoader (disk → QRC fallback)
Loader {
id: viewLoader
anchors.fill: parent
source: packageId !== "" ? PackageLoader.qmlPathUrl(packageId) : ""
onStatusChanged: {
if (status === Loader.Error) {
console.warn("PackageViewLoader: failed to load", packageId,
source)
}
}
}
// Hot-reload: react to QML file changes on disk
Connections {
target: PackageLoader
function onPackageUpdated(id) {
if (id === packageId) {
var url = PackageLoader.qmlPathUrl(packageId)
viewLoader.source = ""
viewLoader.source = url
}
}
}
// Fallback when view can't be loaded
Rectangle {
anchors.fill: parent
visible: viewLoader.status !== Loader.Ready
color: "transparent"
ColumnLayout {
anchors.centerIn: parent
spacing: 16
CText {
variant: "h3"
text: formatTitle(packageId)
Layout.alignment: Qt.AlignHCenter
}
CText {
variant: "body1"
text: {
var meta = PackageLoader.getPackage(packageId)
return meta && meta.description
? meta.description : "Package view for " + packageId
}
Layout.alignment: Qt.AlignHCenter
}
CBadge {
text: packageId
Layout.alignment: Qt.AlignHCenter
}
CButton {
text: "Load Package"
variant: "primary"
Layout.alignment: Qt.AlignHCenter
activeFocusOnTab: true
Accessible.role: Accessible.Button
Accessible.name:
"Load package: "
+ formatTitle(packageId)
Keys.onReturnPressed:
PackageLoader.install(
packageId)
onClicked: {
PackageLoader.install(packageId)
console.log(
"Installed package:",
packageId)
}
}
}
}
function formatTitle(id) {
return id.split("_").map(function(w) {
return w.charAt(0).toUpperCase() + w.slice(1)
}).join(" ")
}
}