🐛 Fix color wrapper choppiness (#5655)

* ♻️ Remove unused state om tokens colorpicker ramp component

* 🐛 Fix color wrapper choppiness

*  Add performance related changes for colorpicker ramp selector

*  Add performance oriented changes to tokens ramp component

---------

Co-authored-by: Andrey Fedorov <oran9e.red@gmail.com>
This commit is contained in:
Andrey Antukh 2025-01-24 09:37:11 +01:00 committed by GitHub
parent cf25614afb
commit 32f0da7514
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 105 additions and 57 deletions

View file

@ -248,11 +248,12 @@
[[h s brightness]] [[h s brightness]]
(if (= s 0) (if (= s 0)
[brightness brightness brightness] [brightness brightness brightness]
(let [sextant (int (mth/floor (/ h 60))) (let [sextant (int (mth/floor (/ h 60)))
remainder (- (/ h 60) sextant) remainder (- (/ h 60) sextant)
val1 (int (* brightness (- 1 s))) brightness (d/nilv brightness 0)
val2 (int (* brightness (- 1 (* s remainder)))) val1 (int (* brightness (- 1 s)))
val3 (int (* brightness (- 1 (* s (- 1 remainder)))))] val2 (int (* brightness (- 1 (* s remainder))))
val3 (int (* brightness (- 1 (* s (- 1 remainder)))))]
(case sextant (case sextant
1 [val2 brightness val1] 1 [val2 brightness val1]
2 [val1 brightness val3] 2 [val1 brightness val3]

View file

@ -33,7 +33,7 @@
[app.main.ui.workspace.colorpicker.harmony :refer [harmony-selector]] [app.main.ui.workspace.colorpicker.harmony :refer [harmony-selector]]
[app.main.ui.workspace.colorpicker.hsva :refer [hsva-selector]] [app.main.ui.workspace.colorpicker.hsva :refer [hsva-selector]]
[app.main.ui.workspace.colorpicker.libraries :refer [libraries]] [app.main.ui.workspace.colorpicker.libraries :refer [libraries]]
[app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector*]]
[app.main.ui.workspace.colorpicker.shortcuts :as sc] [app.main.ui.workspace.colorpicker.shortcuts :as sc]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -346,7 +346,7 @@
[:div {:class (stl/css :picker-detail-wrapper)} [:div {:class (stl/css :picker-detail-wrapper)}
[:div {:class (stl/css :center-circle)}] [:div {:class (stl/css :center-circle)}]
[:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]] [:canvas#picker-detail {:class (stl/css :picker-detail) :width 256 :height 140}]]
[:& ramp-selector [:> ramp-selector*
{:color current-color {:color current-color
:disable-opacity disable-opacity :disable-opacity disable-opacity
:on-change handle-change-color :on-change handle-change-color

View file

@ -8,6 +8,7 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.colors :as cc] [app.common.colors :as cc]
[app.common.data :as d]
[app.common.math :as mth] [app.common.math :as mth]
[app.main.ui.components.color-bullet :as cb] [app.main.ui.components.color-bullet :as cb]
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]] [app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
@ -51,48 +52,82 @@
:top (str (* 100 (- 1 (/ value 255))) "%")}}]])) :top (str (* 100 (- 1 (/ value 255))) "%")}}]]))
(mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}] (defn- enrich-color-map
(let [{hex :hex [{:keys [h s v] :as color}]
hue :h saturation :s value :v alpha :alpha} color (let [h (d/nilv h 0)
s (d/nilv s 0)
v (d/nilv v 0)
hsv [h s v]
[r g b] (cc/hsv->rgb hsv)]
(assoc color
:hex (cc/hsv->hex hsv)
:h h :s s :v v
:r r :g g :b b)))
(mf/defc ramp-selector*
[{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
(let [internal-color*
(mf/use-state #(enrich-color-map color))
internal-color
(deref internal-color*)
h (get internal-color :h)
s (get internal-color :s)
v (get internal-color :v)
hex (get internal-color :hex)
alpha (get internal-color :alpha)
bullet-color
(mf/with-memo [hex alpha]
{:color hex :opacity alpha})
on-change-value-saturation on-change-value-saturation
(fn [new-saturation new-value] (mf/use-fn
(let [hex (cc/hsv->hex [hue new-saturation new-value]) (mf/deps internal-color on-change)
[r g b] (cc/hex->rgb hex)] (fn [saturation value]
(on-change {:hex hex (let [color (-> internal-color
:r r :g g :b b (assoc :s saturation)
:s new-saturation (assoc :v value)
:v new-value}))) (enrich-color-map))]
(reset! internal-color* color)
(on-change color))))
on-change-hue on-change-hue
(fn [new-hue] (mf/use-fn
(let [hex (cc/hsv->hex [new-hue saturation value]) (mf/deps internal-color on-change)
[r g b] (cc/hex->rgb hex)] (fn [hue]
(on-change {:hex hex (let [color (-> internal-color
:r r :g g :b b (assoc :h hue)
:h new-hue}))) enrich-color-map)]
(reset! internal-color* color)
(on-change color))))
on-change-opacity on-change-opacity
(fn [new-opacity] (mf/use-fn
(on-change {:alpha new-opacity}))] (mf/deps internal-color on-change)
(fn [opacity]
(let [color (assoc internal-color :alpha opacity)]
(reset! internal-color* color)
(on-change color))))]
[:* [:*
[:& value-saturation-selector [:& value-saturation-selector
{:hue hue {:hue h
:saturation saturation :saturation s
:value value :value v
:on-change on-change-value-saturation :on-change on-change-value-saturation
:on-start-drag on-start-drag :on-start-drag on-start-drag
:on-finish-drag on-finish-drag}] :on-finish-drag on-finish-drag}]
[:div {:class (stl/css :shade-selector) [:div {:class (stl/css :shade-selector)
:style #js {"--bullet-size" "52px"}} :style {:--bullet-size "52px"}}
[:& cb/color-bullet {:color {:color hex [:& cb/color-bullet {:color bullet-color
:opacity alpha}
:area true}] :area true}]
[:div {:class (stl/css :sliders-wrapper)} [:div {:class (stl/css :sliders-wrapper)}
[:& slider-selector {:type :hue [:& slider-selector {:type :hue
:max-value 360 :max-value 360
:value hue :value h
:on-change on-change-hue :on-change on-change-hue
:on-start-drag on-start-drag :on-start-drag on-start-drag
:on-finish-drag on-finish-drag}] :on-finish-drag on-finish-drag}]

View file

@ -19,7 +19,7 @@
[app.main.ui.ds.foundations.typography.heading :refer [heading*]] [app.main.ui.ds.foundations.typography.heading :refer [heading*]]
[app.main.ui.ds.foundations.typography.text :refer [text*]] [app.main.ui.ds.foundations.typography.text :refer [text*]]
[app.main.ui.workspace.colorpicker :as colorpicker] [app.main.ui.workspace.colorpicker :as colorpicker]
[app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector]] [app.main.ui.workspace.colorpicker.ramp :refer [ramp-selector*]]
[app.main.ui.workspace.tokens.components.controls.input-token-color-bullet :refer [input-token-color-bullet*]] [app.main.ui.workspace.tokens.components.controls.input-token-color-bullet :refer [input-token-color-bullet*]]
[app.main.ui.workspace.tokens.components.controls.input-tokens :refer [input-tokens*]] [app.main.ui.workspace.tokens.components.controls.input-tokens :refer [input-tokens*]]
[app.main.ui.workspace.tokens.errors :as wte] [app.main.ui.workspace.tokens.errors :as wte]
@ -156,31 +156,43 @@
(defonce form-token-cache-atom (atom nil)) (defonce form-token-cache-atom (atom nil))
(mf/defc ramp (defn hex->value
[hex]
(when-let [tc (tinycolor/valid-color hex)]
(let [hex (str "#" (tinycolor/->hex tc))
[r g b] (c/hex->rgb hex)
[h s v] (c/hex->hsv hex)]
{:hex hex
:r r :g g :b b
:h h :s s :v v
:alpha 1})))
(mf/defc ramp*
[{:keys [color on-change]}] [{:keys [color on-change]}]
(let [wrapper-node-ref (mf/use-ref nil) (let [wrapper-node-ref (mf/use-ref nil)
dragging? (mf/use-state) dragging-ref (mf/use-ref false)
hex->value (fn [hex]
(when-let [tc (tinycolor/valid-color hex)] on-start-drag
(let [hex (str "#" (tinycolor/->hex tc)) (mf/use-fn #(mf/set-ref-val! dragging-ref true))
[r g b] (c/hex->rgb hex)
[h s v] (c/hex->hsv hex)] on-finish-drag
{:hex hex (mf/use-fn #(mf/set-ref-val! dragging-ref false))
:r r :g g :b b
:h h :s s :v v on-change'
:alpha 1}))) (mf/use-fn
value (mf/use-state (hex->value color)) (mf/deps on-change)
on-change' (fn [{:keys [hex]}] (fn [{:keys [hex]}]
(reset! value (hex->value hex)) (let [dragging? (mf/ref-val dragging-ref)]
(when-not (and @dragging? hex) (when-not (and dragging? hex)
(on-change hex)))] (on-change hex)))))]
(colorpicker/use-color-picker-css-variables! wrapper-node-ref @value)
(colorpicker/use-color-picker-css-variables! wrapper-node-ref (hex->value color))
[:div {:ref wrapper-node-ref} [:div {:ref wrapper-node-ref}
[:& ramp-selector [:> ramp-selector*
{:color @value {:color (hex->value color)
:disable-opacity true :disable-opacity true
:on-start-drag #(reset! dragging? true) :on-start-drag on-start-drag
:on-finish-drag #(reset! dragging? false) :on-finish-drag on-finish-drag
:on-change on-change'}]])) :on-change on-change'}]]))
(mf/defc token-value-or-errors (mf/defc token-value-or-errors
@ -419,9 +431,9 @@
[:> input-token-color-bullet* [:> input-token-color-bullet*
{:color @color :on-click on-display-colorpicker}])] {:color @color :on-click on-display-colorpicker}])]
(when @color-ramp-open? (when @color-ramp-open?
[:& ramp {:color (some-> (or @token-resolve-result (:value token)) [:> ramp* {:color (some-> (or @token-resolve-result (:value token))
(tinycolor/valid-color)) (tinycolor/valid-color))
:on-change on-update-color}]) :on-change on-update-color}])
[:& token-value-or-errors {:result-or-errors @token-resolve-result}]] [:& token-value-or-errors {:result-or-errors @token-resolve-result}]]
[:div {:class (stl/css :input-row)} [:div {:class (stl/css :input-row)}