diff --git a/common/src/app/common/types/text.cljc b/common/src/app/common/types/text.cljc index f124abf50b..651aee21fc 100644 --- a/common/src/app/common/types/text.cljc +++ b/common/src/app/common/types/text.cljc @@ -431,4 +431,3 @@ [{:type "paragraph-set" :children paragraphs}]} root-styles))) - diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index 4a18a5ba87..54ccc918ca 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -404,6 +404,7 @@ // TEXT SELECTION --text-editor-selection-background-color: var(--da-tertiary-70); --text-editor-selection-foreground-color: var(--app-white); + --text-editor-caret-color: var(--app-black); // NEW TEAM BUTTON // TODO: we should not put these functional tokens here, but rather in the components they belong to diff --git a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs index e1dad90b26..8375cbc379 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.cljs @@ -9,9 +9,11 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.files.helpers :as cfh] [app.common.geom.shapes :as gsh] [app.common.geom.shapes.text :as gst] [app.common.math :as mth] + [app.common.types.color :as color] [app.common.types.text :as txt] [app.config :as cf] [app.main.data.workspace :as dw] @@ -31,6 +33,11 @@ [app.util.text.content.styles :as styles] [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 [editor] (when (some? editor) @@ -54,7 +61,7 @@ (defn- initialize-event-handlers "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 (mf/ref-val editor-ref) @@ -67,7 +74,11 @@ 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 #js {:styleDefaults style-defaults @@ -134,7 +145,8 @@ (st/emit! (dwt/update-editor instance)) (when (some? 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 (fn [] @@ -148,21 +160,45 @@ (dwt/dispose! instance) (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 "Text editor (HTML)" {::mf/wrap [mf/memo] ::mf/props :obj} [{:keys [shape]}] - (let [content (:content shape) - shape-id (dm/get-prop shape :id) + (let [content (:content shape) + shape-id (dm/get-prop shape :id) + fill-color (get-color-from-content content) ;; This is a reference to the dom element that ;; should contain the TextEditor. - editor-ref (mf/use-ref nil) - + editor-ref (mf/use-ref nil) ;; This reference is to the container - container-ref (mf/use-ref nil) - selection-ref (mf/use-ref nil) + container-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 (-> (mf/use-memo (mf/deps content) #(get-fonts content)) @@ -179,7 +215,12 @@ content selection-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 {:class (dm/str (cur/get-dynamic "text" (:rotation shape)) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.scss b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.scss index d2732bd7f3..f797f33e18 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.scss +++ b/frontend/src/app/main/ui/workspace/shapes/text/v2_editor.scss @@ -23,7 +23,7 @@ white-space: pre-wrap; overflow-wrap: break-word; - caret-color: black; + caret-color: var(--text-editor-caret-color); color: transparent; @@ -38,7 +38,7 @@ line-break: auto; line-height: inherit; overflow-wrap: initial; - caret-color: rgb(0, 0, 0); + caret-color: var(--text-editor-caret-color); } [data-itype="root"] {