Early Progress of SettingsWindow
This commit is contained in:
parent
5543b58c3c
commit
dc621647d7
14 changed files with 499 additions and 4 deletions
|
|
@ -6,10 +6,6 @@ import Quickshell.Wayland
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
import qs.Widgets
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
An experiment/demo panel to tweaks widgets
|
|
||||||
*/
|
|
||||||
NLoader {
|
NLoader {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
|
|
||||||
179
Modules/Settings/SettingsWindow.qml
Normal file
179
Modules/Settings/SettingsWindow.qml
Normal file
|
|
@ -0,0 +1,179 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Wayland
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
import "Tabs" as Tabs
|
||||||
|
|
||||||
|
NLoader {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
content: Component {
|
||||||
|
NPanel {
|
||||||
|
id: settingsPanel
|
||||||
|
|
||||||
|
readonly property real scaling: Scaling.scale(screen)
|
||||||
|
// Single source of truth for tabs
|
||||||
|
// Each tab points to a QML file path. The content stack simply loads the file via Loader.source.
|
||||||
|
property var tabsModel: [
|
||||||
|
{ icon: "tune", label: "General", source: "Tabs/General.qml" },
|
||||||
|
{ icon: "web_asset", label: "Bar", source: "Tabs/Bar.qml" },
|
||||||
|
{ icon: "schedule", label: "Time & Weather", source: "Tabs/TimeWeather.qml" },
|
||||||
|
{ icon: "videocam", label: "Screen Recorder", source: "Tabs/ScreenRecorder.qml" },
|
||||||
|
{ icon: "wifi", label: "Network", source: "Tabs/Network.qml" },
|
||||||
|
{ icon: "monitor", label: "Display", source: "Tabs/Display.qml" },
|
||||||
|
{ icon: "image", label: "Wallpaper", source: "Tabs/Wallpaper.qml" },
|
||||||
|
{ icon: "more_horiz", label: "Misc", source: "Tabs/Misc.qml" },
|
||||||
|
{ icon: "info", label: "About", source: "Tabs/About.qml" }
|
||||||
|
]
|
||||||
|
|
||||||
|
// Always default to the first tab (General) when the panel becomes visible
|
||||||
|
onVisibleChanged: function () {
|
||||||
|
if (visible) {
|
||||||
|
Qt.callLater(function () {
|
||||||
|
if (typeof stack !== 'undefined' && stack) {
|
||||||
|
stack.currentIndex = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure panel shows itself once created
|
||||||
|
Component.onCompleted: show()
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: bgRect
|
||||||
|
color: Colors.backgroundPrimary
|
||||||
|
radius: Style.radiusLarge * scaling
|
||||||
|
border.color: Colors.backgroundTertiary
|
||||||
|
border.width: Math.max(1, Style.borderMedium * scaling)
|
||||||
|
layer.enabled: true
|
||||||
|
width: 1040 * scaling
|
||||||
|
height: 640 * scaling
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
// Prevent closing when clicking in the panel bg
|
||||||
|
MouseArea { anchors.fill: parent }
|
||||||
|
|
||||||
|
|
||||||
|
// Main two-pane layout
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.marginLarge * scaling
|
||||||
|
spacing: Style.marginLarge * scaling
|
||||||
|
|
||||||
|
// Sidebar
|
||||||
|
Rectangle {
|
||||||
|
id: sidebar
|
||||||
|
Layout.preferredWidth: 260 * scaling
|
||||||
|
Layout.fillHeight: true
|
||||||
|
radius: Style.radiusMedium * scaling
|
||||||
|
color: Colors.backgroundSecondary
|
||||||
|
border.color: Colors.outline
|
||||||
|
border.width: Math.max(1, Style.borderThin * scaling)
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.marginSmall * scaling
|
||||||
|
spacing: Style.marginSmall * scaling
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: sections
|
||||||
|
model: settingsPanel.tabsModel
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
readonly property bool selected: index === stack.currentIndex
|
||||||
|
Layout.fillWidth: true
|
||||||
|
height: 44 * scaling
|
||||||
|
radius: Style.radiusSmall * scaling
|
||||||
|
color: selected ? Colors.highlight : "transparent"
|
||||||
|
border.color: Colors.outline
|
||||||
|
border.width: Math.max(1, Style.borderThin * scaling)
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Style.marginMedium * scaling
|
||||||
|
anchors.rightMargin: Style.marginMedium * scaling
|
||||||
|
spacing: Style.marginSmall * scaling
|
||||||
|
NText {
|
||||||
|
text: modelData.icon
|
||||||
|
font.family: "Material Symbols Outlined"
|
||||||
|
font.variableAxes: { "wght": (Font.Normal + Font.Bold) / 2.0 }
|
||||||
|
color: selected ? Colors.onAccent : Colors.textSecondary
|
||||||
|
}
|
||||||
|
NText { text: modelData.label; color: selected ? Colors.onAccent : Colors.textPrimary; Layout.fillWidth: true }
|
||||||
|
}
|
||||||
|
MouseArea { anchors.fill: parent; onClicked: stack.currentIndex = index }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Content
|
||||||
|
Rectangle {
|
||||||
|
id: contentPane
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
radius: Style.radiusMedium * scaling
|
||||||
|
color: Colors.surface
|
||||||
|
border.color: Colors.outline
|
||||||
|
border.width: Math.max(1, Style.borderThin * scaling)
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
// Content layout: header + divider + pages
|
||||||
|
ColumnLayout {
|
||||||
|
id: contentLayout
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: Style.marginLarge * scaling
|
||||||
|
spacing: Style.marginSmall * scaling
|
||||||
|
|
||||||
|
// Header row
|
||||||
|
RowLayout {
|
||||||
|
id: headerRow
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Style.marginSmall * scaling
|
||||||
|
NText {
|
||||||
|
text: settingsPanel.tabsModel[stack.currentIndex].label
|
||||||
|
font.weight: Style.fontWeightBold
|
||||||
|
color: Colors.textPrimary
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
NIconButton {
|
||||||
|
id: demoPanelToggle
|
||||||
|
icon: "close"
|
||||||
|
tooltipText: "Open demo panel"
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
onClicked: function () { settingsWindow.isLoaded = !settingsWindow.isLoaded }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider { Layout.fillWidth: true }
|
||||||
|
|
||||||
|
// Stacked pages
|
||||||
|
StackLayout {
|
||||||
|
id: stack
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.fillHeight: true
|
||||||
|
currentIndex: 0
|
||||||
|
Component.onCompleted: currentIndex = 0
|
||||||
|
|
||||||
|
// Pages generated from tabsModel
|
||||||
|
Repeater {
|
||||||
|
model: settingsPanel.tabsModel
|
||||||
|
delegate: Loader {
|
||||||
|
active: index === stack.currentIndex
|
||||||
|
visible: active
|
||||||
|
source: modelData.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/About.qml
Normal file
18
Modules/Settings/Tabs/About.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "About"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
19
Modules/Settings/Tabs/Bar.qml
Normal file
19
Modules/Settings/Tabs/Bar.qml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
// Optional scaling prop to match other tabs
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Bar"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/Display.qml
Normal file
18
Modules/Settings/Tabs/Display.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Display"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
89
Modules/Settings/Tabs/General.qml
Normal file
89
Modules/Settings/Tabs/General.qml
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: generalPage
|
||||||
|
|
||||||
|
// Public API
|
||||||
|
// Scaling factor provided by the parent settings window
|
||||||
|
property real scaling: 1
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
implicitWidth: parent ? parent.width : 0
|
||||||
|
implicitHeight: parent ? parent.height : 0
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 0
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
|
||||||
|
// Profile section
|
||||||
|
NText { text: "Profile"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
|
||||||
|
// Avatar preview
|
||||||
|
Rectangle {
|
||||||
|
width: 40 * scaling
|
||||||
|
height: 40 * scaling
|
||||||
|
radius: 20 * scaling
|
||||||
|
color: Colors.surfaceVariant
|
||||||
|
border.color: Colors.outline
|
||||||
|
border.width: Math.max(1, Style.borderThin * scaling)
|
||||||
|
Image {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 2 * scaling
|
||||||
|
source: Settings.data.general.avatarImage
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
asynchronous: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
spacing: 2 * scaling
|
||||||
|
NText { text: "Profile Image"; color: Colors.textPrimary; font.weight: Style.fontWeightBold }
|
||||||
|
NText { text: "Your profile picture displayed in various places throughout the shell"; color: Colors.textSecondary }
|
||||||
|
NTextBox {
|
||||||
|
text: Settings.data.general.avatarImage
|
||||||
|
placeholderText: "/home/user/.face"
|
||||||
|
Layout.fillWidth: true
|
||||||
|
onEditingFinished: Settings.data.general.avatarImage = text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NDivider { Layout.fillWidth: true; Layout.topMargin: Style.marginSmall * scaling; Layout.bottomMargin: Style.marginSmall * scaling }
|
||||||
|
|
||||||
|
// UI section
|
||||||
|
NText { text: "User Interface"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Show Corners"
|
||||||
|
description: "Display rounded corners on the edge of the screen"
|
||||||
|
value: Settings.data.general.showScreenCorners
|
||||||
|
onToggled: function (v) { Settings.data.general.showScreenCorners = v }
|
||||||
|
}
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Show Dock"
|
||||||
|
description: "Display a dock at the bottom of the screen for quick access to applications"
|
||||||
|
value: Settings.data.general.showDock
|
||||||
|
onToggled: function (v) { Settings.data.general.showDock = v }
|
||||||
|
}
|
||||||
|
|
||||||
|
NToggle {
|
||||||
|
label: "Dim Desktop"
|
||||||
|
description: "Dim the desktop when panels or menus are open"
|
||||||
|
value: Settings.data.general.dimDesktop
|
||||||
|
onToggled: function (v) { Settings.data.general.dimDesktop = v }
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/Misc.qml
Normal file
18
Modules/Settings/Tabs/Misc.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Misc"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/Network.qml
Normal file
18
Modules/Settings/Tabs/Network.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Network"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/ScreenRecorder.qml
Normal file
18
Modules/Settings/Tabs/ScreenRecorder.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Screen Recorder"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/TimeWeather.qml
Normal file
18
Modules/Settings/Tabs/TimeWeather.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Time & Weather"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
18
Modules/Settings/Tabs/Wallpaper.qml
Normal file
18
Modules/Settings/Tabs/Wallpaper.qml
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
import qs.Widgets
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property real scaling: 1
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
spacing: Style.marginMedium * scaling
|
||||||
|
NText { text: "Wallpaper"; font.weight: Style.fontWeightBold; color: Colors.accentSecondary }
|
||||||
|
NText { text: "Coming soon"; color: Colors.textSecondary }
|
||||||
|
Item { Layout.fillHeight: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -10,6 +10,8 @@ NBox {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
readonly property real scaling: Scaling.scale(screen)
|
readonly property real scaling: Scaling.scale(screen)
|
||||||
|
// Hold a single instance of the Settings window (root is NLoader)
|
||||||
|
property var settingsWindow: null
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
// Height driven by content
|
// Height driven by content
|
||||||
|
|
@ -71,6 +73,23 @@ NBox {
|
||||||
NIconButton {
|
NIconButton {
|
||||||
icon: "settings"
|
icon: "settings"
|
||||||
sizeMultiplier: 0.9
|
sizeMultiplier: 0.9
|
||||||
|
onClicked: function () {
|
||||||
|
if (!root.settingsWindow) {
|
||||||
|
const comp = Qt.createComponent("../Settings/SettingsWindow.qml")
|
||||||
|
if (comp.status === Component.Ready) {
|
||||||
|
root.settingsWindow = comp.createObject(root)
|
||||||
|
} else {
|
||||||
|
comp.statusChanged.connect(function () {
|
||||||
|
if (comp.status === Component.Ready) {
|
||||||
|
root.settingsWindow = comp.createObject(root)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (root.settingsWindow) {
|
||||||
|
root.settingsWindow.isLoaded = !root.settingsWindow.isLoaded
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
NIconButton {
|
NIconButton {
|
||||||
icon: "power_settings_new"
|
icon: "power_settings_new"
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ Singleton {
|
||||||
property string avatarImage: Quickshell.env("HOME") + "/.face"
|
property string avatarImage: Quickshell.env("HOME") + "/.face"
|
||||||
property bool dimDesktop: true
|
property bool dimDesktop: true
|
||||||
property bool showScreenCorners: false
|
property bool showScreenCorners: false
|
||||||
|
property bool showDock: false
|
||||||
}
|
}
|
||||||
|
|
||||||
// location
|
// location
|
||||||
|
|
|
||||||
66
Widgets/NTextBox.qml
Normal file
66
Widgets/NTextBox.qml
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Services
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property real scaling: Scaling.scale(screen)
|
||||||
|
|
||||||
|
// API
|
||||||
|
property alias text: input.text
|
||||||
|
property alias placeholderText: input.placeholderText
|
||||||
|
property bool readOnly: false
|
||||||
|
property bool enabled: true
|
||||||
|
property var onEditingFinished: function () {}
|
||||||
|
property var onTextChanged: function (value) {}
|
||||||
|
|
||||||
|
// Sizing
|
||||||
|
implicitHeight: Style.baseWidgetSize * 1.25 * scaling
|
||||||
|
implicitWidth: 320 * scaling
|
||||||
|
|
||||||
|
// Container
|
||||||
|
Rectangle {
|
||||||
|
id: frame
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: Style.radiusMedium * scaling
|
||||||
|
color: Colors.surfaceVariant
|
||||||
|
border.color: Colors.outline
|
||||||
|
border.width: Math.max(1, Style.borderThin * scaling)
|
||||||
|
|
||||||
|
// Focus ring
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
radius: frame.radius
|
||||||
|
color: "transparent"
|
||||||
|
border.color: input.activeFocus ? Colors.accentPrimary : "transparent"
|
||||||
|
border.width: input.activeFocus ? Math.max(1, Style.borderMedium * scaling) : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: Style.marginMedium * scaling
|
||||||
|
anchors.rightMargin: Style.marginMedium * scaling
|
||||||
|
spacing: Style.marginSmall * scaling
|
||||||
|
|
||||||
|
// Optional leading icon slot in the future
|
||||||
|
// Item { Layout.preferredWidth: 0 }
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: input
|
||||||
|
Layout.fillWidth: true
|
||||||
|
echoMode: TextInput.Normal
|
||||||
|
readOnly: root.readOnly
|
||||||
|
enabled: root.enabled
|
||||||
|
color: Colors.textPrimary
|
||||||
|
placeholderTextColor: Colors.textSecondary
|
||||||
|
background: null
|
||||||
|
font.pointSize: Colors.fontSizeSmall * scaling
|
||||||
|
onEditingFinished: root.onEditingFinished()
|
||||||
|
onTextChanged: root.onTextChanged(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue