Native glassmorphic applets for a custom Linux rice
Off-the-shelf KDE Store widgets either look generic or lack the exact Pomodoro behaviour and aesthetic needed for a custom desktop rice — configurable session lengths, auto-start rules, and a glassmorphic glow design. Three native Plasma 6 applets were built from scratch to live in the panel exactly as needed: a glassmorphic Pomodoro timer (org.kde.plasma.pomodorotimerglass), a plain-theme Pomodoro variant, and a CPU/RAM system monitor widget.
The glass timer is the most complete: a full 25/5/15-minute work/break cycle with automatic session switching, colour-coded progress bars (amber for focus, teal for breaks), DropShadow glow effects on timer text and controls, a custom GlassButton inline component with hover and click animations, and a pulsing SequentialAnimation notification overlay on session completion. Both compact (panel strip) and full (popover) representations are implemented. A two-page KDE configuration UI exposes 17 configurable properties — session durations, auto-start rules, notification toggles, appearance options — with a live preview rectangle that updates in real time as settings change.
The KDE community was mid-transition from Plasma 5 to Plasma 6 at the time (mid-2025), and most StackOverflow answers and KDE forum posts still referenced the Plasma 5 API. PlasmoidItem was new in Plasma 6 — the older Plasma 5 pattern used a plain Item with Plasmoid.compactRepresentation. The correct cfg_* alias binding pattern for KDE-native settings persistence, and the difference between Qt5Compat.GraphicalEffects and QtQuick.Effects for the Plasma 6 transition, both required reading first-party KDE widget source code on invent.kde.org rather than relying on community documentation.
Each widget is a self-contained Plasma package: metadata.json declares the Plasma 6 minimum API version (X-Plasma-API-Minimum-Version: 6.0) and supported form factors (desktop, panel). The glass timer's main.qml (713 lines) contains the full timer logic, compact and full representations, and the GlassButton inline component defined using Qt 6's component declaration — a language feature not available in Qt 5 QML. Configuration is exposed via a ConfigModel with two ConfigCategory pages (ConfigGeneral.qml, ConfigAppearance.qml) using KCM.SimpleKCM and Kirigami.FormLayout. Settings persist via the cfg_* alias pattern connecting KDE's config storage system directly to QML property aliases — no explicit save/load code. A package.sh script zips contents/ + metadata.json into a .plasmoid archive installable with kpackagetool6 -t Plasma/Applet -i <widget>.plasmoid.
Targeting Plasma 6 API directly over the safer Plasma 5 target. Writing against PlasmoidItem and QtQuick.Effects from the start avoids a future migration and signals intentional use of modern QML idioms, even though it required reading first-party KDE source rather than following community tutorials.
GlassButton as an inline Qt 6 component declaration. Defining the button once inside main.qml using Qt 6's inline component feature keeps button behaviour co-located with its usage without requiring a separate file, and changes to animation timing or colours propagate everywhere from a single definition.
cfg_* alias pattern for config persistence. The KDE-standard property alias cfg_workDuration: workDurationSpinBox.value connects the config storage system directly to QML aliases — widget settings survive Plasma restarts without any explicit save/load code.
System monitor left as a structured prototype. The system monitor widget uses Math.random() for its data with an explicit comment marking where real org.kde.plasma.system calls would go. The layout, polling timer, and colour threshold logic are production-ready; only the data source binding is deferred — an honest "ship the structure, wire the data later" approach.
All three widgets ship as installable .plasmoid packages ready for kpackagetool6 on any KDE Plasma 6 machine. The glass timer is a complete, polished applet comparable to first-party KDE widgets in config-system integration — 17 configurable properties, live appearance preview, reactive property binding so config changes propagate to a running timer without restart. The project demonstrated that QML's declarative property-binding paradigm — where state changes propagate via bindings rather than explicit re-renders — is a cleaner model than React-style controlled components for persisted desktop widget settings.
lines of QML across 6 source files
configurable properties in the glass timer
KDE config pages with live preview
Swift/SwiftUI + Rust/Tauri + QML timer overlay with timezone math, objc2 FFI, and multi-platform CI
33-panel Tauri v2 + Svelte 5 macOS developer HUD with Rust sysinfo metrics, Docker management, and an embedded webhook server
Did this resonate?