Skip to content

Conversation

@micieslak
Copy link
Member

@micieslak micieslak commented Nov 20, 2025

What does the PR do

Re-implements Theme from stateful singleton to attached property object, with dynamically propagated properties through the visual objects tree.

It consists of following elements:

  • Theme - attached property type, holds state (padding, font size offset, style), which is propagated within the objects tree.
  • StatusColors - singleton, stateless, holds fixed colors definitions
  • ThemePalette <- non-mutable, not creatable component served by Theme, defining colors. We have two instances for dark/light styles
  • ThemeUtils - singleton, stateless utility methods and constants
  • Fonts - singleton, stateless, loads and serves fonts
  • Assets - singleton, stateless, access point for png/svg/emoji

By using attached property type, visual features like colors and sizes are no longer single global state, the same for all components within the app. It brings better flexibility when building responsive layouts for multiple platforms.

Affected areas

Entire QML codebase

Architecture compliance

Impact on end user

This change doesn't bring any changes visible to the end user.

How to test

Run the app and go through all possible views to detect incorrect colors, fonts, paddings, etc.

Risk

As there are many changes, there is a risk of introducing regressions related to visual appearance.

@micieslak micieslak requested review from a team, alexjba, caybro and noeliaSD as code owners November 20, 2025 10:27
@micieslak micieslak marked this pull request as draft November 20, 2025 10:27
@micieslak micieslak force-pushed the feat/theme-attached-type branch from 71355b5 to d6a2153 Compare November 20, 2025 10:34
@status-im-auto
Copy link
Member

status-im-auto commented Nov 20, 2025

Jenkins Builds

Click to see older builds (154)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ d6a2153 #2 2025-11-20 10:42:15 ~7 min tests/nim 📄log
✔️ d6a2153 #2 2025-11-20 10:44:30 ~9 min android/arm64 🤖apk 📲
✔️ d6a2153 #2 2025-11-20 10:49:24 ~14 min tests/ui 📄log
✔️ d6a2153 #2 2025-11-20 10:50:05 ~15 min ios/aarch64 📱ipa
✔️ d6a2153 #2 2025-11-20 10:50:22 ~15 min macos/aarch64 🍎dmg
✔️ d6a2153 #2 2025-11-20 10:52:47 ~17 min linux/x86_64 📦tgz
✔️ d6a2153 #2 2025-11-20 10:53:42 ~18 min macos/aarch64-nwaku 🍎dmg
✔️ d6a2153 #2 2025-11-20 10:57:35 ~22 min linux/x86_64-nwaku 📦tgz
✔️ d6a2153 pr19316 2025-11-20 11:08:48 ~15 min tests/e2e 📊rpt
✔️ d6a2153 #2 2025-11-20 11:10:34 ~35 min windows/x86_64 💿exe
✖️ d6a2153 PR19316 2025-11-20 11:38:10 ~27 min tests/e2e-windows 📊rpt
39086dbb #3 2025-11-20 17:22:25 ~7 min android/arm64 📄log
a21474e #4 2025-11-21 11:18:31 ~6 min android/arm64 📄log
✔️ a21474e #3 2025-11-21 11:19:16 ~6 min tests/nim 📄log
a21474e #3 2025-11-21 11:21:22 ~9 min linux/x86_64-nwaku 📄log
a21474e #3 2025-11-21 11:25:12 ~12 min macos/aarch64-nwaku 📄log
✔️ a21474e #3 2025-11-21 11:26:01 ~13 min macos/aarch64 🍎dmg
✔️ a21474e #3 2025-11-21 11:26:21 ~13 min tests/ui 📄log
✔️ a21474e #3 2025-11-21 11:28:35 ~16 min linux/x86_64 📦tgz
✔️ a21474e #3 2025-11-21 11:38:31 ~26 min ios/aarch64 📱ipa
✔️ a21474e #3 2025-11-21 11:39:09 ~26 min windows/x86_64 💿exe
✔️ a21474e pr19316 2025-11-21 11:44:30 ~15 min tests/e2e 📊rpt
✖️ a21474e PR19316 2025-11-21 12:06:45 ~27 min tests/e2e-windows 📊rpt
✔️ 35c8758d #5 2025-11-21 15:58:00 ~9 min android/arm64 🤖apk 📲
✔️ 42ca45b #4 2025-11-21 16:04:34 ~15 min tests/nim 📄log
✔️ 42ca45b #4 2025-11-21 16:04:40 ~15 min ios/aarch64 📱ipa
✔️ 42ca45b #4 2025-11-21 16:04:40 ~15 min macos/aarch64-nwaku 🍎dmg
✔️ 42ca45b #4 2025-11-21 16:09:50 ~20 min linux/x86_64 📦tgz
✔️ 42ca45b #4 2025-11-21 16:11:05 ~22 min linux/x86_64-nwaku 📦tgz
✔️ 42ca45b #4 2025-11-21 16:11:42 ~22 min tests/ui 📄log
✔️ 42ca45b #4 2025-11-21 16:12:12 ~23 min windows/x86_64 💿exe
✔️ 42ca45b pr19316 2025-11-21 16:27:34 ~17 min tests/e2e 📊rpt
✖️ 42ca45b PR19316 2025-11-21 16:42:24 ~30 min tests/e2e-windows 📊rpt
✔️ 1c5773db #6 2025-11-21 17:26:40 ~10 min android/arm64 🤖apk 📲
✔️ 9f3195d8 #7 2025-11-22 17:27:58 ~12 min android/arm64 🤖apk 📲
✔️ b11fba6b #8 2025-11-24 17:30:49 ~15 min android/arm64 🤖apk 📲
✔️ ad13304e #9 2025-11-25 11:43:08 ~10 min android/arm64 🤖apk 📲
c1b54b0 #5 2025-11-25 11:44:19 ~11 min macos/aarch64-nwaku 📄log
c1b54b0 #5 2025-11-25 11:44:33 ~11 min linux/x86_64-nwaku 📄log
✔️ c1b54b0 #5 2025-11-25 11:46:30 ~13 min tests/nim 📄log
✔️ c1b54b0 #5 2025-11-25 11:48:56 ~16 min macos/aarch64 🍎dmg
c1b54b0 #5 2025-11-25 11:55:45 ~22 min tests/ui 📄log
✔️ c1b54b0 #5 2025-11-25 11:55:55 ~23 min linux/x86_64 📦tgz
✔️ c1b54b0 #5 2025-11-25 12:01:14 ~28 min windows/x86_64 💿exe
✔️ c1b54b0 pr19316 2025-11-25 12:11:55 ~15 min tests/e2e 📊rpt
✖️ c1b54b0 PR19316 2025-11-25 12:20:06 ~18 min tests/e2e-windows 📊rpt
6cf7b25 #6 2025-11-25 12:09:44 ~6 min macos/aarch64-nwaku 📄log
✔️ 6cf7b25 #6 2025-11-25 12:11:18 ~8 min tests/nim 📄log
✔️ 6cf7b25 #6 2025-11-25 12:15:12 ~12 min macos/aarch64 🍎dmg
✖️ 6cf7b25 #6 2025-11-25 12:15:12 ~12 min ios/aarch64 📱ipa
6cf7b25 #6 2025-11-25 12:17:54 ~14 min tests/ui 📄log
✔️ 6cf7b25 #6 2025-11-25 12:18:42 ~15 min linux/x86_64 📦tgz
✔️ 6cf7b25 #6 2025-11-25 12:23:58 ~20 min windows/x86_64 💿exe
✔️ 6cf7b25 #6 2025-11-25 12:24:58 ~22 min linux/x86_64-nwaku 📦tgz
✔️ 6cf7b25 pr19316 2025-11-25 12:36:19 ~17 min tests/e2e 📊rpt
✖️ 6cf7b25 PR19316 2025-11-25 12:52:53 ~28 min tests/e2e-windows 📊rpt
✔️ 6137e074 #10 2025-11-25 12:11:33 ~8 min android/arm64 🤖apk 📲
cf4e110 #7 2025-11-25 15:40:53 ~5 min macos/aarch64-nwaku 📄log
✔️ cf4e110 #7 2025-11-25 15:41:45 ~6 min tests/nim 📄log
✖️ cf4e110 #7 2025-11-25 15:44:29 ~9 min ios/aarch64 📱ipa
✔️ cf4e110 #7 2025-11-25 15:46:16 ~11 min macos/aarch64 🍎dmg
✔️ cf4e110 #7 2025-11-25 15:50:15 ~15 min linux/x86_64 📦tgz
cf4e110 #7 2025-11-25 15:50:28 ~15 min tests/ui 📄log
✔️ cf4e110 #7 2025-11-25 15:51:37 ~16 min linux/x86_64-nwaku 📦tgz
✔️ cf4e110 #7 2025-11-25 16:00:32 ~25 min windows/x86_64 💿exe
✖️ cf4e110 pr19316 2025-11-25 16:08:06 ~17 min tests/e2e 📊rpt
✖️ cf4e110 PR19316 2025-11-25 16:26:41 ~26 min tests/e2e-windows 📊rpt
5309fdb #8 2025-11-25 20:14:50 ~6 min macos/aarch64-nwaku 📄log
✔️ 5309fdb #8 2025-11-25 20:15:07 ~6 min tests/nim 📄log
✔️ 5309fdb #8 2025-11-25 20:22:03 ~13 min ios/aarch64 📱ipa
✔️ 5309fdb #8 2025-11-25 20:23:10 ~14 min macos/aarch64 🍎dmg
✔️ 5309fdb #8 2025-11-25 20:24:13 ~15 min linux/x86_64 📦tgz
✔️ 5309fdb #8 2025-11-25 20:24:32 ~15 min tests/ui 📄log
✔️ 5309fdb #8 2025-11-25 20:25:43 ~17 min linux/x86_64-nwaku 📦tgz
✔️ 5309fdb #8 2025-11-25 20:31:59 ~23 min windows/x86_64 💿exe
✔️ 5309fdb pr19316 2025-11-25 20:41:09 ~16 min tests/e2e 📊rpt
✔️ 85e5f55 #9 2025-11-26 14:28:14 ~6 min tests/nim 📄log
85e5f55 #9 2025-11-26 14:28:18 ~6 min macos/aarch64-nwaku 📄log
✔️ 85e5f55 #9 2025-11-26 14:35:27 ~13 min tests/ui 📄log
✔️ 85e5f55 #9 2025-11-26 14:36:02 ~14 min ios/aarch64 📱ipa
✔️ 85e5f55 #9 2025-11-26 14:36:24 ~14 min macos/aarch64 🍎dmg
✔️ 85e5f55 #9 2025-11-26 14:37:15 ~15 min linux/x86_64-nwaku 📦tgz
✔️ 85e5f55 #9 2025-11-26 14:38:29 ~16 min linux/x86_64 📦tgz
✔️ 85e5f55 #9 2025-11-26 14:46:05 ~24 min windows/x86_64 💿exe
✔️ 85e5f55 pr19316 2025-11-26 14:54:36 ~16 min tests/e2e 📊rpt
✖️ 85e5f55 PR19316 2025-11-26 15:15:15 ~29 min tests/e2e-windows 📊rpt
012c3f1 #10 2025-11-28 13:19:02 ~5 min linux/x86_64-nwaku 📄log
✔️ 012c3f1 #10 2025-11-28 13:20:12 ~7 min tests/nim 📄log
012c3f1 #10 2025-11-28 13:21:02 ~7 min macos/aarch64-nwaku 📄log
012c3f1 #10 2025-11-28 13:21:06 ~7 min macos/aarch64 📄log
✔️ 012c3f1 #14 2025-11-28 13:22:50 ~9 min android/arm64 🤖apk 📲
✔️ 012c3f1 #10 2025-11-28 13:27:59 ~14 min tests/ui 📄log
✔️ 012c3f1 #10 2025-11-28 13:29:27 ~16 min linux/x86_64 📦tgz
✔️ 012c3f1 #10 2025-11-28 13:31:00 ~17 min ios/aarch64 📱ipa
✔️ 012c3f1 #10 2025-11-28 13:42:10 ~28 min windows/x86_64 💿exe
✔️ 012c3f1 pr19316 2025-11-28 13:47:14 ~17 min tests/e2e 📊rpt
✖️ 012c3f1 PR19316 2025-11-28 14:06:47 ~24 min tests/e2e-windows 📊rpt
✔️ 184d157 #11 2025-12-01 14:08:33 ~8 min tests/nim 📄log
184d157 #11 2025-12-01 14:09:24 ~9 min macos/aarch64-nwaku 📄log
184d157 #11 2025-12-01 14:13:51 ~13 min tests/ui 📄log
✔️ 184d157 #11 2025-12-01 14:15:55 ~15 min macos/aarch64 🍎dmg
✔️ 184d157 #11 2025-12-01 14:16:49 ~16 min linux/x86_64 📦tgz
✔️ 184d157 #11 2025-12-01 14:17:55 ~17 min linux/x86_64-nwaku 📦tgz
✔️ 184d157 #11 2025-12-01 14:17:58 ~17 min ios/aarch64 📱ipa
✔️ 184d157 #11 2025-12-01 14:27:53 ~27 min windows/x86_64 💿exe
✖️ 184d157 pr19316 2025-12-01 14:32:56 ~16 min tests/e2e 📊rpt
✖️ 184d157 PR19316 2025-12-01 14:55:50 ~27 min tests/e2e-windows 📊rpt
✔️ 6b85b7ae #15 2025-12-01 14:10:15 ~10 min android/arm64 🤖apk 📲
✔️ c79517d #12 2025-12-01 18:21:07 ~8 min tests/nim 📄log
✔️ c79517d #16 2025-12-01 18:21:43 ~8 min android/arm64 🤖apk 📲
c79517d #12 2025-12-01 18:21:53 ~8 min macos/aarch64-nwaku 📄log
c79517d #12 2025-12-01 18:21:56 ~8 min macos/aarch64 📄log
c79517d #12 2025-12-01 18:26:46 ~13 min tests/ui 📄log
✔️ c79517d #12 2025-12-01 18:30:15 ~17 min linux/x86_64 📦tgz
✔️ c79517d #12 2025-12-01 18:32:45 ~19 min ios/aarch64 📱ipa
✔️ c79517d #12 2025-12-01 18:35:17 ~22 min linux/x86_64-nwaku 📦tgz
✔️ c79517d #12 2025-12-01 18:43:28 ~30 min windows/x86_64 💿exe
✔️ c79517d pr19316 2025-12-01 18:46:35 ~16 min tests/e2e 📊rpt
✔️ c79517d PR19316 2025-12-01 19:05:51 ~22 min tests/e2e-windows 📊rpt
✔️ 2f412cd #13 2025-12-02 12:41:35 ~8 min tests/nim 📄log
2f412cd #13 2025-12-02 12:43:01 ~9 min macos/aarch64 📄log
2f412cd #13 2025-12-02 12:43:01 ~9 min macos/aarch64-nwaku 📄log
✔️ 2f412cd #13 2025-12-02 12:48:13 ~14 min tests/ui 📄log
✔️ 2cb594df #17 2025-12-02 12:43:41 ~10 min android/arm64 🤖apk 📲
✔️ b16bc5d #14 2025-12-02 12:59:29 ~8 min tests/nim 📄log
✔️ b16bc5d #18 2025-12-02 13:01:15 ~10 min android/arm64 🤖apk 📲
✔️ b16bc5d #14 2025-12-02 13:03:27 ~12 min macos/aarch64 🍎dmg
✔️ b16bc5d #14 2025-12-02 13:10:35 ~20 min ios/aarch64 📱ipa
✔️ b16bc5d #14 2025-12-02 13:12:45 ~22 min linux/x86_64 📦tgz
✔️ b16bc5d #14 2025-12-02 13:14:08 ~23 min tests/ui 📄log
✔️ b16bc5d #14 2025-12-02 13:15:56 ~25 min linux/x86_64-nwaku 📦tgz
✔️ b16bc5d #14 2025-12-02 13:16:10 ~25 min macos/aarch64-nwaku 🍎dmg
✔️ b16bc5d #14 2025-12-02 13:24:10 ~33 min windows/x86_64 💿exe
✖️ b16bc5d pr19316 2025-12-02 13:29:53 ~17 min tests/e2e 📊rpt
✖️ b16bc5d PR19316 2025-12-02 13:46:59 ~22 min tests/e2e-windows 📊rpt
✔️ bd198c5 #15 2025-12-02 16:38:15 ~7 min tests/nim 📄log
bd198c5 #15 2025-12-02 16:40:14 ~9 min macos/aarch64 📄log
bd198c5 #15 2025-12-02 16:40:14 ~9 min macos/aarch64-nwaku 📄log
✔️ bd198c5 #15 2025-12-02 16:47:16 ~16 min tests/ui 📄log
✔️ bd198c5 #15 2025-12-02 16:47:56 ~17 min linux/x86_64 📦tgz
✔️ bd198c5 #15 2025-12-02 16:53:21 ~22 min ios/aarch64 📱ipa
✔️ bd198c5 #15 2025-12-02 16:54:01 ~23 min linux/x86_64-nwaku 📦tgz
✔️ bd198c5 #15 2025-12-02 17:02:35 ~32 min windows/x86_64 💿exe
✖️ bd198c5 pr19316 2025-12-02 17:23:05 ~35 min tests/e2e 📊rpt
✖️ bd198c5 PR19316 2025-12-02 17:29:15 ~26 min tests/e2e-windows 📊rpt
✔️ ebc85b0a #19 2025-12-02 16:40:03 ~9 min android/arm64 🤖apk 📲
✔️ 18f96cd6 #20 2025-12-02 17:39:12 ~23 min android/arm64 🤖apk 📲
d6a9bd3 #16 2025-12-02 23:26:19 ~6 min macos/aarch64 📄log
d6a9bd3 #16 2025-12-02 23:26:19 ~6 min macos/aarch64-nwaku 📄log
✖️ d6a9bd3 #16 2025-12-02 23:33:54 ~14 min ios/aarch64 📱ipa
✔️ d6a9bd3 #16 2025-12-02 23:42:07 ~22 min linux/x86_64-nwaku 📦tgz
✔️ d6a9bd3 #16 2025-12-02 23:47:32 ~27 min windows/x86_64 💿exe
✔️ d6a9bd3 PR19316 2025-12-03 00:09:55 ~22 min tests/e2e-windows 📊rpt
✔️ 7ba6ffa9 #21 2025-12-02 23:28:53 ~9 min android/arm64 🤖apk 📲
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ 9573a05d #22 2025-12-03 01:32:31 ~9 min android/arm64 🤖apk 📲
f1bfc61 #18 2025-12-03 01:39:13 ~5 min macos/aarch64 📄log
✔️ f1bfc61 #23 2025-12-03 01:43:03 ~9 min android/arm64 🤖apk 📲
f1bfc61 #18 2025-12-03 01:44:13 ~10 min macos/aarch64-nwaku 📄log
✖️ f1bfc61 #18 2025-12-03 01:44:43 ~10 min ios/aarch64 📱ipa
✔️ f1bfc61 #18 2025-12-03 01:56:09 ~22 min linux/x86_64-nwaku 📦tgz
✔️ f1bfc61 #18 2025-12-03 02:08:03 ~34 min windows/x86_64 💿exe
✔️ f1bfc61 PR19316 2025-12-03 02:30:18 ~22 min tests/e2e-windows 📊rpt

@micieslak micieslak force-pushed the feat/theme-attached-type branch 3 times, most recently from c1b54b0 to 6cf7b25 Compare November 25, 2025 12:02
Copy link
Contributor

@alexjba alexjba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! I love it :beers
Let's get it merged quickly now that we have the release branch. It's probably a burden to maintain.

@micieslak micieslak force-pushed the feat/theme-attached-type branch 2 times, most recently from cf4e110 to 5309fdb Compare November 25, 2025 20:08
Copy link
Member

@caybro caybro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! Just some suggestions and minor things

{
QColor c = color;
if (alpha > 0.0 && alpha <= 1.0)
c.setAlphaF(alpha);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is going to work as expected... you usually want to switch to a HSL/HSV color space first

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old code:

    function setColorAlpha(color, alpha) {
        return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
    }

Copy link
Member Author

@micieslak micieslak Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is replacement for:

    function alphaColor(color, alpha) {
        let actualColor = Qt.darker(color, 1)
        actualColor.a = alpha
        return actualColor
    }

where the first line let actualColor = Qt.darker(color, 1) is just tricky conversion in case e.g. "red" color literal is provided. The version you quoted is from Utils, and it's not related with this code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah but that's why it does the darker first, it probably converts to HSL behind the scene

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's just to convert literals like "red" to color type.


Q_PROPERTY(Style style READ style WRITE setStyle RESET resetStyle
NOTIFY styleChanged)
Q_PROPERTY(const ThemePalette* palette READ palette
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could also expose other old properties (like fonts) in order to minimize the QML diff, wdyt?

Copy link
Member Author

@micieslak micieslak Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found it cleaner to keep things like Fonts as a separate, dedicated component responsible only for fonts. Especially that there is that FontLoader loading logic inside.

It creates bigger diff indeed, but it's just fully automatic replacement.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, bigger diff but also... it will be very hard to backport fixes now, e.g. to 2.36 branch but I agree that's just a temporary problem

readonly property alias monoFont: monoFont.font
readonly property alias codeFont: codeFont.font

FontLoader {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could (pre)load all these fonts from C++ too, and it would be faster imo :) And just expose the three baseFont/monoFont/codeFont properties

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant https://doc.qt.io/qt-6/qfontdatabase.html#addApplicationFont

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was to keep the attached type as small/simple as possible. Ideally only stuff that can benefit from propagation should be there. I found it more modular when keeping things like that separated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, this wouldn't be part of the propagation, just initialized and setup somewhere else, not in QML

@micieslak micieslak force-pushed the feat/theme-attached-type branch 6 times, most recently from b16bc5d to bd198c5 Compare December 2, 2025 16:30
Copy link
Contributor

@noeliaSD noeliaSD left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this implementation! The structure looks solid and the overall approach makes the theming system feel clean and easy to work with. I’ve left a couple of comments and suggestions, but everything is looking really good.

Next step for me will be to run a full test of the PR on both desktop and mobile to ensure everything behaves correctly across breakpoints.

readonly property real disabledOpacity: 0.3
readonly property real pressedOpacity: 0.7

function changeTheme(target: QtObject, theme:int) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could unify the nomenclature with setTheme instead.

Q_PROPERTY(int fontSizeOffset READ fontSizeOffset WRITE setFontSizeOffset
RESET resetFontSizeOffset NOTIFY fontSizeOffsetChanged)

Q_PROPERTY(int secondaryAdditionalTextSize
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we currently use these text properties across the codebase, but I’m increasingly unsure about their usefulness. The naming pattern is really hard to interpret. It's difficult to predict what something like secondaryAdditionalTextSize or tertiaryTextFontSize is supposed to represent. The hierarchy isn’t intuitive, and it makes the system harder to navigate and maintain.

I think we should evaluate whether this abstraction still serves us, or whether we need a more predictable, semantic text scale.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's result of long evolution of design, where new designs were requiring new values and they were put under new, creative names. Now it would be valuable to re-define smaller set of variants, with better naming, in Figma, as part of new design system. Then we can change it in code and refactor usages.

readonly property bool bottomSheet: !bottomSheetAllowed ? false:
d.windowHeight > d.windowWidth
&& d.windowWidth <= Theme.portraitBreakpoint.width
&& d.windowWidth <= ThemeUtils.portraitBreakpoint.width
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While implementing responsive components, I consistently felt that we’re missing a global property for this. Each component ends up checking the window width independently to determine whether it's in a compact/portrait mode, which leads to duplication and inconsistent logic.

Would it make sense to introduce a centralized property (something like portraitMode or a general compactMode flag) that all components can rely on? Having a single source of truth would make the responsive behavior more consistent across the entire app and simplify component logic.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it's good idea to consider using propagated property for that purpose. It will be easy to add to the Theme attached property and control from top-level main component, with possibility to adjust on any level if needed.


// paddings
qreal defaultPadding() const;
qreal defaultXlPadding() const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need these properties? Shouldn't be just internal?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was also my feeling that it should be internal. But now we are using those default values in some components. For some reason it was decided to have some values constant, with no respect to the padding size selected by the user.

}

function linkTypeColor(linkType) {
function linkTypeColor(linkType: int, palette: ThemePalette) : color {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe these colors should be also inside the palette?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, would be great to invent better solution for that, especially that the palette is passed there only for handling default color. However I'm reluctant about making Theme aware of some external enums like that link type in this case.


function colorForColorId(colorId) {
if (colorId < 0 || colorId >= Theme.palette.userCustomizationColors.length) {
function colorForColorId(palette, colorId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be part of StatusColors?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather not because StatusColors holds just fixed definitions. Here we want to fetch color from give palette.

}

function getHoveredColor(colorId) {
function getHoveredColor(palette, colorId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.. shouldn't this be part of StatusColors instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because StatusColors holds just read-only constants. It also doesn't fit to ThemePalette as the colorId abstraction is not part of theme palette.

}

function getIdForColor(color){
function getIdForColor(palette, color){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one

}

function getColorForId(colorId) {
function getColorForId(palette, colorId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this one

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the functions changed here feel like they should belong to StatusColors instead. Conceptually, they align more with color-token handling than with the responsibilities of this module.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that those things could be extracted to more focused ColorUtils, but shouldn't belong to StatusColors which is stateless singleton. Holding app-wise palette in a singleton is against the idea of the whole refactor, as that global mutable state is removed in this PR. Those functions are just "glue" between app logic, mapping concepts from both ends (like colorId and some colors from palette).

@micieslak micieslak force-pushed the feat/theme-attached-type branch 2 times, most recently from d6a9bd3 to e9ab1e6 Compare December 3, 2025 01:23
@micieslak micieslak force-pushed the feat/theme-attached-type branch from e9ab1e6 to f1bfc61 Compare December 3, 2025 01:33
@micieslak micieslak marked this pull request as ready for review December 3, 2025 01:37
@micieslak micieslak requested a review from a team as a code owner December 3, 2025 01:37
@micieslak micieslak requested review from friofry and saledjenic and removed request for a team December 3, 2025 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants