pragma ComponentBehavior: Bound import Quickshell import Quickshell.Widgets import QtQuick import QtQuick.Layouts import QtQuick.Shapes import qs.widgets.theme // Headlessly renderable visual core for variant 11. Inspired by V5's bottom // deck and horizontal carousel, but owns a denser industrial cyberpunk chassis. Item { id: root property var apps: [] property int selectedIndex: 0 property bool showIcons: true property alias query: dockInput.text readonly property var selectedApp: apps.length > 0 && selectedIndex >= 0 && selectedIndex < apps.length ? apps[selectedIndex] : null signal selectionRequested(int index) signal moveRequested(int delta) signal launchRequested(int index) signal dismissRequested function focusSearch() { dockInput.forceActiveFocus(); } function clearSearch() { dockInput.text = ""; } implicitWidth: 1440 implicitHeight: 272 component MicroText: Text { color: Theme.muted font.family: Theme.microFont font.pixelSize: 7 font.letterSpacing: 0.9 elide: Text.ElideRight } Rectangle { anchors.fill: parent; color: Theme.textAlpha(0) } // Main dock chassis with clipped upper corners and heavier lower edge. Shape { id: chassis anchors.fill: parent preferredRendererType: Shape.CurveRenderer ShapePath { fillColor: Theme.surface strokeColor: Theme.hair strokeWidth: 1 startX: 28; startY: 0 PathLine { x: chassis.width - 28; y: 0 } PathLine { x: chassis.width; y: 28 } PathLine { x: chassis.width; y: chassis.height } PathLine { x: 0; y: chassis.height } PathLine { x: 0; y: 28 } PathLine { x: 28; y: 0 } } ShapePath { fillColor: Theme.accent strokeWidth: 0 startX: 28; startY: 0 PathLine { x: 250; y: 0 } PathLine { x: 244; y: 4 } PathLine { x: 32; y: 4 } PathLine { x: 4; y: 32 } PathLine { x: 4; y: 96 } PathLine { x: 0; y: 96 } PathLine { x: 0; y: 28 } PathLine { x: 28; y: 0 } } ShapePath { fillColor: Theme.accent strokeWidth: 0 startX: 0; startY: chassis.height - 6 PathLine { x: chassis.width; y: chassis.height - 6 } PathLine { x: chassis.width; y: chassis.height } PathLine { x: 0; y: chassis.height } PathLine { x: 0; y: chassis.height - 6 } } } // Top caution seam. Row { x: 270; y: 1; spacing: 5 Repeater { model: 58 Rectangle { required property int index width: 10; height: 3 color: index % 4 === 0 ? Theme.accent : Theme.hair transform: Rotation { angle: -32 } } } } // Left system coupler. Item { id: coupler x: 18; y: 18 width: 156; height: 184 Rectangle { anchors.centerIn: parent; width: 112; height: 112; radius: 56; color: Theme.textAlpha(0.012); border.width: 1; border.color: Theme.accentAlpha(0.55) } Rectangle { anchors.centerIn: parent; width: 78; height: 78; radius: 39; color: Theme.textAlpha(0); border.width: 1; border.color: Theme.hair } Rectangle { anchors.centerIn: parent; width: 118; height: 1; color: Theme.hair } Rectangle { anchors.centerIn: parent; width: 1; height: 118; color: Theme.hair } Rectangle { anchors.centerIn: parent; width: 38; height: 38; color: Theme.accentAlpha(0.16); border.width: 1; border.color: Theme.accent; transform: Rotation { angle: 45 } } Text { anchors.centerIn: parent; text: "11"; color: Theme.accent; font.family: Theme.displayFont; font.pixelSize: 13; font.bold: true } MicroText { anchors.horizontalCenter: parent.horizontalCenter; anchors.bottom: parent.bottom; anchors.bottomMargin: 15; text: "DOCK BUS"; color: Theme.accent } } Text { x: 24; y: 16 text: "CYBER//DOCK" color: Theme.text font.family: Theme.displayFont font.pixelSize: 9 font.bold: true font.letterSpacing: 1 } // Horizontal cartridge conveyor. ListView { id: cartridgeList x: 178; y: 20 width: root.width - 356 height: 180 orientation: ListView.Horizontal model: root.apps currentIndex: root.selectedIndex spacing: 8 clip: true boundsBehavior: Flickable.StopAtBounds onCurrentIndexChanged: positionViewAtIndex(currentIndex, ListView.Contain) delegate: MouseArea { id: cartridge required property int index required property var modelData readonly property bool selected: index === root.selectedIndex width: selected ? 128 : 108 height: selected ? 176 : 148 y: selected ? 0 : 24 hoverEnabled: true cursorShape: Qt.PointingHandCursor onEntered: root.selectionRequested(index) onClicked: root.launchRequested(index) Behavior on y { NumberAnimation { duration: 120; easing.type: Easing.OutCubic } } Behavior on height { NumberAnimation { duration: 120; easing.type: Easing.OutCubic } } Shape { id: cartridgeShape anchors.fill: parent preferredRendererType: Shape.CurveRenderer ShapePath { fillColor: cartridge.selected ? Theme.selection : Theme.textAlpha(0.022) strokeColor: cartridge.selected ? Theme.accent : Theme.hair strokeWidth: cartridge.selected ? 2 : 1 startX: 12; startY: 0 PathLine { x: cartridgeShape.width - 8; y: 0 } PathLine { x: cartridgeShape.width; y: 8 } PathLine { x: cartridgeShape.width; y: cartridgeShape.height - 14 } PathLine { x: cartridgeShape.width - 14; y: cartridgeShape.height } PathLine { x: 0; y: cartridgeShape.height } PathLine { x: 0; y: 12 } PathLine { x: 12; y: 0 } } ShapePath { fillColor: cartridge.selected ? Theme.accent : Theme.textAlpha(0.12) strokeWidth: 0 startX: 0; startY: cartridgeShape.height - 6 PathLine { x: cartridgeShape.width - 14; y: cartridgeShape.height - 6 } PathLine { x: cartridgeShape.width - 20; y: cartridgeShape.height } PathLine { x: 0; y: cartridgeShape.height } PathLine { x: 0; y: cartridgeShape.height - 6 } } } MicroText { x: 9; y: 8; text: "C" + String(cartridge.index + 1).padStart(2, "0"); color: cartridge.selected ? Theme.accent : Theme.muted } Rectangle { anchors.horizontalCenter: parent.horizontalCenter y: cartridge.selected ? 30 : 27 width: cartridge.selected ? 68 : 54 height: width color: cartridge.selected ? Theme.accentAlpha(0.12) : Theme.textAlpha(0.018) border.width: 1 border.color: cartridge.selected ? Theme.accent : Theme.hair IconImage { visible: root.showIcons; anchors.centerIn: parent; implicitSize: cartridge.selected ? 48 : 38; source: root.showIcons ? Quickshell.iconPath(cartridge.modelData.icon || "application-x-executable", "application-x-executable") : "" } Text { visible: !root.showIcons; anchors.centerIn: parent; text: String(cartridge.modelData.name || "?").charAt(0).toUpperCase(); color: cartridge.selected ? Theme.accent : Theme.text; font.family: Theme.displayFont; font.pixelSize: cartridge.selected ? 23 : 18; font.bold: true } } Text { x: 8; anchors.bottom: generic.top; anchors.bottomMargin: 4 width: parent.width - 16 text: cartridge.modelData.name || "UNKNOWN" color: cartridge.selected ? Theme.accent : Theme.text font.family: Theme.displayFont font.pixelSize: cartridge.selected ? 10 : 9 font.bold: cartridge.selected horizontalAlignment: Text.AlignHCenter elide: Text.ElideRight } MicroText { id: generic x: 8; anchors.bottom: parent.bottom; anchors.bottomMargin: 13 width: parent.width - 16 text: cartridge.modelData.genericName || "APPLICATION" horizontalAlignment: Text.AlignHCenter } } Text { anchors.centerIn: parent; visible: root.apps.length === 0; text: "NO CARTRIDGES MATCH QUERY"; color: Theme.muted; font.family: Theme.microFont; font.pixelSize: 9; font.letterSpacing: 1.2 } } // Right telemetry clamp. Item { id: clamp anchors.right: parent.right anchors.rightMargin: 18 y: 20; width: 150; height: 180 Shape { anchors.fill: parent preferredRendererType: Shape.CurveRenderer ShapePath { fillColor: Theme.textAlpha(0.018) strokeColor: Theme.hair strokeWidth: 1 startX: 0; startY: 0 PathLine { x: 128; y: 0 } PathLine { x: 150; y: 22 } PathLine { x: 150; y: 180 } PathLine { x: 0; y: 180 } PathLine { x: 0; y: 0 } } } MicroText { x: 12; y: 12; text: "ACTIVE SLOT"; color: Theme.accent } Text { x: 12; y: 35; width: parent.width - 24; text: String(Math.max(0, root.selectedIndex + 1)).padStart(3, "0"); color: Theme.text; font.family: Theme.displayFont; font.pixelSize: 28; font.bold: true } MicroText { x: 12; y: 75; width: parent.width - 24; text: root.selectedApp ? root.selectedApp.name : "NO TARGET"; color: Theme.text } MicroText { x: 12; y: 96; width: parent.width - 24; text: root.apps.length + " AVAILABLE" } Row { x: 12; y: 120; spacing: 3; Repeater { model: 12; Rectangle { required property int index; width: 7; height: 4; color: index < Math.min(12, root.apps.length) ? Theme.accent : Theme.hair } } } MicroText { x: 12; anchors.bottom: parent.bottom; anchors.bottomMargin: 12; text: "BUS // ARMED"; color: Theme.accent } } // Bottom command spine. Shape { id: commandSpine x: 176; y: 211 width: root.width - 352; height: 48 preferredRendererType: Shape.CurveRenderer ShapePath { fillColor: Theme.accentAlpha(0.10) strokeColor: Theme.accent strokeWidth: 1 startX: 14; startY: 0 PathLine { x: commandSpine.width; y: 0 } PathLine { x: commandSpine.width - 14; y: commandSpine.height } PathLine { x: 0; y: commandSpine.height } PathLine { x: 14; y: 0 } } } Text { x: 196; y: 221; text: ">_"; color: Theme.accent; font.family: Theme.displayFont; font.pixelSize: 17; font.bold: true } TextInput { id: dockInput x: 230; y: 219; width: root.width - 650; height: 34 verticalAlignment: TextInput.AlignVCenter color: Theme.text selectionColor: Theme.accent selectedTextColor: Theme.surface font.family: Theme.displayFont font.pixelSize: 14 font.letterSpacing: 1 clip: true onTextChanged: root.selectionRequested(0) Keys.onPressed: event => { switch (event.key) { case Qt.Key_Right: case Qt.Key_Tab: root.moveRequested(1); event.accepted = true; break; case Qt.Key_Left: case Qt.Key_Backtab: root.moveRequested(-1); event.accepted = true; break; case Qt.Key_PageDown: root.moveRequested(5); event.accepted = true; break; case Qt.Key_PageUp: root.moveRequested(-5); event.accepted = true; break; case Qt.Key_Return: case Qt.Key_Enter: root.launchRequested(root.selectedIndex); event.accepted = true; break; case Qt.Key_Escape: root.dismissRequested(); event.accepted = true; break; } } Text { anchors.fill: parent; verticalAlignment: Text.AlignVCenter; visible: dockInput.text.length === 0; text: "FILTER DOCK CARTRIDGES"; color: Theme.muted; font: dockInput.font } } MicroText { x: root.width - 492; y: 228; text: "← → SELECT // ENTER LAUNCH // ESC RETRACT"; color: Theme.accent } // Lower rail hardware. Row { x: 18; anchors.bottom: parent.bottom; anchors.bottomMargin: 1; spacing: 4 Repeater { model: 70; Rectangle { required property int index; width: 10; height: 4; color: index % 5 === 0 ? Theme.accent : Theme.hair; transform: Rotation { angle: -32 } } } } }