Set default new text fill color depending on background color (#6998)

This commit is contained in:
Elena Torró
2025-07-31 12:31:54 +02:00
committed by GitHub
parent d7ec8ccbc0
commit 76d725559e
4 changed files with 54 additions and 13 deletions

View File

@@ -431,4 +431,3 @@
[{:type "paragraph-set" [{:type "paragraph-set"
:children paragraphs}]} :children paragraphs}]}
root-styles))) root-styles)))

View File

@@ -404,6 +404,7 @@
// TEXT SELECTION // TEXT SELECTION
--text-editor-selection-background-color: var(--da-tertiary-70); --text-editor-selection-background-color: var(--da-tertiary-70);
--text-editor-selection-foreground-color: var(--app-white); --text-editor-selection-foreground-color: var(--app-white);
--text-editor-caret-color: var(--app-black);
// NEW TEAM BUTTON // NEW TEAM BUTTON
// TODO: we should not put these functional tokens here, but rather in the components they belong to // TODO: we should not put these functional tokens here, but rather in the components they belong to

View File

@@ -9,9 +9,11 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.geom.shapes.text :as gst] [app.common.geom.shapes.text :as gst]
[app.common.math :as mth] [app.common.math :as mth]
[app.common.types.color :as color]
[app.common.types.text :as txt] [app.common.types.text :as txt]
[app.config :as cf] [app.config :as cf]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
@@ -31,6 +33,11 @@
[app.util.text.content.styles :as styles] [app.util.text.content.styles :as styles]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(defn get-contrast-color [background-color]
(when background-color
(let [luminance (color/hex->lum background-color)]
(if (> luminance 0.5) "#000000" "#ffffff"))))
(defn- gen-name (defn- gen-name
[editor] [editor]
(when (some? editor) (when (some? editor)
@@ -54,7 +61,7 @@
(defn- initialize-event-handlers (defn- initialize-event-handlers
"Internal editor events handler initializer/destructor" "Internal editor events handler initializer/destructor"
[shape-id content selection-ref editor-ref container-ref] [shape-id content selection-ref editor-ref container-ref text-color]
(let [editor-node (let [editor-node
(mf/ref-val editor-ref) (mf/ref-val editor-ref)
@@ -67,7 +74,11 @@
style-defaults style-defaults
(styles/get-style-defaults (styles/get-style-defaults
(merge (txt/get-default-text-attrs) txt/default-root-attrs default-font)) (merge
(txt/get-default-text-attrs)
{:fills [{:fill-color text-color :fill-opacity 1}]}
txt/default-root-attrs
default-font))
options options
#js {:styleDefaults style-defaults #js {:styleDefaults style-defaults
@@ -134,7 +145,8 @@
(st/emit! (dwt/update-editor instance)) (st/emit! (dwt/update-editor instance))
(when (some? content) (when (some? content)
(dwt/set-editor-root! instance (content/cljs->dom content))) (dwt/set-editor-root! instance (content/cljs->dom content)))
(st/emit! (dwt/focus-editor)) (when (some? instance)
(st/emit! (dwt/focus-editor)))
;; This function is called when the component is unmount ;; This function is called when the component is unmount
(fn [] (fn []
@@ -148,6 +160,22 @@
(dwt/dispose! instance) (dwt/dispose! instance)
(st/emit! (dwt/update-editor nil))))) (st/emit! (dwt/update-editor nil)))))
(defn get-color-from-content [content]
(let [fills (->> (tree-seq map? :children content)
(mapcat :fills)
(filter :fill-color))]
(some :fill-color fills)))
(defn get-default-text-color
"Returns the appropriate text color based on fill, frame, and background."
[{:keys [frame background-color]}]
(if (and frame (not (cfh/root? frame)) (seq (:fills frame)))
(let [fill-color (some #(when (:fill-color %) (:fill-color %)) (:fills frame))]
(if fill-color
(get-contrast-color fill-color)
(get-contrast-color background-color)))
(get-contrast-color background-color)))
(mf/defc text-editor-html (mf/defc text-editor-html
"Text editor (HTML)" "Text editor (HTML)"
{::mf/wrap [mf/memo] {::mf/wrap [mf/memo]
@@ -155,15 +183,23 @@
[{:keys [shape]}] [{:keys [shape]}]
(let [content (:content shape) (let [content (:content shape)
shape-id (dm/get-prop shape :id) shape-id (dm/get-prop shape :id)
fill-color (get-color-from-content content)
;; This is a reference to the dom element that ;; This is a reference to the dom element that
;; should contain the TextEditor. ;; should contain the TextEditor.
editor-ref (mf/use-ref nil) editor-ref (mf/use-ref nil)
;; This reference is to the container ;; This reference is to the container
container-ref (mf/use-ref nil) container-ref (mf/use-ref nil)
selection-ref (mf/use-ref nil) selection-ref (mf/use-ref nil)
page (mf/deref refs/workspace-page)
objects (get page :objects)
frame (cfh/get-frame objects shape-id)
background-color (:background page)
text-color (or fill-color (get-default-text-color {:frame frame
:background-color background-color}))
fonts fonts
(-> (mf/use-memo (mf/deps content) #(get-fonts content)) (-> (mf/use-memo (mf/deps content) #(get-fonts content))
(h/use-equal-memo))] (h/use-equal-memo))]
@@ -179,7 +215,12 @@
content content
selection-ref selection-ref
editor-ref editor-ref
container-ref)) container-ref
text-color))
(mf/with-effect [text-color]
(let [container-node (mf/ref-val container-ref)]
(dom/set-style! container-node "--text-editor-caret-color" text-color)))
[:div [:div
{:class (dm/str (cur/get-dynamic "text" (:rotation shape)) {:class (dm/str (cur/get-dynamic "text" (:rotation shape))

View File

@@ -23,7 +23,7 @@
white-space: pre-wrap; white-space: pre-wrap;
overflow-wrap: break-word; overflow-wrap: break-word;
caret-color: black; caret-color: var(--text-editor-caret-color);
color: transparent; color: transparent;
@@ -38,7 +38,7 @@
line-break: auto; line-break: auto;
line-height: inherit; line-height: inherit;
overflow-wrap: initial; overflow-wrap: initial;
caret-color: rgb(0, 0, 0); caret-color: var(--text-editor-caret-color);
} }
[data-itype="root"] { [data-itype="root"] {