aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-10-13 10:26:59 +0200
committerDanilo M. <danix@danix.xyz>2026-10-13 10:27:04 +0200
commitd518e5f691fea8c28978bd4ea7d33c4cbda3232f (patch)
tree896b58b7a79c3d0ff6b0b80ceb541dac062bce10 /desktop
parent47a97f0717fc54b5eb33c266d8dbafdc8d3c15ee (diff)
downloadquickshell-d518e5f691fea8c28978bd4ea7d33c4cbda3232f.tar.gz
quickshell-d518e5f691fea8c28978bd4ea7d33c4cbda3232f.zip
feat(island): the clock pill opens the calendar panel
A click on the pill opens the panel in its capsule, 620px wide, growing left from the gap so the status pill does not move. Focus goes into the panel so its text fields and Escape work; Escape closes the editor before the panel. The Escape hook is back(), not escape(): QML rejects a method named escape with "Illegal method name", since it shadows the global JS function, and the reload failed until it was renamed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop')
-rw-r--r--desktop/island/ClockPill.qml38
-rw-r--r--desktop/island/Island.qml10
-rw-r--r--desktop/island/calendar/CalendarPanel.qml4
3 files changed, 45 insertions, 7 deletions
diff --git a/desktop/island/ClockPill.qml b/desktop/island/ClockPill.qml
index 93e840f..4ed8e38 100644
--- a/desktop/island/ClockPill.qml
+++ b/desktop/island/ClockPill.qml
@@ -14,16 +14,31 @@ import Quickshell.Widgets
import QtQuick
import ".."
import "../modules/vm"
+import "calendar"
import "Logic.js" as Logic
// Date and time at rest, with one dot per VM that is not plainly shut off.
// During a flick: the workspace's desktop icon, the app's icon and its name.
+// A click opens the calendar panel in this capsule.
Capsule {
id: pill
property bool flicking: false
property string flickWs: ""
property string flickApp: ""
+ property string panel: ""
+
+ signal openCalendar()
+ signal closeCalendar()
+
+ expanded: panel === "calendar"
+ panelWidth: 620
+ panelHeight: calendarPanel.implicitHeight + 28
+
+ // The island calls these: focus moves into the panel when it opens, and
+ // Escape asks the panel before closing it.
+ function focusPanel() { calendarPanel.reset(); calendarPanel.forceActiveFocus(); }
+ function back() { return calendarPanel.back(); }
readonly property var entry: flickApp ? DesktopEntries.heuristicLookup(flickApp) : null
readonly property string wsIcon: Workspaces.icon(flickWs)
@@ -42,7 +57,7 @@ Capsule {
id: restRow
anchors.centerIn: parent
spacing: 10
- opacity: pill.flicking ? 0 : 1
+ opacity: pill.flicking || pill.expanded ? 0 : 1
Behavior on opacity { NumberAnimation { duration: 150 } }
Text {
@@ -74,7 +89,7 @@ Capsule {
id: flickRow
anchors.centerIn: parent
spacing: 8
- opacity: pill.flicking ? 1 : 0
+ opacity: pill.flicking && !pill.expanded ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 150 } }
// The desktop sits in a badge so it does not read as a second app
@@ -126,4 +141,23 @@ Capsule {
color: Theme.text
}
}
+
+ // At rest the whole pill is the button; open, the panel takes the clicks.
+ MouseArea {
+ anchors.fill: parent
+ enabled: !pill.expanded
+ cursorShape: Qt.PointingHandCursor
+ onClicked: pill.openCalendar()
+ }
+
+ CalendarPanel {
+ id: calendarPanel
+ x: 14
+ y: 14
+ width: pill.panelWidth - 28
+ opacity: pill.expanded ? 1 : 0
+ visible: opacity > 0
+ Behavior on opacity { NumberAnimation { duration: 160 } }
+ onCloseRequested: pill.closeCalendar()
+ }
}
diff --git a/desktop/island/Island.qml b/desktop/island/Island.qml
index 43422dc..61701d8 100644
--- a/desktop/island/Island.qml
+++ b/desktop/island/Island.qml
@@ -36,7 +36,7 @@ PanelWindow {
WlrLayershell.namespace: "quickshell-island"
WlrLayershell.keyboardFocus: panel !== "" ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
- // "", "sound" or "controls".
+ // "", "sound", "controls" or "calendar".
property string panel: ""
// --- reveal and hide -------------------------------------------------
@@ -57,7 +57,8 @@ PanelWindow {
else if (panel === "" && !menuHeld) hideTimer.restart();
}
onPanelChanged: {
- if (panel !== "") keys.forceActiveFocus();
+ if (panel === "calendar") clock.focusPanel();
+ else if (panel !== "") keys.forceActiveFocus();
else if (!hovered) hideTimer.restart();
}
@@ -140,7 +141,7 @@ PanelWindow {
// Key events reach a focused item, not the window (AGENTS.md).
Item {
id: keys
- Keys.onEscapePressed: win.panel = ""
+ Keys.onEscapePressed: if (!(win.panel === "calendar" && clock.back())) win.panel = ""
}
// --- geometry --------------------------------------------------------
@@ -202,6 +203,9 @@ PanelWindow {
flicking: win.flicking
flickWs: win.flickWs
flickApp: win.flickApp
+ panel: win.panel
+ onOpenCalendar: win.panel = win.panel === "calendar" ? "" : "calendar"
+ onCloseCalendar: win.panel = ""
}
StatusPill {
diff --git a/desktop/island/calendar/CalendarPanel.qml b/desktop/island/calendar/CalendarPanel.qml
index 9515a9a..5d193eb 100644
--- a/desktop/island/calendar/CalendarPanel.qml
+++ b/desktop/island/calendar/CalendarPanel.qml
@@ -90,12 +90,12 @@ Item {
}
// Escape: the editor first, then the panel.
- function escape() {
+ function back() {
if (panel.editing) { panel.closeEditor(); return true; }
return false;
}
- Keys.onEscapePressed: if (!panel.escape()) panel.closeRequested()
+ Keys.onEscapePressed: if (!panel.back()) panel.closeRequested()
Component.onCompleted: panel.reset()