156 lines
4.6 KiB
QML
156 lines
4.6 KiB
QML
import QtQuick
|
|
import qs.config
|
|
|
|
Item {
|
|
id: root
|
|
|
|
default property alias trailingData: trailing.data
|
|
property string icon: ""
|
|
property string label: ""
|
|
property string detail: ""
|
|
property string value: ""
|
|
property bool divider: true
|
|
property int controlWidth: 150
|
|
|
|
// Rows are inert by default. A row that represents a choice -- picking a
|
|
// timezone from a list, say -- opts into being clickable across its whole
|
|
// width, which is a much larger target than the trailing control alone.
|
|
property bool activatable: false
|
|
signal activated
|
|
|
|
// Keyboard and screen-reader reach, added without changing a single thing
|
|
// about how the row looks or behaves under the pointer.
|
|
//
|
|
// Only an activatable row becomes a Tab stop. A row that does nothing when
|
|
// clicked must not collect focus either -- Tab landing on inert text is how
|
|
// keyboard navigation stops being usable long before it stops working.
|
|
function activate(): void {
|
|
if (root.activatable)
|
|
root.activated();
|
|
}
|
|
|
|
width: parent ? parent.width : 620
|
|
implicitHeight: Math.max(56, copy.implicitHeight + 20)
|
|
|
|
activeFocusOnTab: root.activatable
|
|
|
|
Accessible.role: root.activatable ? Accessible.Button : Accessible.StaticText
|
|
Accessible.name: root.label
|
|
Accessible.description: root.detail
|
|
Accessible.focusable: root.activatable
|
|
Accessible.focused: root.activeFocus
|
|
Accessible.onPressAction: root.activate()
|
|
|
|
Keys.onReturnPressed: root.activate()
|
|
Keys.onEnterPressed: root.activate()
|
|
Keys.onSpacePressed: root.activate()
|
|
|
|
Text {
|
|
id: iconLabel
|
|
anchors.left: parent.left
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.icon === "" ? 0 : 28
|
|
visible: root.icon !== ""
|
|
text: root.icon
|
|
color: Theme.accent
|
|
font.family: Theme.fontMono
|
|
font.pixelSize: 17
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
|
|
Column {
|
|
id: copy
|
|
anchors.left: iconLabel.visible ? iconLabel.right : parent.left
|
|
anchors.leftMargin: iconLabel.visible ? 10 : 0
|
|
anchors.right: trailing.left
|
|
anchors.rightMargin: 16
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 3
|
|
|
|
Text {
|
|
width: parent.width
|
|
text: root.label
|
|
color: Theme.fg
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSize
|
|
font.weight: Font.Medium
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
visible: root.detail !== ""
|
|
text: root.detail
|
|
color: Theme.fgDim
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: trailing
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.controlWidth
|
|
height: 32
|
|
|
|
Text {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: root.value !== ""
|
|
text: root.value
|
|
color: Theme.fgDim
|
|
font.family: Theme.fontFamily
|
|
font.features: Theme.tabularFigures
|
|
font.pixelSize: Theme.fontSize
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors.left: copy.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
height: 1
|
|
visible: root.divider
|
|
color: Theme.alpha(Theme.fg, 0.065)
|
|
}
|
|
|
|
// Declared in this component's own body, so it is a child of the row rather
|
|
// than of the trailing slot that `trailingData` routes external children to.
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.bottomMargin: 1
|
|
radius: 8
|
|
z: -1
|
|
visible: root.activatable && rowHover.hovered
|
|
color: Theme.alpha(Theme.fg, 0.05)
|
|
border.width: 0
|
|
}
|
|
|
|
// The focus ring: the hover plate's geometry with a border added, so a row
|
|
// reached by Tab reads as the same target the pointer would have hit. Drawn
|
|
// only while this row holds keyboard focus, so nothing changes at rest.
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.bottomMargin: 1
|
|
radius: 8
|
|
z: -1
|
|
visible: root.activatable && root.activeFocus
|
|
color: Theme.alpha(Theme.fg, 0.05)
|
|
border.width: 2
|
|
border.color: Theme.accentSecondary
|
|
}
|
|
|
|
HoverHandler {
|
|
id: rowHover
|
|
enabled: root.activatable
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
|
|
TapHandler {
|
|
enabled: root.activatable
|
|
onTapped: root.activated()
|
|
}
|
|
}
|