Restyle Quickshell settings inputs to match Omarchy aesthetic

Settings dialogs were rendering text/spin/combo controls with Qt's
default light style, which clashed with the dark Omarchy theme — black
text on dark fills, white dropdown popups, rounded corners, and a
pill-style toggle that didn't match the native StyleToggleRow switch.

- Style.qml: collapse all radius tokens to 0 so Noctalia-compat widgets
  inherit Omarchy's sharp-corner convention
- NToggle: rewrite to mirror the native 48x22 switch with accent fill
  and a sliding 16x16 thumb
- NComboBox: skin contentItem, indicator, popup, and delegate so the
  dropdown reads on dark themes
- NSpinBox: add a styled background, contentItem, and up/down indicators
- SettingsPanel calendar form + DynamicSettingsForm string field: drop
  default TextField chrome for the same translucent foreground fill used
  by WidgetCard, accent border on focus
This commit is contained in:
Jake Weaver
2026-05-15 16:46:56 -04:00
parent 37d6ae7f4b
commit ae70db3c53
6 changed files with 216 additions and 39 deletions
@@ -9,17 +9,18 @@ import "." as Commons
QtObject {
id: root
// Radii.
readonly property real radiusXXS: 1
readonly property real radiusXS: 2
readonly property real radiusS: 3
readonly property real radiusM: 4
readonly property real radiusL: 6
readonly property real radiusXL: 8
readonly property real iRadiusXS: 2
readonly property real iRadiusS: 3
readonly property real iRadiusM: 4
readonly property real iRadiusL: 6
// Radii. Omarchy uses sharp corners; all radius tokens collapse to 0 so
// Noctalia plugins inherit the same look as native widgets.
readonly property real radiusXXS: 0
readonly property real radiusXS: 0
readonly property real radiusS: 0
readonly property real radiusM: 0
readonly property real radiusL: 0
readonly property real radiusXL: 0
readonly property real iRadiusXS: 0
readonly property real iRadiusS: 0
readonly property real iRadiusM: 0
readonly property real iRadiusL: 0
// Margins / paddings. Noctalia uses two parallel scales for margins (one
// tighter, one looser); we map them to the same values.
@@ -17,6 +17,11 @@ ComboBox {
valueRole: "key"
font.family: "JetBrainsMono Nerd Font"
font.pixelSize: Style.fontSizeS
implicitHeight: 32
leftPadding: 10
rightPadding: 28
topPadding: 4
bottomPadding: 4
function itemAt(index) {
if (index < 0) return null
@@ -55,10 +60,79 @@ ComboBox {
root.selected(key, item)
}
contentItem: Text {
text: root.displayText
color: Color.mOnSurface
font: root.font
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: Color.mSurfaceVariant
border.color: Color.mOutline
border.color: root.activeFocus ? Color.mPrimary : Color.mOutline
border.width: Style.borderS
radius: Style.radiusS
radius: 0
}
indicator: Text {
x: root.width - width - 10
y: (root.height - height) / 2
text: "▾"
color: Color.mOnSurfaceVariant
font.family: root.font.family
font.pixelSize: 11
}
delegate: ItemDelegate {
id: del
required property int index
required property var modelData
width: ListView.view ? ListView.view.width : root.width
height: 28
highlighted: root.highlightedIndex === del.index
contentItem: Text {
text: {
var m = del.modelData
if (m === null || m === undefined) return ""
if (root.textRole && m[root.textRole] !== undefined) return String(m[root.textRole])
return String(m)
}
color: Color.mOnSurface
font: root.font
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
color: del.highlighted || del.hovered
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.14)
: "transparent"
radius: 0
}
}
popup: Popup {
y: root.height
width: root.width
implicitHeight: Math.min(contentItem.implicitHeight + 2, 280)
padding: 1
background: Rectangle {
color: Color.mSurface
border.color: Color.mOutline
border.width: Style.borderS
radius: 0
}
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: root.popup.visible ? root.delegateModel : null
currentIndex: root.highlightedIndex
boundsBehavior: Flickable.StopAtBounds
ScrollIndicator.vertical: ScrollIndicator { }
}
}
}
@@ -7,4 +7,69 @@ SpinBox {
property string label: ""
font.family: "JetBrainsMono Nerd Font"
font.pixelSize: Style.fontSizeS
editable: true
implicitHeight: 32
leftPadding: 10
rightPadding: 24
topPadding: 4
bottomPadding: 4
background: Rectangle {
color: Color.mSurfaceVariant
border.color: root.activeFocus ? Color.mPrimary : Color.mOutline
border.width: Style.borderS
radius: Style.radiusS
}
contentItem: TextInput {
text: root.displayText
font: root.font
color: Color.mOnSurface
selectionColor: Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.35)
selectedTextColor: Color.mOnSurface
horizontalAlignment: Qt.AlignLeft
verticalAlignment: Qt.AlignVCenter
readOnly: !root.editable
validator: root.validator
inputMethodHints: Qt.ImhFormattedNumbersOnly
}
up.indicator: Rectangle {
x: root.mirrored ? 0 : root.width - width
width: 20
height: root.height / 2
color: root.up.pressed
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.16)
: root.up.hovered
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.08)
: "transparent"
radius: Style.radiusS
Text {
anchors.centerIn: parent
text: "▲"
font.family: root.font.family
font.pixelSize: 7
color: root.up.hovered ? Color.mOnSurface : Color.mOnSurfaceVariant
}
}
down.indicator: Rectangle {
x: root.mirrored ? 0 : root.width - width
y: root.height / 2
width: 20
height: root.height / 2
color: root.down.pressed
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.16)
: root.down.hovered
? Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.08)
: "transparent"
radius: Style.radiusS
Text {
anchors.centerIn: parent
text: "▼"
font.family: root.font.family
font.pixelSize: 7
color: root.down.hovered ? Color.mOnSurface : Color.mOnSurfaceVariant
}
}
}
@@ -18,21 +18,25 @@ Rectangle {
Rectangle {
id: indicator
width: 32
height: 18
width: 48
height: 22
anchors.verticalCenter: parent.verticalCenter
radius: height / 2
color: root.checked ? Color.mPrimary : Color.mSurfaceVariant
border.color: Color.mOutline
radius: 0
color: root.checked
? Color.mPrimary
: Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.10)
border.color: root.checked
? Color.mPrimary
: Qt.rgba(Color.mOnSurface.r, Color.mOnSurface.g, Color.mOnSurface.b, 0.4)
border.width: Style.borderS
Rectangle {
x: root.checked ? parent.width - width - 2 : 2
y: 2
width: parent.height - 4
height: parent.height - 4
radius: height / 2
color: Color.mOnSurface
width: 16
height: 16
radius: 0
anchors.verticalCenter: parent.verticalCenter
x: root.checked ? parent.width - width - 3 : 3
color: root.checked ? Color.mSurface : Color.mOnSurface
Behavior on x { NumberAnimation { duration: Style.animationFast } }
}
}
@@ -2600,18 +2600,40 @@ Item {
spacing: 8
width: parent ? parent.width : 0
component CalendarField: TextField {
id: calField
property string fieldKey: ""
font.family: root.fontFamily
font.pixelSize: 12
width: parent.width
color: root.foreground
selectionColor: Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b, 0.35)
selectedTextColor: root.foreground
placeholderTextColor: Qt.darker(root.foreground, 1.6)
leftPadding: 10
rightPadding: 10
topPadding: 7
bottomPadding: 7
onEditingFinished: if (fieldKey) calForm.fieldChanged(fieldKey, text)
background: Rectangle {
color: Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b,
calField.activeFocus ? 0.08 : 0.04)
border.color: calField.activeFocus
? Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b, 0.4)
: Qt.rgba(root.foreground.r, root.foreground.g, root.foreground.b, 0.18)
border.width: 1
}
}
Text {
text: "Horizontal format"
color: Qt.darker(root.foreground, 1.4)
font.family: root.fontFamily
font.pixelSize: 11
}
TextField {
CalendarField {
fieldKey: "format"
text: calForm.entry.format || "dddd HH:mm"
font.family: root.fontFamily
font.pixelSize: 12
width: parent.width
onEditingFinished: calForm.fieldChanged("format", text)
}
Text {
@@ -2620,12 +2642,9 @@ Item {
font.family: root.fontFamily
font.pixelSize: 11
}
TextField {
CalendarField {
fieldKey: "formatAlt"
text: calForm.entry.formatAlt || "dd MMMM 'W'ww yyyy"
font.family: root.fontFamily
font.pixelSize: 12
width: parent.width
onEditingFinished: calForm.fieldChanged("formatAlt", text)
}
Text {
@@ -2634,12 +2653,9 @@ Item {
font.family: root.fontFamily
font.pixelSize: 11
}
TextField {
CalendarField {
fieldKey: "verticalFormat"
text: calForm.entry.verticalFormat || "HH\n—\nmm"
font.family: root.fontFamily
font.pixelSize: 12
width: parent.width
onEditingFinished: calForm.fieldChanged("verticalFormat", text)
}
}
}
@@ -83,13 +83,30 @@ Column {
Component {
id: stringField
TextField {
id: stringControl
property string fieldKey: ""
property var field: ({})
width: parent.width
font.family: root.fontFamilyName
font.pixelSize: 12
color: root.foregroundColor
selectionColor: Qt.rgba(root.foregroundColor.r, root.foregroundColor.g, root.foregroundColor.b, 0.35)
selectedTextColor: root.foregroundColor
placeholderTextColor: Qt.darker(root.foregroundColor, 1.6)
leftPadding: 10
rightPadding: 10
topPadding: 7
bottomPadding: 7
text: root.currentValue(field) === undefined ? "" : String(root.currentValue(field))
onEditingFinished: if (fieldKey) root.fieldChanged(fieldKey, text)
background: Rectangle {
color: Qt.rgba(root.foregroundColor.r, root.foregroundColor.g, root.foregroundColor.b,
stringControl.activeFocus ? 0.08 : 0.04)
border.color: stringControl.activeFocus
? Qt.rgba(root.foregroundColor.r, root.foregroundColor.g, root.foregroundColor.b, 0.4)
: Qt.rgba(root.foregroundColor.r, root.foregroundColor.g, root.foregroundColor.b, 0.18)
border.width: 1
}
}
}