0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-18 10:41:29 -05:00

🎉 Picker color palettes interactions

This commit is contained in:
alonso.torres 2020-09-08 12:30:35 +02:00 committed by Hirunatan
parent 568f7f5b3d
commit a0627efffe
7 changed files with 409 additions and 199 deletions

View file

@ -68,8 +68,8 @@
(s/def :internal.shape/collapsed boolean?)
(s/def :internal.shape/content any?)
(s/def :internal.shape/fill-color string?)
(s/def :internal.shape/fill-color-ref-file uuid?)
(s/def :internal.shape/fill-color-ref-id uuid?)
(s/def :internal.shape/fill-color-ref-file (s/nilable uuid?))
(s/def :internal.shape/fill-color-ref-id (s/nilable uuid?))
(s/def :internal.shape/fill-opacity number?)
(s/def :internal.shape/font-family string?)
(s/def :internal.shape/font-size number?)
@ -85,8 +85,8 @@
(s/def :internal.shape/rx number?)
(s/def :internal.shape/ry number?)
(s/def :internal.shape/stroke-color string?)
(s/def :internal.shape/stroke-color-ref-file uuid?)
(s/def :internal.shape/stroke-color-ref-id uuid?)
(s/def :internal.shape/stroke-color-ref-file (s/nilable uuid?))
(s/def :internal.shape/stroke-color-ref-id (s/nilable uuid?))
(s/def :internal.shape/stroke-opacity number?)
(s/def :internal.shape/stroke-style #{:solid :dotted :dashed :mixed :none})
(s/def :internal.shape/stroke-width number?)

File diff suppressed because it is too large Load diff

View file

@ -123,6 +123,10 @@
width: 100%;
height: 4.8rem;
padding: 0.25rem;
&.size-small {
height: 3.5rem;
}
}
.color-palette-inside {
@ -141,15 +145,37 @@
flex-direction: column;
flex-shrink: 0;
position: relative;
flex-basis: 66px;
&.cell-big {
flex-basis: 66px;
}
&.cell-small {
flex-basis: 52px;
}
.color {
background-color: $color-gray-10;
border: 2px solid $color-gray-60;
border-radius: 50%;
flex-shrink: 0;
padding: 1.5rem;
}
&.cell-big .color {
width: 50px;
height: 50px;
}
&.cell-small .color {
width: 40px;
height: 40px;
}
.color.color-big {
width: 50px;
height: 50px;
}
.color-text {
color: $color-gray-20;
font-size: $fs12;
@ -263,3 +289,52 @@
}
}
}
ul.palette-menu {
left: 8px;
top: auto;
bottom: 4.5rem;
color: $color-black;
li {
position: relative;
padding: 5px 1.5rem;
}
hr {
margin: 0.5rem 0;
}
svg {
width: 9px;
height: 9px;
position: absolute;
left: 0.5rem;
top: 10px;
}
hr {
border-color: $color-gray-20;
}
.palette-library {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.color-sample {
display: flex;
flex-direction: row;
margin-top: 0.5rem;
}
.color-bullet {
width: 20px;
height: 20px;
border-radius: 12px;
border: 1px solid $color-gray-10;
margin-right: 5px;
}
}

View file

@ -107,3 +107,25 @@
(update-in [:workspace-file :colors]
(fn [colors] (filter #(not= (:id %) color-id) colors)))))))
(defn change-palette-size [size]
(s/assert #{:big :small} size)
(ptk/reify ::change-palette-size
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:workspace-local :selected-palette-size] size)))))
(defn change-palette-selected [selected]
(ptk/reify ::change-palette-selected
ptk/UpdateEvent
(update [_ state]
(-> state
(assoc-in [:workspace-local :selected-palette] selected)))))
(defn show-palette [selected]
(ptk/reify ::change-palette-selected
ptk/UpdateEvent
(update [_ state]
(-> state
(update :workspace-layout conj :colorpalette)
(assoc-in [:workspace-local :selected-palette] selected)))))

View file

@ -100,7 +100,9 @@
:draw-interaction-to nil
:left-sidebar? true
:right-sidebar? true
:color-for-rename nil})
:color-for-rename nil
:selected-palette :recent
:selected-palette-size :big})
(def initialize-layout
(ptk/reify ::initialize-layout

View file

@ -13,16 +13,19 @@
[goog.events :as events]
[okulary.core :as l]
[rumext.alpha :as mf]
[cuerdas.core :as str]
[app.common.math :as mth]
;; [app.main.data.library :as dlib]
[app.main.data.colors :as mdc]
[app.main.data.workspace :as udw]
[app.main.store :as st]
[app.main.ui.components.context-menu :refer [context-menu]]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.icons :as i]
[app.main.ui.keyboard :as kbd]
[app.util.color :refer [hex->rgb]]
[app.util.dom :as dom]
[app.util.object :as obj]))
[app.util.object :as obj]
[app.main.refs :as refs]
[app.util.i18n :as i18n :refer [t]]))
;; --- Refs
@ -31,7 +34,11 @@
(l/derived st/state)))
(def selected-palette-ref
(-> (l/in [:library-selected :palettes])
(-> (l/in [:workspace-local :selected-palette])
(l/derived st/state)))
(def selected-palette-size-ref
(-> (l/in [:workspace-local :selected-palette-size])
(l/derived st/state)))
(defn- make-selected-palette-item-ref
@ -40,41 +47,40 @@
(l/derived st/state)))
;; --- Components
(mf/defc palette-item
[{:keys [color] :as props}]
(let [rgb-vec (hex->rgb color)
select-color
[{:keys [color size]}]
(let [select-color
(fn [event]
(if (kbd/shift? event)
(st/emit! (udw/update-color-on-selected-shapes {:stroke-color color}))
(st/emit! (udw/update-color-on-selected-shapes {:fill-color color}))))]
(st/emit! (udw/update-color-on-selected-shapes {:stroke-color (:value color)
:stroke-color-ref-file (:file-id color)
:stroke-color-ref-id (:id color)}))
(st/emit! (udw/update-color-on-selected-shapes {:fill-color (:value color)
:fill-color-ref-file (:file-id color)
:fill-color-ref-id (:id color)}))))]
[:div.color-cell {:key (str color)
[:div.color-cell {:class (str "cell-"(name size))
:key (or (str (:id color)) (:value color))
:on-click select-color}
[:span.color {:style {:background color}}]
[:span.color-text color]]))
[:span.color {:style {:background (:value color)}}]
(when (= size :big) [:span.color-text (or (:name color) (:value color))])]))
(mf/defc palette
[{:keys [palettes selected left-sidebar?] :as props}]
(let [items-ref (mf/use-memo
(mf/deps selected)
(partial make-selected-palette-item-ref selected))
items (mf/deref items-ref)
state (mf/use-state {:show-menu false })
[{:keys [left-sidebar? current-colors recent-colors file-colors shared-libs selected size]}]
(let [state (mf/use-state {:show-menu false })
width (:width @state 0)
visible (mth/round (/ width 66))
offset (:offset @state 0)
max-offset (- (count items)
max-offset (- (count current-colors)
visible)
close-fn #(st/emit! (udw/toggle-layout-flags :colorpalette))
container (mf/use-ref nil)
locale (mf/deref i18n/locale)
on-left-arrow-click
(mf/use-callback
(mf/deps max-offset visible)
@ -108,12 +114,8 @@
(fn [event]
(let [dom (mf/ref-val container)
width (obj/get dom "clientWidth")]
(swap! state assoc :width width))))
(swap! state assoc :width width))))]
handle-click
(mf/use-callback
(fn [library]))]
;; (st/emit! (dlib/select-library :palettes (:id library)))))]
(mf/use-layout-effect
#(let [dom (mf/ref-val container)
@ -125,48 +127,116 @@
(fn []
(events/unlistenByKey key1))))
(mf/use-effect
(mf/deps selected)
(fn []
(when selected)))
;; (st/emit! (dlib/retrieve-library-data :palettes selected)))))
[:div.color-palette {:class (when left-sidebar? "left-sidebar-open")}
[:& context-menu
{:selectable true
:selected (->> palettes
(filter #(= (:id %) selected))
first
:name)
:show (:show-menu @state)
:on-close #(swap! state assoc :show-menu false)
:options (mapv #(vector (:name %) (partial handle-click %)) palettes)}]
[:& dropdown {:show (:show-menu @state)
:on-close #(swap! state assoc :show-menu false)}
[:ul.workspace-context-menu.palette-menu
(for [cur-library (vals shared-libs)]
(let [colors (-> cur-library (get-in [:data :colors]) vals)]
[:li.palette-library
{:on-click #(st/emit! (mdc/change-palette-selected (:id cur-library)))}
(when (= selected (:id cur-library)) i/tick)
[:div.library-name (str (:name cur-library) " " (str/format "(%s)" (count colors)))]
[:div.color-sample
(for [[idx {:keys [id value]}] (map-indexed vector (take 7 colors))]
[:div.color-bullet {:key (str "color-" idx)
:style {:background-color value}}])]]))
[:li.palette-library
{:on-click #(st/emit! (mdc/change-palette-selected :file))}
(when (= selected :file) i/tick)
[:div.library-name (str (t locale "workspace.libraries.colors.file-library")
(str/format " (%s)" (count file-colors)))]
[:div.color-sample
(for [[idx {:keys [value]}] (map-indexed vector (take 7 (vals file-colors))) ]
[:div.color-bullet {:key (str "color-" idx)
:style {:background-color value}}])]]
[:li.palette-library
{:on-click #(st/emit! (mdc/change-palette-selected :recent))}
(when (= selected :recent) i/tick)
[:div.library-name (str (t locale "workspace.libraries.colors.recent-colors")
(str/format " (%s)" (count recent-colors)))]
[:div.color-sample
(for [[idx value] (map-indexed vector (take 7 (reverse recent-colors))) ]
[:div.color-bullet {:key (str "color-" idx)
:style {:background-color value}}])]]
[:hr.dropdown-separator]
[:li
{:on-click #(st/emit! (mdc/change-palette-size :big))}
(when (= size :big) i/tick)
(t locale "workspace.libraries.colors.big-thumbnails")]
[:li
{:on-click #(st/emit! (mdc/change-palette-size :small))}
(when (= size :small) i/tick)
(t locale "workspace.libraries.colors.small-thumbnails")]]]
[:div.color-palette-actions
{:on-click #(swap! state assoc :show-menu true)}
[:div.color-palette-actions-button i/actions]]
[:span.left-arrow {:on-click on-left-arrow-click} i/arrow-slide]
[:div.color-palette-content {:ref container :on-wheel on-scroll}
[:div.color-palette-content {:class (if (= size :big) "size-big" "size-small")
:ref container :on-wheel on-scroll}
[:div.color-palette-inside {:style {:position "relative"
:right (str (* 66 offset) "px")}}
(for [item items]
[:& palette-item {:color (:content item) :key (:id item)}])]]
(for [[idx item] (map-indexed vector current-colors)]
[:& palette-item {:size size
:color item
:key idx}])]]
[:span.right-arrow {:on-click on-right-arrow-click} i/arrow-slide]]))
(defn recent->colors [recent-colors]
(map #(hash-map :value %) (reverse (or recent-colors []))))
(defn file->colors [file-colors]
(map #(select-keys % [:id :value :name]) (vals file-colors)))
(defn library->colors [shared-libs selected]
(map #(merge {:file-id selected} (select-keys % [:id :value :name]))
(vals (get-in shared-libs [selected :data :colors]))))
(mf/defc colorpalette
[{:keys [left-sidebar? team-id] :as props}]
(let [palettes (->> (mf/deref palettes-ref)
(vals)
(mapcat identity))
selected (or (mf/deref selected-palette-ref)
(:id (first palettes)))]
[{:keys [left-sidebar? team-id]}]
(let [recent-colors (mf/deref refs/workspace-recent-colors)
file-colors (mf/deref refs/workspace-file-colors)
shared-libs (mf/deref refs/workspace-libraries)
selected (or (mf/deref selected-palette-ref) :recent)
size (or (mf/deref selected-palette-size-ref) :big)
current-library-colors (mf/use-state [])]
(mf/use-effect
(mf/deps team-id)
(fn []))
;; (st/emit! (dlib/retrieve-libraries :palettes)
;; (dlib/retrieve-libraries :palettes team-id))))
(mf/deps selected)
(fn []
(reset! current-library-colors
(into []
(cond
(= selected :recent) (recent->colors recent-colors)
(= selected :file) (file->colors file-colors)
:else (library->colors shared-libs selected))))))
(mf/use-effect
(mf/deps recent-colors)
(fn []
(when (= selected :recent)
(reset! current-library-colors (into [] (recent->colors recent-colors))))))
(mf/use-effect
(mf/deps file-colors)
(fn []
(when (= selected :file)
(reset! current-library-colors (into [] (file->colors file-colors))))))
[:& palette {:left-sidebar? left-sidebar?
:current-colors @current-library-colors
:recent-colors recent-colors
:file-colors file-colors
:shared-libs shared-libs
:selected selected
:palettes palettes}]))
:size size}]))

View file

@ -18,9 +18,11 @@
[app.common.math :as math]
[app.common.uuid :refer [uuid]]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.colors :as dwc]
[app.main.ui.modal :as modal]
[okulary.core :as l]
[app.main.refs :as refs]))
[app.main.refs :as refs]
[app.util.i18n :as i18n :refer [t]]))
;; --- Color Picker Modal
@ -100,9 +102,16 @@
shared-libs (mf/deref refs/workspace-libraries)
recent-colors (mf/deref refs/workspace-recent-colors)
locale (mf/deref i18n/locale)
value-ref (mf/use-var value)
on-change (or on-change identity)]
on-change (or on-change identity)
parse-selected (fn [selected]
(if (#{"recent" "file"} selected)
(keyword selected)
(uuid selected)) )]
;; Update state when there is a change in the props upstream
(mf/use-effect
@ -140,7 +149,8 @@
(mf/use-effect
(mf/deps file-colors)
(fn [] (when (= @selected-library "file")
(reset! current-library-colors (into [] (map :value (vals file-colors)))))))
(let [colors (map #(select-keys % [:id :value]) (vals file-colors))]
(reset! current-library-colors (into [] colors))))))
;; When closing the modal we update the recent-color list
(mf/use-effect
@ -263,8 +273,8 @@
(let [val (-> e dom/get-target dom/get-value)]
(reset! selected-library val)))
:value @selected-library}
[:option {:value "recent"} "Recent colors"]
[:option {:value "file"} "File library"]
[:option {:value "recent"} (t locale "workspace.libraries.colors.recent-colors")]
[:option {:value "file"} (t locale "workspace.libraries.colors.file-library")]
(for [[_ {:keys [name id]}] shared-libs]
[:option {:key id
:value id} name])]
@ -275,7 +285,8 @@
:on-click #(st/emit! (dwl/add-color (:hex @current-color)))}
i/plus])
[:div.color-bullet.button {:style {:background-color "white"}}
[:div.color-bullet.button {:style {:background-color "white"}
:on-click #(st/emit! (dwc/show-palette (parse-selected @selected-library)))}
i/palette]
(for [[idx {:keys [id file-id value]}] (map-indexed vector @current-library-colors)]
@ -298,7 +309,7 @@
{:on-click (fn []
(on-accept @value-ref)
(modal/hide!))}
"Save color"]])])
(t locale "workspace.libraries.colors.save-color")]])])
)
(mf/defc colorpicker-modal