✨ Change iconography to reflect orientation

This commit is contained in:
alonso.torres 2026-10-08 09:54:15 +02:00
parent 5f2d7a1ff1
commit 6dffc7dfcd
13 changed files with 222 additions and 32 deletions

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="m14 8h-5.333m5.333-4h-12m12 8h-9.333"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 216 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="m5.333 8h5.334m-8.667-4h12m-10 8h8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 214 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="m7.333 8h-5.333m12-4h-12m9.333 8h-9.333"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 219 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="M13.334 12H6m9.334-8H6m4.667 4H6m-4 6V2m0 12h1.334M2 14H.667M2 2h1.334M2 2H.667"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 259 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<path d="M5.667 10.667l.863-1.918m0 0l1.537-3.416 1.536 3.416m-3.073 0h3.073m0 0l.864 1.918M2 14V2m0 12h1.334M2 14H.667M2 2h1.334M2 2H.667"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="M6 14l2-2 2 2M3.333 6.667h9.334M3.333 9.333h9.334M10 2L8 4 6 2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 242 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="M14 8H2m12-4H2m12 8H2"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 201 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="M10 3L8 5 6 3m6.667 10H3.333m9.334-2.667H3.333"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 226 B

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
<g transform="rotate(90 8 8)">
<path d="M6 13l2-2 2 2M3.333 3h9.334M3.333 5.667h9.334"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 225 B

View File

@ -270,11 +270,16 @@
(def ^:icon-id swatches "swatches")
(def ^:icon-id switch "switch")
(def ^:icon-id text "text")
(def ^:icon-id text-align-bottom "text-align-bottom")
(def ^:icon-id text-align-center "text-align-center")
(def ^:icon-id text-align-left "text-align-left")
(def ^:icon-id text-align-middle "text-align-middle")
(def ^:icon-id text-align-right "text-align-right")
(def ^:icon-id text-align-top "text-align-top")
(def ^:icon-id text-auto-height "text-auto-height")
(def ^:icon-id text-auto-height-vertical "text-auto-height-vertical")
(def ^:icon-id text-auto-width "text-auto-width")
(def ^:icon-id text-auto-width-vertical "text-auto-width-vertical")
(def ^:icon-id text-bottom "text-bottom")
(def ^:icon-id text-combine-upright-all "text-combine-upright-all")
(def ^:icon-id text-combine-upright-digits "text-combine-upright-digits")
@ -283,7 +288,10 @@
(def ^:icon-id text-font-family "text-font-family")
(def ^:icon-id text-font-size "text-font-size")
(def ^:icon-id text-font-weight "text-font-weight")
(def ^:icon-id text-horizontal-center "text-horizontal-center")
(def ^:icon-id text-justify "text-justify")
(def ^:icon-id text-justify-vertical "text-justify-vertical")
(def ^:icon-id text-left "text-left")
(def ^:icon-id text-letterspacing "text-letterspacing")
(def ^:icon-id text-lineheight "text-lineheight")
(def ^:icon-id text-lowercase "text-lowercase")
@ -294,6 +302,7 @@
(def ^:icon-id text-orientation-upright "text-orientation-upright")
(def ^:icon-id text-palette "text-palette")
(def ^:icon-id text-paragraph "text-paragraph")
(def ^:icon-id text-right "text-right")
(def ^:icon-id text-rtl "text-rtl")
(def ^:icon-id text-stroked "text-stroked")
(def ^:icon-id text-top "text-top")

View File

@ -40,6 +40,7 @@
[app.util.object :as obj]
[app.util.text.content :as content]
[app.util.text.ui :as txu]
[app.util.text.writing-mode :as wm]
[app.util.timers :as ts]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]
@ -56,24 +57,32 @@
(mf/defc text-align-options*
[{:keys [values on-change on-blur]}]
(let [options
(mf/with-memo []
(let [vertical? (and (wm/vertical-layout-active?)
(tjl/vertical-japanese-layout? values))
options
(mf/with-memo [vertical?]
[{:value "left"
:id "text-align-left"
:label (tr "workspace.options.text-options.text-align-left")
:icon i/text-align-left}
:label (if vertical?
(tr "workspace.options.text-options.align-top")
(tr "workspace.options.text-options.text-align-left"))
:icon (if vertical? i/text-align-top i/text-align-left)}
{:value "center"
:id "text-align-center"
:label (tr "workspace.options.text-options.text-align-center")
:icon i/text-align-center}
:label (if vertical?
(tr "workspace.options.text-options.align-middle")
(tr "workspace.options.text-options.text-align-center"))
:icon (if vertical? i/text-align-middle i/text-align-center)}
{:value "right"
:id "text-align-right"
:label (tr "workspace.options.text-options.text-align-right")
:icon i/text-align-right}
:label (if vertical?
(tr "workspace.options.text-options.align-bottom")
(tr "workspace.options.text-options.text-align-right"))
:icon (if vertical? i/text-align-bottom i/text-align-right)}
{:value "justify"
:id "text-align-justify"
:label (tr "workspace.options.text-options.text-align-justify")
:icon i/text-justify}])
:icon (if vertical? i/text-justify-vertical i/text-justify)}])
handle-change
(mf/use-fn
@ -90,7 +99,9 @@
(mf/defc text-direction-options*
[{:keys [values on-change on-blur]}]
(let [direction (radio-selected (:text-direction values))
(let [vertical? (and (wm/vertical-layout-active?)
(tjl/vertical-japanese-layout? values))
direction (radio-selected (:text-direction values))
options
(mf/with-memo []
[{:value "ltr"
@ -109,29 +120,38 @@
(on-change {:text-direction (if (= value direction) "none" value)})
(when (some? on-blur) (on-blur))))]
[:div {:class (stl/css :text-direction-options)}
[:> radio-buttons* {:selected direction
:on-change handle-change
:name "text-direction-options"
:options options}]]))
(when-not vertical?
[:div {:class (stl/css :text-direction-options)}
[:> radio-buttons* {:selected direction
:on-change handle-change
:name "text-direction-options"
:options options}]])))
(mf/defc vertical-align*
[{:keys [values on-change on-blur]}]
(let [vertical-align (radio-selected (:vertical-align values) "top")
(let [vertical? (and (wm/vertical-layout-active?)
(tjl/vertical-japanese-layout? values))
vertical-align (radio-selected (:vertical-align values) "top")
options
(mf/with-memo []
(mf/with-memo [vertical?]
[{:value "top"
:id "vertical-text-align-top"
:label (tr "workspace.options.text-options.align-top")
:icon i/text-top}
:label (if vertical?
(tr "workspace.options.text-options.text-align-right")
(tr "workspace.options.text-options.align-top"))
:icon (if vertical? i/text-right i/text-top)}
{:value "center"
:id "vertical-text-align-center"
:label (tr "workspace.options.text-options.align-middle")
:icon i/text-middle}
:label (if vertical?
(tr "workspace.options.text-options.text-align-center")
(tr "workspace.options.text-options.align-middle"))
:icon (if vertical? i/text-horizontal-center i/text-middle)}
{:value "bottom"
:id "vertical-text-align-bottom"
:label (tr "workspace.options.text-options.align-bottom")
:icon i/text-bottom}])
:label (if vertical?
(tr "workspace.options.text-options.text-align-left")
(tr "workspace.options.text-options.align-bottom"))
:icon (if vertical? i/text-left i/text-bottom)}])
handle-change
(mf/use-fn
@ -148,23 +168,29 @@
(mf/defc grow-options*
[{:keys [ids values on-blur]}]
(let [grow-type (:grow-type values)
(let [vertical? (and (wm/vertical-layout-active?)
(tjl/vertical-japanese-layout? values))
grow-type (:grow-type values)
selected (radio-selected grow-type)
editor-instance (mf/deref refs/workspace-editor)
options
(mf/with-memo []
(mf/with-memo [vertical?]
[{:value "fixed"
:id "text-fixed-grow"
:label (tr "workspace.options.text-options.grow-fixed")
:icon i/text-fixed}
{:value "auto-width"
:id "text-auto-width-grow"
:label (tr "workspace.options.text-options.grow-auto-width")
:icon i/text-auto-width}
:label (if vertical?
(tr "workspace.options.text-options.grow-auto-height")
(tr "workspace.options.text-options.grow-auto-width"))
:icon (if vertical? i/text-auto-width-vertical i/text-auto-width)}
{:value "auto-height"
:id "text-auto-height-grow"
:label (tr "workspace.options.text-options.grow-auto-height")
:icon i/text-auto-height}])
:label (if vertical?
(tr "workspace.options.text-options.grow-auto-width")
(tr "workspace.options.text-options.grow-auto-height"))
:icon (if vertical? i/text-auto-height-vertical i/text-auto-height)}])
handle-change
(mf/use-fn
@ -651,9 +677,6 @@
:on-click toggle-more-options
:icon i/menu}]]
(when japanese-layout-config-enabled?
[:> tjl/line-adjustment-option* common-props])
(when more-options-open?
[:div {:class (stl/css :text-decoration-options)}
[:> vertical-align* common-props]

View File

@ -506,6 +506,7 @@
(when ^boolean vertical?
[:> text-combine-upright-count-options* common-props])
[:> font-features-options* common-props]
[:> line-adjustment-option* common-props]
;; Emphasis marks (圏点 / bouten) apply to the selected characters.
(when ^boolean text-selection-active
[:> span-select-option* (mf/spread-props common-props

View File

@ -10,9 +10,11 @@
[app.common.types.text.cjk-layout :as cjk]
[app.main.data.workspace.texts :as dwt]
[app.main.ui.ds.controls.select :as select]
[app.main.ui.hooks :as hooks]
[app.main.ui.shapes.text.html-text :as html-text]
[app.main.ui.shapes.text.styles :as text-styles]
[app.main.ui.workspace.sidebar.options.common :refer [radio-selected]]
[app.main.ui.workspace.sidebar.options.menus.text :as text-menu]
[app.main.ui.workspace.sidebar.options.menus.text-japanese-layout :as tjl]
[app.util.text.writing-mode :as wm]
[cljs.test :as t :include-macros true]
@ -246,3 +248,115 @@
(t/is (not (str/includes? (markup) "vertical-rl"))))
(with-redefs [wm/vertical-layout-active? (constantly true)]
(t/is (str/includes? (markup) "writing-mode:vertical-rl")))))
(defn- alignment-markup
([component writing-mode wasm-enabled]
(alignment-markup component writing-mode wasm-enabled {}))
([component writing-mode wasm-enabled values]
;; Server rendering has no DOM container for tooltip portals.
(with-redefs [wm/vertical-layout-active? (constantly wasm-enabled)
hooks/use-portal-container (fn ([] nil) ([_] nil))]
(rds/renderToStaticMarkup
(mf/element component #js {:values (assoc values :writing-mode writing-mode)
:on-change identity})))))
(defn- alignment-labels
[markup]
(mapv second (re-seq #"aria-label=\"([^\"]+)\"" markup)))
(defn- alignment-icons
[markup]
(mapv second (re-seq #"href=\"#icon-([^\"]+)\"" markup)))
(t/deftest vertical-paragraph-alignment-shows-top-middle-bottom-and-vertical-justify
(let [markup (alignment-markup text-menu/text-align-options* "vertical-rl" true)]
(t/is (= ["text-align-top" "text-align-middle" "text-align-bottom" "text-justify-vertical"]
(alignment-icons markup)))
(t/is (= ["workspace.options.text-options.align-top"
"workspace.options.text-options.align-middle"
"workspace.options.text-options.align-bottom"
"workspace.options.text-options.text-align-justify"]
(alignment-labels markup)))
(t/is (= ["left" "center" "right" "justify"]
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
(t/deftest vertical-column-block-alignment-shows-right-center-and-left
(let [markup (alignment-markup text-menu/vertical-align* "vertical-rl" true)]
(t/is (= ["text-right" "text-horizontal-center" "text-left"]
(alignment-icons markup)))
(t/is (= ["workspace.options.text-options.text-align-right"
"workspace.options.text-options.text-align-center"
"workspace.options.text-options.text-align-left"]
(alignment-labels markup)))
(t/is (= ["top" "center" "bottom"]
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
(t/deftest horizontal-and-mixed-writing-modes-use-horizontal-alignment-controls
(doseq [writing-mode [nil "horizontal-tb" :multiple]]
(let [paragraph (alignment-markup text-menu/text-align-options* writing-mode true)
block (alignment-markup text-menu/vertical-align* writing-mode true)]
(t/is (= ["text-align-left" "text-align-center" "text-align-right" "text-justify"]
(alignment-icons paragraph)))
(t/is (= ["text-top" "text-middle" "text-bottom"] (alignment-icons block))))))
(t/deftest svg-renderer-keeps-horizontal-alignment-for-stored-vertical-text
(let [paragraph (alignment-markup text-menu/text-align-options* "vertical-rl" false)
block (alignment-markup text-menu/vertical-align* "vertical-rl" false)]
(t/is (= ["text-align-left" "text-align-center" "text-align-right" "text-justify"]
(alignment-icons paragraph)))
(t/is (= ["text-top" "text-middle" "text-bottom"] (alignment-icons block)))
(t/is (= "workspace.options.text-options.text-align-left" (first (alignment-labels paragraph))))
(t/is (= "workspace.options.text-options.align-top" (first (alignment-labels block))))))
(t/deftest vertical-text-growth-controls-show-the-physical-growth-direction
(let [markup (alignment-markup text-menu/grow-options* "vertical-rl" true)]
(t/is (= ["text-fixed" "text-auto-width-vertical" "text-auto-height-vertical"]
(alignment-icons markup)))
(t/is (= ["workspace.options.text-options.grow-fixed"
"workspace.options.text-options.grow-auto-height"
"workspace.options.text-options.grow-auto-width"]
(alignment-labels markup)))
(t/is (= ["fixed" "auto-width" "auto-height"]
(mapv second (re-seq #"value=\"([^\"]+)\"" markup))))))
(t/deftest horizontal-and-svg-text-growth-controls-keep-horizontal-directions
(doseq [[writing-mode wasm-enabled] [[nil true]
["horizontal-tb" true]
[:multiple true]
["vertical-rl" false]]]
(let [markup (alignment-markup text-menu/grow-options* writing-mode wasm-enabled)]
(t/is (= ["text-fixed" "text-auto-width" "text-auto-height"]
(alignment-icons markup)))
(t/is (= ["workspace.options.text-options.grow-fixed"
"workspace.options.text-options.grow-auto-width"
"workspace.options.text-options.grow-auto-height"]
(alignment-labels markup))))))
(t/deftest japanese-layout-controls-include-line-adjustment
(let [markup (alignment-markup tjl/japanese-layout-options* "vertical-rl" true)]
(t/is (str/includes? markup "workspace.options.text-options.line-adjustment"))))
(t/deftest vertical-text-hides-ltr-and-rtl-controls
(t/is (empty? (alignment-markup text-menu/text-direction-options* "vertical-rl" true))))
(t/deftest horizontal-and-svg-text-show-ltr-and-rtl-controls
(doseq [[writing-mode wasm-enabled] [[nil true]
["horizontal-tb" true]
[:multiple true]
["vertical-rl" false]]]
(let [markup (alignment-markup text-menu/text-direction-options* writing-mode wasm-enabled)]
(t/is (= ["text-ltr" "text-rtl"] (alignment-icons markup))))))
(t/deftest hiding-direction-controls-preserves-the-stored-direction
(let [values {:text-direction "rtl"}
render #(alignment-markup text-menu/text-direction-options* % true values)]
(t/is (str/includes? (re-find #"<input[^>]*id=\"rtl-text-direction\"[^>]*>"
(render "horizontal-tb"))
"checked=\"\""))
(t/is (empty? (render "vertical-rl")))
(t/is (str/includes? (re-find #"<input[^>]*id=\"rtl-text-direction\"[^>]*>"
(render "horizontal-tb"))
"checked=\"\""))))