🎉 Introduce UI scale setting and save it in user profile

This commit is contained in:
Belén Albeza 2026-07-15 10:12:32 +02:00
parent bdc078d5ea
commit e2a7b7675b
6 changed files with 76 additions and 8 deletions

View File

@ -145,6 +145,8 @@
;; Show WASM renderer info label (hidden by default).
:render-wasm-info
:render-switch
;; Enables the UI scale setting (PoC: 1x / 1.25x)
:ui-scale
:hide-release-modal
:subscriptions
:subscriptions-old

View File

@ -18,6 +18,15 @@ $lh-115: 1.15;
$lh-133: 1.33;
$size-4: 1rem;
// UI scale: `--ui-scale` is driven from the user profile prop `:ui-scale`
// (see app.main.ui/app). Because DS tokens are `rem`-based, scaling the root
// font-size uniformly scales the whole UI. The viewport/rulers are excluded
// separately (they don't rely on this root font-size).
:root {
--ui-scale: 1;
font-size: calc(100% * var(--ui-scale));
}
body {
background-color: var(--color-background-primary);
color: var(--color-foreground-primary);

View File

@ -370,13 +370,21 @@
(mf/defc app
[]
(let [route (mf/deref refs/route)
edata (mf/deref refs/exception)
profile (mf/deref refs/profile)]
(let [route (mf/deref refs/route)
edata (mf/deref refs/exception)
profile (mf/deref refs/profile)
ui-scale (if (contains? cf/flags :ui-scale)
(or (-> profile :props :ui-scale) 1.0)
1.0)]
;; initialize themes
(theme/use-initialize profile)
;; Apply the UI scale by exposing it as the `--ui-scale` custom property
;; on the root element, which drives the root font-size (see base.scss).
(mf/with-effect [ui-scale]
(dom/set-css-property! (.-documentElement js/document) "--ui-scale" (str ui-scale)))
(dom/prevent-browser-gesture-navigation!)
[:& (mf/provider ctx/current-route) {:value route}

View File

@ -15,6 +15,7 @@
[app.main.router :as rt]
[app.main.store :as st]
[app.main.ui.components.forms :as fm]
[app.main.ui.ds.controls.select :refer [select*]]
[app.main.ui.ds.controls.switch :refer [switch*]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.main.ui.ds.foundations.typography :as t]
@ -115,10 +116,32 @@
:on-change handle-render-change}]]
[:> text* {:typography t/body-medium :class (stl/css :feedback)} [:a {:href "#" :on-click go-settings-feedback :class (stl/css :link)} (tr "dashboard.webgl-switch.feedback") [:> icon* {:icon-id "arrow-up-right" :size "s"}]]]]))
(mf/defc ui-scale-settings*
[{:keys [ui-scale]}]
(let [selected (if (= ui-scale 1.15) "1.15" "1")
handle-scale-change
(mf/use-fn
(fn [value]
(let [scale (if (= value "1.15") 1.15 1.0)]
(st/emit! (ev/event {::ev/name "change-ui-scale"
::ev/origin "settings"
:scale scale})
(du/update-profile-props {:ui-scale scale})
(ntf/success (tr "dashboard.ui-scale.updated"))))))]
[:section {:class (stl/css :ui-scale-container)}
[:header {:class (stl/css :ui-scale-header)}
[:> heading* {:class (stl/css :title) :level 2 :typography t/title-large} (tr "dashboard.ui-scale.title")]]
[:> text* {:class (stl/css :description) :typography t/body-medium} (tr "dashboard.ui-scale.description")]
[:> select* {:default-selected selected
:options [{:id "1" :label (tr "dashboard.ui-scale.1x")}
{:id "1.15" :label (tr "dashboard.ui-scale.115x")}]
:on-change handle-scale-change}]]))
(mf/defc options-page*
[]
(let [profile (mf/deref refs/profile)
renderer (or (-> profile :props :renderer) :svg)]
(let [profile (mf/deref refs/profile)
renderer (or (-> profile :props :renderer) :svg)
ui-scale (or (-> profile :props :ui-scale) 1.0)]
(mf/use-effect
#(dom/set-html-title (tr "title.settings.options")))
@ -128,4 +151,6 @@
[:h2 (tr "labels.settings")]
[:> options-form*]]
(when (contains? cf/flags :render-switch)
[:> webgl-settings* {:renderer renderer}])]]))
[:> webgl-settings* {:renderer renderer}])
(when (contains? cf/flags :ui-scale)
[:> ui-scale-settings* {:ui-scale ui-scale}])]]))

View File

@ -23,7 +23,7 @@
/* Copied from profile.scss .form-container, but without included nested
rules, since we want custom styles for it */
.webgl-container {
.webgl-container, .ui-scale-container {
display: grid;
grid-auto-rows: auto;
gap: var(--sp-s);
@ -34,13 +34,17 @@
color: var(--color-foreground-primary);
}
.webgl-header {
.webgl-header, .ui-scale-header {
display: flex;
flex-direction: row;
align-items: baseline;
gap: var(--sp-m);
}
.ui-scale-container {
padding-block-end: var(--sp-xxxl);
}
.description {
color: var(--color-foreground-secondary);
}

View File

@ -1328,6 +1328,26 @@ msgstr "No limits on creativity"
msgid "dashboard.upgrade-plan.penpot-free"
msgstr "Penpot Free"
#: src/app/main/ui/settings/options.cljs:135
msgid "dashboard.ui-scale.115x"
msgstr "1.15x (Medium)"
#: src/app/main/ui/settings/options.cljs:135
msgid "dashboard.ui-scale.1x"
msgstr "1x (Default)"
#: src/app/main/ui/settings/options.cljs:133
msgid "dashboard.ui-scale.description"
msgstr "Scale the Penpot interface. This does not affect the design canvas."
#: src/app/main/ui/settings/options.cljs:132
msgid "dashboard.ui-scale.title"
msgstr "UI scale"
#: src/app/main/ui/settings/options.cljs:129
msgid "dashboard.ui-scale.updated"
msgstr "UI scale was updated"
#, unused
msgid "dashboard.user-no-longer-belong-org"
msgstr "You are no longer a member of the organization %s"