diff --git a/config/dot/quickshell/prism-gallery.qml b/config/dot/quickshell/prism-gallery.qml new file mode 100644 index 0000000..07a316c --- /dev/null +++ b/config/dot/quickshell/prism-gallery.qml @@ -0,0 +1,375 @@ +// A living reference for Panama's shared visual language. This deliberately +// renders the production widgets instead of lookalike mock components, so a +// change to a control or Theme token is visible here immediately. + +import Quickshell +import QtQuick +import QtQuick.Layouts +import qs.config +import qs.widgets + +ShellRoot { + FloatingWindow { + id: galleryWindow + + title: "Panama Prism Gallery" + visible: true + implicitWidth: 1120 + implicitHeight: 760 + minimumSize: Qt.size(920, 640) + color: Theme.bg + + Rectangle { + anchors.fill: parent + color: Theme.bg + + PrismEdge { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + inset: 0 + } + + RowLayout { + anchors.fill: parent + anchors.margins: 34 + spacing: 34 + + // Quiet editorial rail: enough context to make screenshots + // self-explanatory without competing with the components. + ColumnLayout { + Layout.preferredWidth: 222 + Layout.fillHeight: true + spacing: 0 + + Rectangle { + Layout.preferredWidth: 38 + Layout.preferredHeight: 38 + radius: 12 + color: Theme.alpha(Theme.fg, 0.07) + + ThemedIcon { + anchors.centerIn: parent + size: 20 + icon: "applications-graphics-symbolic" + tint: Theme.accent + } + } + + Text { + Layout.topMargin: 20 + text: "PRISM" + color: Theme.fg + font.family: Theme.fontFamily + font.pixelSize: 26 + font.weight: Font.DemiBold + font.letterSpacing: 1.4 + } + + Text { + Layout.topMargin: 5 + Layout.maximumWidth: 210 + text: "Panama's living interface reference. Calm by default, vivid with purpose." + color: Theme.fgDim + wrapMode: Text.WordWrap + lineHeight: 1.25 + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSize + } + + Item { Layout.preferredHeight: 36 } + + Repeater { + model: [ + { label: "Tokyo Night Moon", color: Theme.bgHighlight }, + { label: "Signal blue", color: Theme.accent }, + { label: "Prism orchid", color: Theme.accentSecondary } + ] + + RowLayout { + required property var modelData + Layout.topMargin: 10 + spacing: 10 + + Rectangle { + Layout.preferredWidth: 12 + Layout.preferredHeight: 12 + radius: 6 + color: modelData.color + } + + Text { + text: modelData.label + color: Theme.fgDim + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSizeSmall + } + } + } + + Item { Layout.fillHeight: true } + + Text { + text: "REAL COMPONENTS · LIVE TOKENS" + color: Theme.fgMuted + font.family: Theme.fontFamily + font.pixelSize: 10 + font.weight: Font.DemiBold + font.letterSpacing: 1.1 + } + } + + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + radius: Theme.popoverRadius + color: Theme.alpha(Theme.bgPopover, Theme.popoverAlpha) + border.width: 1 + border.color: Theme.alpha(Theme.fg, 0.08) + + PrismEdge { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + inset: parent.radius + } + + Flickable { + anchors.fill: parent + anchors.margins: 30 + contentWidth: width + contentHeight: content.implicitHeight + clip: true + boundsBehavior: Flickable.StopAtBounds + + ColumnLayout { + id: content + width: parent.width + spacing: 28 + + RowLayout { + Layout.fillWidth: true + + ColumnLayout { + spacing: 4 + + Text { + text: "Interface inventory" + color: Theme.fg + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSizeTitle + font.weight: Font.DemiBold + } + + Text { + text: "Production controls in their canonical states" + color: Theme.fgDim + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSize + } + } + + Item { Layout.fillWidth: true } + + Pill { + interactive: false + horizontalPadding: 12 + + ThemedIcon { + size: 14 + icon: "emblem-ok-symbolic" + tint: Theme.green + } + + Text { + text: "TOKYO NIGHT MOON" + color: Theme.fgDim + font.family: Theme.fontFamily + font.pixelSize: 10 + font.weight: Font.DemiBold + font.letterSpacing: 0.8 + } + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 12 + + Text { + text: "QUICK CONTROLS" + color: Theme.fgMuted + font.family: Theme.fontFamily + font.pixelSize: 10 + font.weight: Font.DemiBold + font.letterSpacing: 1.1 + } + + RowLayout { + Layout.fillWidth: true + spacing: 12 + + Toggle { + id: wifiToggle + Layout.fillWidth: true + icon: "network-wireless-signal-excellent-symbolic" + label: "Wi-Fi" + sublabel: active ? "Connected" : "Off" + active: true + onToggled: active = !active + } + + Toggle { + id: bluetoothToggle + Layout.fillWidth: true + icon: "bluetooth-active-symbolic" + label: "Bluetooth" + sublabel: active ? "2 devices" : "Off" + active: false + onToggled: active = !active + } + + Toggle { + id: focusToggle + Layout.fillWidth: true + icon: "weather-clear-night-symbolic" + label: "Focus" + sublabel: active ? "Until 5:30" : "Available" + active: false + onToggled: active = !active + } + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 12 + + Text { + text: "CONTINUOUS VALUES" + color: Theme.fgMuted + font.family: Theme.fontFamily + font.pixelSize: 10 + font.weight: Font.DemiBold + font.letterSpacing: 1.1 + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 126 + radius: Theme.cardRadius + color: Theme.alpha(Theme.fg, 0.045) + + ColumnLayout { + anchors.fill: parent + anchors.margins: 18 + spacing: 12 + + RowLayout { + Layout.fillWidth: true + + Text { + text: "System audio" + color: Theme.fg + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSize + font.weight: Font.Medium + } + + Item { Layout.fillWidth: true } + + Text { + text: Math.round(volumeSlider.value * 100) + "%" + color: Theme.fgDim + font.family: Theme.fontFamily + font.features: Theme.tabularFigures + font.pixelSize: Theme.fontSize + } + } + + ValueSlider { + id: volumeSlider + Layout.fillWidth: true + value: 0.68 + icon: "audio-volume-high-symbolic" + onMoved: newValue => volumeSlider.value = newValue + } + } + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 12 + + Text { + text: "BAR MATERIAL" + color: Theme.fgMuted + font.family: Theme.fontFamily + font.pixelSize: 10 + font.weight: Font.DemiBold + font.letterSpacing: 1.1 + } + + Rectangle { + Layout.fillWidth: true + Layout.preferredHeight: 74 + radius: Theme.cardRadius + color: Theme.alpha(Theme.bg, 0.62) + + Row { + anchors.centerIn: parent + spacing: 8 + + Pill { + ThemedIcon { + size: 15 + icon: "view-grid-symbolic" + tint: Theme.accent + } + Text { + text: "1 2 3" + color: Theme.fg + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSizeSmall + } + } + + Pill { + ThemedIcon { + size: 15 + icon: "edit-copy-symbolic" + tint: Theme.fgDim + } + Text { + text: "Clipboard" + color: Theme.fg + font.family: Theme.fontFamily + font.pixelSize: Theme.fontSizeSmall + } + } + + Pill { + ThemedIcon { + size: 15 + icon: "appointment-soon-symbolic" + tint: Theme.fgDim + } + Text { + text: "Tue Aug 18 · 4:46 AM" + color: Theme.fg + font.family: Theme.fontFamily + font.features: Theme.tabularFigures + font.pixelSize: Theme.fontSizeSmall + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/config/dot/quickshell/scripts/panama-prism-gallery b/config/dot/quickshell/scripts/panama-prism-gallery new file mode 100755 index 0000000..b77c6f4 --- /dev/null +++ b/config/dot/quickshell/scripts/panama-prism-gallery @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -euo pipefail + +gallery="${XDG_CONFIG_HOME:-$HOME/.config}/quickshell/prism-gallery.qml" + +if qs -p "$gallery" ipc show >/dev/null 2>&1; then + qs -p "$gallery" kill +else + qs -p "$gallery" --daemonize +fi diff --git a/docs/UPSTREAM-INSPIRATION.md b/docs/UPSTREAM-INSPIRATION.md new file mode 100644 index 0000000..4c7161c --- /dev/null +++ b/docs/UPSTREAM-INSPIRATION.md @@ -0,0 +1,26 @@ +# Upstream inspiration + +Panama is its own desktop experience, but it should learn from strong open-source work without obscuring where an idea came from. This ledger records upstream projects that materially influence its architecture or interaction design. + +## Omarchy + +- Project: [basecamp/omarchy](https://github.com/basecamp/omarchy) +- Reviewed revision: `f32ebbdb730c4e8fe11e4046cef4267e466264ea` +- License: MIT, copyright David Heinemeier Hansson +- Local reference at review time: `/home/gib/Documents/Code/Projects/omarchy` + +### Adopted ideas, rebuilt for Panama + +- `shell/plugins/osd/Osd.qml` and `OsdModel.js`: inspired the separation between a pure presentation model and a single, click-through per-monitor OSD surface. Panama rebuilt the behavior around freedesktop symbolic icons, Tokyo Night Moon tokens, its Prism glass material, Hyprland's focused monitor, and the existing `wpctl`/`brightnessctl`/`playerctl` keybindings. +- `test/shell.d/osd-test.sh` and Omarchy's broader shell contract suite: reinforced Panama's use of fast model and integration contracts alongside live compositor verification. +- Omarchy's small shared visual primitives: reinforced the decision to maintain `prism-gallery.qml`, which renders Panama's production widgets and Theme tokens instead of duplicating mock-only controls. + +No Omarchy user-facing layout or styling was transplanted. Panama keeps its GNOME-derived information architecture, Prism material, Tokyo Night Moon palette, app model, and established interaction choices. + +### Candidates still under evaluation + +- A command palette for shell actions, with Vicinae remaining the application launcher. +- A plugin boundary for optional bar widgets and services once Panama has enough third-party modules to justify one. +- A small first-run health check for missing desktop dependencies and broken service integrations. + +These are research directions, not commitments. They should only land when they improve the daily-driver experience without adding visible complexity or parallel configuration systems. diff --git a/tests/quickshell/prism-gallery-contract.sh b/tests/quickshell/prism-gallery-contract.sh new file mode 100755 index 0000000..6730311 --- /dev/null +++ b/tests/quickshell/prism-gallery-contract.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +gallery="$repo_dir/config/dot/quickshell/prism-gallery.qml" +launcher="$repo_dir/config/dot/quickshell/scripts/panama-prism-gallery" + +fail() { + printf 'Prism gallery contract: %s\n' "$1" >&2 + exit 1 +} + +[[ -f "$gallery" ]] || fail 'the real-component gallery is missing' +[[ -x "$launcher" ]] || fail 'the gallery launcher is missing or not executable' + +rg -Fq 'import qs.widgets' "$gallery" || fail 'gallery does not use the shared widget module' +for component in Pill Toggle ValueSlider ThemedIcon PrismEdge; do + rg -q "^[[:space:]]*${component}[[:space:]]*\\{" "$gallery" \ + || fail "gallery does not render the real ${component} component" +done + +rg -Fq 'title: "Panama Prism Gallery"' "$gallery" \ + || fail 'gallery does not expose a stable compositor window title' +rg -Fq 'FloatingWindow {' "$gallery" \ + || fail 'gallery must be a normal tiled application window' + +if rg -q '#[0-9a-fA-F]{3,8}' "$gallery"; then + fail 'gallery hardcodes a colour instead of using the Theme vocabulary' +fi +if rg -q 'loops:[[:space:]]*(Animation\.Infinite|-1)|running:[[:space:]]*true' "$gallery"; then + fail 'gallery contains an always-running animation' +fi + +rg -Fq 'qs -p "$gallery" --daemonize' "$launcher" \ + || fail 'launcher does not start the isolated Quickshell gallery config' +rg -Fq 'qs -p "$gallery" kill' "$launcher" \ + || fail 'launcher cannot close an already-open gallery instance' + +printf 'Prism gallery contract: PASS\n'