diff --git a/crates/qbz-qt/qml/controls/QbzSearchField.qml b/crates/qbz-qt/qml/controls/QbzSearchField.qml index fc01332bf..45e41440a 100644 --- a/crates/qbz-qt/qml/controls/QbzSearchField.qml +++ b/crates/qbz-qt/qml/controls/QbzSearchField.qml @@ -22,6 +22,14 @@ Rectangle { property alias text: input.text property string placeholder: "" + /// The leading magnifier; off for hosts whose own toggle already shows one + /// (the sidebar's inline filters). + property bool showGlyph: true + /// Escape emptied the field and handed the keyboard back; a host that + /// folds the field away listens here. + signal escaped() + /// The clear cross scales with a short field (the sidebar's 22px rows). + readonly property int clearSize: Math.min(22, Math.max(16, height - 2)) property int glyphSize: 14 property int fontPx: 13 property int sidePadding: 10 @@ -80,6 +88,7 @@ Rectangle { } QbzIcon { + visible: root.showGlyph name: "search" width: root.glyphSize height: root.glyphSize @@ -92,7 +101,7 @@ Rectangle { QbzTextEditMenu { } anchors.left: parent.left anchors.right: clearSlot.left - anchors.leftMargin: root.sidePadding + root.glyphSize + 7 + anchors.leftMargin: root.sidePadding + (root.showGlyph ? root.glyphSize + 7 : 0) anchors.rightMargin: 4 height: parent.height color: theme.textPrimary @@ -106,6 +115,7 @@ Rectangle { } Keys.onEscapePressed: function (event) { root.clearAndBlur() + root.escaped() event.accepted = true } Text { @@ -124,19 +134,19 @@ Rectangle { id: clearSlot anchors.right: parent.right anchors.rightMargin: 5 - width: input.text !== "" ? 22 : 0 + width: input.text !== "" ? root.clearSize : 0 height: parent.height visible: input.text !== "" Rectangle { anchors.centerIn: parent - width: 22 - height: 22 - radius: 11 + width: root.clearSize + height: root.clearSize + radius: root.clearSize / 2 color: clearArea.containsMouse ? theme.surfaceHover : "transparent" QbzIcon { name: "x" - width: 12 - height: 12 + width: Math.round(root.clearSize * 0.55) + height: Math.round(root.clearSize * 0.55) anchors.centerIn: parent tintName: clearArea.containsMouse ? "textPrimary" : "muted" } diff --git a/crates/qbz-qt/qml/shell/Sidebar.qml b/crates/qbz-qt/qml/shell/Sidebar.qml index 3529ea280..06571b6ea 100644 --- a/crates/qbz-qt/qml/shell/Sidebar.qml +++ b/crates/qbz-qt/qml/shell/Sidebar.qml @@ -903,12 +903,10 @@ Rectangle { cursorShape: Qt.PointingHandCursor onClicked: { root.myqbzSearchOpen = !root.myqbzSearchOpen - if (!root.myqbzSearchOpen) { - myqbzSearchEdit.text = "" - root.myqbzSearch = "" - } else { - myqbzSearchEdit.forceActiveFocus() - } + if (!root.myqbzSearchOpen) + myqbzSearchEdit.clear() + else + myqbzSearchEdit.focusField() } } } @@ -999,8 +997,11 @@ Rectangle { onClicked: QbzShell.navigateTo("collections") } } - // Inline search field (filters the tree client-side). - Rectangle { + // Inline search field (filters the tree client-side). The + // shared search box: Escape empties it AND folds it away, + // the cross empties it and keeps the caret. + QbzSearchField { + id: myqbzSearchEdit visible: root.myqbzSearchOpen anchors.left: myqbzBrandIcon.right anchors.leftMargin: 8 @@ -1009,28 +1010,12 @@ Rectangle { anchors.verticalCenter: parent.verticalCenter height: 22 radius: 4 - color: (theme.ambientOn ? theme.surfaceElevatedA50 : theme.surfaceElevated) - border.width: 1 - border.color: theme.borderSubtle - TextInput { - QbzTextEditMenu { } - id: myqbzSearchEdit - anchors.fill: parent - anchors.leftMargin: 6 - color: theme.textPrimary - font.pixelSize: 12 - verticalAlignment: Text.AlignVCenter - clip: true - onTextEdited: root.myqbzSearch = text - Text { - visible: myqbzSearchEdit.text === "" - anchors.fill: parent - text: QbzSession.tr("Search My QBZ", QbzSession.trRev) - color: theme.textMuted - font.pixelSize: 12 - verticalAlignment: Text.AlignVCenter - } - } + showGlyph: false + sidePadding: 6 + fontPx: 12 + placeholder: QbzSession.tr("Search My QBZ", QbzSession.trRev) + onEdited: function (text) { root.myqbzSearch = text } + onEscaped: root.myqbzSearchOpen = false } } @@ -1280,34 +1265,21 @@ Rectangle { font.letterSpacing: 1 verticalAlignment: Text.AlignVCenter } - // Inline search input (filters entries, recursive). - Rectangle { + // Inline search input (filters entries, recursive). The shared + // search box: Escape empties it AND folds it back into the title, + // the cross empties it and keeps the caret. + QbzSearchField { + id: searchEdit visible: root.searchOpen width: parent.width - 4 * 26 height: 22 radius: 4 - color: (theme.ambientOn ? theme.surfaceElevatedA50 : theme.surfaceElevated) - border.width: 1 - border.color: theme.borderSubtle - TextInput { - QbzTextEditMenu { } - id: searchEdit - anchors.fill: parent - anchors.leftMargin: 6 - color: theme.textPrimary - font.pixelSize: 12 - verticalAlignment: Text.AlignVCenter - clip: true - onTextEdited: QbzShell.sidebarSearch(text) - Text { - visible: searchEdit.text === "" - anchors.fill: parent - text: QbzSession.tr("Search playlists", QbzSession.trRev) - color: theme.textMuted - font.pixelSize: 12 - verticalAlignment: Text.AlignVCenter - } - } + showGlyph: false + sidePadding: 6 + fontPx: 12 + placeholder: QbzSession.tr("Search playlists", QbzSession.trRev) + onEdited: function (text) { QbzShell.sidebarSearch(text) } + onEscaped: root.searchOpen = false } // Search toggle. @@ -1330,12 +1302,10 @@ Rectangle { cursorShape: Qt.PointingHandCursor onClicked: { root.searchOpen = !root.searchOpen - if (!root.searchOpen) { - searchEdit.text = "" - QbzShell.sidebarSearch("") - } else { - searchEdit.forceActiveFocus() - } + if (!root.searchOpen) + searchEdit.clear() + else + searchEdit.focusField() } } }