feat(qt6): MD3 top bar — pill nav buttons, tonal level badge, theme toggle pill

Replace CButton-based top bar with MD3-style elements:
- Compact 52px height, tighter spacing
- L-number level pill with tonal indigo background
- DBAL status dot inline with monospace label
- Moon/sun theme toggle in surfaceContainer pill
- Segmented pill buttons for level navigation with hover states
- Filled pill Login button, outlined Logout
- Username shown without parenthetical role

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 03:59:51 +00:00
parent cd2bd3ffcf
commit 6fa7e700cb

View File

@@ -94,98 +94,188 @@ ApplicationWindow {
return pkg.navLabel ? pkg.navLabel.toLowerCase().replace(/ /g, "-") : pkg.packageId
}
// ── MD3 palette helpers (match FrontPage) ──
readonly property bool isDark: Theme.mode === "dark"
readonly property color accentBlue: "#6366F1"
readonly property color surfaceContainer: isDark ? Qt.rgba(1, 1, 1, 0.05) : Qt.rgba(0.31, 0.31, 0.44, 0.06)
readonly property color outlineVariant: isDark ? Qt.rgba(1, 1, 1, 0.06) : Qt.rgba(0, 0, 0, 0.08)
// ── App bar ──
header: CAppBar {
height: 56
height: 52
RowLayout {
anchors.fill: parent
anchors.leftMargin: 20
anchors.rightMargin: 20
spacing: 12
anchors.leftMargin: 16
anchors.rightMargin: 16
spacing: 8
// Logo
CText {
variant: "h4"
text: "MetaBuilder"
font.pixelSize: 16
font.weight: Font.Bold
font.letterSpacing: -0.5
}
CBadge {
text: "Level " + currentLevel
}
// DBAL connection status
Row {
spacing: 4
Layout.leftMargin: 4
Rectangle {
width: 8
height: 8
radius: 4
color: dbalProvider.connected ? "#4caf50" : "#f44336"
anchors.verticalCenter: parent.verticalCenter
}
// Level pill
Rectangle {
width: lvlText.implicitWidth + 16
height: 24
radius: 12
color: Qt.rgba(accentBlue.r, accentBlue.g, accentBlue.b, isDark ? 0.15 : 0.12)
CText {
variant: "caption"
text: "DBAL"
anchors.verticalCenter: parent.verticalCenter
id: lvlText
anchors.centerIn: parent
text: "L" + currentLevel
font.pixelSize: 11
font.weight: Font.Bold
font.family: "monospace"
color: accentBlue
}
}
// Theme toggle
CButton {
variant: "ghost"
size: "sm"
text: currentTheme === "dark" ? "Light" : "Dark"
onClicked: {
currentTheme = currentTheme === "dark" ? "light" : "dark"
if (typeof Theme.setTheme === "function") {
Theme.setTheme(currentTheme)
// DBAL dot
Rectangle {
width: 7
height: 7
radius: 3.5
color: dbalProvider.connected ? accentBlue : "#f44336"
Layout.leftMargin: 4
}
CText {
text: "DBAL"
font.pixelSize: 11
font.family: "monospace"
color: Theme.textSecondary
}
// Theme toggle — MD3 icon-style pill
Rectangle {
width: themeText.implicitWidth + 20
height: 28
radius: 14
color: surfaceContainer
border.color: outlineVariant
border.width: 1
CText {
id: themeText
anchors.centerIn: parent
text: currentTheme === "dark" ? "\u263E Dark" : "\u2600 Light"
font.pixelSize: 11
color: Theme.textSecondary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
currentTheme = currentTheme === "dark" ? "light" : "dark"
if (typeof Theme.setTheme === "function")
Theme.setTheme(currentTheme)
}
}
}
Item { Layout.fillWidth: true }
// Level navigation
// Level navigation — MD3 segmented/pill buttons
Repeater {
model: [
{ label: "Public", level: 1, view: "frontpage" },
{ label: "User", level: 2, view: "dashboard" },
{ label: "Admin", level: 3, view: "admin" },
{ label: "God", level: 4, view: "god-panel" },
{ label: "Super God", level: 5, view: "supergod" }
{ label: "Super", level: 5, view: "supergod" }
]
delegate: CButton {
delegate: Rectangle {
visible: modelData.level <= currentLevel
text: modelData.label
variant: currentView === modelData.view ? "primary" : "ghost"
size: "sm"
onClicked: currentView = modelData.view
width: navLabel.implicitWidth + 20
height: 30
radius: 15
color: currentView === modelData.view
? Qt.rgba(accentBlue.r, accentBlue.g, accentBlue.b, isDark ? 0.2 : 0.15)
: navMA.containsMouse ? surfaceContainer : "transparent"
Behavior on color { ColorAnimation { duration: 150 } }
CText {
id: navLabel
anchors.centerIn: parent
text: modelData.label
font.pixelSize: 12
font.weight: currentView === modelData.view ? Font.DemiBold : Font.Normal
color: currentView === modelData.view ? accentBlue : Theme.textSecondary
}
MouseArea {
id: navMA
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: currentView = modelData.view
}
}
}
Item { width: 8 }
Item { width: 4 }
CButton {
// Login / user info
Rectangle {
visible: !loggedIn
text: "Login"
variant: "primary"
size: "sm"
onClicked: currentView = "login"
width: loginText.implicitWidth + 24
height: 30
radius: 15
color: accentBlue
CText {
id: loginText
anchors.centerIn: parent
text: "Login"
font.pixelSize: 12
font.weight: Font.DemiBold
color: "#ffffff"
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: currentView = "login"
}
}
CText {
visible: loggedIn
text: currentUser + " (" + currentRole + ")"
variant: "body2"
text: currentUser
font.pixelSize: 13
font.weight: Font.Medium
color: Theme.text
}
CButton {
Rectangle {
visible: loggedIn
text: "Logout"
variant: "ghost"
size: "sm"
onClicked: logout()
width: logoutText.implicitWidth + 20
height: 28
radius: 14
color: "transparent"
border.color: outlineVariant
border.width: 1
CText {
id: logoutText
anchors.centerIn: parent
text: "Logout"
font.pixelSize: 11
color: Theme.textSecondary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: logout()
}
}
}
}