mirror of https://github.com/status-im/StatusQ.git
feat(Layout): introduce StatusAppNavBar
This commit introduces a new `StatusAppNavBar` component that can be used to create a Status application's tab bar for dedicated tab sections such as chat, profile, wallet etc. The component is build in a way that it support declarative and imperative usage where necessary. In its most simple form, a `StatusAppNavBar` comes with a single tab button for the chat section. Such button has to be of type `StatusNavBarTabButton`: ```qml import StatusQ.Layout 0.1 StatusAppNavBar { navBarChatButton: StatusNavBarTabButton { icon.name: "chat" badge.value: 33 badge.visible: true tooltip.text: "Chat" } } ``` In addition, it's possible to specify a list of `StatusNavBarTabButton` for other sections of the application using the `navBarTabButtons` property: ```qml StatusAppNavBar { ... navBarTabButtons: [ StatusNavBarTabButton { icon.name: "wallet" tooltip.text: "Wallet" }, StatusNavBarTabButton { icon.name: "browser" tooltip.text: "Browser" }, StatusNavBarTabButton { icon.name: "status-update" tooltip.text: "Timeline" } ] } ``` Lastly, when desired to render tabs for Status community, which can grow in size, `StatusAppNavBar` exposes a list via the `navBarCommunityTabButtons` property that can have a `model` and a `delegate`. The `delegate` should also be a `StatusNavBarTabButton`: ```qml StatusAppNavBar { ... navBarCommunityTabButtons.model: someModel.communities navBarCommunityTabButtons.delegate: StatusNavBarTabButton { name: model.name tooltip.text: model.name anchors.horizontalCenter: parent.horizontalCenter } } ``` The amount of community tab buttons can grow as they need until their dedicated area becomes scrollable, at which point all `navBarTabButtons` will stick to the bottom of `StatusAppNavBar`. Closes #18
This commit is contained in:
parent
91b8d31754
commit
0dfd39afe2
|
@ -0,0 +1,259 @@
|
|||
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.Layout 0.1
|
||||
|
||||
GridLayout {
|
||||
columns: 6
|
||||
columnSpacing: 5
|
||||
rowSpacing: 5
|
||||
property ThemePalette theme
|
||||
|
||||
Button {
|
||||
id: btn
|
||||
text: "Append"
|
||||
onClicked: {
|
||||
buttons.append({
|
||||
name: "Test community",
|
||||
tooltipText: "Test Community"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
StatusAppNavBar {
|
||||
navBarChatButton: StatusNavBarTabButton {
|
||||
icon.name: "chat"
|
||||
badge.value: 33
|
||||
badge.visible: true
|
||||
tooltip.text: "Chat"
|
||||
}
|
||||
}
|
||||
|
||||
StatusAppNavBar {
|
||||
navBarChatButton: StatusNavBarTabButton {
|
||||
icon.name: "chat"
|
||||
badge.value: 33
|
||||
badge.visible: true
|
||||
tooltip.text: "Chat"
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.model: ListModel {
|
||||
id: buttons
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
|
||||
name: model.name
|
||||
tooltip.text: model.name
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
navBarTabButtons: [
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "wallet"
|
||||
tooltip.text: "Wallet"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "browser"
|
||||
tooltip.text: "Browser"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "status-update"
|
||||
tooltip.text: "Timeline"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "profile"
|
||||
badge.visible: true
|
||||
badge.anchors.rightMargin: 4
|
||||
badge.anchors.topMargin: 5
|
||||
badge.border.color: Theme.palette.statusAppNavBar.backgroundColor
|
||||
badge.border.width: 2
|
||||
|
||||
tooltip.text: "Profile"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusAppNavBar {
|
||||
navBarChatButton: StatusNavBarTabButton {
|
||||
icon.name: "chat"
|
||||
badge.value: 33
|
||||
badge.visible: true
|
||||
tooltip.text: "Chat"
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.model: ListModel {
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
|
||||
name: model.name
|
||||
tooltip.text: model.name
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
navBarTabButtons: [
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "wallet"
|
||||
tooltip.text: "Wallet"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "browser"
|
||||
tooltip.text: "Browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusAppNavBar {
|
||||
navBarChatButton: StatusNavBarTabButton {
|
||||
icon.name: "chat"
|
||||
badge.value: 33
|
||||
badge.visible: true
|
||||
tooltip.text: "Chat"
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.model: ListModel {
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
|
||||
name: model.name
|
||||
tooltip.text: model.name
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
navBarTabButtons: [
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "wallet"
|
||||
tooltip.text: "Wallet"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "browser"
|
||||
tooltip.text: "Browser"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "status-update"
|
||||
tooltip.text: "Timeline"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "profile"
|
||||
badge.visible: true
|
||||
badge.anchors.rightMargin: 4
|
||||
badge.anchors.topMargin: 5
|
||||
badge.border.color: Theme.palette.statusAppNavBar.backgroundColor
|
||||
badge.border.width: 2
|
||||
|
||||
tooltip.text: "Profile"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusAppNavBar {
|
||||
id: test
|
||||
navBarChatButton: StatusNavBarTabButton {
|
||||
icon.name: "chat"
|
||||
badge.value: 33
|
||||
badge.visible: true
|
||||
tooltip.text: "Chat"
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.model: ListModel {
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
ListElement {
|
||||
name: "Test community"
|
||||
tooltipText: "Test Community"
|
||||
}
|
||||
}
|
||||
|
||||
navBarCommunityTabButtons.delegate: StatusNavBarTabButton {
|
||||
name: model.name
|
||||
tooltip.text: model.name
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
navBarTabButtons: [
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "wallet"
|
||||
tooltip.text: "Wallet"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "browser"
|
||||
tooltip.text: "Browser"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "status-update"
|
||||
tooltip.text: "Timeline"
|
||||
},
|
||||
StatusNavBarTabButton {
|
||||
icon.name: "profile"
|
||||
badge.visible: true
|
||||
badge.anchors.rightMargin: 4
|
||||
badge.anchors.topMargin: 5
|
||||
badge.border.color: Theme.palette.statusAppNavBar.backgroundColor
|
||||
badge.border.width: 2
|
||||
|
||||
tooltip.text: "Profile"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,11 @@ Window {
|
|||
checkable: true
|
||||
text: "Controls"
|
||||
}
|
||||
Button {
|
||||
id: layoutTab
|
||||
checkable: true
|
||||
text: "Layout"
|
||||
}
|
||||
Button {
|
||||
id: otherTab
|
||||
checkable: true
|
||||
|
@ -87,6 +92,8 @@ Window {
|
|||
return iconsComponent;
|
||||
case controlsTab:
|
||||
return controlsComponent;
|
||||
case layoutTab:
|
||||
return layoutComponent;
|
||||
case otherTab:
|
||||
return othersComponent;
|
||||
case buttonsTab:
|
||||
|
@ -96,6 +103,7 @@ Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: switchRow
|
||||
scale: 0.8
|
||||
|
@ -169,6 +177,14 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: layoutComponent
|
||||
Layout {
|
||||
anchors.centerIn: parent
|
||||
theme: Theme.palette
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: othersComponent
|
||||
Others {
|
||||
|
|
|
@ -116,5 +116,9 @@ ThemePalette {
|
|||
miscColor9: getColor('moss2')
|
||||
miscColor10: getColor('brown3')
|
||||
miscColor11: getColor('yellow2')
|
||||
|
||||
property QtObject statusAppNavBar: QtObject {
|
||||
property color backgroundColor: baseColor5
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -116,5 +116,9 @@ ThemePalette {
|
|||
miscColor9: getColor('moss')
|
||||
miscColor10: getColor('brown')
|
||||
miscColor11: getColor('brown2')
|
||||
|
||||
property QtObject statusAppNavBar: QtObject {
|
||||
property color backgroundColor: baseColor4
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,10 @@ QtObject {
|
|||
property color miscColor10
|
||||
property color miscColor11
|
||||
|
||||
property QtObject statusAppNavBar: QtObject {
|
||||
property color backgroundColor
|
||||
}
|
||||
|
||||
function alphaColor(color, alpha) {
|
||||
let actualColor = Qt.darker(color, 1)
|
||||
actualColor.a = alpha
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Rectangle {
|
||||
id: statusAppNavBar
|
||||
|
||||
property StatusNavBarTabButton navBarChatButton
|
||||
property list<StatusNavBarTabButton> navBarTabButtons
|
||||
property alias navBarCommunityTabButtons: navBarCommunityTabButtons
|
||||
|
||||
property int navBarContentHeight: 0
|
||||
property int navBarContentHeightWithoutCommunityButtons: 0
|
||||
|
||||
width: 78
|
||||
implicitHeight: 600
|
||||
color: Theme.palette.statusAppNavBar.backgroundColor
|
||||
|
||||
Component.onCompleted: {
|
||||
navBarContentHeightWithoutCommunityButtons = (navBarChatButtonSlot.anchors.topMargin + navBarChatButtonSlot.height) +
|
||||
(separator.anchors.topMargin + separator.height) +
|
||||
(navBarTabButtonsSlot.height + navBarTabButtonsSlot.anchors.topMargin + navBarTabButtonsSlot.anchors.bottomMargin)
|
||||
navBarContentHeight = navBarContentHeightWithoutCommunityButtons +
|
||||
(navBarCommunityTabButtonsSlot.height + navBarScrollSection.anchors.topMargin)
|
||||
}
|
||||
|
||||
onNavBarChatButtonChanged: {
|
||||
if (!!navBarChatButton) {
|
||||
navBarChatButton.parent = navBarChatButtonSlot
|
||||
}
|
||||
}
|
||||
|
||||
onNavBarTabButtonsChanged: {
|
||||
if (navBarTabButtons.length) {
|
||||
for (let idx in navBarTabButtons) {
|
||||
navBarTabButtons[idx].parent = navBarTabButtonsSlot
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: navBarChatButtonSlot
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 48
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: statusAppNavBar.navBarChatButton.height
|
||||
width: statusAppNavBar.navBarChatButton.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: separatorTop
|
||||
height: 1
|
||||
width: 30
|
||||
color: Theme.palette.directColor7
|
||||
anchors.top: navBarChatButtonSlot.bottom
|
||||
anchors.topMargin: 16
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: separator.anchors.topMargin === 0
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: navBarScrollSection
|
||||
anchors.top: separatorTop.visible ? separatorTop.bottom : navBarChatButtonSlot.bottom
|
||||
anchors.topMargin: separatorTop.visible ? 0 : 12
|
||||
anchors.horizontalCenter: statusAppNavBar.horizontalCenter
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
clip: true
|
||||
|
||||
Component.onCompleted: {
|
||||
if (navBarContentHeight > statusAppNavBar.height) {
|
||||
height = statusAppNavBar.height -
|
||||
statusAppNavBar.navBarContentHeightWithoutCommunityButtons -
|
||||
(!!navBarTabButtonsSlot.anchors.bottom ? navBarTabButtonsSlot.anchors.bottomMargin : navBarTabButtonsSlot.anchors.topMargin)
|
||||
bottomPadding = 16
|
||||
topPadding = 16
|
||||
} else {
|
||||
height = navBarCommunityTabButtonsSlot.implicitHeight
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: navBarCommunityTabButtonsSlot
|
||||
width: navBarScrollSection.width
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 12
|
||||
|
||||
onImplicitHeightChanged: {
|
||||
statusAppNavBar.Component.onCompleted()
|
||||
navBarTabButtonsSlot.Component.onCompleted()
|
||||
navBarScrollSection.Component.onCompleted()
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: navBarCommunityTabButtons
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: separator
|
||||
height: 1
|
||||
width: 30
|
||||
color: Theme.palette.directColor7
|
||||
anchors.top: navBarCommunityTabButtons.model && navBarCommunityTabButtons.model.count > 0 ? navBarScrollSection.bottom : navBarChatButtonSlot.bottom
|
||||
anchors.topMargin: navBarScrollSection.height < navBarCommunityTabButtonsSlot.implicitHeight ? 0 : 16
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: navBarChatButton !== null && navBarTabButtons.length > 0
|
||||
}
|
||||
|
||||
Column {
|
||||
id: navBarTabButtonsSlot
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: 12
|
||||
|
||||
Component.onCompleted: {
|
||||
if (navBarContentHeight > statusAppNavBar.height) {
|
||||
anchors.top = undefined
|
||||
anchors.topMargin = 0
|
||||
anchors.bottom = statusAppNavBar.bottom
|
||||
anchors.bottomMargin = 32
|
||||
} else {
|
||||
anchors.bottom = undefined
|
||||
anchors.bottomMargin = 0
|
||||
anchors.top = separator.visible ? separator.bottom : parent.top
|
||||
anchors.topMargin = separator.visible ? 16 : navBarChatButtonSlot.anchors.topMargin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
module StatusQ.Layout
|
||||
|
||||
StatusAppNavBar 0.1 StatusAppNavBar.qml
|
||||
|
||||
|
Loading…
Reference in New Issue