Files
Panama/config/dot/quickshell/modules/settings/SettingRow.qml
T

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()
}
}