mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 14:25:02 +00:00
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>
99 lines
2.8 KiB
QML
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(" ")
|
|
}
|
|
}
|