mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +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>
94 lines
3.1 KiB
QML
94 lines
3.1 KiB
QML
import QtQuick
|
|
import QtQuick.Layouts
|
|
import QmlComponents 1.0
|
|
|
|
CCard {
|
|
id: root
|
|
objectName: "mediaHeader"
|
|
Accessible.role: Accessible.Pane
|
|
Accessible.name: "Media service header"
|
|
Layout.fillWidth: true
|
|
|
|
property string serviceStatus: "unknown"
|
|
property string serviceVersion: ""
|
|
property string lastHealthCheck: ""
|
|
property int jobCount: 0
|
|
property int radioCount: 0
|
|
property int tvCount: 0
|
|
property int pluginCount: 0
|
|
|
|
signal refreshClicked()
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent; anchors.margins: 20; spacing: 12
|
|
|
|
FlexRow {
|
|
Layout.fillWidth: true; spacing: 12
|
|
CText { variant: "h2"; text: "Media Service" }
|
|
CBadge { text: "God Panel" }
|
|
CStatusBadge {
|
|
status: root.serviceStatus === "online"
|
|
? "success"
|
|
: root.serviceStatus === "offline"
|
|
? "error" : "warning"
|
|
text: root.serviceStatus === "online"
|
|
? "Online"
|
|
: root.serviceStatus === "offline"
|
|
? "Offline" : "Checking..."
|
|
}
|
|
Item { Layout.fillWidth: true }
|
|
CButton {
|
|
text: "Refresh"
|
|
variant: "ghost"; size: "sm"
|
|
activeFocusOnTab: true
|
|
Accessible.role: Accessible.Button
|
|
Accessible.name: "Refresh media service"
|
|
Keys.onReturnPressed: root.refreshClicked()
|
|
Keys.onSpacePressed: root.refreshClicked()
|
|
onClicked: root.refreshClicked()
|
|
}
|
|
}
|
|
CDivider { Layout.fillWidth: true }
|
|
FlexRow {
|
|
Layout.fillWidth: true; spacing: 8
|
|
CChip {
|
|
text: root.jobCount + " Jobs"
|
|
Accessible.role: Accessible.StaticText
|
|
Accessible.name: root.jobCount + " Jobs"
|
|
}
|
|
CChip {
|
|
text: root.radioCount + " Radio Channels"
|
|
Accessible.role: Accessible.StaticText
|
|
Accessible.name: root.radioCount
|
|
+ " Radio Channels"
|
|
}
|
|
CChip {
|
|
text: root.tvCount + " TV Channels"
|
|
Accessible.role: Accessible.StaticText
|
|
Accessible.name: root.tvCount
|
|
+ " TV Channels"
|
|
}
|
|
CChip {
|
|
text: root.pluginCount + " Plugins"
|
|
Accessible.role: Accessible.StaticText
|
|
Accessible.name: root.pluginCount
|
|
+ " Plugins"
|
|
}
|
|
Item { Layout.fillWidth: true }
|
|
CText {
|
|
visible: root.lastHealthCheck.length > 0
|
|
variant: "caption"
|
|
text: "Last check: "
|
|
+ root.lastHealthCheck
|
|
color: Theme.textSecondary
|
|
}
|
|
CText {
|
|
visible: root.serviceVersion.length > 0
|
|
variant: "caption"
|
|
text: "v" + root.serviceVersion
|
|
color: Theme.textSecondary
|
|
}
|
|
}
|
|
}
|
|
}
|