pragma ComponentBehavior: Bound import qs.components import qs.services import qs.config import Quickshell import QtQuick Item { id: root required property Repeater workspaces required property var occupied required property int groupOffset property list pills: [] onOccupiedChanged: { let count = 0; const start = groupOffset; const end = start + Config.bar.workspaces.shown; for (const [ws, occ] of Object.entries(occupied)) { if (ws > start && ws <= end && occ) { if (!occupied[ws - 1]) { if (pills[count]) pills[count].start = ws; else pills.push(pillComp.createObject(root, { start: ws })); count++; } if (!occupied[ws + 1]) pills[count - 1].end = ws; } } if (pills.length > count) pills.splice(count, pills.length - count).forEach(p => p.destroy()); } Repeater { model: ScriptModel { values: root.pills.filter(p => p) } StyledRect { id: rect required property var modelData readonly property Workspace start: root.workspaces.itemAt((modelData.start - 1) % Config.bar.workspaces.shown) ?? null readonly property Workspace end: root.workspaces.itemAt((modelData.end - 1) % Config.bar.workspaces.shown) ?? null anchors.horizontalCenter: root.horizontalCenter y: (start?.y ?? 0) - 1 implicitWidth: Config.bar.sizes.innerWidth - Appearance.padding.small * 2 + 2 implicitHeight: start && end ? end.y + end.size - start.y + 2 : 0 color: Colours.layer(Colours.palette.m3surfaceContainerHigh, 2) radius: Appearance.rounding.full scale: 0 Component.onCompleted: scale = 1 Behavior on scale { Anim { easing.bezierCurve: Appearance.anim.curves.standardDecel } } Behavior on y { Anim {} } Behavior on implicitHeight { Anim {} } } } component Anim: NumberAnimation { duration: Appearance.anim.durations.normal easing.type: Easing.BezierSpline easing.bezierCurve: Appearance.anim.curves.standard } component Pill: QtObject { property int start property int end } Component { id: pillComp Pill {} } }