From d518e5f691fea8c28978bd4ea7d33c4cbda3232f Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Tue, 13 Oct 2026 10:26:59 +0200 Subject: 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 --- desktop/island/ClockPill.qml | 38 +++++++++++++++++++++++++++++-- desktop/island/Island.qml | 10 +++++--- desktop/island/calendar/CalendarPanel.qml | 4 ++-- 3 files changed, 45 insertions(+), 7 deletions(-) (limited to 'desktop') 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() -- cgit v1.2.3