refactor(i18n): qbz-i18n owns its catalogues; macOS immersive band drops below the lights

QBZ-I18N WAS NOT FRONTEND-AGNOSTIC, whatever its own header said. No slint or
tauri entry in its Cargo.toml — and eight `include_str!` reaching into
`crates/qbz-ui/translations/`. Deleting the Slint crate, which is planned before
the Qt release, would have failed to compile `qbz-i18n` and with it `qbz-qt`,
i.e. the entire app, over a data directory nobody read as a dependency. The
extraction that created this crate took the code and left the data behind.

The eight .po files move to `crates/qbz-i18n/translations/` (git tracks them as
renames, so history follows) and the includes become `../translations/`.
`qbz-ui/build.rs` borrows them back through `../qbz-i18n/translations` for as
long as that tree exists — the direction of the dependency is what matters, and
it now points the way the deletion needs.

MACOS: THE IMMERSIVE BAND GOES BELOW THE TRAFFIC LIGHTS, not beside them. It
was inset to their right with the shell HeaderBar's rule, which is right for the
shell — the lights sit at the head of a full toolbar row there — and wrong here,
where the row is three floating glass pills over artwork and a 44px pill parked
against the lights reads as debris.

Vertical clearance comes from `SafeArea.margins.top`, the same question the left
inset asks in the other axis: with ExpandedClientAreaHint the client area covers
the titlebar region and SafeArea reports how much of it is unsafe, with a 28px
floor for a 0 reading. The band keeps `leftMargin: 24` on every platform, which
puts the trigger's leading edge in the same 20-24 band the lights start in, and
the 16px gap under them is the band's own margin reused rather than a new
number.

The view trigger matches the cluster's width on macOS (SafeArea left margin,
78 floor): stacked, a 44px pill under a ~78px cluster reads as misaligned even
with the left edges lined up. Its radius becomes height/2 rather than a constant
18, or the widened pill would have been a rounded rectangle beside three
circles. Every other platform keeps the natural 44px, and the glyph was already
centred so it needed nothing.

The menu opens downward from a band that now has more room under it, so the
flyout has more clearance than before rather than less.

Built and smoked on Linux (gate green) and built on the Mac mini M2 (3m32s, no
errors). The macOS geometry itself needs eyes on a Mac.

cc
This commit is contained in:
vicrodh committed 2026-08-19 16:03:02 -06:00
1 parent 1352e499f9
commit d1fd99f947
12 files changed
+75 -24

No files matched your search

+32 -10
View File
@@ -200,10 +200,27 @@ Item {
hideTimer.restart()
}
// C1 macOS traffic-light inset (contract 03 §6) — same rule as the
// shell's HeaderBar: ask SafeArea, floor at 78, only when the native
// lights float over client area (i.e. not with the system title bar).
readonly property int chromeLeftInset:
// C1 macOS traffic lights (contract 03 §6). Only when the native lights
// float over client area, i.e. not with the system title bar.
//
// The band used to be pushed to their RIGHT (`leftMargin: 24 + inset`,
// the shell HeaderBar's rule). On the shell that reads fine — the lights
// sit at the head of a full toolbar row. Here the row is three floating
// glass pills over artwork, and a 44px pill parked beside the lights read
// as debris rather than as chrome. It goes BELOW them now.
//
// Vertical clearance from SafeArea's TOP margin, which is the same
// question the left inset asks in the other axis: with
// `ExpandedClientAreaHint` the client area covers the titlebar region and
// SafeArea reports how much of it is unsafe. The floor is the standard
// 28px title-bar height for the case where it reads 0.
readonly property int chromeTopInset:
QbzShell.isMacos && !QbzShell.systemTitleBar
? Math.max(root.SafeArea.margins.top, 28) : 0
// The cluster's WIDTH, handed to the header so the view trigger can match
// it: stacked, a 44px pill under a ~78px cluster reads as misaligned even
// when the left edges line up. 0 = leave the trigger its natural width.
readonly property int chromeClusterWidth:
QbzShell.isMacos && !QbzShell.systemTitleBar
? Math.max(root.SafeArea.margins.left, 78) : 0
@@ -676,13 +693,18 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
// C1 macOS: clear the native traffic-light cluster (it floats over
// the top-left corner, x ≈ 7-85 — the view trigger's exact spot) with
// the same inset the shell HeaderBar computes
// (HeaderBar.qml chromeLeftInset: SafeArea left margin, 78 floor).
anchors.leftMargin: 24 + root.chromeLeftInset
// C1 macOS: the lights float over the top-left corner (x ~ 7-85,
// which is the view trigger's exact spot), so the band drops BELOW
// them instead of shifting right — see `chromeTopInset`. The left
// margin stays 24 on every platform, which puts the trigger's leading
// edge in the same 20-24 band the lights start in, so the two read as
// one column.
anchors.leftMargin: 24
anchors.rightMargin: 24
anchors.topMargin: 16
// 16 is the band's own gap from the window edge; reusing it as the gap
// UNDER the lights keeps the rhythm instead of inventing a number.
anchors.topMargin: 16 + root.chromeTopInset
triggerWidth: root.chromeClusterWidth
height: 36
opacity: root.chromeVisible ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 300 } }