Compare commits

..

82 commits

Author SHA1 Message Date
Benjamin Palko
618fc22e80 allow drawers to close on parent window focus lost 2025-11-10 11:54:25 -05:00
Benjamin Palko
3c3fe368bc simplify tray item 2025-10-28 20:57:58 -04:00
Benjamin Palko
fe8261f7af move theme types to Styling 2025-09-25 13:55:51 -04:00
Benjamin Palko
823dd66719 much better 2025-09-24 22:57:33 -04:00
Benjamin Palko
617931a115 initial load 2025-09-24 09:43:28 -04:00
Benjamin Palko
2aa72accda strip unused WallpaperService stuff 2025-09-23 23:01:33 -04:00
Benjamin Palko
6b9ecc5b3d add wallpaper config 2025-09-23 23:01:21 -04:00
Benjamin Palko
7ba6222105 powermenu config in shell json 2025-09-23 15:06:23 -04:00
Benjamin Palko
7935487295 reee 2025-09-23 14:13:24 -04:00
Benjamin Palko
d58144a853 styledimage 2025-09-23 13:19:38 -04:00
Benjamin Palko
2bfa0c189a wallpaper selection 2025-09-22 21:29:36 -04:00
Benjamin Palko
3d1816c0f1 wallpaper service 2025-09-20 23:08:57 -04:00
Benjamin Palko
9c074dc9e5 double import...fixed 2025-09-20 23:07:37 -04:00
Benjamin Palko
2d251c044d remove wallpaper view 2025-09-20 23:07:10 -04:00
Benjamin Palko
e2816bcb1e directory watcher 2025-09-20 21:21:30 -04:00
Benjamin Palko
d5a92eb19b remove, doesnt do anything 2025-09-18 21:16:15 -04:00
Benjamin Palko
8fe50936a0 kind of fix tabs for now
its fucked I dont want to deal with it right now
2025-09-18 21:04:08 -04:00
Benjamin Palko
450ff7a503 wallpapers WIP 2025-09-18 08:37:56 -04:00
Benjamin Palko
3a67bc5204 alias data 2025-09-17 17:39:03 -04:00
Benjamin Palko
0a445eaa08 remove padding and increase window size 2025-09-17 12:00:25 -04:00
Benjamin Palko
5e82fd906d formatting tabs 2025-09-17 11:57:21 -04:00
Benjamin Palko
338e81d3ad set default property on windowpanel for styling 2025-09-17 10:21:59 -04:00
Benjamin Palko
c22a8f796d move process, window cant take it atm 2025-09-17 10:21:42 -04:00
Benjamin Palko
ed6cd2c8d5 root panel window handles focus 2025-09-17 09:47:32 -04:00
Benjamin Palko
bd826c14ac refactor out theme object 2025-09-16 10:45:54 -04:00
Benjamin Palko
c03d24de15 create ThemeComboBox 2025-09-16 10:33:55 -04:00
Benjamin Palko
7a04cccf0c should use Styling 2025-09-16 10:33:42 -04:00
Benjamin Palko
fdf61a0e90 remove font family from theme 2025-09-16 10:32:19 -04:00
Benjamin Palko
37afb798bc move mpris player selector 2025-09-16 10:20:54 -04:00
Benjamin Palko
4007344d9d move mpris controller 2025-09-16 10:20:35 -04:00
Benjamin Palko
06bbd34b73 fuck that was easy 2025-09-16 08:59:56 -04:00
Benjamin Palko
c76f29345e tabbbss are still kinda fucked 2025-09-16 08:48:23 -04:00
Benjamin Palko
9d6a88aa43 add wayland and hyprland focus 2025-09-16 08:43:18 -04:00
Benjamin Palko
185121d0d7 style tab bar 2025-09-16 08:36:07 -04:00
Benjamin Palko
f687e17c94 limit volume 2025-09-15 22:05:02 -04:00
Benjamin Palko
b0d9342e1d forward control spacing 2025-09-15 22:04:46 -04:00
Benjamin Palko
1c30ea270f alias panel window background 2025-09-15 20:43:24 -04:00
Benjamin Palko
ebb66dee21 add audio volume slider 2025-09-15 20:37:53 -04:00
Benjamin Palko
141c64a0bb alias rectangle radius on tab button 2025-09-15 20:37:20 -04:00
Benjamin Palko
ad3a275c21 color animatinos 2025-09-15 16:16:35 -04:00
Benjamin Palko
1a8a14bf53 add more icons 2025-09-13 23:29:01 -04:00
Benjamin Palko
22cf6cc53e basic audio configurations 2025-09-13 22:53:40 -04:00
Benjamin Palko
8ba0567d28 vertical tabs on configuration 2025-09-11 23:57:12 -04:00
Benjamin Palko
83e9c6f08c override contentItem and alias orientation 2025-09-11 23:56:56 -04:00
Benjamin Palko
93b3a09a0a remove id 2025-09-11 23:41:14 -04:00
Benjamin Palko
9adae58589 swipeview 2025-09-11 23:41:07 -04:00
Benjamin Palko
f974911b1c color text on checked 2025-09-11 23:26:58 -04:00
Benjamin Palko
3306bb959c reduce default padding 2025-09-11 22:38:03 -04:00
Benjamin Palko
8104e3c099 wrap all items in pane 2025-09-11 17:05:14 -04:00
Benjamin Palko
2b6b9aee28 change border on tab button when active 2025-09-11 17:01:08 -04:00
Benjamin Palko
0ab37420a2 change pane border on hover 2025-09-11 17:00:43 -04:00
Benjamin Palko
01c2ea9044 add new dependencies 2025-09-10 12:02:37 -04:00
Benjamin Palko
fbc2a10b69 use quickshell idle inhib 2025-09-09 23:16:20 -04:00
Benjamin Palko
a10c2f0254 use pane on items 2025-09-08 10:56:07 -04:00
Benjamin Palko
162f8f6b6f tab button padding 2025-09-08 10:13:13 -04:00
Benjamin Palko
e180fee2a9 styled pane 2025-09-08 08:23:57 -04:00
Benjamin Palko
32167ef44e make storybook a tabbed window 2025-09-07 23:33:03 -04:00
Benjamin Palko
8aced615ce add theme selector to configurations 2025-09-07 22:32:25 -04:00
Benjamin Palko
47532bd626 add configuration menu 2025-09-07 13:25:02 -04:00
Benjamin Palko
25e313e31b clean up launcher, make it guuud 2025-09-07 12:52:53 -04:00
Benjamin Palko
ea86cc575d panel window contains background styling 2025-09-07 12:45:54 -04:00
Benjamin Palko
4bda51f02c panel window 2025-09-07 12:22:27 -04:00
Benjamin Palko
351fb82ac7 use wrapper rect 2025-09-07 12:21:33 -04:00
Benjamin Palko
112ed0d6de simplify StyledPopupWindow 2025-09-07 09:34:42 -04:00
Benjamin Palko
fdcaa77581 remove scuffed popup handling 2025-09-07 09:23:51 -04:00
Benjamin Palko
0405dc3414 rename to styled rectangle 2025-09-06 22:31:17 -04:00
Benjamin Palko
4e2a1874d1 delete styled popup 2025-09-06 22:28:06 -04:00
Benjamin Palko
96d1352666 move styledpopupwindow 2025-09-06 22:27:42 -04:00
Benjamin Palko
7022c3a9ae move bar to root window 2025-09-06 22:08:19 -04:00
Benjamin Palko
8c59137716 remove menu 2025-09-06 09:03:33 -04:00
Benjamin Palko
0c4d2dc597 rename pomodoro service 2025-09-06 09:01:38 -04:00
Benjamin Palko
af396bc2c5 layout, radius and border 2025-09-06 08:45:35 -04:00
Benjamin Palko
7de7ae19bb add typography 2025-09-05 22:41:21 -04:00
Benjamin Palko
205ad37e3e only watch theme files 2025-09-05 17:33:48 -04:00
Benjamin Palko
4375f6e13d move theme to styling 2025-09-05 17:30:09 -04:00
Benjamin Palko
467c9bc0e3 move lucide to Styling 2025-09-05 17:22:16 -04:00
Benjamin Palko
9fc91a92f7 add styling with animation speed 2025-09-05 15:48:24 -04:00
Benjamin Palko
f7e8fb7720 adjust theme on components 2025-09-05 15:15:17 -04:00
Benjamin Palko
a44b6f5e44 implement theme file storage 2025-09-05 13:12:40 -04:00
Benjamin Palko
c53f0c2c41 migrate themes to config dir 2025-09-05 12:12:11 -04:00
Benjamin Palko
a12b36c188 paths 2025-09-04 20:01:36 -04:00
Benjamin Palko
16e5059c7a empty item 2025-09-04 17:26:00 -04:00
84 changed files with 1783 additions and 999 deletions

View file

@ -12,13 +12,11 @@ Run the shell
quickshell -c shell quickshell -c shell
``` ```
Run app launcher
```shell
quickshell -c launcher
```
## Dependencies ## Dependencies
- `quickshell` - `quickshell`
- `qt6-wayland`
- `app2unit` - `app2unit`
- `meson`
- `ninja`
- `python3`

View file

@ -2,13 +2,12 @@ import qs.config
import QtQuick import QtQuick
Text { Text {
color: Theme.palette.basecontent font.family: Styling.lucide.font.family
font.pixelSize: 16
color: Styling.theme.basecontent
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.fast
} }
} }
font.family: Theme.lucide.font.family
font.pixelSize: Dimensions.gpu.iconSize
font.bold: true
} }

View file

@ -7,19 +7,21 @@ Button {
property alias border: rectangle.border property alias border: rectangle.border
property alias radius: rectangle.radius property alias radius: rectangle.radius
font.pixelSize: 14 font.pixelSize: Styling.typography.textSize.base
padding: 6 font.family: Styling.typography.fontFamily
verticalPadding: 6
horizontalPadding: 8
palette.button: hovered ? Theme.palette.primary : Theme.palette.base100 palette.button: hovered ? Styling.theme.primary : Styling.theme.base200
Behavior on palette.button { Behavior on palette.button {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.normal
} }
} }
palette.buttonText: hoverEnabled && hovered ? Theme.palette.primarycontent : Theme.palette.basecontent palette.buttonText: hoverEnabled && hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
Behavior on palette.buttonText { Behavior on palette.buttonText {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.normal
} }
} }
@ -32,6 +34,6 @@ Button {
background: Rectangle { background: Rectangle {
id: rectangle id: rectangle
color: root.palette.button color: root.palette.button
radius: 8 radius: Styling.theme.radiusField
} }
} }

View file

@ -0,0 +1,107 @@
pragma ComponentBehavior: Bound
import qs.config
import QtQuick
import QtQuick.Controls
import Quickshell.Widgets
ComboBox {
id: control
palette.button: Styling.theme.base200
palette.buttonText: Styling.theme.basecontent
palette.highlight: Styling.theme.primary
palette.highlightedText: Styling.theme.primarycontent
palette.text: Styling.theme.basecontent
palette.window: Styling.theme.base200
implicitHeight: 40
delegate: ItemDelegate {
id: delegate
required property var model
required property int index
width: control.width
contentItem: StyledText {
text: delegate.model[control.textRole]
color: delegate.highlighted ? palette.highlightedText : palette.buttonText
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
background: Rectangle {
color: delegate.highlighted ? palette.highlight : palette.button
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
}
highlighted: control.highlightedIndex === index
}
contentItem: StyledText {
leftPadding: 12
text: control.displayText
color: control.hovered || control.down ? palette.highlightedText : palette.buttonText
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
color: control.hovered || control.down ? palette.highlight : palette.button
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
border.color: Styling.theme.base100
border.width: control.visualFocus ? 2 : 1
radius: Styling.theme.radiusSelector
}
popup: Popup {
palette: control.palette
y: control.height - 1
width: control.width
height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)
padding: 1
contentItem: ClippingWrapperRectangle {
radius: Styling.theme.radiusField
ListView {
clip: true
implicitHeight: contentHeight + 2
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
ScrollIndicator.vertical: ScrollIndicator {}
}
}
background: Rectangle {
color: palette.window
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
radius: Styling.theme.radiusField
}
}
}

View file

@ -1,11 +1,29 @@
import qs.config import qs.config
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Widgets
Drawer { Drawer {
id: control id: control
dim: false dim: false
background: Rectangle { property bool focused: false
onVisibleChanged: {
focused = visible;
}
HyprlandFocusGrab {
active: control.focused
windows: [QsWindow.window]
onCleared: {
control.focused = false;
}
}
background: ClippingWrapperRectangle {
margin: 4
Component.onCompleted: { Component.onCompleted: {
if (control.edge == Qt.TopEdge) { if (control.edge == Qt.TopEdge) {
radius = 8; radius = 8;
@ -20,6 +38,24 @@ Drawer {
topRightRadius = 8; topRightRadius = 8;
} }
} }
color: Theme.palette.base200 color: Styling.theme.base300
Rectangle {
Component.onCompleted: {
if (control.edge == Qt.TopEdge) {
radius = 8;
} else if (control.edge == Qt.LeftEdge) {
topRightRadius = 8;
bottomRightRadius = 8;
} else if (control.edge == Qt.RightEdge) {
topLeftRadius = 8;
bottomLeftRadius = 8;
} else if (control.edge == Qt.BottomEdge) {
topLeftRadius = 8;
topRightRadius = 8;
}
}
color: Styling.theme.base100
}
} }
} }

View file

@ -5,19 +5,14 @@ import QtQuick.Controls
RoundButton { RoundButton {
id: control id: control
FontLoader {
id: loader
source: "../assets/lucide.woff"
}
property alias border: rect.border property alias border: rect.border
property color color: hovered ? Theme.palette.primarycontent : Theme.palette.basecontent property color color: hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
property int rotation: 0 property int rotation: 0
font.family: loader.font.family font.family: Styling.lucide.font.family
font.pixelSize: 18 font.pixelSize: 16
radius: 8 radius: Styling.theme.radiusField
padding: 6 padding: 8
HoverHandler { HoverHandler {
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
@ -27,34 +22,35 @@ RoundButton {
id: icon id: icon
font: control.font font: control.font
text: control.text text: control.text
verticalAlignment: Text.AlignVCenter
color: control.color color: control.color
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.normal
} }
} }
rotation: control.rotation rotation: control.rotation
Behavior on rotation { Behavior on rotation {
RotationAnimation { RotationAnimation {
duration: 200 duration: Styling.animations.speed.slow
easing.type: Easing.InOutCubic easing.type: Easing.OutQuad
} }
} }
} }
background: Rectangle { background: Rectangle {
id: rect id: rect
border.color: control.hovered ? Theme.palette.primary : Theme.palette.base100 border.color: control.hovered ? Styling.theme.base300 : Styling.theme.base200
Behavior on border.color { Behavior on border.color {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.normal
} }
} }
border.width: 2 border.width: 0
color: control.hovered ? Theme.palette.primary : Theme.palette.base100 color: control.hovered ? Styling.theme.primary : Styling.theme.base200
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: 100 duration: Styling.animations.speed.normal
} }
} }
radius: control.radius radius: control.radius

View file

@ -0,0 +1,17 @@
import qs.config
import QtQuick
import Quickshell.Widgets
Image {
property alias radius: rectangle.radius
property alias skeletonColor: rectangle.color
ClippingRectangle {
id: rectangle
color: Styling.theme.base200
anchors.fill: parent
}
}

View file

@ -1,16 +0,0 @@
import qs.config
import QtQuick
import Quickshell.Widgets
WrapperRectangle {
id: root
margin: 8
radius: 8
color: Theme.palette.base100
Behavior on color {
ColorAnimation {
duration: 200
easing.type: Easing.InOutQuad
}
}
}

View file

@ -1,3 +1,4 @@
import qs.config
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
@ -14,7 +15,7 @@ ListView {
rebound: Transition { rebound: Transition {
NumberAnimation { NumberAnimation {
properties: "x,y" properties: "x,y"
duration: 400 duration: Styling.animations.speed.slow
easing.type: Easing.BezierSpline easing.type: Easing.BezierSpline
easing.bezierCurve: [0.2, 0, 0, 1, 1, 1] easing.bezierCurve: [0.2, 0, 0, 1, 1, 1]
} }

21
components/StyledPane.qml Normal file
View file

@ -0,0 +1,21 @@
import qs.config
import QtQuick
import QtQuick.Controls
Pane {
id: pane
padding: 8
background: Rectangle {
color: "transparent"
border.width: Styling.theme.border
border.color: pane.hovered ? Styling.theme.accent : Styling.theme.basecontent
opacity: 0.33
Behavior on border.color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
radius: Styling.theme.radiusBox
}
}

View file

@ -0,0 +1,74 @@
import qs.config
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland
PanelWindow {
id: window
default property alias content: contentItem.data
property alias background: background
required property string name
property bool canFocus: true
property bool focused: false
property int padding: 4
WlrLayershell.namespace: `lux-${name}`
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: window.visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
onVisibleChanged: {
if (!canFocus)
return;
focused = visible;
}
HyprlandFocusGrab {
active: window.focused
windows: [window]
onCleared: {
if (!window.canFocus)
return;
window.focused = false;
}
}
color: "transparent"
Rectangle {
id: background
anchors.fill: parent
radius: Styling.theme.radiusBox
Behavior on radius {
NumberAnimation {
duration: Styling.animations.speed.normal
}
}
color: Styling.theme.base100
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
Behavior on opacity {
NumberAnimation {
duration: Styling.animations.speed.fast
}
}
border.width: 2
border.color: Styling.theme.base300
Behavior on border.color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
}
}
Item {
id: contentItem
anchors.centerIn: parent
implicitWidth: parent.width - 2 * window.padding
implicitHeight: parent.height - 2 * window.padding
}
}

View file

@ -6,33 +6,87 @@ import Quickshell.Hyprland
PopupWindow { PopupWindow {
id: root id: root
implicitWidth: contentItem.children.reduce((prev, child) => Math.max(prev, child.width), 0) required property Component content
implicitHeight: contentItem.children.reduce((prev, child) => prev + child.height, 0)
implicitWidth: background.width
implicitHeight: background.height
color: "transparent" color: "transparent"
contentItem.focus: visible
function open() {
visible = true;
}
function close() {
visible = false;
}
// WlrLayershell.layer: WlrLayer.Top
// WlrLayershell.keyboardFocus: root.visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
HyprlandFocusGrab { HyprlandFocusGrab {
id: grab
active: root.visible active: root.visible
windows: [root] windows: [root]
onCleared: { onCleared: {
root.close(); background.state = "closed";
} }
} }
Rectangle { function toggle() {
background.state = background.state == "opened" ? "closed" : "opened";
}
StyledWrapperRectangle {
id: background id: background
anchors.fill: parent
color: Theme.palette.base200 margin: 16
radius: 8 focus: true
onFocusChanged: {
if (!focus) {
grab.active = false;
}
}
Behavior on opacity {
NumberAnimation {
duration: Styling.animations.speed.normal
}
}
state: "closed"
states: [
State {
name: "closed"
PropertyChanges {
background {
opacity: 0
}
}
},
State {
name: "opened"
PropertyChanges {
background {
opacity: 1
}
}
}
]
transitions: [
Transition {
from: "closed"
to: "opened"
ScriptAction {
script: root.visible = true
}
},
Transition {
from: "opened"
to: "closed"
SequentialAnimation {
PauseAnimation {
duration: root.animationDuration
}
ScriptAction {
script: root.visible = false
}
}
}
]
Loader {
active: root.visible
sourceComponent: root.content
}
} }
} }

View file

@ -15,8 +15,8 @@ ProgressBar {
background: Rectangle { background: Rectangle {
implicitWidth: 200 implicitWidth: 200
implicitHeight: 6 implicitHeight: 6
color: Theme.palette.base100 color: Styling.theme.base100
radius: 8 radius: Styling.theme.radiusField
} }
contentItem: Item { contentItem: Item {
@ -27,8 +27,8 @@ ProgressBar {
Rectangle { Rectangle {
width: control.visualPosition * parent.width width: control.visualPosition * parent.width
height: parent.height height: parent.height
radius: 8 radius: Styling.theme.radiusField
color: Theme.palette.primary color: Styling.theme.primary
visible: !control.indeterminate visible: !control.indeterminate
} }
@ -41,14 +41,14 @@ ProgressBar {
Row { Row {
Rectangle { Rectangle {
id: rect id: rect
color: Theme.palette.primary color: Styling.theme.primary
width: 40 width: 40
height: control.height height: control.height
} }
XAnimator on x { XAnimator on x {
from: control.width + rect.width from: control.width + rect.width
to: -rect.width to: -rect.width
duration: 1000 duration: Styling.animations.speed.verySlow
loops: Animation.Infinite loops: Animation.Infinite
running: control.indeterminate running: control.indeterminate
} }

View file

@ -0,0 +1,12 @@
import qs.config
import QtQuick
Rectangle {
radius: Styling.theme.radiusBox
color: Styling.theme.base200
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.normal
}
}
}

View file

@ -18,19 +18,19 @@ Slider {
implicitHeight: control.height implicitHeight: control.height
width: control.availableWidth width: control.availableWidth
height: implicitHeight height: implicitHeight
radius: 8 radius: Styling.theme.radiusField
color: Theme.palette.base100 color: Styling.theme.base200
Rectangle { Rectangle {
width: control.visualPosition * parent.width width: control.visualPosition * parent.width
Behavior on width { Behavior on width {
NumberAnimation { NumberAnimation {
duration: 75 duration: Styling.animations.speed.fast
} }
} }
height: parent.height height: parent.height
color: Theme.palette.primary color: Styling.theme.primary
radius: 8 radius: Styling.theme.radiusField
} }
} }
handle: null handle: null

View file

@ -11,7 +11,7 @@ Switch {
text: control.text text: control.text
font: control.font font: control.font
opacity: enabled ? 1.0 : 0.3 opacity: enabled ? 1.0 : 0.3
color: Theme.palette.basecontent color: Styling.theme.basecontent
elide: Text.ElideRight elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
} }
@ -29,9 +29,9 @@ Switch {
implicitHeight: 24 implicitHeight: 24
x: control.width - width - control.rightPadding x: control.width - width - control.rightPadding
y: parent.height / 2 - height / 2 y: parent.height / 2 - height / 2
radius: 16 radius: Styling.theme.radiusSelector
color: "transparent" color: "transparent"
border.color: control.checked ? Theme.palette.primary : Theme.palette.basecontent border.color: control.checked ? Styling.theme.primary : Styling.theme.basecontent
border.width: 2 border.width: 2
Rectangle { Rectangle {
@ -40,16 +40,15 @@ Switch {
y: parent.height / 2 - height / 2 y: parent.height / 2 - height / 2
Behavior on x { Behavior on x {
NumberAnimation { NumberAnimation {
duration: 100 duration: Styling.animations.speed.fast
} }
} }
width: parent.width / 2 - indicator.padding width: parent.width / 2 - indicator.padding
height: parent.height - indicator.padding height: parent.height - indicator.padding
radius: 16 radius: Styling.theme.radiusSelector
color: control.checked ? Theme.palette.primary : Theme.palette.basecontent color: control.checked ? Styling.theme.primary : Styling.theme.basecontent
// border.color: control.checked ? (control.down ? "#17a81a" : "#21be2b") : "#999999"
} }
} }
background: null background: Item {}
} }

View file

@ -0,0 +1,19 @@
import QtQuick
import QtQuick.Controls
Container {
id: control
property alias orientation: view.orientation
contentItem: ListView {
id: view
model: control.contentModel
currentIndex: control.currentIndex
spacing: control.spacing
orientation: ListView.Horizontal
boundsBehavior: Flickable.StopAtBounds
}
background: Item {}
}

View file

@ -0,0 +1,46 @@
import qs.config
import QtQuick
import QtQuick.Controls
Button {
id: control
property alias radius: rectangle.radius
padding: 8
radius: Styling.theme.radiusField
contentItem: Text {
font.pixelSize: Styling.typography.textSize.base
font.family: Styling.typography.fontFamily
text: control.text
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
color: control.hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.normal
}
}
}
background: Rectangle {
id: rectangle
color: control.hovered ? Styling.theme.primary : Styling.theme.base100
Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.normal
}
}
opacity: control.checked || control.hovered ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
duration: Styling.animations.speed.normal
}
}
}
HoverHandler {
cursorShape: Qt.PointingHandCursor
}
}

View file

@ -2,9 +2,12 @@ import qs.config
import QtQuick import QtQuick
Text { Text {
font.family: Theme.fontFamily font.family: Styling.typography.fontFamily
color: Theme.palette.basecontent font.pixelSize: Styling.typography.textSize.base
ColorAnimation on color { color: Styling.theme.basecontent
duration: 100 Behavior on color {
ColorAnimation {
duration: Styling.animations.speed.fast
}
} }
} }

View file

@ -1,8 +1,9 @@
import qs.config import qs.config
import QtQuick
import QtQuick.Controls import QtQuick.Controls
TextField { TextField {
color: Theme.palette.basecontent color: Styling.theme.basecontent
background: null background: Item {}
} }

View file

@ -9,11 +9,13 @@ ToolTip {
contentItem: Text { contentItem: Text {
text: control.text text: control.text
font: control.font font: control.font
color: Theme.palette.basecontent color: Styling.theme.basecontent
} }
background: Rectangle { background: Rectangle {
radius: 8 radius: Styling.theme.radiusBox
color: Theme.palette.base200 color: Styling.theme.base100
border.color: Styling.theme.base200
border.width: Styling.theme.border
} }
} }

View file

@ -1,9 +0,0 @@
import Quickshell
import Quickshell.Wayland
PanelWindow {
required property string name
WlrLayershell.namespace: `lux-${name}`
color: "transparent"
}

View file

@ -3,12 +3,19 @@ import QtQuick
import Quickshell.Widgets import Quickshell.Widgets
WrapperRectangle { WrapperRectangle {
radius: 8 margin: 8
color: Theme.palette.base300 radius: Styling.theme.radiusBox
color: Styling.theme.base100
Behavior on color { Behavior on color {
ColorAnimation { ColorAnimation {
duration: 200 duration: Styling.animations.speed.fast
easing.type: Easing.InOutQuad }
}
border.width: 2
border.color: Styling.theme.base100
Behavior on border.color {
ColorAnimation {
duration: Styling.animations.speed.fast
} }
} }
} }

View file

@ -2,8 +2,6 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Services.Mpris import Quickshell.Services.Mpris
@ -16,35 +14,43 @@ Loader {
active: player != null active: player != null
sourceComponent: ColumnLayout { sourceComponent: ColumnLayout {
spacing: 12 spacing: Styling.layout.spacing.xl
implicitWidth: 800 implicitWidth: 800
StyledText { StyledText {
id: text id: text
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
font.pixelSize: Styling.typography.textSize.base
text: `${root.player.trackTitle} - ${root.player.trackArtist}` text: `${root.player.trackTitle} - ${root.player.trackArtist}`
font.pixelSize: Dimensions.mpris.fontSize
} }
RowLayout { RowLayout {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
StyledIconButton { StyledIconButton {
id: backButton id: backButton
text: Icons.skipBack
text: Styling.lucide.icons.skipBack
onClicked: { onClicked: {
root.player.previous(); root.player.previous();
} }
} }
StyledIconButton { StyledIconButton {
id: playPauseButton id: playPauseButton
text: root.player.isPlaying ? Icons.pause : Icons.play
text: root.player.isPlaying ? Styling.lucide.icons.pause : Styling.lucide.icons.play
onClicked: { onClicked: {
root.player.isPlaying = !root.player.isPlaying; root.player.isPlaying = !root.player.isPlaying;
} }
} }
StyledIconButton { StyledIconButton {
id: forwardButton id: forwardButton
text: Icons.skipForward
text: Styling.lucide.icons.skipForward
onClicked: { onClicked: {
root.player.next(); root.player.next();
} }
@ -53,21 +59,24 @@ Loader {
StyledText { StyledText {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
font.pixelSize: Styling.typography.textSize.sm
text: { text: {
function formatTime(num) { function formatTime(num) {
return Math.floor(num).toString().padStart(2, "0"); return Math.floor(num).toString().padStart(2, "0");
} }
return `${formatTime(root.player.position / 60)}:${formatTime(root.player.position % 60)} - ${formatTime(root.player.length / 60)}:${formatTime(root.player.length % 60)}`; return `${formatTime(root.player.position / 60)}:${formatTime(root.player.position % 60)} - ${formatTime(root.player.length / 60)}:${formatTime(root.player.length % 60)}`;
} }
font.pixelSize: Dimensions.mpris.fontSize
} }
StyledSlider { StyledSlider {
Layout.fillWidth: true
from: 0 from: 0
to: root.player.length ?? 0 to: root.player.length ?? 0
value: root.player.position value: root.player.position
implicitHeight: 6 implicitHeight: 6
Layout.fillWidth: true
onMoved: { onMoved: {
root.player.position = value; root.player.position = value;
} }

View file

@ -1,12 +1,11 @@
import qs.config
import qs.components import qs.components
import qs.constants
import qs.services import qs.services
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
RowLayout { RowLayout {
spacing: 8 spacing: Styling.layout.spacing.xl
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
@ -14,7 +13,7 @@ RowLayout {
id: previousPlayerButton id: previousPlayerButton
visible: Mpris.players.length > 1 visible: Mpris.players.length > 1
text: Icons.chevronLeft text: Styling.lucide.icons.chevronLeft
onClicked: { onClicked: {
Mpris.previousPlayer(); Mpris.previousPlayer();
@ -22,6 +21,7 @@ RowLayout {
} }
StyledText { StyledText {
font.pixelSize: Styling.typography.textSize.xl
text: { text: {
if (!Mpris.active) { if (!Mpris.active) {
return "inactive"; return "inactive";
@ -36,14 +36,13 @@ RowLayout {
} }
return displayName; return displayName;
} }
font.pixelSize: 20
} }
StyledIconButton { StyledIconButton {
id: nextPlayerButton id: nextPlayerButton
visible: Mpris.players.length > 1 visible: Mpris.players.length > 1
text: Icons.chevronRight text: Styling.lucide.icons.chevronRight
onClicked: { onClicked: {
Mpris.nextPlayer(); Mpris.nextPlayer();

View file

@ -0,0 +1,13 @@
import qs.components
import qs.config
import QtQuick
StyledComboBox {
id: control
currentIndex: Theme.themes.indexOf(Theme.currentTheme)
model: Theme.themes
onActivated: index => {
Theme.currentTheme = Theme.themes[index];
}
}

View file

@ -0,0 +1,14 @@
import QtQuick
Image {
asynchronous: true
fillMode: Image.PreserveAspectCrop
sourceSize.width: parent.width
sourceSize.height: parent.height
Behavior on scale {
NumberAnimation {
duration: 200
}
}
}

View file

@ -0,0 +1,65 @@
pragma ComponentBehavior: Bound
import qs.config
import qs.services
import QtQuick
import Qt.labs.folderlistmodel 2.9
import Quickshell.Widgets
ListView {
id: list
orientation: ListView.Horizontal
clip: true
spacing: 8
snapMode: ListView.SnapToItem
implicitWidth: 160 * 3
implicitHeight: 90
model: FolderListModel {
nameFilters: ["*.jpg"]
folder: `file://${Paths.expandTilde(Config.wallpaper.directory)}`
showDirs: false
}
delegate: Item {
id: delegate
required property url fileUrl
required property int index
property bool hovered: ListView.isCurrentItem
implicitWidth: 160
implicitHeight: 90
Rectangle {
color: Styling.theme.base200
anchors.fill: parent
radius: 12
scale: delegate.hovered ? 1.0 : 0.9
Behavior on scale {
NumberAnimation {
duration: Styling.animations.veryFast
}
}
Image {
id: image
asynchronous: true
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: delegate.fileUrl
}
MouseArea {
anchors.fill: image
cursorShape: Qt.PointingHandCursor
hoverEnabled: true
onEntered: list.currentIndex = delegate.index
onClicked: WallpaperService.currentWallpaper = delegate.fileUrl
}
}
}
}

View file

@ -1,9 +1,39 @@
pragma Singleton pragma Singleton
import Quickshell import Quickshell
import Quickshell.Io
Singleton { Singleton {
id: root id: root
readonly property PowerMenu powermenu: PowerMenu {} readonly property alias powermenu: adapter.powermenu
readonly property alias wallpaper: adapter.wallpaper
FileView {
path: `${Paths.config}/shell.json`
watchChanges: true
onFileChanged: reload()
// onAdapterUpdated: writeAdapter()
JsonAdapter {
id: adapter
property var powermenu: PowerMenu {}
property var wallpaper: Wallpaper {}
}
}
component PowerMenu: JsonObject {
property list<PowerMenuItem> actions
}
component PowerMenuItem: JsonObject {
property string text
property string command
}
component Wallpaper: JsonObject {
property string directory
}
} }

View file

@ -1,144 +0,0 @@
pragma Singleton
import QtQuick
import Quickshell
Singleton {
id: root
property int radius: 8
property Bar bar: Bar {}
property Mpris mpris: Mpris {}
property Clock clock: Clock {}
property Pipewire pipewire: Pipewire {}
property Network network: Network {}
property Bluetooth bluetooth: Bluetooth {}
property Storage storage: Storage {}
property Memory memory: Memory {}
property Cpu cpu: Cpu {}
property Gpu gpu: Gpu {}
property Caffeine caffeine: Caffeine {}
property Notifications notifications: Notifications {}
property Workspace workspace: Workspace {}
property Tray tray: Tray {}
property TrayMenu trayMenu: TrayMenu {}
component Bar: QtObject {
property int spacing: 8
property int border: 2
property int height: 50
property int verticalMargins: 4
property int horizontalMargins: 8
property int verticalPadding: 2
property int horizontalPadding: 8
}
component Mpris: QtObject {
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Clock: QtObject {
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Pipewire: QtObject {
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Network: QtObject {
property int iconSize: 14
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Bluetooth: QtObject {
property int fontSize: 16
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Storage: QtObject {
property int iconSize: 14
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Memory: QtObject {
property int iconSize: 14
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Cpu: QtObject {
property int iconSize: 14
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Gpu: QtObject {
property int iconSize: 14
property int fontSize: 14
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Caffeine: QtObject {
property int fontSize: 16
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Notifications: QtObject {
property int fontSize: 16
property int height: 30
property int horizontalPadding: 8
property int verticalPadding: 6
}
component Workspace: QtObject {
property int spacing: 5
property int iconSize: 16
property int width: 30
property int height: 30
property int verticalPadding: 6
property int horizontalPadding: 7
}
component Tray: QtObject {
property int spacing: 5
property int iconSize: 18
property int width: 30
property int height: 30
property int verticalPadding: 6
property int horizontalPadding: 7
}
component TrayMenu: QtObject {
property int fontSize: 10
property int width: 30
property int height: 30
property int verticalPadding: 6
property int horizontalPadding: 7
}
}

45
config/Paths.qml Normal file
View file

@ -0,0 +1,45 @@
pragma Singleton
import Quickshell
import Qt.labs.platform
Singleton {
id: root
readonly property url home: StandardPaths.standardLocations(StandardPaths.HomeLocation)[0]
readonly property url pictures: StandardPaths.standardLocations(StandardPaths.PicturesLocation)[0]
readonly property url data: `${StandardPaths.standardLocations(StandardPaths.GenericDataLocation)[0]}/lux`
readonly property url state: `${StandardPaths.standardLocations(StandardPaths.GenericStateLocation)[0]}/lux`
readonly property url cache: `${StandardPaths.standardLocations(StandardPaths.GenericCacheLocation)[0]}/lux`
readonly property url config: `${StandardPaths.standardLocations(StandardPaths.GenericConfigLocation)[0]}/lux`
function stringify(path: url): string {
let str = path.toString();
if (str.startsWith("root:/"))
str = `file://${Quickshell.shellDir}/${str.slice(6)}`;
else if (str.startsWith("/"))
str = `file://${str}`;
return new URL(str).pathname;
}
function expandTilde(path: string): string {
return strip(path.replace("~", stringify(root.home)));
}
function shortenHome(path: string): string {
return path.replace(strip(root.home), "~");
}
function strip(path: url): string {
return stringify(path).replace("file://", "");
}
function mkdir(path: url): void {
Quickshell.execDetached(["mkdir", "-p", strip(path)]);
}
function copy(from: url, to: url): void {
Quickshell.execDetached(["cp", strip(from), strip(to)]);
}
}

View file

@ -1,18 +0,0 @@
import Quickshell
PersistentProperties {
property list<var> actions: [
{
text: "󰍃 Logout",
command: "hyprctl dispatch exit"
},
{
text: "󰜉 Reboot",
command: "systemctl reboot"
},
{
text: " Shutdown",
command: "systemctl poweroff"
}
]
}

132
config/Styling.qml Normal file
View file

@ -0,0 +1,132 @@
pragma Singleton
import QtQuick
import Quickshell
import Quickshell.Io
Singleton {
id: root
readonly property Animations animations: Animations {}
readonly property Typography typography: Typography {}
readonly property Layout layout: Layout {}
readonly property alias theme: theme
readonly property Lucide lucide: Lucide {}
component Animations: QtObject {
readonly property AnimationSpeed speed: AnimationSpeed {}
}
component AnimationSpeed: QtObject {
readonly property int veryFast: 50
readonly property int fast: 100
readonly property int normal: 200
readonly property int slow: 400
readonly property int verySlow: 1000
}
component Typography: QtObject {
readonly property string fontFamily: "JetBrainsMono Nerd Font"
readonly property FontSize textSize: FontSize {}
}
component FontSize: QtObject {
readonly property int sm: 12
readonly property int base: 14
readonly property int lg: 18
readonly property int xl: 24
}
component Layout: QtObject {
readonly property LayoutSpacing spacing: LayoutSpacing {}
}
component LayoutSpacing: QtObject {
readonly property int sm: 2
readonly property int base: 4
readonly property int lg: 8
readonly property int xl: 12
}
component Lucide: Item {
readonly property alias font: loader.font
readonly property LucideIcons icons: LucideIcons {}
FontLoader {
id: loader
source: "../assets/lucide.woff"
}
}
component LucideIcons: QtObject {
readonly property string activity: "\u{E038}"
readonly property string audioLines: "\u{E55F}"
readonly property string batteryCharging: "\u{E058}"
readonly property string batteryFull: "\u{E059}"
readonly property string batteryMedium: "\u{E05b}"
readonly property string batteryLow: "\u{E05a}"
readonly property string batteryWarning: "\u{E3b0}"
readonly property string bell: "\u{E05d}"
readonly property string bellRing: "\u{E224}"
readonly property string bluetooth: "\u{E060}"
readonly property string bluetoothConnected: "\u{E1b8}"
readonly property string brickWall: "\u{E586}"
readonly property string coffee: "\u{E09a}"
readonly property string chevronLeft: "\u{E072}"
readonly property string chevronRight: "\u{E073}"
readonly property string cpu: "\u{E0ad}"
readonly property string gpu: "\u{E66f}"
readonly property string hardDrive: "\u{E0f1}"
readonly property string layoutDashboard: "\u{E1C1}"
readonly property string memoryStick: "\u{E44a}"
readonly property string pause: "\u{E132}"
readonly property string play: "\u{E140}"
readonly property string search: "\u{E155}"
readonly property string skipBack: "\u{E163}"
readonly property string skipForward: "\u{E164}"
readonly property string square: "\u{E16B}"
readonly property string stop: "\u{E132}"
readonly property string swatchBook: "\u{E5A4}"
readonly property string wifiOff: "\u{E1af}"
readonly property string wifiLow: "\u{E5fd}"
readonly property string wifiHigh: "\u{E5fc}"
readonly property string wifi: "\u{E1ae}"
readonly property string triangle: "\u{E192}"
readonly property string triangleDashed: "\u{E642}"
}
FileView {
path: `${Paths.config}/themes/${Theme.currentTheme}.json`
watchChanges: true
onFileChanged: reload()
// when changes are made to properties in the adapter, save them
onAdapterUpdated: writeAdapter()
JsonAdapter {
id: theme
property color primary: "#605dff"
property color primarycontent: "#edf1fe"
property color secondary: "#f43098"
property color secondarycontent: "#f9e4f0"
property color accent: "#00d3bb"
property color accentcontent: "#084d49"
property color neutral: "#09090b"
property color neutralcontent: "#e4e4e7"
property color base100: "#1d232a"
property color base200: "#191e24"
property color base300: "#15191e"
property color basecontent: "#ecf9ff"
property color info: "#00bafe"
property color infocontent: "#042e49"
property color success: "#00d390"
property color successcontent: "#004c39"
property color warning: "#fcb700"
property color warningcontent: "#793205"
property color error: "#ff627d"
property color errorcontent: "#4d0218"
property int radiusSelector: 8
property int radiusField: 8
property int radiusBox: 8
property int border: 2
}
}
}

View file

@ -1,39 +1,50 @@
pragma Singleton pragma Singleton
import QtQuick import QtQuick
import Qt.labs.folderlistmodel 2.9
import Quickshell import Quickshell
import Quickshell.Io
Singleton { Singleton {
id: root id: root
property var lucide: FontLoader { property alias themes: cache.themes
source: "../assets/lucide.woff" property alias currentTheme: cache.current
} property int currentThemeIndex: themes.indexOf(currentTheme)
property string fontFamily: "JetBrainsMono Nerd Font"
property Palette palette: Palette {}
component Palette: QtObject { FolderListModel {
id: palette id: model
nameFilters: ["*.json"]
folder: `${Paths.config}/themes/`
showDirs: false
onCountChanged: {
const arr = [];
for (let i = 0; i < count; i++) {
arr.push(get(i, "fileName").replace(".json", ""));
}
root.themes = arr;
}
}
property color primary: "#1fb854" FileView {
property color primarycontent: "#000000" path: `${Paths.cache}/theme.json`
property color secondary: "#1eb88e"
property color secondarycontent: "#000c07" watchChanges: true
property color accent: "#1fb8ab" onFileChanged: reload()
property color accentcontent: "#010c0b"
property color neutral: "#19362d" // when changes are made to properties in the adapter, save them
property color neutralcontent: "#cdd3d1" onAdapterUpdated: writeAdapter()
property color base100: "#1b1717"
property color base200: "#161212" JsonAdapter {
property color base300: "#110d0d" id: cache
property color basecontent: "#cac9c9"
property color info: "#00b5ff" property string current: "dark"
property color infocontent: "#000000" property list<string> themes: ["dark"]
property color success: "#00a96e" onThemesChanged: {
property color successcontent: "#000000" if (!themes.includes(current)) {
property color warning: "#ffbe00" current = themes[0];
property color warningcontent: "#000000" }
property color error: "#ff5861" }
property color errorcontent: "#000000" }
} }
} }

View file

@ -1,36 +0,0 @@
pragma Singleton
import Quickshell
Singleton {
property string batteryCharging: "\u{E058}"
property string batteryFull: "\u{E059}"
property string batteryMedium: "\u{E05b}"
property string batteryLow: "\u{E05a}"
property string batteryWarning: "\u{E3b0}"
property string bell: "\u{E05d}"
property string bellRing: "\u{E224}"
property string bluetooth: "\u{E060}"
property string bluetoothConnected: "\u{E1b8}"
property string brickWall: "\u{E586}"
property string coffee: "\u{E09a}"
property string chevronLeft: "\u{E072}"
property string chevronRight: "\u{E073}"
property string cpu: "\u{E0ad}"
property string gpu: "\u{E66f}"
property string hardDrive: "\u{E0f1}"
property string memoryStick: "\u{E44a}"
property string pause: "\u{E132}"
property string play: "\u{E140}"
property string search: "\u{E155}"
property string skipBack: "\u{E163}"
property string skipForward: "\u{E164}"
property string stop: "\u{E132}"
property string square: "\u{E16B}"
property string wifiOff: "\u{E1af}"
property string wifiLow: "\u{E5fd}"
property string wifiHigh: "\u{E5fc}"
property string wifi: "\u{E1ae}"
property string triangle: "\u{E192}"
property string triangleDashed: "\u{E642}"
}

View file

@ -1,9 +1,11 @@
import "bar" import "bar"
import "configuration"
import "drawers" import "drawers"
import "launcher" import "launcher"
import "pomodoro" import "pomodoro"
import "powermenu" import "powermenu"
import "storybook" import "storybook"
import "wallpaper"
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Wayland import Quickshell.Wayland
@ -16,6 +18,23 @@ Variants {
required property ShellScreen modelData required property ShellScreen modelData
PanelWindow {
id: background
// visible: false
anchors.top: true
anchors.left: true
anchors.right: true
anchors.bottom: true
color: "transparent"
WlrLayershell.exclusionMode: ExclusionMode.Ignore
WlrLayershell.layer: WlrLayer.Background
Wallpaper {}
}
PanelWindow { PanelWindow {
id: exclusionZone id: exclusionZone
@ -24,7 +43,7 @@ Variants {
anchors.right: true anchors.right: true
implicitWidth: bar.width implicitWidth: bar.width
implicitHeight: bar.height implicitHeight: bar.height + bar.anchors.margins
color: "transparent" color: "transparent"
} }
@ -75,14 +94,11 @@ Variants {
} }
} }
} }
Configuration {}
Launcher {} Launcher {}
Pomodoro {} Pomodoro {}
PowerMenu {} PowerMenu {}
Storybook { Storybook {}
anchor.window: topWindow
anchor.rect.x: topWindow.width / 2 - width / 2
anchor.rect.y: topWindow.height / 4
}
Drawers {} Drawers {}
} }
} }

View file

@ -5,6 +5,12 @@ import Quickshell.Hyprland
Scope { Scope {
id: root id: root
LuxShortcut {
name: 'configuration'
description: 'Open the configuration screen'
onPressed: Visibility.configuration = !Visibility.configuration
}
LuxShortcut { LuxShortcut {
name: 'launcher' name: 'launcher'
description: 'Open the application launcher' description: 'Open the application launcher'

View file

@ -14,19 +14,24 @@ StyledWrapperRectangle {
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.leftMargin: Dimensions.bar.horizontalMargins anchors.margins: 6
anchors.rightMargin: Dimensions.bar.horizontalMargins anchors.leftMargin: 10
anchors.topMargin: Dimensions.bar.verticalMargins anchors.rightMargin: 10
anchors.bottomMargin: Dimensions.bar.verticalMargins
margin: 6 border.width: 3
border.color: Styling.theme.base200
margin: 4
color: Styling.theme.base100
RowLayout { RowLayout {
uniformCellSizes: true
RowLayout { RowLayout {
id: leftbar id: leftbar
spacing: Dimensions.bar.spacing spacing: Styling.layout.spacing.base
SystemLogo { SystemLogo {
implicitSize: 22 implicitSize: 22
@ -42,7 +47,7 @@ StyledWrapperRectangle {
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
spacing: Dimensions.bar.spacing spacing: Styling.layout.spacing.base
Mpris {} Mpris {}
} }
@ -52,7 +57,7 @@ StyledWrapperRectangle {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
spacing: Dimensions.bar.spacing spacing: Styling.layout.spacing.base
Pywal {} Pywal {}

View file

@ -1,13 +1,13 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
StyledIconButton { StyledIconButton {
id: root id: root
border.color: Caffeine.enabled ? Theme.palette.secondary : root.hovered ? Theme.palette.primary : Theme.palette.base100 border.width: 2
text: Icons.coffee border.color: Caffeine.enabled ? Styling.theme.secondary : root.hovered ? Styling.theme.primary : Styling.theme.base300
text: Styling.lucide.icons.coffee
onClicked: { onClicked: {
Caffeine.toggle(); Caffeine.toggle();

View file

@ -1,19 +1,10 @@
import qs.components import qs.components
import qs.config
import qs.widgets
import Quickshell import Quickshell
StyledLabel {
StyledText { StyledText {
id: text
font.pixelSize: Dimensions.clock.fontSize
text: ` ${Qt.formatDateTime(clock.date, "hh:mm:ss AP")}` text: ` ${Qt.formatDateTime(clock.date, "hh:mm:ss AP")}`
SystemClock { SystemClock {
id: clock id: clock
precision: SystemClock.Seconds precision: SystemClock.Seconds
} }
} }
}

View file

@ -1,9 +1,7 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.utils import qs.utils
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
@ -17,30 +15,23 @@ StyledButton {
} }
contentItem: RowLayout { contentItem: RowLayout {
id: row
spacing: 0 spacing: 0
Ref { Ref {
service: SystemInfo service: SystemInfo
} }
StyledText {
id: icon
font.family: Theme.lucide.font.family LucideIcon {
font.pixelSize: Dimensions.cpu.iconSize text: Styling.lucide.icons.cpu
font.bold: true color: root.hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
text: Icons.cpu
color: root.hovered ? Theme.palette.primarycontent : Theme.palette.basecontent
} }
StyledText { StyledText {
id: text id: text
font.pixelSize: Dimensions.cpu.fontSize
text: ` ${(SystemInfo.cpuPerc * 100).toFixed().toString().padStart(2, "_")}%` text: ` ${(SystemInfo.cpuPerc * 100).toFixed().toString().padStart(2, "_")}%`
color: root.hovered ? Theme.palette.primarycontent : Theme.palette.basecontent color: root.hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
states: [ states: [
State { State {
name: "showTemp" name: "showTemp"

View file

@ -1,9 +1,7 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.utils import qs.utils
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
@ -13,34 +11,27 @@ StyledButton {
property bool showTemp: false property bool showTemp: false
onClicked: { onClicked: {
root.showTemp = !root.showTemp; showTemp = !showTemp;
} }
contentItem: RowLayout { contentItem: RowLayout {
id: row
spacing: 0 spacing: 0
Ref { Ref {
service: SystemInfo service: SystemInfo
} }
StyledText {
id: icon
font.family: Theme.lucide.font.family LucideIcon {
font.pixelSize: Dimensions.gpu.iconSize text: Styling.lucide.icons.gpu
font.bold: true color: root.hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
text: Icons.gpu
color: root.hovered ? Theme.palette.primarycontent : Theme.palette.basecontent
} }
StyledText { StyledText {
id: text id: text
font.pixelSize: Dimensions.gpu.fontSize
text: ` ${(SystemInfo.gpuPerc * 100).toFixed().toString().padStart(2, "_")}%` text: ` ${(SystemInfo.gpuPerc * 100).toFixed().toString().padStart(2, "_")}%`
color: root.hovered ? Theme.palette.primarycontent : Theme.palette.basecontent color: root.hovered ? Styling.theme.primarycontent : Styling.theme.basecontent
states: [ states: [
State { State {
name: "temp" name: "temp"

View file

@ -1,28 +1,21 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.widgets
import qs.utils import qs.utils
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
StyledLabel {
RowLayout { RowLayout {
Ref { Ref {
service: SystemInfo service: SystemInfo
} }
StyledText {
font.family: Theme.lucide.font.family LucideIcon {
font.pixelSize: Dimensions.memory.iconSize text: Styling.lucide.icons.memoryStick
font.bold: true
text: Icons.memoryStick
} }
StyledText { StyledText {
id: text
font.pixelSize: Dimensions.memory.fontSize
text: ` ${(SystemInfo.memPerc * 100).toFixed()}%` text: ` ${(SystemInfo.memPerc * 100).toFixed()}%`
} }
} }
}

View file

@ -1,32 +1,26 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.utils import qs.utils
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
StyledLabel {
RowLayout { RowLayout {
Ref { Ref {
service: NetworkService service: NetworkService
} }
StyledText {
LucideIcon {
id: icon id: icon
text: Styling.lucide.icons.wifiOff
font.family: Theme.lucide.font.family
font.pixelSize: Dimensions.network.iconSize
font.bold: true
text: Icons.wifiOff
states: [ states: [
State { State {
name: "high" name: "high"
when: NetworkService.active?.strength > 50 when: NetworkService.active?.strength > 50
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.wifi text: Styling.lucide.icons.wifi
} }
} }
}, },
@ -35,7 +29,7 @@ StyledLabel {
when: NetworkService.active?.strength > 25 when: NetworkService.active?.strength > 25
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.wifiHigh text: Styling.lucide.icons.wifiHigh
} }
} }
}, },
@ -44,7 +38,7 @@ StyledLabel {
when: NetworkService.active?.strength > 0 when: NetworkService.active?.strength > 0
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.wifiLow text: Styling.lucide.icons.wifiLow
} }
} }
} }
@ -53,8 +47,6 @@ StyledLabel {
StyledText { StyledText {
id: text id: text
font.pixelSize: Dimensions.network.fontSize
text: ` ${(NetworkService.active?.strength ?? 0).toFixed()}%` text: ` ${(NetworkService.active?.strength ?? 0).toFixed()}%`
} }
} }
}

View file

@ -28,7 +28,7 @@ StyledButton {
when: Pipewire.muted when: Pipewire.muted
PropertyChanges { PropertyChanges {
root { root {
palette.button: Theme.palette.error palette.button: Styling.theme.error
} }
} }
} }

View file

@ -1,6 +1,5 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Services.UPower import Quickshell.Services.UPower
@ -10,50 +9,56 @@ StyledButton {
property UPowerDevice laptopBattery: UPower.devices.values.find(device => device.isLaptopBattery) ?? null property UPowerDevice laptopBattery: UPower.devices.values.find(device => device.isLaptopBattery) ?? null
property bool isCritical: laptopBattery?.percentage < 0.10 property bool isCritical: laptopBattery?.percentage < 0.10
visible: laptopBattery
contentItem: RowLayout { contentItem: RowLayout {
spacing: 4 spacing: 4
LucideIcon { LucideIcon {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: { color: {
if (root.isCritical) { if (root.isCritical) {
return Theme.palette.error; return Styling.theme.error;
} }
if (root.hovered) { if (root.hovered) {
return Theme.palette.primarycontent; return Styling.theme.primarycontent;
} }
return Theme.palette.basecontent; return Styling.theme.basecontent;
} }
font.pixelSize: 16
text: { text: {
if (root.laptopBattery?.state == UPowerDeviceState.Charging) { if (root.laptopBattery?.state == UPowerDeviceState.Charging) {
return Icons.batteryCharging; return Styling.lucide.icons.batteryCharging;
} }
if (root.isCritical) { if (root.isCritical) {
return Icons.batteryWarning; return Styling.lucide.icons.batteryWarning;
} }
if (root.laptopBattery?.percentage < 0.33) { if (root.laptopBattery?.percentage < 0.33) {
return Icons.batteryLow; return Styling.lucide.icons.batteryLow;
} }
if (root.laptopBattery?.percentage < 0.66) { if (root.laptopBattery?.percentage < 0.66) {
return Icons.batteryMedium; return Styling.lucide.icons.batteryMedium;
} }
return Icons.batteryFull; return Styling.lucide.icons.batteryFull;
} }
} }
StyledText { StyledText {
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
color: { color: {
if (root.isCritical) { if (root.isCritical) {
return Theme.palette.error; return Styling.theme.error;
} }
if (root.hovered) { if (root.hovered) {
return Theme.palette.primarycontent; return Styling.theme.primarycontent;
} }
return Theme.palette.basecontent; return Styling.theme.basecontent;
} }
text: `${(root.laptopBattery?.percentage.toFixed(2) * 100)}%` text: `${(root.laptopBattery?.percentage.toFixed(2) * 100)}%`
} }
} }
visible: laptopBattery
} }

View file

@ -1,12 +1,12 @@
import qs.components import qs.components
import qs.constants import qs.config
import QtQuick import QtQuick
import Quickshell.Io import Quickshell.Io
StyledIconButton { StyledIconButton {
id: clickable id: clickable
text: Icons.brickWall text: Styling.lucide.icons.brickWall
onClicked: { onClicked: {
process.running = true; process.running = true;

View file

@ -1,30 +1,23 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.utils import qs.utils
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
StyledLabel {
RowLayout { RowLayout {
Ref { Ref {
service: SystemInfo service: SystemInfo
} }
StyledText {
id: icon
font.family: Theme.lucide.font.family LucideIcon {
font.pixelSize: Dimensions.storage.iconSize text: Styling.lucide.icons.hardDrive
font.bold: true
text: Icons.hardDrive
} }
StyledText { StyledText {
id: text id: text
font.pixelSize: Dimensions.storage.fontSize
text: ` ${(SystemInfo.storagePerc * 100).toFixed()}%` text: ` ${(SystemInfo.storagePerc * 100).toFixed()}%`
} }
} }
}

View file

@ -1,21 +1,21 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.widgets import qs.config
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Bluetooth import Quickshell.Bluetooth
import Quickshell.Widgets import Quickshell.Widgets
StyledLabel { StyledWrapperRectangle {
id: root id: root
required property BluetoothDevice modelData required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
spacing: 8 spacing: Styling.layout.spacing.base
Loader { Loader {
active: root.modelData?.icon != undefined active: root.modelData?.icon != undefined

View file

@ -1,10 +1,10 @@
import qs.components import qs.components
import qs.constants import qs.config
StyledIconButton { StyledIconButton {
id: root id: root
text: Icons.bluetooth text: Styling.lucide.icons.bluetooth
onClicked: popup.toggle() onClicked: popup.toggle()

View file

@ -1,8 +1,6 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
@ -11,10 +9,6 @@ import Quickshell.Bluetooth
StyledPopupWindow { StyledPopupWindow {
id: root id: root
backgroundColor: Theme.palette.base300
margins: 16
radius: 8
content: ColumnLayout { content: ColumnLayout {
spacing: 8 spacing: 8
StyledWrapperRectangle { StyledWrapperRectangle {

View file

@ -2,22 +2,20 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Bluetooth import Quickshell.Bluetooth
import Quickshell.Widgets import Quickshell.Widgets
StyledLabel { StyledWrapperRectangle {
id: root id: root
required property BluetoothDevice modelData required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
spacing: 8 spacing: Styling.layout.spacing.base
Loader { Loader {
active: root.modelData?.icon != undefined active: root.modelData?.icon != undefined
@ -34,12 +32,9 @@ StyledLabel {
Loader { Loader {
active: root.modelData.batteryAvailable active: root.modelData.batteryAvailable
sourceComponent: RowLayout { sourceComponent: RowLayout {
StyledText { LucideIcon {
id: icon id: icon
font.family: Theme.lucide.font.family text: Styling.lucide.icons.batteryFull
font.pixelSize: Dimensions.cpu.iconSize
font.bold: true
text: Icons.batteryFull
states: [ states: [
State { State {
name: "full" name: "full"
@ -50,7 +45,7 @@ StyledLabel {
when: root.modelData.battery > 0.33 when: root.modelData.battery > 0.33
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryFull text: Styling.lucide.icons.batteryFull
} }
} }
}, },
@ -59,7 +54,7 @@ StyledLabel {
when: root.modelData.battery > 0.10 when: root.modelData.battery > 0.10
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryFull text: Styling.lucide.icons.batteryFull
} }
} }
}, },
@ -68,8 +63,8 @@ StyledLabel {
when: root.modelData.battery > 0.10 when: root.modelData.battery > 0.10
PropertyChanges { PropertyChanges {
icon { icon {
text: Icons.batteryWarning text: Styling.lucide.icons.batteryWarning
color: Theme.palette.error color: Styling.theme.error
} }
} }
} }
@ -81,7 +76,7 @@ StyledLabel {
StyledButton { StyledButton {
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: 'Disconnect' text: 'Disconnect'
palette.button: hovered ? Theme.palette.error : Theme.palette.base200 palette.button: hovered ? Styling.theme.error : Styling.theme.base200
onClicked: { onClicked: {
if (root.modelData.state != BluetoothDeviceState.Connected) { if (root.modelData.state != BluetoothDeviceState.Connected) {

View file

@ -2,21 +2,20 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Bluetooth import Quickshell.Bluetooth
import Quickshell.Widgets import Quickshell.Widgets
StyledLabel { StyledWrapperRectangle {
id: root id: root
required property BluetoothDevice modelData required property BluetoothDevice modelData
RowLayout { RowLayout {
id: row id: row
spacing: 8 spacing: Styling.layout.spacing.base
Loader { Loader {
active: root.modelData?.icon != undefined active: root.modelData?.icon != undefined
@ -48,7 +47,7 @@ StyledLabel {
hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected hoverEnabled: root.modelData.state == BluetoothDeviceState.Disconnected
text: 'Unpair' text: 'Unpair'
palette.button: hovered ? Theme.palette.error : Theme.palette.base100 palette.button: hovered ? Styling.theme.error : Styling.theme.base100
onClicked: { onClicked: {
if (!hoverEnabled) { if (!hoverEnabled) {

View file

@ -1,6 +1,5 @@
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import QtQuick import QtQuick
import Quickshell.Hyprland import Quickshell.Hyprland
@ -9,7 +8,7 @@ StyledIconButton {
required property HyprlandWorkspace workspace required property HyprlandWorkspace workspace
text: Icons.triangle text: Styling.lucide.icons.triangle
font.bold: true font.bold: true
font.pixelSize: 17 font.pixelSize: 17
padding: 8 padding: 8
@ -23,7 +22,7 @@ StyledIconButton {
PropertyChanges { PropertyChanges {
root { root {
rotation: 180 rotation: 180
color: root.hovered ? Theme.palette.basecontent : Theme.palette.primary color: root.hovered ? Styling.theme.basecontent : Styling.theme.primary
} }
} }
}, },
@ -32,9 +31,9 @@ StyledIconButton {
when: root.workspace.active when: root.workspace.active
PropertyChanges { PropertyChanges {
root { root {
text: Icons.triangleDashed text: Styling.lucide.icons.triangleDashed
rotation: 180 rotation: 180
color: root.hovered ? Theme.palette.basecontent : Theme.palette.primary color: root.hovered ? Styling.theme.basecontent : Styling.theme.primary
} }
} }
} }

View file

@ -1,6 +1,5 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.config
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Hyprland import Quickshell.Hyprland
@ -8,7 +7,7 @@ import Quickshell.Hyprland
RowLayout { RowLayout {
id: root id: root
spacing: Dimensions.workspace.spacing spacing: 4
Repeater { Repeater {

View file

@ -1,18 +1,16 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
StyledLabel { StyledWrapperRectangle {
id: root id: root
required property var modelData required property var modelData
margin: 16
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View file

@ -1,19 +1,13 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config
import qs.services import qs.services
import qs.widgets
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
StyledPopupWindow { StyledPopupWindow {
id: root id: root
backgroundColor: Theme.palette.base300
margins: 16
radius: 8
content: GridLayout { content: GridLayout {
columns: 2 columns: 2
@ -30,9 +24,8 @@ StyledPopupWindow {
onClicked: Notifications.clear() onClicked: Notifications.clear()
} }
StyledLabel { StyledWrapperRectangle {
Layout.columnSpan: 2 Layout.columnSpan: 2
color: Theme.palette.base200
StyledListView { StyledListView {
id: notifications id: notifications

View file

@ -1,5 +1,5 @@
import qs.components import qs.components
import qs.constants import qs.config
import qs.services import qs.services
import QtQuick import QtQuick
@ -10,13 +10,13 @@ StyledIconButton {
menu.toggle(); menu.toggle();
} }
text: Notifications.hasNotifications ? Icons.bell : Icons.bellRing text: Notifications.hasNotifications ? Styling.lucide.icons.bell : Styling.lucide.icons.bellRing
states: State { states: State {
when: Notifications.hasNotifications when: Notifications.hasNotifications
PropertyChanges { PropertyChanges {
root { root {
text: Icons.bellRing text: Styling.lucide.icons.bellRing
} }
} }
} }

View file

@ -1,6 +1,5 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.config
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
@ -8,10 +7,10 @@ import Quickshell.Services.SystemTray
RowLayout { RowLayout {
id: root id: root
spacing: Dimensions.tray.spacing spacing: 4
Repeater { Repeater {
model: SystemTray.items model: SystemTray.items.values
Loader { Loader {
id: loader id: loader

View file

@ -5,12 +5,11 @@ import QtQuick
import Quickshell import Quickshell
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import Quickshell.Widgets import Quickshell.Widgets
import "menu/"
StyledIconButton { StyledIconButton {
id: root id: root
property SystemTrayItem trayItem required property SystemTrayItem trayItem
onClicked: menu.toggle() onClicked: menu.toggle()
@ -28,7 +27,7 @@ StyledIconButton {
} }
} }
Menu { TrayMenu {
id: menu id: menu
anchor.item: root anchor.item: root

View file

@ -0,0 +1,49 @@
pragma ComponentBehavior: Bound
import qs.components
import qs.config
import QtQuick
import QtQuick.Layouts
import Quickshell
import Quickshell.Widgets
StyledPopupWindow {
id: window
required property QsMenuOpener menuOpener
content: ColumnLayout {
spacing: 4
Repeater {
model: window.menuOpener.children.values
delegate: Loader {
id: loader
required property QsMenuEntry modelData
active: true
Component.onCompleted: {
console.log(modelData.text);
}
Layout.fillWidth: true
Layout.minimumWidth: 160
sourceComponent: modelData.isSeparator ? menuSeperator : menuItem
property Component menuSeperator: WrapperItem {
margin: 4
Rectangle {
implicitHeight: 2
color: Styling.theme.base200
}
}
property Component menuItem: StyledButton {
text: loader.modelData.text
onClicked: loader.modelData.triggered()
}
}
}
}
}

View file

@ -1,43 +0,0 @@
pragma ComponentBehavior: Bound
import qs.config
import qs.widgets
import QtQuick
import QtQuick.Layouts
import Quickshell
StyledPopupWindow {
id: window
backgroundColor: Theme.palette.base300
margins: 14
radius: 8
property QsMenuOpener menuOpener
content: ColumnLayout {
spacing: 8
Repeater {
model: window.menuOpener.children
delegate: Loader {
id: loader
required property QsMenuEntry modelData
active: true
Layout.fillWidth: true
Layout.minimumWidth: 160
sourceComponent: modelData.isSeparator ? menuSeperator : menuItem
property Component menuSeperator: Rectangle {
implicitHeight: 2
color: Theme.palette.base100
}
property Component menuItem: MenuItem {
menuEntry: loader.modelData
}
}
}
}
}

View file

@ -1,12 +0,0 @@
import qs.components
import Quickshell
StyledButton {
id: root
property QsMenuEntry menuEntry
text: root.menuEntry.text
onClicked: menuEntry.triggered()
}

View file

@ -0,0 +1,88 @@
import qs.components
import qs.config
import qs.services
import QtQuick
import QtQuick.Layouts
ColumnLayout {
anchors.fill: parent
spacing: Styling.layout.spacing.xl
StyledText {
text: "Speaker Settings"
}
StyledPane {
Layout.fillWidth: true
padding: 24
GridLayout {
Layout.fillWidth: true
columnSpacing: Styling.layout.spacing.xl
StyledText {
Layout.column: 1
Layout.row: 1
text: "Device"
}
StyledComboBox {
Layout.column: 2
Layout.row: 1
Layout.fillWidth: true
currentIndex: Pipewire.sinks.indexOf(Pipewire.sink)
model: Pipewire.sinks.map(sink => sink.nickname ?? sink.name)
onActivated: index => {
Pipewire.setSink(Pipewire.sinks[index]);
}
}
StyledText {
Layout.column: 1
Layout.row: 2
text: "Volume"
}
StyledSlider {
Layout.column: 2
Layout.row: 2
from: 0.0
to: 1.0
value: Pipewire.volume
onMoved: {
Pipewire.setVolume(value);
}
}
}
}
StyledText {
text: "Microphone Settings"
}
StyledPane {
Layout.fillWidth: true
padding: 24
GridLayout {
Layout.fillWidth: true
columnSpacing: Styling.layout.spacing.xl
StyledText {
Layout.column: 1
Layout.row: 2
text: "Microphones"
}
StyledComboBox {
Layout.column: 2
Layout.row: 2
Layout.fillWidth: true
currentIndex: Pipewire.sources.indexOf(Pipewire.source)
model: Pipewire.sources.map(source => source.nickname ?? source.name)
onActivated: index => {
Pipewire.setSource(Pipewire.sinks[index]);
}
}
}
}
}

View file

@ -0,0 +1,128 @@
pragma ComponentBehavior: Bound
import qs.components
import qs.config
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell.Widgets
StyledPanelWindow {
id: window
name: "configuration"
visible: Visibility.configuration
implicitWidth: 1000
implicitHeight: 600
background.color: Styling.theme.base200
onFocusedChanged: {
Visibility.configuration = focused;
}
RowLayout {
anchors.fill: parent
StyledTabBar {
id: tabs
Layout.preferredWidth: 150
Layout.fillHeight: true
Layout.margins: 2
orientation: ListView.Vertical
spacing: 12
Repeater {
model: views.data
delegate: StyledTabButton {
id: tabButton
required property ConfigurationView modelData
anchors.left: parent.left
anchors.right: parent.right
required property int index
contentItem: RowLayout {
states: [
State {
when: tabButton.hovered
PropertyChanges {
tabIcon.color: Styling.theme.primarycontent
tabText.color: Styling.theme.primarycontent
}
}
]
LucideIcon {
id: tabIcon
text: tabButton.modelData.icon
font.pixelSize: Styling.typography.textSize.lg
}
StyledText {
id: tabText
text: tabButton.modelData.title
font.pixelSize: Styling.typography.textSize.lg
}
}
text: tabButton.modelData.title
onClicked: tabs.setCurrentIndex(index)
}
}
}
SwipeView {
id: view
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
orientation: Qt.Vertical
currentIndex: tabs.currentIndex
background: Rectangle {
color: Styling.theme.base100
radius: Styling.theme.radiusBox
}
Repeater {
model: views.data
delegate: ScrollView {
id: scrollView
required property ConfigurationView modelData
padding: 24
Loader {
anchors.fill: parent
active: scrollView.modelData.view
sourceComponent: scrollView.modelData.view
}
}
}
}
}
Item {
id: views
ConfigurationView {
icon: Styling.lucide.icons.audioLines
title: "Audio"
view: AudioView {}
}
ConfigurationView {
icon: Styling.lucide.icons.swatchBook
title: "Styling"
view: StylingView {}
}
}
component ConfigurationView: QtObject {
property string icon
property string title
property Component view
}
}

View file

@ -0,0 +1,40 @@
pragma ComponentBehavior: Bound
import qs.components
import qs.components.composite
import qs.config
import qs.services
import QtQuick
import QtQuick.Layouts
import Qt.labs.folderlistmodel 2.9
import Quickshell.Widgets
ColumnLayout {
StyledPane {
GridLayout {
columnSpacing: Styling.layout.spacing.xl
StyledText {
text: "Theme"
font.pixelSize: Styling.typography.textSize.lg
}
ThemeComboBox {}
}
}
// StyledPane {
// WallpaperList {}
// }
StyledPane {
padding: 2
ClippingWrapperRectangle {
radius: Styling.theme.radiusBox
color: "transparent"
WallpaperList {}
}
}
}

View file

@ -1,16 +1,22 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.components.composite
import qs.services import qs.services
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Widgets
StyledDrawer { StyledDrawer {
id: root id: root
visible: Visibility.dashboard visible: Visibility.dashboard
StyledWrapperRectangle { onFocusedChanged: {
Visibility.dashboard = focused;
}
WrapperItem {
margin: 32 margin: 32
ColumnLayout { ColumnLayout {
spacing: 8 spacing: 8

View file

@ -4,7 +4,6 @@ import "items"
import "services" import "services"
import qs.components import qs.components
import qs.config import qs.config
import qs.widgets
import Quickshell import Quickshell
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
@ -32,7 +31,7 @@ StyledListView {
highlightResizeDuration: 0 highlightResizeDuration: 0
highlight: Rectangle { highlight: Rectangle {
radius: 8 radius: 8
color: Theme.palette.primary color: Styling.theme.primary
} }
header: StyledText { header: StyledText {

View file

@ -1,40 +1,29 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import "services" import "services"
import qs.config
import qs.components import qs.components
import qs.constants
import qs.services import qs.services
import Quickshell.Hyprland
import Quickshell.Wayland
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Widgets
StyledWindow { StyledPanelWindow {
id: root id: window
name: "launcher" name: "launcher"
visible: Visibility.launcher visible: Visibility.launcher
implicitWidth: rect.width onVisibleChanged: {
implicitHeight: rect.height if (!visible) {
WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: root.visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None
HyprlandFocusGrab {
active: root.visible
windows: [search]
onCleared: {
root.reset();
}
}
function reset() {
Visibility.launcher = false;
list.currentIndex = 0; list.currentIndex = 0;
search.clear(); search.clear();
} }
Visibility.launcher = focused;
}
implicitWidth: rect.width
implicitHeight: rect.height
StyledWrapperRectangle { WrapperItem {
id: rect id: rect
margin: 18 margin: 18
@ -45,13 +34,13 @@ StyledWindow {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
margin: 4
color: Styling.theme.base200
RowLayout { RowLayout {
LucideIcon { LucideIcon {
id: icon
Layout.leftMargin: 8 Layout.leftMargin: 8
text: Icons.search text: Styling.lucide.icons.search
} }
StyledTextField { StyledTextField {
@ -60,19 +49,19 @@ StyledWindow {
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: 40 implicitHeight: 40
cursorVisible: true cursorVisible: true
focus: root.visible focus: window.visible
placeholderText: "Applications" placeholderText: "Applications"
placeholderTextColor: "grey" placeholderTextColor: "grey"
Keys.onEscapePressed: event => { Keys.onEscapePressed: event => {
event.accepted = true; event.accepted = true;
root.reset(); Visibility.launcher = false;
} }
Keys.onReturnPressed: event => { Keys.onReturnPressed: event => {
event.accepted = true; event.accepted = true;
Apps.launch(list.currentItem.modelData); Apps.launch(list.currentItem.modelData);
root.reset(); Visibility.launcher = false;
} }
Keys.onUpPressed: event => { Keys.onUpPressed: event => {
event.accepted = true; event.accepted = true;

View file

@ -42,8 +42,7 @@ Item {
Layout.alignment: Qt.AlignBottom Layout.alignment: Qt.AlignBottom
Layout.fillWidth: true Layout.fillWidth: true
color: root.active ? Theme.palette.primarycontent : Theme.palette.basecontent color: root.active ? Styling.theme.primarycontent : Styling.theme.basecontent
font.pixelSize: 14
font.bold: true font.bold: true
} }
@ -52,8 +51,8 @@ Item {
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true Layout.fillWidth: true
color: root.active ? Theme.palette.primarycontent : Theme.palette.basecontent color: root.active ? Styling.theme.primarycontent : Styling.theme.basecontent
font.pixelSize: 10 font.pixelSize: Styling.typography.textSize.sm
elide: Text.ElideRight elide: Text.ElideRight
} }
} }

View file

@ -2,15 +2,13 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import qs.widgets import qs.widgets
import Quickshell.Hyprland
import Quickshell.Wayland
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Widgets
StyledWindow { StyledPanelWindow {
id: root id: root
name: "pomodoro" name: "pomodoro"
@ -18,10 +16,11 @@ StyledWindow {
implicitWidth: rect.width implicitWidth: rect.width
implicitHeight: rect.height implicitHeight: rect.height
WlrLayershell.layer: WlrLayer.Top onFocusedChanged: {
WlrLayershell.keyboardFocus: root.visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None Visibility.pomodoro = focused;
}
StyledWrapperRectangle { WrapperItem {
id: rect id: rect
leftMargin: 48 leftMargin: 48
@ -29,14 +28,6 @@ StyledWindow {
topMargin: 24 topMargin: 24
bottomMargin: 24 bottomMargin: 24
HyprlandFocusGrab {
active: Visibility.pomodoro
windows: [root]
onCleared: {
Visibility.pomodoro = false;
}
}
ColumnLayout { ColumnLayout {
spacing: 22 spacing: 22
@ -54,10 +45,10 @@ StyledWindow {
Circle { Circle {
id: circle id: circle
radius: 150 radius: 150
borderColor: Theme.palette.base100 borderColor: Styling.theme.base100
strokeColor: PomodoroService.state == "timer" ? Theme.palette.primary : Theme.palette.warning strokeColor: PomodoroService.state == "timer" ? Styling.theme.primary : Styling.theme.warning
strokeWidth: 12 strokeWidth: 12
fillColor: button.hovered ? Theme.palette.primary : "transparent" fillColor: button.hovered ? Styling.theme.primary : "transparent"
percentage: (PomodoroService.state == "timer" ? (PomodoroService.initialTime - PomodoroService.remainingTime) : PomodoroService.remainingTime) / PomodoroService.initialTime % 1 percentage: (PomodoroService.state == "timer" ? (PomodoroService.initialTime - PomodoroService.remainingTime) : PomodoroService.remainingTime) / PomodoroService.initialTime % 1
} }
@ -69,10 +60,10 @@ StyledWindow {
radius: 9999 radius: 9999
focus: root.visible focus: root.visible
text: PomodoroService.running ? Icons.square : Icons.play text: PomodoroService.running ? Styling.lucide.icons.square : Styling.lucide.icons.play
font.pixelSize: 48 font.pixelSize: 48
background: undefined background: Item {}
onClicked: { onClicked: {
PomodoroService.toggle(); PomodoroService.toggle();
} }

View file

@ -3,14 +3,12 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.services import qs.services
import qs.widgets
import Quickshell.Hyprland
import Quickshell.Io
import Quickshell.Wayland
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import Quickshell.Io
import Quickshell.Widgets
StyledWindow { StyledPanelWindow {
id: root id: root
name: "powermenu" name: "powermenu"
@ -18,27 +16,18 @@ StyledWindow {
implicitWidth: rect.width implicitWidth: rect.width
implicitHeight: rect.height implicitHeight: rect.height
WlrLayershell.layer: WlrLayer.Top onFocusedChanged: {
WlrLayershell.keyboardFocus: root.visible ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None Visibility.powermenu = focused;
}
Process { Process {
id: process id: process
} }
StyledWrapperRectangle { WrapperItem {
id: rect id: rect
color: Theme.palette.base300
margin: 14 margin: 14
radius: 8
HyprlandFocusGrab {
active: Visibility.powermenu
windows: [root]
onCleared: {
Visibility.powermenu = false;
}
}
StyledListView { StyledListView {
id: list id: list
@ -69,7 +58,7 @@ StyledWindow {
model: Config.powermenu.actions model: Config.powermenu.actions
spacing: 8 spacing: Styling.layout.spacing.base
implicitWidth: 220 implicitWidth: 220
implicitHeight: 185 implicitHeight: 185
@ -78,7 +67,7 @@ StyledWindow {
highlightResizeDuration: 0 highlightResizeDuration: 0
highlight: Rectangle { highlight: Rectangle {
radius: 8 radius: 8
color: Theme.palette.primary color: Styling.theme.primary
} }
onCurrentItemChanged: { onCurrentItemChanged: {
@ -105,9 +94,9 @@ StyledWindow {
} }
padding: 16 padding: 16
color: list.currentIndex == index ? Theme.palette.primarycontent : Theme.palette.basecontent color: list.currentIndex == index ? Styling.theme.primarycontent : Styling.theme.basecontent
text: modelData.text text: modelData.text
font.pixelSize: 18 font.pixelSize: Styling.typography.textSize.lg
font.bold: true font.bold: true
} }
} }

View file

@ -0,0 +1,150 @@
import qs.components
import qs.components.composite
import qs.config
import qs.services
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
GridLayout {
flow: GridLayout.TopToBottom
columns: 2
rows: 10
ColumnLayout {
StyledText {
text: "ToolTip"
font.pixelSize: 18
}
StyledPane {
Button {
id: toolTipButton
text: "Hello world!"
StyledToolTip {
visible: toolTipButton.hovered
text: qsTr("Save the active project")
}
}
}
}
ColumnLayout {
StyledText {
text: "ProgressBar"
font.pixelSize: 18
}
StyledPane {
StyledProgressBar {
id: progressBar
indeterminate: true
implicitHeight: 10
from: 0
to: 100
value: 50
}
}
}
ColumnLayout {
StyledText {
text: "ListView"
font.pixelSize: 18
}
StyledPane {
StyledWrapperRectangle {
border.color: Styling.theme.base100
border.width: 2
StyledListView {
implicitWidth: 200
implicitHeight: 100
model: 10
delegate: StyledText {
text: "Hello world!"
}
}
}
}
}
ColumnLayout {
StyledText {
text: "Mpris Player Selector"
font.pixelSize: 18
}
StyledPane {
MprisPlayerSelector {}
}
}
ColumnLayout {
StyledText {
text: "Mpris Controller"
font.pixelSize: 18
}
StyledPane {
MprisController {
player: Mpris.active ?? null
}
}
}
ColumnLayout {
StyledText {
text: "Drawer"
font.pixelSize: 18
}
StyledPane {
RowLayout {
Button {
text: "Top"
onClicked: {
drawer.x = root.width / 2 - drawer.width / 2;
drawer.y = 0;
drawer.edge = Qt.TopEdge;
drawer.open();
}
}
Button {
text: "Left"
onClicked: {
drawer.y = root.height / 2 - drawer.height / 2;
drawer.x = 0;
drawer.edge = Qt.LeftEdge;
drawer.open();
}
}
Button {
text: "Right"
onClicked: {
drawer.y = root.height / 2 - drawer.height / 2;
drawer.x = 0;
drawer.edge = Qt.RightEdge;
drawer.open();
}
}
Button {
text: "Bottom"
onClicked: {
drawer.x = root.width / 2 - drawer.width / 2;
drawer.y = 0;
drawer.edge = Qt.BottomEdge;
drawer.open();
}
}
}
}
}
StyledDrawer {
id: drawer
edge: Qt.TopEdge
width: 400
height: 200
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Close"
onClicked: drawer.close()
}
}
}

View file

@ -0,0 +1,53 @@
import qs.components
import qs.config
import QtQuick
import QtQuick.Layouts
ColumnLayout {
spacing: Styling.layout.spacing.xl
ColumnLayout {
StyledText {
text: "Button"
font.pixelSize: 18
}
StyledPane {
StyledButton {
text: "Button"
}
}
}
ColumnLayout {
StyledText {
text: "Icon Button"
font.pixelSize: 18
}
StyledPane {
StyledIconButton {
text: Styling.lucide.icons.square
}
}
}
ColumnLayout {
StyledText {
text: "Slider"
font.pixelSize: 18
}
StyledPane {
StyledSlider {
id: slider
from: 0
to: 100
value: 50
}
}
}
component FieldElement: QtObject {
property string title
property Component component
}
}

View file

@ -0,0 +1,22 @@
import qs.components
import QtQuick
import QtQuick.Layouts
GridLayout {
flow: GridLayout.TopToBottom
columns: 2
rows: 10
ColumnLayout {
StyledText {
text: "Switch"
font.pixelSize: 18
}
StyledPane {
StyledSwitch {
text: "Enable"
}
}
}
}

View file

@ -2,191 +2,72 @@ pragma ComponentBehavior: Bound
import qs.components import qs.components
import qs.config import qs.config
import qs.constants
import qs.services import qs.services
import QtQuick import QtQuick
import QtQuick.Controls import QtQuick.Controls
import QtQuick.Layouts
StyledPopupWindow { StyledPanelWindow {
id: root id: root
name: "storybook"
visible: Visibility.storybook visible: Visibility.storybook
implicitWidth: 500
implicitHeight: 600
GridLayout { background.color: Styling.theme.base200
id: grid
flow: GridLayout.TopToBottom onFocusedChanged: {
columns: 2 Visibility.storybook = focused;
rows: 10 }
StyledText { StyledTabBar {
Layout.columnSpan: grid.columns id: tabs
Layout.alignment: Qt.AlignHCenter anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: view.top
implicitHeight: 40
StyledTabButton {
text: "Fields"
onClicked: tabs.setCurrentIndex(0)
}
StyledTabButton {
text: "Selectors"
onClicked: tabs.setCurrentIndex(1)
}
StyledTabButton {
text: "Components" text: "Components"
font.pixelSize: 24 onClicked: tabs.setCurrentIndex(2)
font.bold: true
font.underline: true
bottomPadding: 24
}
ColumnLayout {
StyledText {
text: "Icon Button"
font.pixelSize: 18
}
StyledIconButton {
text: Icons.square
} }
} }
ColumnLayout { SwipeView {
StyledText { id: view
text: "Switch"
font.pixelSize: 18 anchors.top: tabs.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
currentIndex: tabs.currentIndex
background: Rectangle {
color: Styling.theme.base100
radius: Styling.theme.radiusBox
} }
StyledSwitch { ScrollView {
text: "Enable" padding: 36
Fields {}
} }
ScrollView {
padding: 36
Selectors {}
} }
ScrollView {
ColumnLayout { padding: 36
StyledText { Components {}
text: "ToolTip"
font.pixelSize: 18
}
Button {
id: toolTipButton
text: "Hello world!"
StyledToolTip {
visible: toolTipButton.hovered
text: qsTr("Save the active project")
}
}
}
ColumnLayout {
StyledText {
text: "Slider"
font.pixelSize: 18
}
StyledSlider {
id: slider
from: 0
to: 100
value: 50
}
}
ColumnLayout {
StyledText {
text: "ProgressBar"
font.pixelSize: 18
}
StyledProgressBar {
id: progressBar
indeterminate: true
implicitHeight: 10
from: 0
to: 100
value: 50
}
}
ColumnLayout {
StyledText {
text: "ListView"
font.pixelSize: 18
}
StyledWrapperRectangle {
border.color: Theme.palette.base100
border.width: 2
StyledListView {
implicitWidth: 200
implicitHeight: 100
model: 10
delegate: StyledText {
text: "Hello world!"
}
}
}
}
ColumnLayout {
StyledText {
text: "Mpris Player Selector"
font.pixelSize: 18
}
MprisPlayerSelector {}
}
ColumnLayout {
StyledText {
text: "Mpris Controller"
font.pixelSize: 18
}
MprisController {
player: Mpris.active ?? null
}
}
ColumnLayout {
StyledText {
text: "Drawer"
font.pixelSize: 18
}
RowLayout {
Button {
text: "Top"
onClicked: {
drawer.x = root.width / 2 - drawer.width / 2;
drawer.y = 0;
drawer.edge = Qt.TopEdge;
drawer.open();
}
}
Button {
text: "Left"
onClicked: {
drawer.y = root.height / 2 - drawer.height / 2;
drawer.x = 0;
drawer.edge = Qt.LeftEdge;
drawer.open();
}
}
Button {
text: "Right"
onClicked: {
drawer.y = root.height / 2 - drawer.height / 2;
drawer.x = 0;
drawer.edge = Qt.RightEdge;
drawer.open();
}
}
Button {
text: "Bottom"
onClicked: {
drawer.x = root.width / 2 - drawer.width / 2;
drawer.y = 0;
drawer.edge = Qt.BottomEdge;
drawer.open();
}
}
}
}
}
StyledDrawer {
id: drawer
edge: Qt.TopEdge
width: 400
height: 200
Button {
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
text: "Close"
onClicked: drawer.close()
} }
} }
} }

View file

@ -0,0 +1,35 @@
import qs.services
import QtQuick
import QtQuick.Controls
StackView {
id: stack
property url wallpaper: WallpaperService.currentWallpaper
anchors.fill: parent
replaceEnter: Transition {
OpacityAnimator {
from: 0.0
to: 1.0
duration: 1000
}
}
replaceExit: Transition {
PauseAnimation {
duration: 1100
}
}
Component {
id: img
Image {}
}
Component.onCompleted: stack.replace(img, {
"source": stack.wallpaper
})
onWallpaperChanged: stack.replace(img, {
"source": stack.wallpaper
})
}

View file

@ -1,7 +1,7 @@
pragma Singleton pragma Singleton
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Wayland
Singleton { Singleton {
@ -16,16 +16,14 @@ Singleton {
function toggle() { function toggle() {
if (properties.enabled) { if (properties.enabled) {
process.signal(888);
properties.enabled = false; properties.enabled = false;
} else { } else {
properties.enabled = true; properties.enabled = true;
} }
} }
Process { IdleInhibitor {
id: process id: inhibitor
running: properties.enabled enabled: properties.enabled
command: ["sh", "-c", "systemd-inhibit --what=idle --who=Caffeine --why='Caffeine module is active' --mode=block sleep inf"]
} }
} }

View file

@ -10,13 +10,16 @@ Singleton {
readonly property PwNode sink: Pipewire.defaultAudioSink readonly property PwNode sink: Pipewire.defaultAudioSink
readonly property PwNode source: Pipewire.defaultAudioSource readonly property PwNode source: Pipewire.defaultAudioSource
readonly property list<PwNode> sinks: Pipewire.nodes.values.filter(node => node.audio != null && node.isSink && !node.isStream)
readonly property list<PwNode> sources: Pipewire.nodes.values.filter(node => node.audio != null && !node.isSink && !node.isStream)
readonly property bool muted: sink?.audio?.muted ?? false readonly property bool muted: sink?.audio?.muted ?? false
readonly property real volume: sink?.audio?.volume ?? 0 readonly property real volume: sink?.audio?.volume ?? 0
function setVolume(volume: real): void { function setVolume(volume: real): void {
if (sink?.ready && sink?.audio) { if (sink?.ready && sink?.audio) {
sink.audio.muted = false; sink.audio.muted = false;
sink.audio.volume = volume; sink.audio.volume = Math.min(volume, 1.0);
} }
} }
@ -42,6 +45,18 @@ Singleton {
sink.audio.muted = !sink.audio.muted; sink.audio.muted = !sink.audio.muted;
} }
function setSink(node: PwNode) {
if (node.audio != null && node.isSink && !node.isStream) {
Pipewire.preferredDefaultAudioSink = node;
}
}
function setSource(node: PwNode) {
if (node.audio != null && !node.isSink && !node.isStream) {
Pipewire.preferredDefaultAudioSource = node;
}
}
PwObjectTracker { PwObjectTracker {
objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource] objects: [Pipewire.defaultAudioSink, Pipewire.defaultAudioSource]
} }

View file

@ -1,27 +1,19 @@
pragma Singleton pragma Singleton
import qs.widgets
import Quickshell import Quickshell
Singleton { Singleton {
property alias configuration: properties.configuration
property alias dashboard: properties.dashboard property alias dashboard: properties.dashboard
property alias launcher: properties.launcher property alias launcher: properties.launcher
property alias pomodoro: properties.pomodoro property alias pomodoro: properties.pomodoro
property alias powermenu: properties.powermenu property alias powermenu: properties.powermenu
property alias storybook: properties.storybook property alias storybook: properties.storybook
property StyledPopupWindow activePopup
function togglePopup(popup: StyledPopupWindow) {
if (activePopup && popup != activePopup) {
activePopup.state = "";
}
popup.state = popup.state == "opened" ? "" : "opened";
activePopup = popup;
}
PersistentProperties { PersistentProperties {
id: properties id: properties
property bool configuration
property bool dashboard property bool dashboard
property bool launcher property bool launcher
property bool pomodoro property bool pomodoro

View file

@ -0,0 +1,27 @@
pragma Singleton
import qs.config
import Quickshell
import Quickshell.Io
Singleton {
id: root
property alias currentWallpaper: properties.currentWallpaper
FileView {
path: `${Paths.cache}/wallpaper.json`
watchChanges: true
onFileChanged: reload()
// when changes are made to properties in the adapter, save them
onAdapterUpdated: writeAdapter()
JsonAdapter {
id: properties
property url currentWallpaper: ""
}
}
}

View file

@ -0,0 +1,43 @@
import QtQuick
import Quickshell.Io
Item {
id: root
required property string path
property bool recursive: true
property list<string> fileFilter: []
signal created(path: string)
signal modified(path: string)
signal deleted(path: string)
signal movedFrom(path: string)
signal movedTo(path: string)
Process {
running: true
command: ["bash", "-c", `inotifywait -m ${root.recursive ? "-r" : ""} ${root.path} -e modify,move,create,delete --format "%e-%w%f"`]
stderr: StdioCollector {
onStreamFinished: console.error(`DirectoryWatcher: ${this.text}`)
}
stdout: SplitParser {
splitMarker: "\n"
onRead: data => {
const [action, path] = data.split("-");
if (path.endsWith("~") || root.fileFilter.length > 0 && !root.fileFilter.some(filter => path.endsWith(filter))) {
return;
}
if (action.includes("CREATE")) {
root.created(path);
} else if (action.includes("MODIFY")) {
root.modified(path);
} else if (action.includes("DELETE")) {
root.deleted(path);
} else if (action.includes("MOVED_FROM")) {
root.movedFrom(path);
} else if (action.includes("MOVED_TO")) {
root.movedTo(path);
}
}
}
}
}

View file

@ -22,8 +22,8 @@ Item {
ShapePath { ShapePath {
id: fill id: fill
fillColor: Theme.palette.base100 fillColor: Styling.theme.base100
strokeColor: Theme.palette.base200 strokeColor: Styling.theme.base200
strokeWidth: 8 strokeWidth: 8
PathAngleArc { PathAngleArc {

View file

@ -1,102 +0,0 @@
import qs.services
import QtQuick
import Quickshell
import Quickshell.Widgets
PopupWindow {
id: root
property bool opened: false
property int animationDuration: 200
property alias margins: background.margin
property alias backgroundColor: background.color
property alias radius: background.radius
property alias state: background.state
required property Component content
color: "transparent"
function toggle() {
Visibility.togglePopup(this);
}
implicitWidth: background.width
Behavior on implicitWidth {
NumberAnimation {
duration: 100
}
}
implicitHeight: background.height
Behavior on implicitHeight {
NumberAnimation {
duration: 100
}
}
Timer {
id: timer
interval: 750
onTriggered: {
if (!root.visible) {
return;
}
root.toggle();
}
}
WrapperMouseArea {
hoverEnabled: true
onExited: {
timer.start();
}
onEntered: {
timer.stop();
}
WrapperRectangle {
id: background
opacity: 0
Behavior on opacity {
NumberAnimation {
duration: root.animationDuration
}
}
states: State {
name: "opened"
when: root.opened
PropertyChanges {
background {
opacity: 1
}
}
}
transitions: [
Transition {
from: ""
to: "opened"
ScriptAction {
script: root.visible = true
}
},
Transition {
from: "opened"
to: ""
SequentialAnimation {
PauseAnimation {
duration: root.animationDuration
}
ScriptAction {
script: root.visible = false
}
}
}
]
Loader {
active: root.visible
sourceComponent: root.content
}
}
}
}