import QtQuick import QtQuick.Controls import QtQuick.Layouts import KomplexHub Item { property string author: "" property string description: "" property string title: "" property string thumbnail: "" property string uuid: "" property bool selected: false property bool pexels: false signal triggered signal viewMoreTriggered id: searchResultItemRoot width: 256 height: 256 clip: true Rectangle { id: searchResultItemContainer anchors.fill: parent border.color: palette.alternateBase.lighter(1.75) color: palette.alternateBase.lighter(1.25) MouseArea { property string lastState id: mouseArea anchors.fill: parent hoverEnabled: true onEntered: () => { states.hovered = true } onExited: () => { if(!viewMoreButton.hovered) states.hovered = false } onReleased: () => { if(!states.selected) { searchResultItemRoot.triggered() } } } ColumnLayout { anchors.fill: parent Rectangle { Layout.preferredWidth: 250 Layout.preferredHeight: 141 Layout.alignment: Qt.AlignHCenter | Qt.AlignTop Layout.topMargin: 3 border.color: palette.alternateBase.lighter(1.75) color: palette.base.lighter(1.25) Image { anchors.fill: parent fillMode: Image.PreserveAspectCrop id: thumnailImage source: searchResultItemRoot.thumbnail } Image { antialiasing: true anchors.right: parent.right anchors.bottom: parent.bottom anchors.margins: Constants.mediumMargin width: 24 height: 24 transform: Image.PreserveAspectFit opacity: 0.5 source: "qrc:/images/icons/pexels-icon-filled-256.svg" visible: searchResultItemRoot.pexels } } Text { color: palette.text text: searchResultItemRoot.title font.pixelSize: 16 font.bold: true elide: Text.ElideRight Layout.preferredWidth: 246 Layout.alignment: Qt.AlignHCenter | Qt.AlignTop } Item { Layout.fillHeight: true } Text { color: palette.text font.pixelSize: 12 text: "By: " + searchResultItemRoot.author leftPadding: 12 Layout.alignment: Qt.AlignLeft | Qt.AlignBottom Layout.preferredWidth: 250 visible: !searchResultItemRoot.pexels } Text { id: descriptionText clip: true color: palette.text font.pixelSize: 12 text: searchResultItemRoot.description wrapMode: Text.WrapAtWordBoundaryOrAnywhere textFormat: Text.PlainText elide: Text.ElideRight Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.maximumHeight: 32 Layout.preferredHeight: 32 Layout.preferredWidth: 236 Layout.maximumWidth: 236 Layout.bottomMargin: 3 } SquareButton { id: viewMoreButton Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.maximumHeight: 50 Layout.preferredHeight: 32 Layout.preferredWidth: 236 Layout.maximumWidth: 236 Layout.bottomMargin: 3 text: qsTr("View More") opacity: 0 onTriggered: () => { searchResultItemRoot.viewMoreTriggered() } } Item { Layout.fillHeight: true } } } QtObject { id: states property bool clicked: false property bool hovered: false property alias selected: searchResultItemRoot.selected property bool idle: true onIdleChanged: () => { if(idle) { clicked = false hovered = false selected = false } } } states: [ State { name: "hovered" when: states.hovered && !states.selected PropertyChanges { target: searchResultItemContainer color: palette.alternateBase.lighter(1.5) border.color: Qt.hsva(palette.accent.hslHue, palette.accent.hslSaturation, 0.5, // Set custom lightness 1.0) } PropertyChanges { target: viewMoreButton opacity: 0 Layout.preferredHeight: 0 } PropertyChanges { target: descriptionText opacity: 1 Layout.preferredHeight: 32 } }, State { name: "selected" when: states.selected && !states.hovered PropertyChanges { target: searchResultItemContainer color: palette.accent } }, State { name: "view_more" when: states.selected && states.hovered PropertyChanges { target: viewMoreButton opacity: 1 Layout.preferredHeight: 32 } PropertyChanges { target: descriptionText opacity: 0 Layout.preferredHeight: 0 } }, State { name: "default" when: states.idle PropertyChanges { target: viewMoreButton opacity: 0 Layout.preferredHeight: 0 } PropertyChanges { target: descriptionText opacity: 1 Layout.preferredHeight: 32 } } ] transitions: [ Transition { to: "selected" ColorAnimation { target: searchResultItemContainer duration: 250 } }, Transition { from: "selected" to: "view_more" NumberAnimation { target: viewMoreButton property: "opacity" duration: 250 easing.type: Easing.InOutQuad } }, Transition { from: "view_more" to: "selected" NumberAnimation { target: descriptionText property: "opacity" duration: 250 easing.type: Easing.InOutQuad } }, Transition { to: "default" ColorAnimation { target: searchResultItemContainer duration: 250 } }, Transition { to: "hovered" ColorAnimation { target: searchResultItemContainer duration: 250 } } ] }