pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell import ZShell.Config import ZShell.Llm import qs.Components import qs.Services Item { id: root property int breakpoint: 700 property alias conversationModel: sidebar.model property var currentConversation: null // whatever model item is "open" readonly property bool isWide: root.width >= root.breakpoint property bool narrowShowsSidebar: true function closeConversation() { narrowShowsSidebar = true; } function openConversation(conv) { currentConversation = conv; narrowShowsSidebar = false; // in narrow mode, jump to the chat } ChatList { id: sidebar anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: root.isWide ? undefined : parent.right anchors.top: parent.top implicitWidth: 20 list.currentIndex: -1 list.highlightFollowsCurrentItem: false Behavior on anchors.right { AnchorAnim {} } Behavior on implicitWidth { Anim {} } list.highlight: CustomRect { color: Colors.palette.m3primary implicitHeight: sidebar.list.currentItem?.implicitHeight ?? 0 implicitWidth: sidebar.list.width radius: Tokens.rounding.medium x: sidebar.list.currentItem?.chat.x ?? 0 y: sidebar.list.currentItem?.y ?? 0 Behavior on y { Anim { duration: Tokens.anim.durations.small easing: Tokens.anim.expressiveDefaultEffects } } } model: ScriptModel { values: Chat.chats.values } anchors.onRightChanged: { if (anchors.right === undefined) implicitWidth = 20; } onLoadChatRequest: (chat, index) => { sidebar.list.currentIndex = index; root.openConversation(chat); } } CustomClippingWrapperRect { anchors.bottom: parent.bottom anchors.left: sidebar.right anchors.right: parent.right anchors.top: parent.top child: conversationView } ChatContent { id: conversationView anchors.fill: root anchors.leftMargin: root.isWide ? Config.sidebar.sizes.width / 2 : 0 chatData: root.currentConversation } }