nosignal-shell/modules/nsbar/NsOverlay.qml
28allday 36f6f5a157 feat(nosignal): interface redesign — slim glass bar + floating popouts
Convert the caelestia shell to the NoSignal "design_handoff_quickshell_shell"
spec: a slim translucent top bar with floating glass popouts, fixed dark-glass
chrome + Material You dynamic accent, square corners, JetBrains Mono.

- Theme singleton (services/Theme.qml): design tokens; accent = m3primary
  (dynamic), fixed glass/text, square radii.
- New slim bar as its own PanelWindow (modules/nsbar/NsBar.qml), additive in
  shell.qml; reuses caelestia services + components. Helpers: BarPill,
  NsWorkspaces (numbered, active=accent pill), NsOverlay (popout host, one-at-a-
  time via services/NsShell.qml, outside-click + Esc), components/NsPanel +
  components/NsSwitch.
- Old caelestia frame removed: BarWrapper collapsed; ContentWindow border 0 +
  borderTop 0; Exclusions zones 0. Drawer engine kept for launcher/OSD/lock.
- 9 popouts (modules/nsbar/panels/): Calendar, QuickSettings, Network,
  Bluetooth, Notifications, Audio, SystemTray, Overview, PowerMenu.
- Clock restyled (date muted + time DemiBold).
- nexus (Settings) reskinned: dark-glass window + cards, square corners
  (Nexus.qml, common/ConnectedRect.qml) — keeps all pages/functionality.

Launcher kept as-is. Font (JetBrainsMono) + rounding.scale=0 + Super+Alt+Space
nexus bind are caelestia/hypr CONFIG and ship in the OS, not this fork.
Next: full Material Symbols -> Nerd Font icon remap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 10:36:33 +01:00

161 lines
4 KiB
QML

pragma ComponentBehavior: Bound
// NoSignal popup overlay: one full-screen layer per screen that hosts the active
// floating panel (driven by NsShell.open). A transparent click-catcher behind the
// panel closes on outside-click; Escape also closes. Panels are positioned below
// the bar, anchored center / right / under-trigger per their `anchorMode`.
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.services
import "panels" as Panels
Variants {
model: Screens.screens
PanelWindow {
id: ov
required property ShellScreen modelData
screen: modelData
visible: NsShell.open !== ""
color: "transparent"
WlrLayershell.namespace: "nspanels"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
anchors.top: true
anchors.bottom: true
anchors.left: true
anchors.right: true
exclusiveZone: 0
// outside-click closes
MouseArea {
anchors.fill: parent
onClicked: NsShell.close()
}
// Escape closes
Item {
anchors.fill: parent
focus: ov.visible
Keys.onEscapePressed: NsShell.close()
}
// full-screen modal: Power Menu
Loader {
anchors.fill: parent
active: NsShell.open === "power"
sourceComponent: powerC
Component {
id: powerC
Panels.NsPowerMenu {}
}
}
Loader {
id: loader
active: NsShell.open !== "" && NsShell.open !== "power"
y: Theme.size.barHeight + 6
x: {
if (!item)
return 0;
const w = item.implicitWidth;
const mode = item.anchorMode ?? "right";
if (mode === "center")
return Math.round((ov.width - w) / 2);
if (mode === "trigger")
return Math.max(8, Math.min(ov.width - w - 8, NsShell.anchorX - w / 2));
return ov.width - w - 12; // right
}
// small enter slide
opacity: active ? 1 : 0
transform: Translate {
y: loader.active ? 0 : -5
}
Behavior on opacity {
NumberAnimation {
duration: 120
}
}
sourceComponent: {
switch (NsShell.open) {
case "calendar":
return calendarC;
case "quicksettings":
return quickSettingsC;
case "network":
return networkC;
case "bluetooth":
return bluetoothC;
case "notifications":
return notificationsC;
case "audio":
return audioC;
case "tray":
return trayC;
case "overview":
return overviewC;
default:
return null;
}
}
Component {
id: calendarC
Panels.NsCalendar {}
}
Component {
id: quickSettingsC
Panels.NsQuickSettings {}
}
Component {
id: networkC
Panels.NsNetwork {}
}
Component {
id: bluetoothC
Panels.NsBluetooth {}
}
Component {
id: notificationsC
Panels.NsNotifications {}
}
Component {
id: audioC
Panels.NsAudio {}
}
Component {
id: trayC
Panels.NsSystemTray {}
}
Component {
id: overviewC
Panels.NsOverview {}
}
}
}
}