mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
✨ Set default new text fill color depending on background color (#6998)
This commit is contained in:
@@ -431,4 +431,3 @@
|
|||||||
[{:type "paragraph-set"
|
[{:type "paragraph-set"
|
||||||
:children paragraphs}]}
|
:children paragraphs}]}
|
||||||
root-styles)))
|
root-styles)))
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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"] {
|
||||||
|
|||||||
Reference in New Issue
Block a user