Render shell-owned icons with theme masks

Use masked Kirigami icons with explicit theme colors for shell controls so the Shift icon theme renders reliably across light and dark surfaces. Replace the status-bar battery helper with theme icon names so battery glyphs also come from org.shift.icons.

Give the app-thumbnail close affordance a symbolic white X on a dark circular backing so it remains visible over previews.
This commit is contained in:
Marco Allegretti 2026-05-17 08:57:06 +02:00
parent e6f076ed54
commit a3173160e2
25 changed files with 192 additions and 8 deletions

View file

@ -60,6 +60,8 @@ Item {
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: width Layout.preferredHeight: width
source: "low-brightness" source: "low-brightness"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Slider { PC3.Slider {
@ -105,6 +107,8 @@ Item {
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: width Layout.preferredHeight: width
source: "high-brightness" source: "high-brightness"
isMask: true
color: Kirigami.Theme.textColor
} }
} }
} }

View file

@ -90,6 +90,10 @@ QuickSettingsDelegate {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: width implicitHeight: width
source: root.icon source: root.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
ColumnLayout { ColumnLayout {

View file

@ -86,6 +86,10 @@ QuickSettingsDelegate {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: width implicitHeight: width
source: root.icon source: root.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
} }
} }

View file

@ -142,6 +142,10 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: implicitWidth implicitHeight: implicitWidth
source: root.icon source: root.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
// Indicator bar // Indicator bar
@ -235,6 +239,10 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: implicitWidth implicitHeight: implicitWidth
source: "go-next-symbolic" source: "go-next-symbolic"
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
opacity: 0.5 opacity: 0.5
} }
} }

View file

@ -64,6 +64,10 @@ QQC2.Popup {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: implicitWidth implicitHeight: implicitWidth
source: "preferences-desktop-notification-symbolic" source: "preferences-desktop-notification-symbolic"
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
ColumnLayout { ColumnLayout {
@ -167,6 +171,10 @@ QQC2.Popup {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: implicitWidth implicitHeight: implicitWidth
source: model.iconName ? model.iconName : (model.icon ? model.icon : "") source: model.iconName ? model.iconName : (model.icon ? model.icon : "")
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
ColumnLayout { ColumnLayout {
@ -194,6 +202,10 @@ QQC2.Popup {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: implicitWidth implicitHeight: implicitWidth
source: "go-next-symbolic" source: "go-next-symbolic"
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
opacity: 0.45 opacity: 0.45
} }
} }

View file

@ -135,6 +135,8 @@ Controls.Drawer {
width: Kirigami.Units.iconSizes.large width: Kirigami.Units.iconSizes.large
height: width height: width
source: "view-preview" source: "view-preview"
isMask: true
color: Kirigami.Theme.textColor
visible: !walliePreview.visible visible: !walliePreview.visible
} }

View file

@ -146,6 +146,8 @@ Window {
transformOrigin: Item.Center transformOrigin: Item.Center
rotation: root.angle rotation: root.angle
source: root.iconSource source: root.iconSource
isMask: true
color: Kirigami.Theme.textColor
} }
} }

View file

@ -195,6 +195,8 @@ Window {
Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
source: "settings-configure" source: "settings-configure"
isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.Label { PlasmaComponents.Label {
text: i18n("Open audio settings") text: i18n("Open audio settings")

View file

@ -227,6 +227,10 @@ Item {
source: 'arrow-down' source: 'arrow-down'
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom anchors.bottom: parent.bottom

View file

@ -30,6 +30,10 @@ Item {
width: Math.min(parent.width, parent.height) width: Math.min(parent.width, parent.height)
height: width height: width
anchors.centerIn: parent anchors.centerIn: parent
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
Controls.ToolTip.text: model.toolTipTitle ? model.toolTipTitle : (model.title ? model.title : "") Controls.ToolTip.text: model.toolTipTitle ? model.toolTipTitle : (model.title ? model.title : "")

View file

@ -13,7 +13,6 @@ import org.kde.kirigami as Kirigami
import org.kde.kitemmodels import org.kde.kitemmodels
import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.workspace.components 2.0 as PW
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.battery // needed for charging state import org.kde.plasma.private.battery // needed for charging state
@ -21,6 +20,35 @@ import org.kde.plasma.private.battery // needed for charging state
RowLayout { RowLayout {
property real textPixelSize: Kirigami.Units.gridUnit * 0.6 property real textPixelSize: Kirigami.Units.gridUnit * 0.6
function batteryIconName(percent, charging) {
let name;
if (percent >= 95) {
name = "battery-100";
} else if (percent >= 85) {
name = "battery-090";
} else if (percent >= 75) {
name = "battery-080";
} else if (percent >= 65) {
name = "battery-070";
} else if (percent >= 55) {
name = "battery-060";
} else if (percent >= 45) {
name = "battery-050";
} else if (percent >= 35) {
name = "battery-040";
} else if (percent >= 25) {
name = "battery-030";
} else if (percent >= 15) {
name = "battery-020";
} else if (percent > 5) {
name = "battery-010";
} else {
name = "battery-000";
}
return charging ? name + "-charging" : name;
}
visible: MobileShell.BatteryInfo.isVisible visible: MobileShell.BatteryInfo.isVisible
ListView { ListView {
@ -51,16 +79,17 @@ RowLayout {
height: batteryRepeater.height height: batteryRepeater.height
PW.BatteryIcon { Kirigami.Icon {
id: battery id: battery
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
Layout.fillHeight: true Layout.fillHeight: true
width: batteryLabel.height width: batteryLabel.height
source: PluggedIn ? batteryIconName(Percent, ChargeState === BatteryControlModel.Charging) : "battery-missing"
hasBattery: PluggedIn Kirigami.Theme.inherit: false
percent: Percent Kirigami.Theme.colorSet: Kirigami.Theme.Window
pluggedIn: ChargeState === BatteryControlModel.Charging isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.Label { PlasmaComponents.Label {

View file

@ -16,6 +16,10 @@ Kirigami.Icon {
id: connectionIcon id: connectionIcon
source: MobileShell.BluetoothInfo.icon source: MobileShell.BluetoothInfo.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
visible: MobileShell.BluetoothInfo.isVisible visible: MobileShell.BluetoothInfo.isVisible
} }

View file

@ -33,6 +33,10 @@ Item {
anchors.fill: parent anchors.fill: parent
visible: !connectingIndicator.visible visible: !connectingIndicator.visible
source: connectionIcon.icon source: connectionIcon.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
} }
// Connecting indicator // Connecting indicator

View file

@ -33,6 +33,10 @@ Item {
height: parent.height height: parent.height
source: MobileShell.SignalStrengthInfo.icon source: MobileShell.SignalStrengthInfo.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
// don't show mobile indicator icon if the networkmanager one is already showing // don't show mobile indicator icon if the networkmanager one is already showing
visible: (!isInternetIndicatorMobileData || wirelessStatus.hotspotSSID.length !== 0) && MobileShell.SignalStrengthInfo.showIndicator visible: (!isInternetIndicatorMobileData || wirelessStatus.hotspotSSID.length !== 0) && MobileShell.SignalStrengthInfo.showIndicator

View file

@ -18,6 +18,10 @@ Kirigami.Icon {
id: paIcon id: paIcon
source: MobileShell.AudioInfo.icon source: MobileShell.AudioInfo.icon
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Window
isMask: true
color: Kirigami.Theme.textColor
visible: MobileShell.AudioInfo.isVisible visible: MobileShell.AudioInfo.isVisible
} }

View file

@ -50,11 +50,13 @@ Item {
anchors.rightMargin: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing anchors.rightMargin: Kirigami.Units.gridUnit + Kirigami.Units.largeSpacing
anchors.fill: parent anchors.fill: parent
Kirigami.SearchField { QQC2.TextField {
id: searchField id: searchField
onTextChanged: folio.ApplicationListSearchModel.setFilterFixedString(text) onTextChanged: folio.ApplicationListSearchModel.setFilterFixedString(text)
Layout.maximumWidth: Kirigami.Units.gridUnit * 30 Layout.maximumWidth: Kirigami.Units.gridUnit * 30
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
leftPadding: Kirigami.Units.iconSizes.small + Kirigami.Units.largeSpacing * 2
rightPadding: clearSearchArea.visible ? clearSearchArea.width + Kirigami.Units.largeSpacing : Kirigami.Units.largeSpacing
background: Rectangle { background: Rectangle {
radius: Kirigami.Units.cornerRadius radius: Kirigami.Units.cornerRadius
@ -76,6 +78,42 @@ Item {
font.weight: Font.Bold font.weight: Font.Bold
Kirigami.Icon {
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.largeSpacing
anchors.verticalCenter: parent.verticalCenter
width: Kirigami.Units.iconSizes.small
height: width
source: "search"
isMask: true
color: Kirigami.Theme.textColor
opacity: 0.65
}
MouseArea {
id: clearSearchArea
anchors.right: parent.right
anchors.rightMargin: Kirigami.Units.smallSpacing
anchors.verticalCenter: parent.verticalCenter
width: Kirigami.Units.iconSizes.smallMedium
height: width
visible: searchField.text.length > 0
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: searchField.clear()
Kirigami.Icon {
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.small
height: width
source: "window-close-symbolic"
isMask: true
color: Kirigami.Theme.textColor
opacity: clearSearchArea.containsMouse ? 0.9 : 0.65
}
}
Connections { Connections {
target: folio.HomeScreenState target: folio.HomeScreenState
function onViewStateChanged(): void { function onViewStateChanged(): void {

View file

@ -157,6 +157,8 @@ Rectangle {
height: width height: width
source: tile.catIcon source: tile.catIcon
active: tileArea.containsMouse || tile.isActive active: tileArea.containsMouse || tile.isActive
isMask: true
color: tile.isActive ? Kirigami.Theme.highlightColor : Kirigami.Theme.textColor
} }
PlasmaComponents.Label { PlasmaComponents.Label {

View file

@ -330,6 +330,8 @@ MouseArea {
height: width height: width
source: "start-here-shift" source: "start-here-shift"
active: homeMouseArea.containsMouse active: homeMouseArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
MouseArea { MouseArea {
@ -400,6 +402,8 @@ MouseArea {
height: width height: width
source: "user-desktop" source: "user-desktop"
active: desktopMouseArea.containsMouse || WindowPlugin.WindowUtil.isShowingDesktop active: desktopMouseArea.containsMouse || WindowPlugin.WindowUtil.isShowingDesktop
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.ToolTip { PC3.ToolTip {
@ -508,6 +512,8 @@ MouseArea {
height: width height: width
source: "activities" source: "activities"
active: overviewMouseArea.containsMouse active: overviewMouseArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
MouseArea { MouseArea {
@ -574,6 +580,8 @@ MouseArea {
height: width height: width
source: "search" source: "search"
active: searchMouseArea.containsMouse active: searchMouseArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.ToolTip { PC3.ToolTip {
@ -899,6 +907,8 @@ MouseArea {
height: width height: width
source: trashFilesModel.count > 0 ? "user-trash-full" : "user-trash" source: trashFilesModel.count > 0 ? "user-trash-full" : "user-trash"
active: trashMouseArea.containsMouse active: trashMouseArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.ToolTip { PC3.ToolTip {
@ -1595,7 +1605,16 @@ MouseArea {
Kirigami.Icon { Kirigami.Icon {
anchors.fill: parent anchors.fill: parent
source: "window-close" source: "window-close-symbolic"
isMask: true
color: "white"
}
Rectangle {
anchors.fill: parent
radius: width / 2
color: Qt.rgba(0, 0, 0, 0.55)
z: -1
} }
} }
} }

View file

@ -513,6 +513,8 @@ Item {
source: 'arrow-up' source: 'arrow-up'
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
isMask: true
color: Kirigami.Theme.textColor
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small

View file

@ -53,6 +53,8 @@ MouseArea {
height: width height: width
source: button.iconName source: button.iconName
active: button.containsMouse || button.checked active: button.containsMouse || button.checked
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.ToolTip { PC3.ToolTip {

View file

@ -599,6 +599,8 @@ Window {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
source: "system-run" source: "system-run"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Label { PC3.Label {
@ -1022,6 +1024,8 @@ Window {
source: "starred" source: "starred"
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
isMask: true
color: Kirigami.Theme.textColor
} }
} }
} }
@ -1036,6 +1040,8 @@ Window {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
source: "input-gaming" source: "input-gaming"
isMask: true
color: Kirigami.Theme.textColor
} }
Repeater { Repeater {

View file

@ -201,6 +201,8 @@ Window {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
isMask: true
color: "white"
} }
QQC2.Label { QQC2.Label {

View file

@ -319,6 +319,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: "low-brightness" source: "low-brightness"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Slider { PC3.Slider {
@ -380,6 +382,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: "high-brightness" source: "high-brightness"
isMask: true
color: Kirigami.Theme.textColor
} }
} }
} }
@ -403,6 +407,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: "audio-volume-low" source: "audio-volume-low"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Slider { PC3.Slider {
@ -462,6 +468,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.smallMedium implicitWidth: Kirigami.Units.iconSizes.smallMedium
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
source: "audio-volume-high" source: "audio-volume-high"
isMask: true
color: Kirigami.Theme.textColor
} }
} }
} }
@ -555,6 +563,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
source: "games-achievements" source: "games-achievements"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Label { PC3.Label {
text: GamingShell.GameModeControl.active text: GamingShell.GameModeControl.active
@ -659,6 +669,8 @@ Item {
implicitWidth: Kirigami.Units.iconSizes.small implicitWidth: Kirigami.Units.iconSizes.small
implicitHeight: Kirigami.Units.iconSizes.small implicitHeight: Kirigami.Units.iconSizes.small
source: "input-gaming" source: "input-gaming"
isMask: true
color: Kirigami.Theme.textColor
} }
PC3.Label { PC3.Label {

View file

@ -583,6 +583,8 @@ ContainmentItem {
height: width height: width
source: "window-close-symbolic" source: "window-close-symbolic"
active: closeArea.containsMouse active: closeArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.ToolTip { PlasmaComponents.ToolTip {
text: i18n("Close") text: i18n("Close")
@ -633,6 +635,8 @@ ContainmentItem {
height: width height: width
source: "system-lock-screen" source: "system-lock-screen"
active: lockArea.containsMouse active: lockArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.ToolTip { PlasmaComponents.ToolTip {
text: i18n("Lock Screen") text: i18n("Lock Screen")
@ -665,6 +669,8 @@ ContainmentItem {
height: width height: width
source: "system-reboot" source: "system-reboot"
active: rebootArea.containsMouse active: rebootArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.ToolTip { PlasmaComponents.ToolTip {
text: i18n("Restart") text: i18n("Restart")
@ -697,6 +703,8 @@ ContainmentItem {
height: width height: width
source: "system-shutdown" source: "system-shutdown"
active: shutdownArea.containsMouse active: shutdownArea.containsMouse
isMask: true
color: Kirigami.Theme.textColor
} }
PlasmaComponents.ToolTip { PlasmaComponents.ToolTip {
text: i18n("Shut Down") text: i18n("Shut Down")

View file

@ -27,6 +27,8 @@ PC3.ToolButton {
implicitHeight: Kirigami.Units.iconSizes.smallMedium implicitHeight: Kirigami.Units.iconSizes.smallMedium
Layout.fillHeight: true Layout.fillHeight: true
source: iconName source: iconName
isMask: true
color: Kirigami.Theme.textColor
} }
QQC2.Label { QQC2.Label {