added quickshell and updated zsh

This commit is contained in:
2026-08-17 23:16:05 -07:00
parent 9bca669f4e
commit 1f3dde6de2
55 changed files with 4251 additions and 381 deletions

View File

@@ -0,0 +1,260 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import "../theme"
import ".."
PanelWindow {
id: aboutWindow
visible: GlobalState.aboutMacVisible
anchors {
top: true
left: true
right: true
bottom: true
}
color: Qt.rgba(0, 0, 0, 0.35)
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-aboutmac"
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
// Dismiss when clicking outside modal
MouseArea {
anchors.fill: parent
onClicked: GlobalState.aboutMacVisible = false
}
// Centered Dialog
Rectangle {
id: dialogBox
anchors.centerIn: parent
width: 540
height: 330
radius: Theme.radiusModal
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
// Prevent clicking inside from dismissing
MouseArea {
anchors.fill: parent
onClicked: {}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 16
spacing: 12
// Top Traffic Lights Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
// Red Close Dot
Rectangle {
width: 12
height: 12
radius: 6
color: closeMouse.containsMouse ? "#E0443E" : "#FF5F56"
border.color: "#E0443E"
border.width: 0.5
Text {
anchors.centerIn: parent
visible: closeMouse.containsMouse
text: "×"
font.pixelSize: 10
color: "#4A0002"
}
MouseArea {
id: closeMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.aboutMacVisible = false
}
}
// Yellow Minimize Dot
Rectangle {
width: 12
height: 12
radius: 6
color: "#FFBD2E"
border.color: "#DEA123"
border.width: 0.5
}
// Green Zoom Dot
Rectangle {
width: 12
height: 12
radius: 6
color: "#27C93F"
border.color: "#1AAB29"
border.width: 0.5
}
Item { Layout.fillWidth: true }
Text {
text: "Overview"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
}
Item { Layout.fillWidth: true }
}
// Main Specs Content
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 24
// Left: Catalina Island Badge
Image {
Layout.alignment: Qt.AlignVCenter
width: 130
height: 130
source: "../assets/catalina-badge.svg"
sourceSize: Qt.size(130, 130)
}
// Right: System Details
ColumnLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
spacing: 6
Text {
text: "macOS Catalina"
font.family: Theme.fontFamily
font.pixelSize: 22
font.weight: Font.Bold
color: "#FFFFFF"
}
Text {
text: "Version 10.15.7 (NixOS Edition)"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Specs Rows
SpecRow { label: "Host"; value: "Hades (AMD + NVIDIA RTX)" }
SpecRow { label: "Processor"; value: "AMD High-Performance Multi-Core" }
SpecRow { label: "Memory"; value: `${GlobalState.memTotalGb} GB RAM (${GlobalState.memUsedGb} GB in use)` }
SpecRow { label: "Graphics"; value: "NVIDIA GeForce RTX (Proprietary Driver)" }
SpecRow { label: "Compositor"; value: "Hyprland 0.55+ (Wayland)" }
SpecRow { label: "Operating System"; value: "NixOS 26.05 (x86_64-linux)" }
}
}
// Bottom Action Buttons
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignRight
spacing: 12
Rectangle {
implicitWidth: sysRepText.implicitWidth + 20
height: 24
radius: Theme.radiusSmall
color: repMouse.containsMouse ? Qt.rgba(1,1,1,0.2) : Qt.rgba(1,1,1,0.1)
border.color: Qt.rgba(1,1,1,0.15)
border.width: 1
Text {
id: sysRepText
anchors.centerIn: parent
text: "System Report..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: repMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.aboutMacVisible = false;
GlobalState.launchApp("foot -e btop");
}
}
}
Rectangle {
implicitWidth: updText.implicitWidth + 20
height: 24
radius: Theme.radiusSmall
color: updMouse.containsMouse ? Qt.rgba(1,1,1,0.2) : Qt.rgba(1,1,1,0.1)
border.color: Qt.rgba(1,1,1,0.15)
border.width: 1
Text {
id: updText
anchors.centerIn: parent
text: "Software Update..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: updMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.aboutMacVisible = false;
GlobalState.launchApp("foot -e zsh -c 'echo \"Checking NixOS system configuration...\"; sudo nixos-rebuild dry-activate --flake /home/anish/NixOS-Configs#hades; exec zsh'");
}
}
}
}
}
}
component SpecRow: RowLayout {
property string label: ""
property string value: ""
Layout.fillWidth: true
spacing: 10
Text {
text: label
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
Layout.preferredWidth: 105
}
Text {
text: value
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
}
}

View File

@@ -0,0 +1,147 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
property string menuName: ""
width: 200
implicitHeight: menuCol.implicitHeight + 12
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: menuCol
anchors.fill: parent
anchors.margins: 6
spacing: 2
// FILE MENU
Repeater {
model: root.menuName === "File" ? [
{ text: "New Window", shortcut: "⌘N", cmd: "foot &" },
{ text: "New Incognito Window", shortcut: "⇧⌘N", cmd: "brave --incognito &" },
{ text: "Close Window", shortcut: "⌘W", cmd: "hyprctl dispatch killactive" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Take Screenshot", shortcut: "⇧⌘5", cmd: "grim -g \"$(slurp)\" ~/screenshot.png" }
] : []
delegate: MenuEntryDelegate {}
}
// EDIT MENU
Repeater {
model: root.menuName === "Edit" ? [
{ text: "Undo", shortcut: "⌘Z", cmd: "" },
{ text: "Redo", shortcut: "⇧⌘Z", cmd: "" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Cut", shortcut: "⌘X", cmd: "wl-copy" },
{ text: "Copy", shortcut: "⌘C", cmd: "wl-copy" },
{ text: "Paste", shortcut: "⌘V", cmd: "wl-paste" },
{ text: "Select All", shortcut: "⌘A", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
// VIEW MENU
Repeater {
model: root.menuName === "View" ? [
{ text: "Toggle Fullscreen", shortcut: "⌃⌘F", cmd: "hyprctl dispatch fullscreen 0" },
{ text: "Toggle Floating", shortcut: "⌘V", cmd: "hyprctl dispatch togglefloating" },
{ text: "Toggle Group", shortcut: "⌘G", cmd: "hyprctl dispatch togglegroup" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Zoom In", shortcut: "⌘+", cmd: "" },
{ text: "Zoom Out", shortcut: "⌘-", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
// WINDOW MENU
Repeater {
model: root.menuName === "Window" ? [
{ text: "Minimize Window", shortcut: "⌘M", cmd: "hyprctl dispatch movetoworkspacesilent special:scratch" },
{ text: "Tile Left", shortcut: "⌃⌥←", cmd: "hyprctl dispatch movewindow l" },
{ text: "Tile Right", shortcut: "⌃⌥→", cmd: "hyprctl dispatch movewindow r" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "Show Scratchpad", shortcut: "⌘↩", cmd: "hyprctl dispatch togglespecialworkspace scratch" },
{ text: "Show Messaging", shortcut: "⌘M", cmd: "hyprctl dispatch togglespecialworkspace messaging" }
] : []
delegate: MenuEntryDelegate {}
}
// HELP MENU
Repeater {
model: root.menuName === "Help" ? [
{ text: "Hyprland Documentation", shortcut: "", cmd: "brave https://wiki.hyprland.org &" },
{ text: "NixOS Manual", shortcut: "", cmd: "brave https://nixos.org/manual/nixos/stable/ &" },
{ text: "---", shortcut: "", cmd: "" },
{ text: "About Antigravity", shortcut: "", cmd: "" }
] : []
delegate: MenuEntryDelegate {}
}
}
component MenuEntryDelegate: Item {
Layout.fillWidth: true
Layout.preferredHeight: modelData.text === "---" ? 7 : 22
Rectangle {
anchors.fill: parent
visible: modelData.text === "---"
color: "transparent"
Rectangle {
anchors.centerIn: parent
width: parent.width
height: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
}
Rectangle {
anchors.fill: parent
visible: modelData.text !== "---"
radius: Theme.radiusSmall
color: itemMouse.containsMouse ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 8
Text {
text: modelData.text
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
color: itemMouse.containsMouse ? Theme.menuTextHover : Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
visible: modelData.shortcut !== ""
text: modelData.shortcut
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: itemMouse.containsMouse ? Theme.menuTextHover : Theme.textTertiary
}
}
MouseArea {
id: itemMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.activeDropdownMenu = "";
if (modelData.cmd) {
GlobalState.launchApp(modelData.cmd);
}
}
}
}
}
}

View File

@@ -0,0 +1,158 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 220
implicitHeight: menuColumn.implicitHeight + 12
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
// Drop shadow
layer.enabled: true
ColumnLayout {
id: menuColumn
anchors.fill: parent
anchors.margins: 6
spacing: 2
// About This Mac
MenuItem {
text: "About This Mac"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.toggleAboutMac();
}
}
MenuSeparator {}
MenuItem {
text: "System Preferences..."
onTriggered: {
GlobalState.launchApp("pavucontrol");
}
}
MenuItem {
text: "App Store..."
onTriggered: {
GlobalState.launchApp("foot -e zsh -c 'echo NixOS Packages; nix-env -qaP | head -n 50; exec zsh'");
}
}
MenuSeparator {}
MenuItem {
text: "Activity Monitor"
shortcut: "⌥⌘Esc"
onTriggered: {
GlobalState.launchApp("foot -e btop");
}
}
MenuSeparator {}
MenuItem {
text: "Sleep"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl suspend");
}
}
MenuItem {
text: "Restart..."
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl reboot");
}
}
MenuItem {
text: "Shut Down..."
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("systemctl poweroff");
}
}
MenuSeparator {}
MenuItem {
text: "Lock Screen"
shortcut: "⌃⌘Q"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("hyprlock");
}
}
MenuItem {
text: "Log Out anish..."
shortcut: "⇧⌘Q"
onTriggered: {
GlobalState.appleMenuVisible = false;
GlobalState.launchApp("hyprctl dispatch exit");
}
}
}
component MenuItem: Rectangle {
id: itemRoot
property string text: ""
property string shortcut: ""
signal triggered()
Layout.fillWidth: true
Layout.preferredHeight: 22
radius: Theme.radiusSmall
color: mouseArea.containsMouse ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 8
Text {
text: itemRoot.text
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
color: mouseArea.containsMouse ? Theme.menuTextHover : Theme.textPrimary
Layout.fillWidth: true
elide: Text.ElideRight
}
Text {
visible: itemRoot.shortcut !== ""
text: itemRoot.shortcut
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: mouseArea.containsMouse ? Theme.menuTextHover : Theme.textTertiary
}
}
MouseArea {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: itemRoot.triggered()
}
}
component MenuSeparator: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
Layout.topMargin: 3
Layout.bottomMargin: 3
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
}

View File

@@ -0,0 +1,102 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
implicitHeight: batCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: batCol
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Battery"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: `${GlobalState.batteryPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: GlobalState.batteryPercent <= 20 ? Theme.accentRed : Theme.accentGreen
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 3
Text {
text: GlobalState.batteryPresent
? (GlobalState.batteryCharging ? "Power Source: Power Adapter" : "Power Source: Battery")
: "Power Source: AC Connected"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
Text {
text: GlobalState.batteryPresent
? `Status: ${GlobalState.batteryStatus}`
: "Desktop Workstation Mode"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: batPrefMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Energy Saver Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: batPrefMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.batteryPopupVisible = false;
GlobalState.launchApp("foot -e btop");
}
}
}
}
}

View File

@@ -0,0 +1,94 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 250
implicitHeight: calCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: calCol
anchors.fill: parent
anchors.margins: 12
spacing: 10
Text {
text: GlobalState.fullDateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.alignment: Qt.AlignHCenter
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: 22
font.weight: Font.Light
color: Theme.accentBlue
Layout.alignment: Qt.AlignHCenter
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Days grid header
RowLayout {
Layout.fillWidth: true
Repeater {
model: ["S", "M", "T", "W", "T", "F", "S"]
delegate: Text {
text: modelData
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textTertiary
horizontalAlignment: Text.AlignHCenter
Layout.fillWidth: true
}
}
}
// Quick mini-calendar representation
GridLayout {
id: gridDays
columns: 7
Layout.fillWidth: true
rowSpacing: 4
columnSpacing: 4
readonly property var todayDate: new Date()
readonly property int currentDay: todayDate.getDate()
Repeater {
model: 31
delegate: Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 22
radius: 11
color: (index + 1) === gridDays.currentDay ? Theme.accentBlue : "transparent"
Text {
anchors.centerIn: parent
text: `${index + 1}`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: (index + 1) === gridDays.currentDay ? Font.Bold : Font.Normal
color: (index + 1) === gridDays.currentDay ? "#FFFFFF" : Theme.textSecondary
}
}
}
}
}
}

View File

@@ -0,0 +1,638 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import "../theme"
import ".."
PanelWindow {
id: ccWindow
visible: GlobalState.controlCenterVisible
anchors {
top: true
right: true
bottom: true
}
margins {
top: Theme.menuBarHeight
}
implicitWidth: 360
color: "transparent"
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-controlcenter"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
property int activeTab: 0 // 0 = Today, 1 = Notifications
// Sidebar Container
Rectangle {
id: sidebarPanel
anchors.fill: parent
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 14
spacing: 12
// =================================================================
// TAB SWITCHER (Today | Notifications)
// =================================================================
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 30
radius: Theme.radiusMedium
color: Qt.rgba(0.0, 0.0, 0.0, 0.3)
RowLayout {
anchors.fill: parent
spacing: 0
// Today Tab Button
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.radiusMedium
color: ccWindow.activeTab === 0 ? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Text {
anchors.centerIn: parent
text: "Today"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: ccWindow.activeTab === 0 ? Font.DemiBold : Font.Normal
color: ccWindow.activeTab === 0 ? "#FFFFFF" : Theme.textTertiary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: ccWindow.activeTab = 0
}
}
// Notifications Tab Button
Rectangle {
Layout.fillWidth: true
Layout.fillHeight: true
radius: Theme.radiusMedium
color: ccWindow.activeTab === 1 ? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Text {
anchors.centerIn: parent
text: "Notifications"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: ccWindow.activeTab === 1 ? Font.DemiBold : Font.Normal
color: ccWindow.activeTab === 1 ? "#FFFFFF" : Theme.textTertiary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: ccWindow.activeTab = 1
}
}
}
}
// =================================================================
// TAB 1: TODAY VIEW
// =================================================================
ScrollView {
visible: ccWindow.activeTab === 0
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
ColumnLayout {
width: parent.width
spacing: 12
// 1. Large Date & Time Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 70
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 2
Text {
text: GlobalState.fullDateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.accentBlue
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: 26
font.weight: Font.Light
color: "#FFFFFF"
}
}
}
// 2. Control Toggles (Wi-Fi, Bluetooth, DND, Night Shift)
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 120
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
GridLayout {
anchors.fill: parent
anchors.margins: 10
columns: 2
rowSpacing: 8
columnSpacing: 8
// Wi-Fi Toggle
ToggleCard {
iconSource: "../assets/wifi.svg"
title: "Wi-Fi"
subtitle: GlobalState.wifiSsid
isActive: GlobalState.wifiConnected
onClicked: GlobalState.launchApp("nm-connection-editor || foot -e nmtui")
}
// Bluetooth Toggle
ToggleCard {
iconSource: "../assets/bluetooth.svg"
title: "Bluetooth"
subtitle: "Active"
isActive: true
onClicked: GlobalState.launchApp("foot -e bluetoothctl")
}
// Do Not Disturb Toggle
ToggleCard {
iconSource: "../assets/preferences.svg"
title: "Do Not Disturb"
subtitle: "Off"
isActive: false
onClicked: {}
}
// Sound Mute Toggle
ToggleCard {
iconSource: "../assets/volume.svg"
title: "Sound"
subtitle: GlobalState.volumeMuted ? "Muted" : `${GlobalState.volume}%`
isActive: !GlobalState.volumeMuted
onClicked: GlobalState.toggleVolumeMute()
}
}
}
// 3. Brightness & Volume Sliders
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 110
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
// Display Brightness Slider
RowLayout {
Layout.fillWidth: true
spacing: 8
Image {
width: 16
height: 16
source: "../assets/brightness.svg"
sourceSize: Qt.size(16, 16)
}
Item {
Layout.fillWidth: true
height: 18
Rectangle {
anchors.fill: parent
radius: 9
color: Qt.rgba(1,1,1,0.18)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.brightness / 100.0)
radius: 9
color: "#FFFFFF"
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
function update(m) {
const frac = Math.max(0.01, Math.min(1.0, m.x / width));
GlobalState.setBrightness(Math.round(frac * 100));
}
onPressed: (m) => update(m)
onPositionChanged: (m) => { if (pressed) update(m); }
}
}
}
// Sound Volume Slider
RowLayout {
Layout.fillWidth: true
spacing: 8
Image {
width: 16
height: 16
source: "../assets/volume.svg"
sourceSize: Qt.size(16, 16)
}
Item {
Layout.fillWidth: true
height: 18
Rectangle {
anchors.fill: parent
radius: 9
color: Qt.rgba(1,1,1,0.18)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.volume / 100.0)
radius: 9
color: Theme.accentBlue
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
function update(m) {
const frac = Math.max(0.0, Math.min(1.0, m.x / width));
GlobalState.setVolume(Math.round(frac * 100));
}
onPressed: (m) => update(m)
onPositionChanged: (m) => { if (pressed) update(m); }
}
}
}
}
}
// 4. System Resources Monitor Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 90
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 6
Text {
text: "System Performance"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
color: Theme.textSecondary
}
// CPU Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
Text {
text: "CPU"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.preferredWidth: 32
}
Rectangle {
Layout.fillWidth: true
height: 6
radius: 3
color: Qt.rgba(1,1,1,0.15)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.cpuPercent / 100.0)
radius: 3
color: GlobalState.cpuPercent > 80 ? Theme.accentRed : Theme.accentGreen
}
}
Text {
text: `${GlobalState.cpuPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
Layout.preferredWidth: 36
horizontalAlignment: Text.AlignRight
}
}
// Memory Bar
RowLayout {
Layout.fillWidth: true
spacing: 8
Text {
text: "RAM"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
Layout.preferredWidth: 32
}
Rectangle {
Layout.fillWidth: true
height: 6
radius: 3
color: Qt.rgba(1,1,1,0.15)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width * (GlobalState.memPercent / 100.0)
radius: 3
color: Theme.accentBlue
}
}
Text {
text: `${GlobalState.memUsedGb}G`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
Layout.preferredWidth: 36
horizontalAlignment: Text.AlignRight
}
}
}
}
// 5. Now Playing Media Widget
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 80
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
Image {
width: 36
height: 36
source: "../assets/music.svg"
sourceSize: Qt.size(36, 36)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2
Text {
text: GlobalState.mediaTitle || "No Media Playing"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: GlobalState.mediaArtist || "Apple Music"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textTertiary
elide: Text.ElideRight
Layout.fillWidth: true
}
}
// Playback controls
RowLayout {
spacing: 4
Rectangle {
width: 24
height: 24
radius: 12
color: Qt.rgba(1,1,1,0.1)
Text { anchors.centerIn: parent; text: "⏮"; color: "#FFFFFF"; font.pixelSize: 10 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaPrevious() }
}
Rectangle {
width: 28
height: 28
radius: 14
color: Theme.accentBlue
Text { anchors.centerIn: parent; text: GlobalState.mediaPlaying ? "⏸" : "▶"; color: "#FFFFFF"; font.pixelSize: 11 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaPlayPause() }
}
Rectangle {
width: 24
height: 24
radius: 12
color: Qt.rgba(1,1,1,0.1)
Text { anchors.centerIn: parent; text: "⏭"; color: "#FFFFFF"; font.pixelSize: 10 }
MouseArea { anchors.fill: parent; cursorShape: Qt.PointingHandCursor; onClicked: GlobalState.mediaNext() }
}
}
}
}
}
}
// =================================================================
// TAB 2: NOTIFICATIONS VIEW
// =================================================================
ColumnLayout {
visible: ccWindow.activeTab === 1
Layout.fillWidth: true
Layout.fillHeight: true
spacing: 12
RowLayout {
Layout.fillWidth: true
Text {
text: "Notifications"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
color: "#FFFFFF"
Layout.fillWidth: true
}
Rectangle {
implicitWidth: clearText.implicitWidth + 12
height: 22
radius: Theme.radiusSmall
color: Qt.rgba(1,1,1,0.12)
Text {
id: clearText
anchors.centerIn: parent
text: "Clear All"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {}
}
}
}
// Placeholder / Active notifications card
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 70
radius: Theme.radiusLarge
color: Theme.cardBg
border.color: Theme.cardBorder
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 10
Image {
width: 28
height: 28
source: "../assets/apple.svg"
sourceSize: Qt.size(28, 28)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 2
Text {
text: "macOS Catalina on Hyprland"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
}
Text {
text: "Quickshell desktop loaded successfully."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
}
}
Item {
Layout.fillHeight: true
}
}
}
}
// Toggle Card Component
component ToggleCard: Rectangle {
id: cardRoot
property string iconSource: ""
property string title: ""
property string subtitle: ""
property bool isActive: false
signal clicked()
Layout.fillWidth: true
Layout.preferredHeight: 46
radius: Theme.radiusMedium
color: cardMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.22) : Qt.rgba(1.0, 1.0, 1.0, 0.12)
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 8
Rectangle {
width: 28
height: 28
radius: 14
color: cardRoot.isActive ? Theme.accentBlue : Qt.rgba(1,1,1,0.2)
Image {
anchors.centerIn: parent
width: 14
height: 14
source: cardRoot.iconSource
sourceSize: Qt.size(14, 14)
}
}
ColumnLayout {
Layout.fillWidth: true
spacing: 1
Text {
text: cardRoot.title
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
}
Text {
text: cardRoot.subtitle
font.family: Theme.fontFamily
font.pixelSize: 10
color: Theme.textTertiary
elide: Text.ElideRight
}
}
}
MouseArea {
id: cardMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: cardRoot.clicked()
}
}
}

View File

@@ -0,0 +1,338 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import "../theme"
import ".."
PanelWindow {
id: dockWindow
property var modelData
screen: modelData
anchors {
bottom: true
}
margins {
bottom: 6
}
// Adjust width to fit content
implicitWidth: dockTray.implicitWidth + 32
implicitHeight: 90
color: "transparent"
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "quickshell-dock"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
// Reserve 70px exclusive zone so windows don't overlap the dock
exclusiveZone: 70
// Tooltip overlay container
Item {
id: tooltipContainer
anchors.fill: parent
z: 100
}
// 2.5D Frosted Glass Dock Tray
Rectangle {
id: dockTray
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
implicitWidth: dockLayout.implicitWidth + 24
height: 68
radius: Theme.radiusDock
color: Theme.dockBg
border.color: Theme.dockBorder
border.width: 1
// Top glossy reflection edge line (Catalina shelf characteristic)
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: 12
anchors.rightMargin: 12
height: 1
color: Theme.dockHighlight
opacity: 0.8
}
// Inner items layout
RowLayout {
id: dockLayout
anchors.centerIn: parent
spacing: 6
// =================================================================
// 1. PINNED APPS
// =================================================================
DockItem {
id: finderItem
name: "Finder"
iconSource: "../assets/finder.svg"
execCmd: "foot -e sh -c 'cd ~; lf || yazi || ls -la; exec zsh'"
appClass: "foot"
isPinned: true
}
DockItem {
name: "Launchpad"
iconSource: "../assets/launchpad.svg"
execCmd: ""
isPinned: true
onCustomClicked: GlobalState.toggleSpotlight()
}
DockItem {
name: "Brave Browser"
iconSource: "../assets/browser.svg"
execCmd: "brave"
appClass: "brave-browser"
isPinned: true
}
DockItem {
name: "Terminal"
iconSource: "../assets/terminal.svg"
execCmd: "foot"
appClass: "foot"
isPinned: true
}
DockItem {
name: "Neovim"
iconSource: "../assets/code.svg"
execCmd: "foot -e nvim"
appClass: "nvim"
isPinned: true
}
DockItem {
name: "System Preferences"
iconSource: "../assets/preferences.svg"
execCmd: "pavucontrol"
appClass: "pavucontrol"
isPinned: true
}
DockItem {
name: "App Store"
iconSource: "../assets/appstore.svg"
execCmd: "foot -e zsh -c 'echo NixOS Packages; nix-env -qaP | head -n 50; exec zsh'"
appClass: ""
isPinned: true
}
DockItem {
name: "Music"
iconSource: "../assets/music.svg"
execCmd: ""
appClass: ""
isPinned: true
onCustomClicked: GlobalState.mediaPlayPause()
}
// =================================================================
// 2. DYNAMIC RUNNING APPS (Not pinned)
// =================================================================
Repeater {
model: {
const pinnedClasses = ["foot", "brave-browser", "pavucontrol", "nvim"];
const list = [];
const seen = {};
if (Array.isArray(GlobalState.runningApps)) {
for (let i = 0; i < GlobalState.runningApps.length; i++) {
const client = GlobalState.runningApps[i];
const cls = (client.class || "").toLowerCase();
if (cls && !pinnedClasses.includes(cls) && !seen[cls]) {
seen[cls] = true;
list.push({
name: client.title || client.class || "App",
cls: client.class,
address: client.address
});
}
}
}
return list;
}
delegate: DockItem {
required property var modelData
name: modelData.name
iconSource: "../assets/code.svg"
appClass: modelData.cls
isPinned: false
onCustomClicked: {
if (modelData.address) {
Hyprland.dispatch(`focuswindow address:${modelData.address}`);
}
}
}
}
// =================================================================
// 3. DOCK SEPARATOR DIVIDER
// =================================================================
Rectangle {
Layout.preferredWidth: 1
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignVCenter
Layout.leftMargin: 4
Layout.rightMargin: 4
color: Qt.rgba(1.0, 1.0, 1.0, 0.22)
}
// =================================================================
// 4. DOWNLOADS FOLDER & TRASH
// =================================================================
DockItem {
name: "Downloads"
iconSource: "../assets/folder-downloads.svg"
execCmd: "foot -e sh -c 'cd ~/Downloads; ls -la; exec zsh'"
isPinned: true
}
DockItem {
name: "Trash"
iconSource: "../assets/trash-empty.svg"
execCmd: "foot -e sh -c 'cd ~/.local/share/Trash/files 2>/dev/null || cd ~; ls -la; exec zsh'"
isPinned: true
}
}
}
// Reusable Dock Item Component
component DockItem: Item {
id: itemRoot
property string name: ""
property string iconSource: ""
property string execCmd: ""
property string appClass: ""
property bool isPinned: true
signal customClicked()
// Check if app is running
readonly property bool isRunning: {
if (!itemRoot.appClass) return false;
const target = itemRoot.appClass.toLowerCase();
if (GlobalState.activeWindowClass.toLowerCase().includes(target)) return true;
if (Array.isArray(GlobalState.runningApps)) {
for (let i = 0; i < GlobalState.runningApps.length; i++) {
const c = GlobalState.runningApps[i];
if ((c.class || "").toLowerCase().includes(target)) return true;
}
}
return false;
}
implicitWidth: 50
implicitHeight: 64
Layout.alignment: Qt.AlignBottom
// Container with scale & bounce transform
Item {
id: iconWrapper
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
width: 48
height: 48
scale: itemArea.containsMouse ? 1.28 : 1.0
y: itemArea.containsMouse ? -8 : 0
Behavior on scale {
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
}
Behavior on y {
NumberAnimation { duration: 180; easing.type: Easing.OutCubic }
}
// Icon Image
Image {
anchors.centerIn: parent
width: 46
height: 46
source: itemRoot.iconSource
sourceSize: Qt.size(92, 92)
smooth: true
mipmap: true
}
// Click Bounce Sequential Animation
SequentialAnimation {
id: bounceAnim
NumberAnimation { target: iconWrapper; property: "y"; to: -24; duration: 150; easing.type: Easing.OutQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: -4; duration: 130; easing.type: Easing.InQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: -14; duration: 100; easing.type: Easing.OutQuad }
NumberAnimation { target: iconWrapper; property: "y"; to: 0; duration: 100; easing.type: Easing.InQuad }
}
}
// Active App Running Indicator Dot (White glowing pill)
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
width: 4
height: 4
radius: 2
color: Theme.dockDot
visible: itemRoot.isRunning
}
// Hover Tooltip Badge (macOS Catalina Style Black Pill)
Rectangle {
id: tooltipPill
visible: itemArea.containsMouse
opacity: itemArea.containsMouse ? 1.0 : 0.0
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.top
anchors.bottomMargin: 6
implicitWidth: tooltipText.implicitWidth + 16
height: 24
radius: 6
color: Qt.rgba(0.08, 0.08, 0.10, 0.92)
border.color: Qt.rgba(1.0, 1.0, 1.0, 0.18)
border.width: 1
Behavior on opacity {
NumberAnimation { duration: 120 }
}
Text {
id: tooltipText
anchors.centerIn: parent
text: itemRoot.name
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: "#FFFFFF"
}
}
// Mouse interaction
MouseArea {
id: itemArea
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
bounceAnim.start();
if (itemRoot.execCmd !== "") {
GlobalState.launchApp(itemRoot.execCmd);
} else {
itemRoot.customClicked();
}
}
}
}
}

View File

@@ -0,0 +1,507 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Hyprland
import Quickshell.Services.SystemTray
import "../theme"
import ".."
PanelWindow {
id: menuBarWindow
property var modelData
screen: modelData
anchors {
top: true
left: true
right: true
}
// Set implicitHeight to accommodate bar + open popups without clipping
implicitHeight: (GlobalState.appleMenuVisible || GlobalState.activeDropdownMenu !== "" ||
GlobalState.volumePopupVisible || GlobalState.wifiPopupVisible ||
GlobalState.batteryPopupVisible || GlobalState.calendarPopupVisible) ? 420 : Theme.menuBarHeight
color: "transparent"
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.namespace: "quickshell-menubar"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
// Set exclusive zone only for the 26px bar
exclusiveZone: Theme.menuBarHeight
// Background Bar (26px)
Rectangle {
id: barRect
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: Theme.menuBarHeight
color: Theme.menuBarBg
border.color: Theme.menuBarBorder
border.width: 0
// Bottom hairline border
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 1
color: Theme.menuBarBorder
}
RowLayout {
anchors.fill: parent
anchors.leftMargin: 12
anchors.rightMargin: 12
spacing: 0
// =================================================================
// LEFT SIDE: Apple Menu + App Title + Standard Menus
// =================================================================
RowLayout {
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
spacing: 2
// Apple Logo Button
Rectangle {
id: appleBtn
width: 28
height: 20
radius: Theme.radiusSmall
color: (GlobalState.appleMenuVisible || appleMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.18) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/apple.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: appleMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.appleMenuVisible;
GlobalState.closeAllPopups();
GlobalState.appleMenuVisible = !wasOpen;
}
}
}
// Active App Title (Bold)
Rectangle {
id: appTitleBtn
implicitWidth: appTitleText.implicitWidth + 16
height: 20
radius: Theme.radiusSmall
color: titleMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Text {
id: appTitleText
anchors.centerIn: parent
text: GlobalState.activeWindowClass || "Finder"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Bold
color: Theme.textPrimary
}
MouseArea {
id: titleMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = (GlobalState.activeDropdownMenu === "File");
GlobalState.closeAllPopups();
GlobalState.activeDropdownMenu = wasOpen ? "" : "File";
}
}
}
// Standard Menus: File, Edit, View, Window, Help
Repeater {
model: ["File", "Edit", "View", "Window", "Help"]
delegate: Rectangle {
id: menuBtn
implicitWidth: menuText.implicitWidth + 14
height: 20
radius: Theme.radiusSmall
color: (GlobalState.activeDropdownMenu === modelData || menuMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Text {
id: menuText
anchors.centerIn: parent
text: modelData
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Normal
color: Theme.textPrimary
}
MouseArea {
id: menuMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: {
// If a menu is already open, hovering switches to this one
if (GlobalState.activeDropdownMenu !== "") {
GlobalState.activeDropdownMenu = modelData;
}
}
onClicked: {
const wasOpen = (GlobalState.activeDropdownMenu === modelData);
GlobalState.closeAllPopups();
GlobalState.activeDropdownMenu = wasOpen ? "" : modelData;
}
}
}
}
}
// Spacer
Item {
Layout.fillWidth: true
}
// =================================================================
// RIGHT SIDE: Tray + Media + Volume + Wifi + Battery + Spotlight + Control Center + Clock
// =================================================================
RowLayout {
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
spacing: 4
// System Tray Icons
Repeater {
model: SystemTray.items
delegate: Rectangle {
required property SystemTrayItem modelData
width: 22
height: 20
radius: Theme.radiusSmall
color: trayMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 15
height: 15
source: modelData.icon || ""
sourceSize: Qt.size(15, 15)
}
MouseArea {
id: trayMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: modelData.activate()
}
}
}
// Media Indicator (visible if playing)
Rectangle {
visible: GlobalState.mediaPlaying
implicitWidth: mediaRow.implicitWidth + 12
height: 20
radius: Theme.radiusSmall
color: mediaMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: mediaRow
anchors.centerIn: parent
spacing: 4
Image {
width: 13
height: 13
source: "../assets/music.svg"
sourceSize: Qt.size(13, 13)
}
Text {
text: GlobalState.mediaTitle ? `${GlobalState.mediaTitle.substring(0, 18)}...` : "Playing"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
MouseArea {
id: mediaMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.mediaPlayPause()
}
}
// Volume Item
Rectangle {
id: volBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.volumePopupVisible || volMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/volume.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: volMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.volumePopupVisible;
GlobalState.closeAllPopups();
GlobalState.volumePopupVisible = !wasOpen;
}
}
}
// Wi-Fi Item
Rectangle {
id: wifiBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.wifiPopupVisible || wifiMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/wifi.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: wifiMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.wifiPopupVisible;
GlobalState.closeAllPopups();
GlobalState.wifiPopupVisible = !wasOpen;
}
}
}
// Battery Item
Rectangle {
id: batBtn
implicitWidth: batRow.implicitWidth + 8
height: 20
radius: Theme.radiusSmall
color: (GlobalState.batteryPopupVisible || batMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: batRow
anchors.centerIn: parent
spacing: 4
Text {
visible: GlobalState.batteryPresent
text: `${GlobalState.batteryPercent}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
Image {
width: 18
height: 12
source: "../assets/battery.svg"
sourceSize: Qt.size(18, 12)
}
}
MouseArea {
id: batMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.batteryPopupVisible;
GlobalState.closeAllPopups();
GlobalState.batteryPopupVisible = !wasOpen;
}
}
}
// Spotlight Search Button
Rectangle {
id: spotBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.spotlightVisible || spotMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/spotlight.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: spotMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleSpotlight()
}
}
// Control Center / Notification Center Toggle Button
Rectangle {
id: ccBtn
width: 26
height: 20
radius: Theme.radiusSmall
color: (GlobalState.controlCenterVisible || ccMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
Image {
anchors.centerIn: parent
width: 14
height: 14
source: "../assets/controlcenter.svg"
sourceSize: Qt.size(14, 14)
}
MouseArea {
id: ccMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleControlCenter()
}
}
// Date & Time (Clock)
Rectangle {
id: clockBtn
implicitWidth: clockRow.implicitWidth + 10
height: 20
radius: Theme.radiusSmall
color: (GlobalState.calendarPopupVisible || clockMouse.containsMouse)
? Qt.rgba(1.0, 1.0, 1.0, 0.15) : "transparent"
RowLayout {
id: clockRow
anchors.centerIn: parent
spacing: 6
Text {
text: GlobalState.dateString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
color: Theme.textSecondary
}
Text {
text: GlobalState.timeString
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeMenuBar
font.weight: Font.Medium
color: Theme.textPrimary
}
}
MouseArea {
id: clockMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
const wasOpen = GlobalState.calendarPopupVisible;
GlobalState.closeAllPopups();
GlobalState.calendarPopupVisible = !wasOpen;
}
}
}
}
}
}
// =========================================================================
// DROPDOWNS & POPUPS
// =========================================================================
// 1. Apple Menu Dropdown
AppleMenu {
id: appleDropdown
visible: GlobalState.appleMenuVisible
x: 8
y: Theme.menuBarHeight + 2
}
// 2. Application Menus Dropdown (File, Edit, View, Window, Help)
AppMenuDropdown {
id: appMenuDropdown
visible: GlobalState.activeDropdownMenu !== ""
menuName: GlobalState.activeDropdownMenu
x: 60
y: Theme.menuBarHeight + 2
}
// 3. Volume Popup
VolumePopup {
id: volumeDropdown
visible: GlobalState.volumePopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 190
}
// 4. Wi-Fi Popup
WifiPopup {
id: wifiDropdown
visible: GlobalState.wifiPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 160
}
// 5. Battery Popup
BatteryPopup {
id: batteryDropdown
visible: GlobalState.batteryPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 110
}
// 6. Calendar Popup
CalendarPopup {
id: calDropdown
visible: GlobalState.calendarPopupVisible
anchors.top: barRect.bottom
anchors.topMargin: 2
anchors.right: parent.right
anchors.rightMargin: 10
}
}

View File

@@ -0,0 +1,340 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import Quickshell.Io
import "../theme"
import ".."
PanelWindow {
id: spotWindow
visible: GlobalState.spotlightVisible
anchors {
top: true
left: true
right: true
bottom: true
}
color: Qt.rgba(0, 0, 0, 0.35)
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "quickshell-spotlight"
WlrLayershell.keyboardFocus: visible ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None
// Dismiss when clicking outside modal
MouseArea {
anchors.fill: parent
onClicked: GlobalState.spotlightVisible = false
}
// App Database Loader Process
readonly property Process appScanProc: Process {
command: ["bash", "-c", "dirs=(\"/run/current-system/sw/share/applications\" \"$HOME/.nix-profile/share/applications\" \"$HOME/.local/share/applications\"); echo '['; first=1; for d in \"${dirs[@]}\"; do [ -d \"$d\" ] && for f in \"$d\"/*.desktop; do [ -e \"$f\" ] || continue; grep -q \"^NoDisplay=true\" \"$f\" 2>/dev/null && continue; n=$(grep -m 1 \"^Name=\" \"$f\" 2>/dev/null | cut -d= -f2-); e=$(grep -m 1 \"^Exec=\" \"$f\" 2>/dev/null | cut -d= -f2- | sed -E 's/%[fFuUdDnNickvm]//g'); if [ -n \"$n\" ] && [ -n \"$e\" ]; then [ $first -eq 0 ] && echo ','; first=0; echo \"{\\\"name\\\":\\\"$n\\\",\\\"exec\\\":\\\"$e\\\"}\"; fi; done; done; echo ']'"]
stdout: StdioCollector {
onDataChanged: {
try {
const parsed = JSON.parse(data.trim());
if (Array.isArray(parsed)) {
spotWindow.allApps = parsed;
}
} catch(e) {}
}
}
}
property var allApps: [
{ name: "Brave Browser", exec: "brave", comment: "Web Browser", icon: "browser" },
{ name: "Foot Terminal", exec: "foot", comment: "Terminal Emulator", icon: "terminal" },
{ name: "Neovim", exec: "foot -e nvim", comment: "Code Editor", icon: "code" },
{ name: "Activity Monitor (Btop)", exec: "foot -e btop", comment: "System Resources", icon: "preferences" },
{ name: "Volume & Sound (Pavucontrol)", exec: "pavucontrol", comment: "Audio Settings", icon: "preferences" },
{ name: "Lock Screen", exec: "hyprlock", comment: "Lock Session", icon: "preferences" },
{ name: "System Reboot", exec: "systemctl reboot", comment: "Reboot NixOS", icon: "preferences" },
{ name: "Shut Down", exec: "systemctl poweroff", comment: "Power Off", icon: "preferences" }
]
property int selectedIndex: 0
onVisibleChanged: {
if (visible) {
appScanProc.running = true;
searchInput.text = "";
selectedIndex = 0;
searchInput.forceActiveFocus();
}
}
// Centered Spotlight Search Modal
Rectangle {
id: modalBox
anchors.horizontalCenter: parent.horizontalCenter
y: 140
width: 640
implicitHeight: searchBarRow.height + (resultsListView.count > 0 || mathResultText !== "" ? 340 : 0)
radius: Theme.radiusModal
color: Theme.windowBg
border.color: Theme.windowBorder
border.width: 1
Behavior on implicitHeight {
NumberAnimation { duration: 180; easing.type: Easing.OutQuad }
}
// Prevent clicking inside from closing modal
MouseArea {
anchors.fill: parent
onClicked: {}
}
ColumnLayout {
anchors.fill: parent
anchors.margins: 14
spacing: 12
// Top Search Bar
RowLayout {
id: searchBarRow
Layout.fillWidth: true
Layout.preferredHeight: 44
spacing: 12
Image {
width: 24
height: 24
source: "../assets/spotlight.svg"
sourceSize: Qt.size(24, 24)
}
TextInput {
id: searchInput
Layout.fillWidth: true
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSpotlight
font.weight: Font.Light
color: Theme.textPrimary
focus: true
clip: true
Text {
anchors.fill: parent
visible: searchInput.text === ""
text: "Spotlight Search"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSpotlight
font.weight: Font.Light
color: Theme.textTertiary
}
Keys.onEscapePressed: GlobalState.spotlightVisible = false
Keys.onDownPressed: {
if (resultsListView.count > 0) {
spotWindow.selectedIndex = Math.min(resultsListView.count - 1, spotWindow.selectedIndex + 1);
}
}
Keys.onUpPressed: {
if (resultsListView.count > 0) {
spotWindow.selectedIndex = Math.max(0, spotWindow.selectedIndex - 1);
}
}
Keys.onReturnPressed: {
if (filteredModel.count > 0 && spotWindow.selectedIndex < filteredModel.count) {
const item = filteredModel.get(spotWindow.selectedIndex);
GlobalState.launchApp(item.exec);
}
}
}
// Clear button
Rectangle {
visible: searchInput.text !== ""
width: 20
height: 20
radius: 10
color: Qt.rgba(1.0, 1.0, 1.0, 0.2)
Text {
anchors.centerIn: parent
text: "✕"
font.pixelSize: 11
color: Theme.textPrimary
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: searchInput.text = ""
}
}
}
// Math Calculation Result Banner (if valid formula)
Rectangle {
visible: mathResultText !== ""
Layout.fillWidth: true
Layout.preferredHeight: 36
radius: Theme.radiusSmall
color: Qt.rgba(0.04, 0.52, 1.0, 0.2)
border.color: Theme.accentBlue
border.width: 1
RowLayout {
anchors.fill: parent
anchors.margins: 8
spacing: 8
Text {
text: "="
font.family: Theme.fontFamily
font.pixelSize: 16
font.weight: Font.Bold
color: Theme.accentBlue
}
Text {
text: mathResultText
font.family: Theme.fontFamily
font.pixelSize: 16
font.weight: Font.DemiBold
color: "#FFFFFF"
Layout.fillWidth: true
}
}
}
// Divider Line
Rectangle {
visible: resultsListView.count > 0
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Search Results List View
ListView {
id: resultsListView
visible: count > 0
Layout.fillWidth: true
Layout.preferredHeight: Math.min(270, count * 42)
clip: true
spacing: 2
model: filteredModel
delegate: Rectangle {
id: itemDelegate
required property int index
required property string name
required property string exec
required property string comment
width: resultsListView.width
height: 40
radius: Theme.radiusSmall
color: spotWindow.selectedIndex === index ? Theme.menuHoverBlue : "transparent"
RowLayout {
anchors.fill: parent
anchors.leftMargin: 10
anchors.rightMargin: 10
spacing: 10
Image {
width: 22
height: 22
source: "../assets/terminal.svg"
sourceSize: Qt.size(22, 22)
}
ColumnLayout {
Layout.fillWidth: true
spacing: 1
Text {
text: itemDelegate.name
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.Medium
color: "#FFFFFF"
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
text: itemDelegate.comment || itemDelegate.exec
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: spotWindow.selectedIndex === itemDelegate.index
? Qt.rgba(1,1,1,0.85) : Theme.textTertiary
elide: Text.ElideRight
Layout.fillWidth: true
}
}
Text {
text: "↩"
font.pixelSize: 14
color: spotWindow.selectedIndex === itemDelegate.index
? "#FFFFFF" : "transparent"
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: spotWindow.selectedIndex = itemDelegate.index
onClicked: GlobalState.launchApp(itemDelegate.exec)
}
}
}
}
}
// Math calculation evaluator property
readonly property string mathResultText: {
const query = searchInput.text.trim();
if (/^[0-9+\-*/^().\s%]+$/.test(query) && /[0-9]/.test(query) && /[+\-*/^%]/.test(query)) {
try {
// Safe evaluation of arithmetic
const res = Function(`"use strict"; return (${query.replace(/\^/g, "**")})`)();
if (typeof res === "number" && !isNaN(res) && isFinite(res)) {
return `${res}`;
}
} catch(e) {}
}
return "";
}
// Filtered ListModel updated on text change
ListModel {
id: filteredModel
}
function updateFilter() {
filteredModel.clear();
const query = searchInput.text.toLowerCase().trim();
let count = 0;
for (let i = 0; i < allApps.length && count < 12; i++) {
const app = allApps[i];
if (!app.name) continue;
if (query === "" || app.name.toLowerCase().includes(query) || (app.exec && app.exec.toLowerCase().includes(query))) {
filteredModel.append({
name: app.name,
exec: app.exec || "",
comment: app.comment || ""
});
count++;
}
}
}
Connections {
target: searchInput
function onTextChanged() {
spotWindow.selectedIndex = 0;
updateFilter();
}
}
Component.onCompleted: updateFilter()
}

View File

@@ -0,0 +1,148 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
height: 110
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Sound"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: `${GlobalState.volume}%`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
// Custom Catalina Volume Slider
Item {
Layout.fillWidth: true
Layout.preferredHeight: 24
Rectangle {
id: track
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 6
radius: 3
color: Qt.rgba(1.0, 1.0, 1.0, 0.2)
Rectangle {
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: track.width * (GlobalState.volume / 100.0)
radius: 3
color: Theme.accentBlue
}
}
Rectangle {
id: thumb
x: Math.max(0, Math.min(track.width - width, (track.width * (GlobalState.volume / 100.0)) - width / 2))
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
radius: 8
color: "#FFFFFF"
border.color: Qt.rgba(0, 0, 0, 0.2)
border.width: 1
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
preventStealing: true
function updateFromMouse(mouse) {
const frac = Math.max(0.0, Math.min(1.0, mouse.x / width));
GlobalState.setVolume(Math.round(frac * 100));
}
onPressed: (mouse) => updateFromMouse(mouse)
onPositionChanged: (mouse) => {
if (pressed) updateFromMouse(mouse);
}
}
}
// Bottom Controls
RowLayout {
Layout.fillWidth: true
spacing: 8
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: muteMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: GlobalState.volumeMuted ? "Unmute" : "Mute"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: muteMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: GlobalState.toggleVolumeMute()
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: prefMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Sound Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: prefMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.volumePopupVisible = false;
GlobalState.launchApp("pavucontrol");
}
}
}
}
}
}

View File

@@ -0,0 +1,102 @@
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
import "../theme"
import ".."
Rectangle {
id: root
width: 240
implicitHeight: wifiCol.implicitHeight + 24
radius: Theme.radiusMedium
color: Theme.menuDropdownBg
border.color: Theme.menuDropdownBorder
border.width: 1
ColumnLayout {
id: wifiCol
anchors.fill: parent
anchors.margins: 12
spacing: 8
RowLayout {
Layout.fillWidth: true
Text {
text: "Wi-Fi"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeNormal
font.weight: Font.DemiBold
color: Theme.textPrimary
Layout.fillWidth: true
}
Text {
text: GlobalState.wifiConnected ? "On" : "Off"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: GlobalState.wifiConnected ? Theme.accentGreen : Theme.textTertiary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
// Active network info
ColumnLayout {
Layout.fillWidth: true
spacing: 3
Text {
text: GlobalState.wifiConnected ? `Connected to: ${GlobalState.wifiSsid}` : "No Network Connected"
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.Medium
color: Theme.textPrimary
elide: Text.ElideRight
Layout.fillWidth: true
}
Text {
visible: GlobalState.ipAddress !== "" && GlobalState.ipAddress !== "Offline"
text: `IP: ${GlobalState.ipAddress}`
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textSecondary
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Qt.rgba(1.0, 1.0, 1.0, 0.12)
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 24
radius: Theme.radiusSmall
color: netMouse.containsMouse ? Qt.rgba(1.0, 1.0, 1.0, 0.15) : Qt.rgba(1.0, 1.0, 1.0, 0.08)
Text {
anchors.centerIn: parent
text: "Network Preferences..."
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
color: Theme.textPrimary
}
MouseArea {
id: netMouse
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
GlobalState.wifiPopupVisible = false;
GlobalState.launchApp("nm-connection-editor || foot -e nmtui");
}
}
}
}
}