diff --git a/sandbox/StatusSelectPage.qml b/sandbox/StatusSelectPage.qml new file mode 100644 index 00000000..f9a38e7c --- /dev/null +++ b/sandbox/StatusSelectPage.qml @@ -0,0 +1,54 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Popups 0.1 + +import Sandbox 0.1 +Column { + spacing: 8 + + StatusSelect { + id: select + label: "Some label" + model: ListModel { + ListElement { + name: "Pascal" + } + ListElement { + name: "Khushboo" + } + ListElement { + name: "Alexandra" + } + ListElement { + name: "Eric" + } + } + selectMenu.delegate: StatusMenuItemDelegate { + statusPopupMenu: select + action: StatusMenuItem { + iconSettings.name: "filled-account" + text: name + onTriggered: { + selectedItem.text = name + } + } + } + selectedItemComponent: Item { + id: selectedItem + anchors.fill: parent + property string text: "" + + StatusBaseText { + text: selectedItem.text + anchors.centerIn: parent + color: Theme.palette.directColor1 + } + } + } +} + diff --git a/sandbox/main.qml b/sandbox/main.qml index 0ed4bd98..228c3284 100644 --- a/sandbox/main.qml +++ b/sandbox/main.qml @@ -153,6 +153,11 @@ StatusWindow { selected: page.sourceComponent == statusInputPageComponent onClicked: page.sourceComponent = statusInputPageComponent } + StatusNavigationListItem { + title: "StatusSelect" + selected: page.sourceComponent == statusSelectPageComponent + onClicked: page.sourceComponent = statusSelectPageComponent + } StatusListSectionHeadline { text: "StatusQ.Components" } StatusNavigationListItem { title: "List Items" @@ -256,6 +261,11 @@ StatusWindow { StatusInputPage {} } + Component { + id: statusSelectPageComponent + StatusSelectPage {} + } + Component { id: listItemsComponent ListItems {} diff --git a/src/StatusQ/Controls/StatusSelect.qml b/src/StatusQ/Controls/StatusSelect.qml new file mode 100644 index 00000000..61b298da --- /dev/null +++ b/src/StatusQ/Controls/StatusSelect.qml @@ -0,0 +1,175 @@ +import QtQuick 2.13 +import QtQuick.Controls 2.13 +import QtQuick.Layouts 1.13 +import QtGraphicalEffects 1.13 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Popups 0.1 + +Item { + enum MenuAlignment { + Left, + Right, + Center + } + property string label: "" + readonly property bool hasLabel: label !== "" + property color bgColor: Theme.palette.baseColor2 + readonly property int labelMargin: 7 + property var model + property alias selectMenu: selectMenu + property color bgColorHover: bgColor + property alias selectedItemComponent: selectedItemContainer.children + property int caretRightMargin: 16 + property alias select: inputRectangle + property int menuAlignment: StatusSelect.MenuAlignment.Right + property Item zeroItemsView: Item {} + property string validationError: "" + property alias validationErrorAlignment: validationErrorText.horizontalAlignment + property int validationErrorTopMargin: 11 + implicitWidth: 448 + + id: root + height: inputRectangle.height + (hasLabel ? inputLabel.height + labelMargin : 0) + (!!validationError ? (validationErrorText.height + validationErrorTopMargin) : 0) + + StatusBaseText { + id: inputLabel + visible: hasLabel + text: root.label + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.top: parent.top + anchors.topMargin: 0 + font.pixelSize: 15 + color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1 + } + + Rectangle { + property bool hovered: false + id: inputRectangle + height: 56 + color: hovered ? bgColorHover : bgColor + radius: 8 + anchors.top: root.hasLabel ? inputLabel.bottom : parent.top + anchors.topMargin: root.hasLabel ? root.labelMargin : 0 + anchors.right: parent.right + anchors.left: parent.left + border.width: !!validationError ? 1 : 0 + border.color: Theme.palette.dangerColor1 + + Item { + id: selectedItemContainer + anchors.fill: parent + } + + StatusIcon { + id: caret + anchors.right: parent.right + anchors.rightMargin: caretRightMargin + anchors.verticalCenter: parent.verticalCenter + width: 24 + height: 24 + icon: "chevron-down" + color: Theme.palette.baseColor1 + } + } + + Rectangle { + width: selectMenu.width + height: selectMenu.height + x: selectMenu.x + y: selectMenu.y + visible: selectMenu.opened + color: Theme.palette.statusSelect.menuItemBackgroundColor + radius: 8 + border.color: Theme.palette.baseColor2 + layer.enabled: true + layer.effect: DropShadow { + verticalOffset: 3 + radius: 8 + samples: 15 + fast: true + cached: true + color: Theme.palette.dropShadow + } + } + + StatusPopupMenu { + id: selectMenu + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + width: parent.width + clip: true + + Repeater { + id: menuItems + model: root.model + property int zeroItemsViewHeight + delegate: selectMenu.delegate + onItemAdded: { + root.zeroItemsView.visible = false + root.zeroItemsView.height = 0 + } + onItemRemoved: { + if (count === 0) { + root.zeroItemsView.visible = true + root.zeroItemsView.height = zeroItemsViewHeight + } + } + Component.onCompleted: { + zeroItemsViewHeight = root.zeroItemsView.height + root.zeroItemsView.visible = count === 0 + root.zeroItemsView.height = count !== 0 ? 0 : root.zeroItemsView.height + selectMenu.insertItem(0, root.zeroItemsView) + } + } + } + + StatusBaseText { + id: validationErrorText + visible: !!validationError + text: validationError + anchors.top: inputRectangle.bottom + anchors.topMargin: validationErrorTopMargin + anchors.right: parent.right + anchors.left: parent.left + font.pixelSize: 12 + height: visible ? implicitHeight : 0 + color: Theme.palette.dangerColor1 + horizontalAlignment: TextEdit.AlignRight + wrapMode: Text.WordWrap + } + + MouseArea { + id: mouseArea + anchors.fill: inputRectangle + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onEntered: { + inputRectangle.hovered = true + } + onExited: { + inputRectangle.hovered = false + } + onClicked: { + if (selectMenu.opened) { + selectMenu.close() + } else { + const rightOffset = inputRectangle.width - selectMenu.width + let offset = rightOffset + switch (root.menuAlignment) { + case StatusSelect.MenuAlignment.Left: + offset = 0 + break + case StatusSelect.MenuAlignment.Right: + offset = rightOffset + break + case StatusSelect.MenuAlignment.Center: + offset = rightOffset / 2 + } + selectMenu.popup(inputRectangle.x + offset, inputRectangle.y + inputRectangle.height + 8) + } + } + } +} + diff --git a/src/StatusQ/Controls/qmldir b/src/StatusQ/Controls/qmldir index 8c3aa572..8f837863 100644 --- a/src/StatusQ/Controls/qmldir +++ b/src/StatusQ/Controls/qmldir @@ -14,6 +14,7 @@ StatusSwitch 0.1 StatusSwitch.qml StatusRadioButton 0.1 StatusRadioButton.qml StatusCheckBox 0.1 StatusCheckBox.qml StatusSlider 0.1 StatusSlider.qml +StatusSelect 0.1 StatusSelect.qml StatusBaseInput 0.1 StatusBaseInput.qml StatusInput 0.1 StatusInput.qml StatusPickerButton 0.1 StatusPickerButton.qml diff --git a/src/StatusQ/Core/Theme/StatusDarkTheme.qml b/src/StatusQ/Core/Theme/StatusDarkTheme.qml index d868c90c..c27438b9 100644 --- a/src/StatusQ/Core/Theme/StatusDarkTheme.qml +++ b/src/StatusQ/Core/Theme/StatusDarkTheme.qml @@ -205,5 +205,10 @@ ThemePalette { property QtObject statusSwitchTab: QtObject { property color backgroundColor: baseColor3 } + + property QtObject statusSelect: QtObject { + property color menuItemBackgroundColor: baseColor2 + property color menuItemHoverBackgroundColor: directColor7 + } } diff --git a/src/StatusQ/Core/Theme/StatusLightTheme.qml b/src/StatusQ/Core/Theme/StatusLightTheme.qml index 2518f2c6..3abf4171 100644 --- a/src/StatusQ/Core/Theme/StatusLightTheme.qml +++ b/src/StatusQ/Core/Theme/StatusLightTheme.qml @@ -203,5 +203,10 @@ ThemePalette { property QtObject statusSwitchTab: QtObject { property color backgroundColor: white } + + property QtObject statusSelect: QtObject { + property color menuItemBackgroundColor: white + property color menuItemHoverBackgroundColor: baseColor2 + } } diff --git a/src/StatusQ/Core/Theme/ThemePalette.qml b/src/StatusQ/Core/Theme/ThemePalette.qml index 3571dd51..8fde020a 100644 --- a/src/StatusQ/Core/Theme/ThemePalette.qml +++ b/src/StatusQ/Core/Theme/ThemePalette.qml @@ -150,6 +150,11 @@ QtObject { property color backgroundColor } + property QtObject statusSelect: QtObject { + property color menuItemBackgroundColor + property color menuItemHoeverBackgroundColor + } + function alphaColor(color, alpha) { let actualColor = Qt.darker(color, 1) actualColor.a = alpha diff --git a/statusq.qrc b/statusq.qrc index b76e6a69..c9b0bad0 100644 --- a/statusq.qrc +++ b/statusq.qrc @@ -51,6 +51,7 @@ src/StatusQ/Controls/StatusSwitch.qml src/StatusQ/Controls/StatusCheckBox.qml src/StatusQ/Controls/StatusButton.qml + src/StatusQ/Controls/StatusSelect.qml src/StatusQ/Controls/StatusToolTip.qml src/StatusQ/Controls/Validators/StatusValidator.qml src/StatusQ/Controls/Validators/StatusMinLengthValidator.qml