Improvements after review

This commit is contained in:
alonso.torres 2023-11-27 22:59:20 +01:00
parent 6b5c75bf6a
commit a899d94619
17 changed files with 359 additions and 256 deletions

View file

@ -217,9 +217,9 @@
:tab-index "0" :tab-index "0"
:on-key-down (fn [event] :on-key-down (fn [event]
(dom/prevent-default event))} (dom/prevent-default event))}
[:div {:class (stl/css :context-menu-action :submenu-back) [:button {:class (stl/css :context-menu-action :submenu-back)
:data-no-close true :data-no-close true
:on-click exit-submenu} :on-click exit-submenu}
[:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor] [:span {:class (stl/css :submenu-icon-back)} i/arrow-refactor]
parent-option]] parent-option]]

View file

@ -72,6 +72,9 @@
display: flex; display: flex;
align-items: center; align-items: center;
font-weight: $fw700; font-weight: $fw700;
background: none;
border: none;
cursor: pointer;
.submenu-icon-back svg { .submenu-icon-back svg {
@extend .button-icon-small; @extend .button-icon-small;
stroke: var(--menu-foreground-color); stroke: var(--menu-foreground-color);

View file

@ -85,17 +85,17 @@
} }
.dropdown { .dropdown {
@include menuShadow;
background-color: $db-tertiary; background-color: $db-tertiary;
border-radius: $br-8; border-radius: $br-8;
border: $s-1 solid transparent; border: $s-1 solid transparent;
bottom: $s-4; bottom: $s-4;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
height: 40vh; height: 40vh;
max-height: $s-480; max-height: $s-480;
min-height: $s-200; min-height: $s-200;
position: absolute; position: absolute;
width: 100%; width: 100%;
z-index: 12; z-index: $z-index-3;
hr { hr {
margin: 0; margin: 0;

View file

@ -113,7 +113,13 @@
(fn [items] (fn [items]
(run! on-delete items)) (run! on-delete items))
problematic-fonts? (some :height-warning? (vals @fonts))] problematic-fonts? (some :height-warning? (vals @fonts))
handle-upload-all
(mf/use-callback (mf/deps @fonts) #(on-upload-all (vals @fonts)))
handle-dismiss-all
(mf/use-callback (mf/deps @fonts) #(on-dismiss-all (vals @fonts)))]
(if new-css-system (if new-css-system
[:div {:class (stl/css :dashboard-fonts-upload)} [:div {:class (stl/css :dashboard-fonts-upload)}
@ -144,20 +150,18 @@
[:div {:class (stl/css :icon)} i/msg-warning] [:div {:class (stl/css :icon)} i/msg-warning]
[:div {:class (stl/css :content)} [:div {:class (stl/css :content)}
[:& i18n/tr-html {:tag-name "span" [:& i18n/tr-html {:tag-name "span"
:label "dashboard.fonts.warning-text"}]]])] :label "dashboard.fonts.warning-text"}]]])]]
]
[:* [:*
(when (some? (vals @fonts)) (when (some? (vals @fonts))
[:div {:class (stl/css :font-item :table-row)} [:div {:class (stl/css :font-item :table-row)}
[:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))] [:span (tr "dashboard.fonts.fonts-added" (i18n/c (count (vals @fonts))))]
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:div {:class (stl/css :btn-primary) [:button {:class (stl/css :btn-primary)
:on-click #(on-upload-all (vals @fonts)) :data-test "upload-all"} :on-click handle-upload-all :data-test "upload-all"}
[:span (tr "dashboard.fonts.upload-all")]] [:span (tr "dashboard.fonts.upload-all")]]
[:div {:class (stl/css :btn-secondary) [:button {:class (stl/css :btn-secondary)
:on-click #(on-dismiss-all (vals @fonts)) :data-test "dismiss-all"} :on-click handle-dismiss-all :data-test "dismiss-all"}
[:span (tr "dashboard.fonts.dismiss-all")]]]]) [:span (tr "dashboard.fonts.dismiss-all")]]]])
(for [item (sort-by :font-family (vals @fonts))] (for [item (sort-by :font-family (vals @fonts))]
@ -340,19 +344,16 @@
:on-click #(on-delete-variant (:id item))} :on-click #(on-delete-variant (:id item))}
i/plus]])] i/plus]])]
[:div]
(if @edit? (if @edit?
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:button [:button
{ {:disabled (str/blank? @state)
:disabled (str/blank? @state)
:on-click on-save :on-click on-save
:class (stl/css-case :btn-primary true :class (stl/css-case :btn-primary true
:btn-disabled (str/blank? @state))} :btn-disabled (str/blank? @state))}
(tr "labels.save")] (tr "labels.save")]
[:span {:class (stl/css :icon :close) [:button {:class (stl/css :icon :close)
:on-click on-cancel} i/close]] :on-click on-cancel} i/close]]
[:div {:class (stl/css :table-field :options)} [:div {:class (stl/css :table-field :options)}
[:span {:class (stl/css :icon) [:span {:class (stl/css :icon)
@ -427,7 +428,6 @@
[:div {:class (stl/css :installed-fonts-header)} [:div {:class (stl/css :installed-fonts-header)}
[:div {:class (stl/css :table-field :family)} (tr "labels.font-family")] [:div {:class (stl/css :table-field :family)} (tr "labels.font-family")]
[:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")] [:div {:class (stl/css :table-field :variants)} (tr "labels.font-variants")]
[:div]
[:div {:class (stl/css :table-field :search-input)} [:div {:class (stl/css :table-field :search-input)}
[:input {:placeholder (tr "labels.search-font") [:input {:placeholder (tr "labels.search-font")
:default-value "" :default-value ""

View file

@ -14,6 +14,10 @@
padding-left: $s-120; padding-left: $s-120;
overflow-y: auto; overflow-y: auto;
padding-bottom: $s-120; padding-bottom: $s-120;
.btn-primary {
font-size: $fs-11;
}
} }
.dashboard-installed-fonts { .dashboard-installed-fonts {
@ -193,6 +197,8 @@
} }
&.close { &.close {
background: none;
border: none;
svg { svg {
transform: rotate(45deg); transform: rotate(45deg);
fill: $df-secondary; fill: $df-secondary;

View file

@ -431,7 +431,19 @@
(dom/stop-propagation event) (dom/stop-propagation event)
(swap! local assoc (swap! local assoc
:edition true :edition true
:menu-open false)))] :menu-open false)))
handle-key-down
(mf/use-callback
(mf/deps on-navigate on-select)
(fn [event]
(dom/stop-propagation event)
(when (kbd/enter? event)
(on-navigate event))
(when (kbd/shift? event)
(when (or (kbd/down-arrow? event) (kbd/left-arrow? event) (kbd/up-arrow? event) (kbd/right-arrow? event))
(on-select event)) ;; TODO Fix this
)))]
(mf/with-effect [selected? local] (mf/with-effect [selected? local]
(when (and (not selected?) (:menu-open @local)) (when (and (not selected?) (:menu-open @local))
@ -441,19 +453,11 @@
[:li [:li
{:class (stl/css-case :grid-item true :project-th true :library library-view?)} {:class (stl/css-case :grid-item true :project-th true :library library-view?)}
[:button [:button
{:tab-index "0" {:class (stl/css-case :selected selected? :library library-view?)
:class (stl/css-case :selected selected? :library library-view?)
:ref node-ref :ref node-ref
:draggable true :draggable true
:on-click on-select :on-click on-select
:on-key-down (fn [event] :on-key-down handle-key-down
(dom/stop-propagation event)
(when (kbd/enter? event)
(on-navigate event))
(when (kbd/shift? event)
(when (or (kbd/down-arrow? event) (kbd/left-arrow? event) (kbd/up-arrow? event) (kbd/right-arrow? event))
(on-select event)) ;; TODO Fix this
))
:on-double-click on-navigate :on-double-click on-navigate
:on-drag-start on-drag-start :on-drag-start on-drag-start
:on-context-menu on-menu-click} :on-context-menu on-menu-click}

View file

@ -170,7 +170,7 @@
width: $s-32; width: $s-32;
height: $s-32; height: $s-32;
background-color: $da-tertiary; background-color: $da-tertiary;
border-radius: 50%; border-radius: $br-circle;
color: $db-secondary; color: $db-secondary;
font-size: $fs-16; font-size: $fs-16;
display: flex; display: flex;

View file

@ -257,9 +257,9 @@
toggle-pin toggle-pin
(mf/use-fn (mf/use-fn
(mf/deps project) (mf/deps project)
(fn [event] (fn [event]
(dom/stop-propagation event) (dom/stop-propagation event)
(st/emit! (dd/toggle-project-pin project)))) (st/emit! (dd/toggle-project-pin project))))
on-menu-click on-menu-click
(mf/use-fn (mf/use-fn
@ -324,7 +324,23 @@
(st/emit! (dd/fetch-files {:project-id project-id}) (st/emit! (dd/fetch-files {:project-id project-id})
(dd/fetch-recent-files (:id team)) (dd/fetch-recent-files (:id team))
(dd/fetch-projects (:id team)) (dd/fetch-projects (:id team))
(dd/clear-selected-files))))] (dd/clear-selected-files))))
handle-create-click
(mf/use-callback
(mf/deps on-create-click)
(fn [event]
(when (kbd/enter? event)
(on-create-click event))))
handle-menu-click
(mf/use-callback
(mf/deps on-menu-click)
(fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event))))]
(if new-css-system (if new-css-system
[:article {:class (stl/css-case :dashboard-project-row true :first first?)} [:article {:class (stl/css-case :dashboard-project-row true :first first?)}
@ -375,10 +391,7 @@
:alt (tr "dashboard.new-file") :alt (tr "dashboard.new-file")
:aria-label (tr "dashboard.new-file") :aria-label (tr "dashboard.new-file")
:data-test "project-new-file" :data-test "project-new-file"
:tab-index "0" :on-key-down handle-create-click}
:on-key-down (fn [event]
(when (kbd/enter? event)
(on-create-click event)))}
i/close] i/close]
[:button [:button
@ -387,11 +400,7 @@
:alt (tr "dashboard.options") :alt (tr "dashboard.options")
:aria-label (tr "dashboard.options") :aria-label (tr "dashboard.options")
:data-test "project-options" :data-test "project-options"
:tab-index "0" :on-key-down handle-menu-click}
:on-key-down (fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions]]]] i/actions]]]]
[:& line-grid [:& line-grid

View file

@ -47,12 +47,13 @@
selected-project (:selected-project dstate) selected-project (:selected-project dstate)
edit-id (:project-for-edit dstate) edit-id (:project-for-edit dstate)
local (mf/use-state local* (mf/use-state
{:menu-open false {:menu-open false
:menu-pos nil :menu-pos nil
:edition? (= (:id item) edit-id) :edition? (= (:id item) edit-id)
:dragging? false}) :dragging? false})
local @local*
on-click on-click
(mf/use-callback (mf/use-callback
(mf/deps item) (mf/deps item)
@ -78,15 +79,15 @@
(fn [event] (fn [event]
(let [position (dom/get-client-position event)] (let [position (dom/get-client-position event)]
(dom/prevent-default event) (dom/prevent-default event)
(swap! local assoc (swap! local* assoc
:menu-open true :menu-open true
:menu-pos position)))) :menu-pos position))))
on-menu-close on-menu-close
(mf/use-callback #(swap! local assoc :menu-open false)) (mf/use-callback #(swap! local* assoc :menu-open false))
on-edit-open on-edit-open
(mf/use-callback #(swap! local assoc :edition? true)) (mf/use-callback #(swap! local* assoc :edition? true))
on-edit on-edit
(mf/use-callback (mf/use-callback
@ -94,7 +95,7 @@
(fn [name] (fn [name]
(st/emit! (-> (dd/rename-project (assoc item :name name)) (st/emit! (-> (dd/rename-project (assoc item :name name))
(with-meta {::ev/origin "dashboard:sidebar"}))) (with-meta {::ev/origin "dashboard:sidebar"})))
(swap! local assoc :edition? false))) (swap! local* assoc :edition? false)))
on-drag-enter on-drag-enter
(mf/use-callback (mf/use-callback
@ -104,7 +105,7 @@
(dom/prevent-default e) (dom/prevent-default e)
(when-not (dnd/from-child? e) (when-not (dnd/from-child? e)
(when (not= selected-project (:id item)) (when (not= selected-project (:id item))
(swap! local assoc :dragging? true)))))) (swap! local* assoc :dragging? true))))))
on-drag-over on-drag-over
(mf/use-callback (mf/use-callback
@ -116,7 +117,7 @@
(mf/use-callback (mf/use-callback
(fn [e] (fn [e]
(when-not (dnd/from-child? e) (when-not (dnd/from-child? e)
(swap! local assoc :dragging? false)))) (swap! local* assoc :dragging? false))))
on-drop-success on-drop-success
(mf/use-callback (mf/use-callback
@ -128,7 +129,7 @@
(mf/use-callback (mf/use-callback
(mf/deps item selected-files) (mf/deps item selected-files)
(fn [_] (fn [_]
(swap! local assoc :dragging? false) (swap! local* assoc :dragging? false)
(when (not= selected-project (:id item)) (when (not= selected-project (:id item))
(let [data {:ids selected-files (let [data {:ids selected-files
:project-id (:id item)} :project-id (:id item)}
@ -139,7 +140,7 @@
[:* [:*
[:li {:tab-index "0" [:li {:tab-index "0"
:class (if selected? (stl/css :current) :class (if selected? (stl/css :current)
(when (:dragging? @local) (stl/css :dragging))) (when (:dragging? local) (stl/css :dragging)))
:on-click on-click :on-click on-click
:on-key-down on-key-down :on-key-down on-key-down
:on-double-click on-edit-open :on-double-click on-edit-open
@ -148,14 +149,14 @@
:on-drag-over on-drag-over :on-drag-over on-drag-over
:on-drag-leave on-drag-leave :on-drag-leave on-drag-leave
:on-drop on-drop} :on-drop on-drop}
(if (:edition? @local) (if (:edition? local)
[:& inline-edition {:content (:name item) [:& inline-edition {:content (:name item)
:on-end on-edit}] :on-end on-edit}]
[:span {:class (stl/css :element-title)} (:name item)])] [:span {:class (stl/css :element-title)} (:name item)])]
[:& project-menu {:project item [:& project-menu {:project item
:show? (:menu-open @local) :show? (:menu-open local)
:left (:x (:menu-pos @local)) :left (:x (:menu-pos local))
:top (:y (:menu-pos @local)) :top (:y (:menu-pos local))
:on-edit on-edit-open :on-edit on-edit-open
:on-menu-close on-menu-close}]] :on-menu-close on-menu-close}]]
@ -163,7 +164,7 @@
[:* [:*
[:li {:tab-index "0" [:li {:tab-index "0"
:class (if selected? "current" :class (if selected? "current"
(when (:dragging? @local) "dragging")) (when (:dragging? local) "dragging"))
:on-click on-click :on-click on-click
:on-key-down on-key-down :on-key-down on-key-down
:on-double-click on-edit-open :on-double-click on-edit-open
@ -172,14 +173,14 @@
:on-drag-over on-drag-over :on-drag-over on-drag-over
:on-drag-leave on-drag-leave :on-drag-leave on-drag-leave
:on-drop on-drop} :on-drop on-drop}
(if (:edition? @local) (if (:edition? local)
[:& inline-edition {:content (:name item) [:& inline-edition {:content (:name item)
:on-end on-edit}] :on-end on-edit}]
[:span.element-title (:name item)])] [:span.element-title (:name item)])]
[:& project-menu {:project item [:& project-menu {:project item
:show? (:menu-open @local) :show? (:menu-open local)
:left (:x (:menu-pos @local)) :left (:x (:menu-pos local))
:top (:y (:menu-pos @local)) :top (:y (:menu-pos local))
:on-edit on-edit-open :on-edit on-edit-open
:on-menu-close on-menu-close}]]))) :on-menu-close on-menu-close}]])))
@ -225,7 +226,14 @@
(dom/focus! search-title) (dom/focus! search-title)
(dom/set-attribute! search-title "tabindex" "-1"))))) (dom/set-attribute! search-title "tabindex" "-1")))))
(dom/prevent-default e) (dom/prevent-default e)
(dom/stop-propagation e))))] (dom/stop-propagation e))))
handle-clear-search
(mf/use-callback
(mf/deps on-clear-click)
(fn [event]
(when (kbd/enter? event)
(on-clear-click event))))]
(if new-css-system (if new-css-system
[:form {:class (stl/css :sidebar-search)} [:form {:class (stl/css :sidebar-search)}
@ -249,9 +257,7 @@
{:class (stl/css :clear-search) {:class (stl/css :clear-search)
:tab-index "0" :tab-index "0"
:on-click on-clear-click :on-click on-clear-click
:on-key-down (fn [event] :on-key-down handle-clear-search}
(when (kbd/enter? event)
(on-clear-click event)))}
i/close] i/close]
[:div [:div
@ -299,14 +305,22 @@
team-selected team-selected
(mf/use-callback (mf/use-callback
(fn [team-id] (fn [team-id]
(st/emit! (dd/go-to-projects team-id))))] (st/emit! (dd/go-to-projects team-id))))
handle-select-default
(fn [event]
(when (kbd/enter? event)
(team-selected (:default-team-id profile) event)))
handle-select-team
(fn [id event]
(when (kbd/enter? event)
(team-selected id event)))]
(if new-css-system (if new-css-system
[:* [:*
[:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile)) [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile))
:on-key-down (fn [event] :on-key-down handle-select-default
(when (kbd/enter? event)
(team-selected (:default-team-id profile) event)))
:id "teams-selector-default-team" :id "teams-selector-default-team"
:class (stl/css :team-name)} :class (stl/css :team-name)}
[:span {:class (stl/css :team-icon)} i/logo-icon] [:span {:class (stl/css :team-icon)} i/logo-icon]
@ -316,9 +330,7 @@
(for [team-item (remove :is-default (vals teams))] (for [team-item (remove :is-default (vals teams))]
[:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item)) [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item))
:on-key-down (fn [event] :on-key-down (partial handle-select-team (:id team-item))
(when (kbd/enter? event)
(team-selected (:id team-item) event)))
:id (str "teams-selector-" (:id team-item)) :id (str "teams-selector-" (:id team-item))
:class (stl/css :team-name) :class (stl/css :team-name)
:key (str "teams-selector-" (:id team-item))} :key (str "teams-selector-" (:id team-item))}
@ -560,7 +572,47 @@
"teams-options-rename") "teams-options-rename")
"teams-options-leave-team" "teams-options-leave-team"
(when (get-in team [:permissions :is-owner]) (when (get-in team [:permissions :is-owner])
"teams-options-delete-team")]] "teams-options-delete-team")]
handle-show-team-click
(fn [event]
(dom/stop-propagation event)
(swap! show-teams-ddwn? not)
(reset! show-team-opts-ddwn? false))
handle-show-team-keydown
(fn [event]
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-teams-ddwn? true)
(reset! show-team-opts-ddwn? false)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first ids))]
(when first-element
(dom/focus! first-element)))))))
handle-show-opts-click
(fn [event]
(dom/stop-propagation event)
(swap! show-team-opts-ddwn? not)
(reset! show-teams-ddwn? false))
handle-show-opts-keydown
(fn [event]
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-team-opts-ddwn? true)
(reset! show-teams-ddwn? false)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first options-ids))]
(when first-element
(dom/focus! first-element)))))))
handle-close-team
(fn []
(reset! show-teams-ddwn? false))]
(if new-css-system (if new-css-system
[:div {:class (stl/css :sidebar-team-switch)} [:div {:class (stl/css :sidebar-team-switch)}
@ -568,21 +620,9 @@
[:button [:button
{:class (stl/css :current-team) {:class (stl/css :current-team)
:tab-index "0" :tab-index "0"
:on-click :on-click handle-show-team-click
(fn [event] :on-key-down handle-show-team-keydown}
(dom/stop-propagation event)
(reset! show-teams-ddwn? true))
:on-key-down
(fn [event]
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-teams-ddwn? true)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first ids))]
(when first-element
(dom/focus! first-element)))))))}
(if (:is-default team) (if (:is-default team)
[:div {:class (stl/css :team-name)} [:div {:class (stl/css :team-name)}
@ -599,24 +639,14 @@
(when-not (:is-default team) (when-not (:is-default team)
[:button [:button
{:class (stl/css :switch-options) {:class (stl/css :switch-options)
:on-click (fn [event] :on-click handle-show-opts-click
(dom/stop-propagation event)
(reset! show-team-opts-ddwn? true))
:tab-index "0" :tab-index "0"
:on-key-down (fn [event] :on-key-down handle-show-opts-keydown}
(when (or (kbd/space? event) (kbd/enter? event))
(dom/prevent-default event)
(reset! show-team-opts-ddwn? true)
(ts/schedule-on-idle
(fn []
(let [first-element (dom/get-element (first options-ids))]
(when first-element
(dom/focus! first-element)))))))}
i/actions])] i/actions])]
;; Teams Dropdown ;; Teams Dropdown
[:& dropdown-menu {:show @show-teams-ddwn? [:& dropdown-menu {:show @show-teams-ddwn?
:on-close #(reset! show-teams-ddwn? false) :on-close handle-close-team
:ids ids :ids ids
:list-class (stl/css :dropdown :teams-dropdown)} :list-class (stl/css :dropdown :teams-dropdown)}
[:& teams-selector-dropdown-items {:ids ids [:& teams-selector-dropdown-items {:ids ids
@ -922,7 +952,77 @@
handle-show-comments handle-show-comments
(mf/use-callback (mf/use-callback
(fn [] (fn []
(reset! show-comments* true)))] (reset! show-comments* true)))
handle-click
(mf/use-callback
(fn [event]
(dom/stop-propagation event)
(swap! show not)))
handle-key-down
(mf/use-callback
(fn [event]
(when (kbd/enter? event)
(reset! show true))))
handle-close
(fn [event]
(dom/stop-propagation event)
(reset! show false))
handle-key-down-profile
(mf/use-callback
(mf/deps on-click)
(fn [event]
(when (kbd/enter? event)
(on-click :settings-profile event))))
handle-click-url
(mf/use-callback
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))]
(dom/open-new-window url))))
handle-keydown-url
(mf/use-callback
(fn [event]
(let [url (-> (dom/get-current-target event)
(dom/get-data "url"))]
(when (kbd/enter? event)
(dom/open-new-window url)))))
handle-show-release-notes
(mf/use-callback
(mf/deps show-release-notes)
(fn [event]
(when (kbd/enter? event)
(show-release-notes))))
handle-feedback-click
(mf/use-callback
(mf/deps on-click)
#(on-click :settings-feedback %))
handle-feedback-keydown
(mf/use-callback
(mf/deps on-click)
(fn [event]
(when (kbd/enter? event)
(on-click :settings-feedback event))))
handle-logout-click
(mf/use-callback
(mf/deps on-click)
#(on-click (du/logout) %))
handle-logout-keydown
(mf/use-callback
(mf/deps on-click)
(fn [event]
(when (kbd/enter? event)
(on-click (du/logout) event))))]
(if new-css-system (if new-css-system
[:* [:*
(when (and team profile) (when (and team profile)
@ -936,99 +1036,78 @@
[:div {:class (stl/css :profile-section)} [:div {:class (stl/css :profile-section)}
[:div {:class (stl/css :profile) [:div {:class (stl/css :profile)
:tab-index "0" :tab-index "0"
:on-click (fn [event] :on-click handle-click
(dom/stop-propagation event) :on-key-down handle-key-down
(reset! show true))
:on-key-down (fn [event]
(when (kbd/enter? event)
(reset! show true)))
:data-test "profile-btn"} :data-test "profile-btn"}
[:img {:src photo [:img {:src photo
:alt (:fullname profile)}] :alt (:fullname profile)}]
[:span (:fullname profile)]] [:span (:fullname profile)]]
[:& dropdown-menu {:on-close (fn [event] [:& dropdown-menu {:on-close handle-close :show @show}
(dom/stop-propagation event)
(reset! show false))
:show @show}
[:ul {:class (stl/css :dropdown)} [:ul {:class (stl/css :dropdown)}
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click (partial on-click :settings-profile) :on-click (partial on-click :settings-profile)
:on-key-down (fn [event] :on-key-down handle-key-down-profile
(when (kbd/enter? event)
(on-click :settings-profile event)))
:data-test "profile-profile-opt"} :data-test "profile-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.your-account")]] [:span {:class (stl/css :text)} (tr "labels.your-account")]]
[:li {:class (stl/css :separator) [:li {:class (stl/css :separator)
:tab-index (if show "0" "-1") :tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://help.penpot.app") :data-url "https://help.penpot.app"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url
(dom/open-new-window "https://help.penpot.app")))
:data-test "help-center-profile-opt"} :data-test "help-center-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.help-center")]] [:span {:class (stl/css :text)} (tr "labels.help-center")]]
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://community.penpot.app") :data-url "https://community.penpot.app"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url}
(dom/open-new-window "https://community.penpot.app")))}
[:span {:class (stl/css :text)} (tr "labels.community")]] [:span {:class (stl/css :text)} (tr "labels.community")]]
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://www.youtube.com/c/Penpot") :data-url "https://www.youtube.com/c/Penpot"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url}
(dom/open-new-window "https://www.youtube.com/c/Penpot")))}
[:span {:class (stl/css :text)} (tr "labels.tutorials")]] [:span {:class (stl/css :text)} (tr "labels.tutorials")]]
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click show-release-notes :on-click show-release-notes
:on-key-down (fn [event] :on-key-down handle-show-release-notes}
(when (kbd/enter? event)
(show-release-notes)))}
[:span {:class (stl/css :text)} (tr "labels.release-notes")]] [:span {:class (stl/css :text)} (tr "labels.release-notes")]]
[:li {:class (stl/css :separator) [:li {:class (stl/css :separator)
:tab-index (if show "0" "-1") :tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://penpot.app/libraries-templates") :data-url "https://penpot.app/libraries-templates"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url
(dom/open-new-window "https://penpot.app/libraries-templates")))
:data-test "libraries-templates-profile-opt"} :data-test "libraries-templates-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]] [:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]]
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://github.com/penpot/penpot") :data-url "https://github.com/penpot/penpot"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url}
(dom/open-new-window "https://github.com/penpot/penpot")))}
[:span {:class (stl/css :text)} (tr "labels.github-repo")]] [:span {:class (stl/css :text)} (tr "labels.github-repo")]]
[:li {:tab-index (if show "0" "-1") [:li {:tab-index (if @show "0" "-1")
:on-click #(dom/open-new-window "https://penpot.app/terms") :data-url "https://penpot.app/terms"
:on-key-down (fn [event] :on-click handle-click-url
(when (kbd/enter? event) :on-key-down handle-keydown-url}
(dom/open-new-window "https://penpot.app/terms")))}
[:span {:class (stl/css :text)} (tr "auth.terms-of-service")]] [:span {:class (stl/css :text)} (tr "auth.terms-of-service")]]
(when (contains? cf/flags :user-feedback) (when (contains? cf/flags :user-feedback)
[:li {:class (stl/css :separator) [:li {:class (stl/css :separator)
:tab-index (if show "0" "-1") :tab-index (if @show "0" "-1")
:on-click (partial on-click :settings-feedback) :on-click handle-feedback-click
:on-key-down (fn [event] :on-key-down handle-feedback-keydown
(when (kbd/enter? event)
(on-click :settings-feedback event)))
:data-test "feedback-profile-opt"} :data-test "feedback-profile-opt"}
[:span {:class (stl/css :text)} (tr "labels.give-feedback")]]) [:span {:class (stl/css :text)} (tr "labels.give-feedback")]])
[:li {:class (stl/css :separator) [:li {:class (stl/css :separator)
:tab-index (if show "0" "-1") :tab-index (if @show "0" "-1")
:on-click #(on-click (du/logout) %) :on-click handle-logout-click
:on-key-down (fn [event] :on-key-down handle-logout-keydown
(when (kbd/enter? event)
(on-click (du/logout) event)))
:data-test "logout-profile-opt"} :data-test "logout-profile-opt"}
[:span {:class (stl/css :icon)} i/exit] [:span {:class (stl/css :icon)} i/exit]
[:span {:class (stl/css :text)} (tr "labels.logout")]]]] [:span {:class (stl/css :text)} (tr "labels.logout")]]]]
@ -1176,4 +1255,3 @@
[:& profile-section [:& profile-section
{:profile profile {:profile profile
:team team}]]))) :team team}]])))

View file

@ -16,7 +16,7 @@
margin: 0 $s-16 0 0; margin: 0 $s-16 0 0;
padding: $s-16 0 0 0; padding: $s-16 0 0 0;
z-index: 1; z-index: $z-index-1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
@ -123,6 +123,7 @@
cursor: pointer; cursor: pointer;
background-color: transparent; background-color: transparent;
border: none; border: none;
height: 100%;
svg { svg {
fill: $df-secondary; fill: $df-secondary;
@ -140,12 +141,12 @@
} }
.dropdown { .dropdown {
@include menuShadow;
position: absolute; position: absolute;
z-index: 12; z-index: $z-index-4;
background-color: $db-tertiary; background-color: $db-tertiary;
border: $s-1 solid $db-cuaternary; border: $s-1 solid $db-cuaternary;
border-radius: $br-8; border-radius: $br-8;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.25);
.separator { .separator {
border-color: transparent; border-color: transparent;
@ -199,7 +200,7 @@
left: 0; left: 0;
top: $s-52; top: $s-52;
z-index: 12;
max-height: $s-480; max-height: $s-480;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;

View file

@ -102,16 +102,8 @@
} }
} }
.btn-primary { .btn-primary {
flex-shrink: 0; @extends .button-primary;
width: 100%; height: $s-32;
font-size: $fs-12;
text-transform: uppercase;
background-color: $db-tertiary;
color: $df-primary;
&:hover {
color: $da-primary;
background-color: $db-cuaternary;
}
} }
} }
@ -127,7 +119,7 @@
position: absolute; position: absolute;
top: $s-32; top: $s-32;
width: $s-152; width: $s-152;
z-index: 12; z-index: $z-index-4;
hr { hr {
margin: 0; margin: 0;
@ -511,7 +503,7 @@
align-items: center; align-items: center;
border-radius: 50%; border-radius: 50%;
color: $df-primary; color: $df-primary;
z-index: 14; z-index: $z-index-modal;
background-color: $da-primary; background-color: $da-primary;
height: $s-120; height: $s-120;

View file

@ -10,8 +10,8 @@
.dashboard { .dashboard {
background-color: $db-primary; background-color: $db-primary;
display: grid; display: grid;
grid-template-rows: 50px 1fr; grid-template-rows: $s-48 1fr;
grid-template-columns: 40px 256px 1fr; grid-template-columns: $s-40 $s-256 1fr;
height: 100vh; height: 100vh;
} }
@ -20,7 +20,7 @@
flex-direction: column; flex-direction: column;
position: relative; position: relative;
grid-row: 1 / span 2; grid-row: 1 / span 2;
padding: 1rem 1rem 0 0; padding: $s-16 $s-16 0 0;
} }
.dashboard-container { .dashboard-container {
@ -54,24 +54,24 @@
} }
.form-container { .form-container {
width: 800px; width: $s-800;
margin: 50px auto 2rem 120px; margin: $s-48 auto $s-32 $s-120;
display: flex; display: flex;
max-width: 368px; max-width: $s-368;
width: 100%; width: 100%;
&.two-columns { &.two-columns {
max-width: 536px; max-width: $s-520;
justify-content: space-between; justify-content: space-between;
flex-direction: row; flex-direction: row;
} }
h2 { h2 {
margin-bottom: 1rem; margin-bottom: $s-16;
} }
form { form {
width: 468px; width: $s-468;
.custom-input, .custom-input,
.custom-select { .custom-select {
@ -80,26 +80,26 @@
position: relative; position: relative;
text-transform: uppercase; text-transform: uppercase;
color: $df-primary; color: $df-primary;
font-size: 11px; font-size: $fs-11;
margin-bottom: 12px; margin-bottom: $s-12;
margin-left: -4px; margin-left: calc(-1 * $s-4);
} }
input, input,
select { select {
background-color: $db-tertiary; background-color: $db-tertiary;
border-radius: 8px; border-radius: $s-8;
border-color: transparent; border-color: transparent;
color: $df-primary; color: $df-primary;
padding: 0 15px; padding: 0 $s-16;
&:focus { &:focus {
outline: 1px solid $da-primary; outline: $s-1 solid $da-primary;
} }
::placeholder { ::placeholder {
color: $df-secondary; color: $df-secondary;
} }
} }
.help-icon { .help-icon {
bottom: 12px; bottom: $s-12;
top: auto; top: auto;
svg { svg {
fill: $df-secondary; fill: $df-secondary;
@ -114,30 +114,30 @@
} }
.input-container { .input-container {
background-color: $db-tertiary; background-color: $db-tertiary;
border-radius: 8px; border-radius: $s-8;
border-color: transparent; border-color: transparent;
margin-top: 22px; margin-top: $s-24;
.main-content { .main-content {
label { label {
position: absolute; position: absolute;
top: -24px; top: calc(-1 * $s-24);
} }
span { span {
color: $df-primary; color: $df-primary;
} }
} }
&:focus { &:focus {
border: 1px solid $da-primary; border: $s-1 solid $da-primary;
} }
} }
textarea { textarea {
border-radius: 8px; border-radius: $s-8;
padding: 12px 14px; padding: $s-12 $s-16;
background-color: $db-tertiary; background-color: $db-tertiary;
color: $df-primary; color: $df-primary;
border: none; border: none;
&:focus { &:focus {
outline: 1px solid $da-primary; outline: $s-1 solid $da-primary;
} }
} }
} }
@ -146,7 +146,7 @@
color: $df-primary; color: $df-primary;
} }
.field-title:not(:first-child) { .field-title:not(:first-child) {
margin-top: 64px; margin-top: $s-64;
} }
.field-text { .field-text {
@ -155,7 +155,7 @@
button, button,
.btn-secondary { .btn-secondary {
width: 100%; width: 100%;
font-size: 11px; font-size: $fs-11;
text-transform: uppercase; text-transform: uppercase;
background-color: $db-tertiary; background-color: $db-tertiary;
color: $df-primary; color: $df-primary;
@ -169,21 +169,21 @@
} }
} }
.links { .links {
margin-top: 12px; margin-top: $s-12;
} }
} }
.profile-form { .profile-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
max-width: 368px; max-width: $s-368;
width: 100%; width: 100%;
.newsletter-subs { .newsletter-subs {
border-bottom: 1px solid $df-secondary; border-bottom: $s-1 solid $df-secondary;
border-top: 1px solid $df-secondary; border-top: $s-1 solid $df-secondary;
padding: 30px 0; padding: $s-32 0;
margin-bottom: 31px; margin-bottom: $s-32;
.newsletter-title { .newsletter-title {
font-family: "worksans", sans-serif; font-family: "worksans", sans-serif;
@ -195,15 +195,15 @@
font-family: "worksans", sans-serif; font-family: "worksans", sans-serif;
color: $db-primary; color: $db-primary;
font-size: $fs-12; font-size: $fs-12;
margin-right: -17px; margin-right: calc(-1 * $s-16);
margin-bottom: 13px; margin-bottom: $s-12;
} }
.info { .info {
font-family: "worksans", sans-serif; font-family: "worksans", sans-serif;
color: $df-secondary; color: $df-secondary;
font-size: $fs-12; font-size: $fs-12;
margin-bottom: 8px; margin-bottom: $s-8;
} }
.input-checkbox label { .input-checkbox label {
@ -215,28 +215,28 @@
.avatar-form { .avatar-form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 120px; width: $s-120;
min-width: 120px; min-width: $s-120;
img { img {
border-radius: 50%; border-radius: 50%;
flex-shrink: 0; flex-shrink: 0;
height: 120px; height: $s-120;
margin-right: $s-16; margin-right: $s-16;
width: 120px; width: $s-120;
} }
.image-change-field { .image-change-field {
position: relative; position: relative;
width: 120px; width: $s-120;
height: 120px; height: $s-120;
.update-overlay { .update-overlay {
opacity: 0; opacity: 0;
cursor: pointer; cursor: pointer;
position: absolute; position: absolute;
width: 121px; width: $s-120;
height: 121px; height: $s-120;
border-radius: 50%; border-radius: 50%;
font-size: $fs-24; font-size: $fs-24;
color: $df-primary; color: $df-primary;
@ -247,8 +247,8 @@
} }
input[type="file"] { input[type="file"] {
width: 120px; width: $s-120;
height: 120px; height: $s-120;
position: absolute; position: absolute;
opacity: 0; opacity: 0;
cursor: pointer; cursor: pointer;
@ -268,6 +268,6 @@
.password-form { .password-form {
h2 { h2 {
font-size: $fs-14; font-size: $fs-14;
margin-bottom: 20px; margin-bottom: $s-20;
} }
} }

View file

@ -291,7 +291,15 @@
(mf/use-fn (mf/use-fn
(fn [event] (fn [event]
(dom/prevent-default event) (dom/prevent-default event)
(swap! local assoc :menu-open true)))] (swap! local assoc :menu-open true)))
on-keydown
(mf/use-callback
(mf/deps on-menu-click)
(fn [event]
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event))))]
(if new-css-system (if new-css-system
[:div [:div
@ -299,10 +307,7 @@
:tab-index "0" :tab-index "0"
:ref menu-ref :ref menu-ref
:on-click on-menu-click :on-click on-menu-click
:on-key-down (fn [event] :on-key-down on-keydown}
(when (kbd/enter? event)
(dom/stop-propagation event)
(on-menu-click event)))}
i/actions i/actions
[:& context-menu-a11y [:& context-menu-a11y
{:on-close on-menu-close {:on-close on-menu-close

View file

@ -49,7 +49,15 @@
form (fm/use-form :spec ::profile-form form (fm/use-form :spec ::profile-form
:initial profile :initial profile
:validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long")) :validators [(fm/validate-length :fullname fm/max-length-allowed (tr "auth.name.too-long"))
(fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))])] (fm/validate-not-empty :fullname (tr "auth.name.not-all-space"))])
handle-show-change-email
(mf/use-callback
#(modal/show! :change-email {}))
handle-show-delete-account
(mf/use-callback
#(modal/show! :delete-account {}))]
(if new-css-system (if new-css-system
[:& fm/form {:on-submit on-submit [:& fm/form {:on-submit on-submit
@ -62,7 +70,7 @@
:label (tr "dashboard.your-name")}]] :label (tr "dashboard.your-name")}]]
[:div {:class (stl/css :fields-row) [:div {:class (stl/css :fields-row)
:on-click #(modal/show! :change-email {})} :on-click handle-show-change-email}
[:& fm/input [:& fm/input
{:type "email" {:type "email"
:name :email :name :email
@ -72,7 +80,7 @@
[:div {:class (stl/css :options)} [:div {:class (stl/css :options)}
[:div.change-email [:div.change-email
[:a {:on-click #(modal/show! :change-email {})} [:a {:on-click handle-show-change-email}
(tr "dashboard.change-email")]]]] (tr "dashboard.change-email")]]]]
[:> fm/submit-button* [:> fm/submit-button*
@ -82,7 +90,7 @@
[:div {:class (stl/css :links)} [:div {:class (stl/css :links)}
[:div {:class (stl/css :link-item)} [:div {:class (stl/css :link-item)}
[:a {:on-click #(modal/show! :delete-account {}) [:a {:on-click handle-show-delete-account
:data-test "remove-acount-btn"} :data-test "remove-acount-btn"}
(tr "dashboard.remove-account")]]]] (tr "dashboard.remove-account")]]]]

View file

@ -266,7 +266,7 @@ form.avatar-form {
line-height: 6; line-height: 6;
text-align: center; text-align: center;
background: $da-tertiary; background: $da-tertiary;
z-index: 14; z-index: $z-index-modal;
} }
input[type="file"] { input[type="file"] {
@ -276,7 +276,7 @@ form.avatar-form {
opacity: 0; opacity: 0;
cursor: pointer; cursor: pointer;
top: 0; top: 0;
z-index: 15; z-index: $z-index-modal;
} }
&:hover { &:hover {

View file

@ -16,7 +16,7 @@
height: 100%; height: 100%;
margin: 0 $s-16 0 0; margin: 0 $s-16 0 0;
padding: $s-16 0 0 0; padding: $s-16 0 0 0;
z-index: 1; z-index: $z-index-1;
} }
.sidebar-content { .sidebar-content {

View file

@ -57,65 +57,62 @@
(mf/defc bad-gateway (mf/defc bad-gateway
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (let [new-css-system (mf/use-ctx ctx/new-css-system)
handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system (if new-css-system
[:> static-header {} [:> static-header {}
[:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")] [:div {:class (stl/css :main-message)} (tr "labels.bad-gateway.main-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")] [:div {:class (stl/css :desc-message)} (tr "labels.bad-gateway.desc-message")]
[:div {:class (stl/css :sign-info)} [:div {:class (stl/css :sign-info)}
[:button [:button {:on-click handle-retry} (tr "labels.retry")]]]
{:on-click (fn [] (st/emit! (rt/assign-exception nil)))}
(tr "labels.retry")]]]
[:> static-header {} [:> static-header {}
[:div.image i/icon-empty] [:div.image i/icon-empty]
[:div.main-message (tr "labels.bad-gateway.main-message")] [:div.main-message (tr "labels.bad-gateway.main-message")]
[:div.desc-message (tr "labels.bad-gateway.desc-message")] [:div.desc-message (tr "labels.bad-gateway.desc-message")]
[:div.sign-info [:div.sign-info
[:a.btn-primary.btn-small [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
{:on-click (fn [] (st/emit! #(dissoc % :exception)))}
(tr "labels.retry")]]])))
(mf/defc service-unavailable (mf/defc service-unavailable
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (let [new-css-system (mf/use-ctx ctx/new-css-system)
handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system (if new-css-system
[:> static-header {} [:> static-header {}
[:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")] [:div {:class (stl/css :main-message)} (tr "labels.service-unavailable.main-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")] [:div {:class (stl/css :desc-message)} (tr "labels.service-unavailable.desc-message")]
[:div {:class (stl/css :sign-info)} [:div {:class (stl/css :sign-info)}
[:button [:button {:on-click handle-retry} (tr "labels.retry")]]]
{:on-click (fn [] (st/emit! (rt/assign-exception nil)))}
(tr "labels.retry")]]]
[:> static-header {} [:> static-header {}
[:div.main-message (tr "labels.service-unavailable.main-message")] [:div.main-message (tr "labels.service-unavailable.main-message")]
[:div.desc-message (tr "labels.service-unavailable.desc-message")] [:div.desc-message (tr "labels.service-unavailable.desc-message")]
[:div.sign-info [:div.sign-info
[:a.btn-primary.btn-small [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
{:on-click (fn [] (st/emit! #(dissoc % :exception)))}
(tr "labels.retry")]]])))
(mf/defc internal-error (mf/defc internal-error
[] []
(let [new-css-system (mf/use-ctx ctx/new-css-system)] (let [new-css-system (mf/use-ctx ctx/new-css-system)
handle-retry
(mf/use-callback
(fn [] (st/emit! (rt/assign-exception nil))))]
(if new-css-system (if new-css-system
[:> static-header {} [:> static-header {}
[:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")] [:div {:class (stl/css :main-message)} (tr "labels.internal-error.main-message")]
[:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")] [:div {:class (stl/css :desc-message)} (tr "labels.internal-error.desc-message")]
[:div {:class (stl/css :sign-info)} [:div {:class (stl/css :sign-info)}
[:button [:button {:on-click handle-retry} (tr "labels.retry")]]]
{:on-click (fn [] (st/emit! (rt/assign-exception nil)))}
(tr "labels.retry")]]]
[:> static-header {} [:> static-header {}
[:div.image i/icon-empty] [:div.image i/icon-empty]
[:div.main-message (tr "labels.internal-error.main-message")] [:div.main-message (tr "labels.internal-error.main-message")]
[:div.desc-message (tr "labels.internal-error.desc-message")] [:div.desc-message (tr "labels.internal-error.desc-message")]
[:div.sign-info [:div.sign-info
[:a.btn-primary.btn-small [:a.btn-primary.btn-small {:on-click handle-retry} (tr "labels.retry")]]])))
{:on-click (fn [] (st/emit! (rt/assign-exception nil)))}
(tr "labels.retry")]]])))
(mf/defc exception-page (mf/defc exception-page
[{:keys [data] :as props}] [{:keys [data] :as props}]