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(getWsIdx(modelData.start)) ?? null readonly property Workspace end: root.workspaces.itemAt(getWsIdx(modelData.end)) ?? null function getWsIdx(ws: int): int { let i = ws - 1; while (i < 0) i += Config.bar.workspaces.shown; return i % Config.bar.workspaces.shown; } 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 Pill: QtObject { property int start property int end } Component { id: pillComp Pill {} } }