From c2b8e5c946cd96887f517f275b40ab3827e5fa13 Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Fri, 1 Mar 2024 15:57:29 +0100 Subject: [PATCH] :recycle: Refactor dashboard sidebar css --- .../styles/common/refactor/basic-rules.scss | 1 + .../styles/common/refactor/design-tokens.scss | 17 + frontend/src/app/main/ui/components/link.cljs | 4 +- .../src/app/main/ui/dashboard/sidebar.cljs | 604 ++++++++------ .../src/app/main/ui/dashboard/sidebar.scss | 751 ++++++++---------- 5 files changed, 700 insertions(+), 677 deletions(-) diff --git a/frontend/resources/styles/common/refactor/basic-rules.scss b/frontend/resources/styles/common/refactor/basic-rules.scss index b7d4b68583..61a1c4c497 100644 --- a/frontend/resources/styles/common/refactor/basic-rules.scss +++ b/frontend/resources/styles/common/refactor/basic-rules.scss @@ -848,6 +848,7 @@ color: var(--title-foreground-color-hover); background-color: var(--menu-background-color); border: $s-2 solid var(--panel-border-color); + margin: 0; } .menu-item-base { diff --git a/frontend/resources/styles/common/refactor/design-tokens.scss b/frontend/resources/styles/common/refactor/design-tokens.scss index d4f854702f..eb1116b7f7 100644 --- a/frontend/resources/styles/common/refactor/design-tokens.scss +++ b/frontend/resources/styles/common/refactor/design-tokens.scss @@ -155,6 +155,7 @@ --icon-foreground-hover: var(--color-foreground-primary); --icon-foreground-accept: var(--status-color-success-500); --icon-foreground-discard: var(--status-color-error-500); + --icon-foreground-active: var(--color-accent-primary); // INPUTS, SELECTS, DROPDOWNS @@ -201,6 +202,7 @@ --menu-background-color: var(--color-background-tertiary); --menu-foreground-color: var(--color-foreground-primary); + --menu-icon-foreground-color: var(--color-foreground-secondary); --menu-background-color-selected: var(--color-background-tertiary); --menu-background-color-hover: var(--color-background-quaternary); --menu-foreground-color-hover: var(--color-foreground-primary); @@ -358,6 +360,11 @@ --search-bar-background-color: var(--color-background-primary); --search-bar-input-background-color: var(--color-background-tertiary); --search-bar-input-border-color: var(--color-background-tertiary); + --search-bar-input-border-color-focus: var(--color-accent-primary); + --search-bar-placeholder-foreground-color: var(--color-foreground-secondary); + --search-bar-foreground-color: var(--color-foreground-primary); + --search-bar-icon-foreground-color: var(--color-foreground-secondary); + --search-bar-icon-foreground-color-hover: var(--color-accent-primary); --pill-background-color: var(--color-background-tertiary); --pill-foreground-color: var(--color-foreground-primary); @@ -369,6 +376,8 @@ --resize-area-background-color: var(--color-background-primary); --resize-area-border-color: var(--color-background-quaternary); + --profile-section-background-color: var(--color-background-tertiary); + --flow-tag-background-color: var(--color-background-tertiary); --flow-tag-foreground-color: var(--color-foreground-secondary); --flow-tag-background-color-hover: var(--color-background-quaternary); @@ -393,6 +402,14 @@ // NEW TEAM BUTTON // TODO: we should not put these functional tokens here, but rather in the components they belong to --new-team-button-background-color: var(--color-background-primary); + + //DASHBOARD + --sidebar-element-foreground-color: var(--color-foreground-secondary); + --sidebar-element-background-color-hover: var(--color-background-secondary); + --sidebar-element-foreground-color-hover: var(--color-accent-primary); + --sidebar-element-background-color-selected: var(--color-background-quaternary); + --sidebar-element-foreground-color-selected: var(--color-accent-primary); + --profile-foreground-color: var(--color-foreground-primary); } #app { diff --git a/frontend/src/app/main/ui/components/link.cljs b/frontend/src/app/main/ui/components/link.cljs index ddaad53615..4c48681bba 100644 --- a/frontend/src/app/main/ui/components/link.cljs +++ b/frontend/src/app/main/ui/components/link.cljs @@ -12,10 +12,10 @@ (mf/defc link {::mf/wrap-props false} - [{:keys [action klass data-test keyboard-action children]}] + [{:keys [action class data-test keyboard-action children]}] (let [keyboard-action (d/nilv keyboard-action action)] [:a {:on-click action - :class klass + :class class :on-key-down (fn [event] (when ^boolean (kbd/enter? event) (keyboard-action event))) diff --git a/frontend/src/app/main/ui/dashboard/sidebar.cljs b/frontend/src/app/main/ui/dashboard/sidebar.cljs index dffd26c787..7bad200fef 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.cljs +++ b/frontend/src/app/main/ui/dashboard/sidebar.cljs @@ -54,13 +54,13 @@ local @local* on-click - (mf/use-callback + (mf/use-fn (mf/deps item) (fn [] (st/emit! (dd/go-to-files (:id item))))) on-key-down - (mf/use-callback + (mf/use-fn (mf/deps item) (fn [event] (when (kbd/enter? event) @@ -74,7 +74,7 @@ (dom/set-attribute! project-title "tabindex" "-1"))))))))) on-menu-click - (mf/use-callback + (mf/use-fn (fn [event] (let [position (dom/get-client-position event)] (dom/prevent-default event) @@ -83,13 +83,13 @@ :menu-pos position)))) on-menu-close - (mf/use-callback #(swap! local* assoc :menu-open false)) + (mf/use-fn #(swap! local* assoc :menu-open false)) on-edit-open - (mf/use-callback #(swap! local* assoc :edition? true)) + (mf/use-fn #(swap! local* assoc :edition? true)) on-edit - (mf/use-callback + (mf/use-fn (mf/deps item) (fn [name] (when-not (str/blank? name) @@ -98,7 +98,7 @@ (swap! local* assoc :edition? false))) on-drag-enter - (mf/use-callback + (mf/use-fn (mf/deps selected-project) (fn [e] (when (dnd/has-type? e "penpot/files") @@ -108,25 +108,25 @@ (swap! local* assoc :dragging? true)))))) on-drag-over - (mf/use-callback + (mf/use-fn (fn [e] (when (dnd/has-type? e "penpot/files") (dom/prevent-default e)))) on-drag-leave - (mf/use-callback + (mf/use-fn (fn [e] (when-not (dnd/from-child? e) (swap! local* assoc :dragging? false)))) on-drop-success - (mf/use-callback + (mf/use-fn (mf/deps (:id item)) #(st/emit! (msg/success (tr "dashboard.success-move-file")) (dd/go-to-files (:id item)))) on-drop - (mf/use-callback + (mf/use-fn (mf/deps item selected-files) (fn [_] (swap! local* assoc :dragging? false) @@ -139,6 +139,7 @@ [:* [:li {:tab-index "0" :class (stl/css-case :project-element true + :sidebar-nav-item true :current selected? :dragging (:dragging? local)) :on-click on-click @@ -167,19 +168,19 @@ emit! (mf/use-memo #(f/debounce st/emit! 500)) on-search-blur - (mf/use-callback + (mf/use-fn (fn [_] (reset! focused? false))) on-search-change - (mf/use-callback + (mf/use-fn (mf/deps team-id) (fn [event] (let [value (dom/get-target-val event)] (emit! (dd/go-to-search value))))) on-clear-click - (mf/use-callback + (mf/use-fn (mf/deps team-id) (fn [e] (let [search-input (dom/get-element "search-input")] @@ -190,7 +191,7 @@ (dom/stop-propagation e)))) on-key-press - (mf/use-callback + (mf/use-fn (fn [e] (when (kbd/enter? e) (ts/schedule-on-idle @@ -204,93 +205,105 @@ (dom/stop-propagation e)))) handle-clear-search - (mf/use-callback + (mf/use-fn (mf/deps on-clear-click) (fn [event] (when (kbd/enter? event) (on-clear-click event))))] [:form {:class (stl/css :sidebar-search)} - [:input - {:class (stl/css :input-text) - :key "images-search-box" - :id "search-input" - :type "text" - :aria-label (tr "dashboard.search-placeholder") - :placeholder (tr "dashboard.search-placeholder") - :default-value search-term - :auto-complete "off" - ;; :on-focus on-search-focus - :on-blur on-search-blur - :on-change on-search-change - :on-key-press on-key-press - :ref #(when % (set! (.-value %) search-term))}] + [:input {:class (stl/css :input-text) + :key "images-search-box" + :id "search-input" + :type "text" + :aria-label (tr "dashboard.search-placeholder") + :placeholder (tr "dashboard.search-placeholder") + :default-value search-term + :auto-complete "off" + ;; :on-focus on-search-focus + :on-blur on-search-blur + :on-change on-search-change + :on-key-press on-key-press + :ref #(when % (set! (.-value %) search-term))}] (if (or @focused? (seq search-term)) - [:div - {:class (stl/css :clear-search) - :tab-index "0" - :on-click on-clear-click - :on-key-down handle-clear-search} + [:button {:class (stl/css :search-btn :clear-search-btn) + :tab-index "0" + :on-click on-clear-click + :on-key-down handle-clear-search} i/close] - [:div - {:class (stl/css :search) - :on-click on-clear-click} + [:button {:class (stl/css :search-btn) + :on-click on-clear-click} i/search])])) (mf/defc teams-selector-dropdown-items {::mf/wrap-props false} [{:keys [team profile teams] :as props}] (let [on-create-clicked - (mf/use-callback + (mf/use-fn #(st/emit! (modal/show :team-form {}))) team-selected - (mf/use-callback - (fn [team-id] - (st/emit! (dd/go-to-projects team-id)))) + (mf/use-fn + (fn [event] + (let [team-id (-> (dom/get-current-target event) + (dom/get-data "value"))] + (st/emit! (dd/go-to-projects team-id))))) handle-select-default - (fn [event] - (when (kbd/enter? event) - (team-selected (:default-team-id profile) event))) + (mf/use-fn + (mf/deps profile team-selected) + (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)))] + (mf/use-fn + (mf/deps team-selected) + (fn [event] + (when (kbd/enter? event) + (team-selected event)))) + + handle-creation-key-down + (mf/use-fn + (mf/deps on-create-clicked) + (fn [event] + (when (kbd/enter? event) + (on-create-clicked event))))] [:* - [:> dropdown-menu-item* {:on-click (partial team-selected (:default-team-id profile)) + [:> dropdown-menu-item* {:on-click team-selected + :data-value (:default-team-id profile) :on-key-down handle-select-default :id "teams-selector-default-team" - :class (stl/css :team-name)} + :class (stl/css :team-dropdown-item)} [:span {:class (stl/css :team-icon)} i/logo-icon] [:span {:class (stl/css :team-text)} (tr "dashboard.your-penpot")] (when (= (:default-team-id profile) (:id team)) - [:span {:class (stl/css :icon)} i/tick])] + [:span {:class (stl/css :check-icon)} i/tick])] (for [team-item (remove :is-default (vals teams))] - [:> dropdown-menu-item* {:on-click (partial team-selected (:id team-item)) - :on-key-down (partial handle-select-team (:id team-item)) + [:> dropdown-menu-item* {:on-click team-selected + :data-value (:id team-item) + :on-key-down handle-select-team :id (str "teams-selector-" (:id team-item)) - :class (stl/css :team-name) + :class (stl/css :team-dropdown-item) :key (str "teams-selector-" (:id team-item))} - [:span {:class (stl/css :team-icon)} - [:img {:src (cf/resolve-team-photo-url team-item) - :alt (:name team-item)}]] + [:img {:src (cf/resolve-team-photo-url team-item) + :class (stl/css :team-picture) + :alt (:name team-item)}] [:span {:class (stl/css :team-text) :title (:name team-item)} (:name team-item)] (when (= (:id team-item) (:id team)) - [:span {:class (stl/css :icon)} i/tick])]) - [:hr {:role "separator"}] + [:span {:class (stl/css :check-icon)} i/tick])]) + + [:hr {:role "separator" + :class (stl/css :team-separator)}] [:> dropdown-menu-item* {:on-click on-create-clicked - :on-key-down (fn [event] - (when (kbd/enter? event) - (on-create-clicked event))) + :on-key-down handle-creation-key-down :id "teams-selector-create-team" - :class (stl/css :team-name :action)} + :class (stl/css :team-dropdown-item :action)} [:span {:class (stl/css :team-icon :new-team)} i/close] [:span {:class (stl/css :team-text)} (tr "dashboard.create-new-team")]]])) @@ -330,130 +343,200 @@ (rx/throw error))) leave-fn - (fn [member-id] - (let [params (cond-> {} (uuid? member-id) (assoc :reassign-to member-id))] - (st/emit! (dd/leave-team (with-meta params - {:on-success on-success - :on-error on-error}))))) + (mf/use-fn + (mf/deps on-success on-error) + (fn [member-id] + (let [params (cond-> {} (uuid? member-id) (assoc :reassign-to member-id))] + (st/emit! (dd/leave-team (with-meta params + {:on-success on-success + :on-error on-error})))))) delete-fn - (fn [] - (st/emit! (dd/delete-team (with-meta team {:on-success on-success - :on-error on-error})))) + (mf/use-fn + (mf/deps team on-success on-error) + (fn [] + (st/emit! (dd/delete-team (with-meta team {:on-success on-success + :on-error on-error}))))) on-rename-clicked - (fn [] - (st/emit! (modal/show :team-form {:team team}))) + (mf/use-fn + (mf/deps team) + (fn [] + (st/emit! (modal/show :team-form {:team team})))) on-leave-clicked - #(st/emit! (modal/show - {:type :confirm - :title (tr "modals.leave-confirm.title") - :message (tr "modals.leave-confirm.message") - :accept-label (tr "modals.leave-confirm.accept") - :on-accept leave-fn})) + (mf/use-fn + (mf/deps leave-fn) + #(st/emit! (modal/show + {:type :confirm + :title (tr "modals.leave-confirm.title") + :message (tr "modals.leave-confirm.message") + :accept-label (tr "modals.leave-confirm.accept") + :on-accept leave-fn}))) on-leave-as-owner-clicked - (fn [] - (st/emit! (dd/fetch-team-members (:id team)) - (modal/show - {:type :leave-and-reassign - :profile profile - :team team - :accept leave-fn}))) + (mf/use-fn + (mf/deps team profile leave-fn) + (fn [] + (st/emit! (dd/fetch-team-members (:id team)) + (modal/show + {:type :leave-and-reassign + :profile profile + :team team + :accept leave-fn})))) leave-and-close - #(st/emit! (modal/show - {:type :confirm - :title (tr "modals.leave-confirm.title") - :message (tr "modals.leave-and-close-confirm.message" (:name team)) - :scd-message (tr "modals.leave-and-close-confirm.hint") - :accept-label (tr "modals.leave-confirm.accept") - :on-accept delete-fn})) + (mf/use-fn + (mf/deps team delete-fn) + #(st/emit! (modal/show + {:type :confirm + :title (tr "modals.leave-confirm.title") + :message (tr "modals.leave-and-close-confirm.message" (:name team)) + :scd-message (tr "modals.leave-and-close-confirm.hint") + :accept-label (tr "modals.leave-confirm.accept") + :on-accept delete-fn}))) on-delete-clicked - #(st/emit! - (modal/show - {:type :confirm - :title (tr "modals.delete-team-confirm.title") - :message (tr "modals.delete-team-confirm.message") - :accept-label (tr "modals.delete-team-confirm.accept") - :on-accept delete-fn}))] + (mf/use-fn + (mf/deps delete-fn) + #(st/emit! + (modal/show + {:type :confirm + :title (tr "modals.delete-team-confirm.title") + :message (tr "modals.delete-team-confirm.message") + :accept-label (tr "modals.delete-team-confirm.accept") + :on-accept delete-fn}))) + + handle-members + (mf/use-fn + (mf/deps go-members) + (fn [event] + (when (kbd/enter? event) + (go-members)))) + + handle-invitations + (mf/use-fn + (mf/deps go-invitations) + (fn [event] + (when (kbd/enter? event) + (go-invitations)))) + + handle-webhooks + (mf/use-fn + (mf/deps go-webhooks) + (fn [event] + (when (kbd/enter? event) + (go-webhooks)))) + + handle-settings + (mf/use-fn + (mf/deps go-settings) + (fn [event] + (when (kbd/enter? event) + (go-settings)))) + + + handle-rename + (mf/use-fn + (mf/deps on-rename-clicked) + (fn [event] + (when (kbd/enter? event) + (on-rename-clicked)))) + + + handle-leave-and-close + (mf/use-fn + (mf/deps leave-and-close) + (fn [event] + (when (kbd/enter? event) + (leave-and-close)))) + + handle-leave-as-owner-clicked + (mf/use-fn + (mf/deps on-leave-as-owner-clicked) + (fn [event] + (when (kbd/enter? event) + (on-leave-as-owner-clicked)))) + + + handle-on-leave-clicked + (mf/use-fn + (mf/deps on-leave-clicked) + (fn [event] + (when (kbd/enter? event) + (on-leave-clicked)))) + + handle-on-delete-clicked + (mf/use-fn + (mf/deps on-delete-clicked) + (fn [event] + (when (kbd/enter? event) + (on-delete-clicked))))] [:* [:> dropdown-menu-item* {:on-click go-members - :on-key-down (fn [event] - (when (kbd/enter? event) - (go-members))) + :on-key-down handle-members + :className (stl/css :team-options-item) :id "teams-options-members" :data-test "team-members"} (tr "labels.members")] [:> dropdown-menu-item* {:on-click go-invitations - :on-key-down (fn [event] - (when (kbd/enter? event) - (go-invitations))) + :on-key-down handle-invitations + :className (stl/css :team-options-item) :id "teams-options-invitations" :data-test "team-invitations"} (tr "labels.invitations")] (when (contains? cf/flags :webhooks) [:> dropdown-menu-item* {:on-click go-webhooks - :on-key-down (fn [event] - (when (kbd/enter? event) - (go-webhooks))) + :on-key-down handle-webhooks + :className (stl/css :team-options-item) :id "teams-options-webhooks"} (tr "labels.webhooks")]) [:> dropdown-menu-item* {:on-click go-settings - :on-key-down (fn [event] - (when (kbd/enter? event) - (go-settings))) + :on-key-down handle-settings + :className (stl/css :team-options-item) :id "teams-options-settings" :data-test "team-settings"} (tr "labels.settings")] - [:hr] + [:hr {:class (stl/css :team-option-separator)}] (when can-rename? [:> dropdown-menu-item* {:on-click on-rename-clicked - :on-key-down (fn [event] - (when (kbd/enter? event) - (on-rename-clicked))) + :on-key-down handle-rename :id "teams-options-rename" + :className (stl/css :team-options-item) :data-test "rename-team"} (tr "labels.rename")]) (cond (= (count members) 1) [:> dropdown-menu-item* {:on-click leave-and-close - :on-key-down (fn [event] - (when (kbd/enter? event) - (leave-and-close))) + :on-key-down handle-leave-and-close + :className (stl/css :team-options-item) :id "teams-options-leave-team"} (tr "dashboard.leave-team")] (get-in team [:permissions :is-owner]) [:> dropdown-menu-item* {:on-click on-leave-as-owner-clicked - :on-key-down (fn [event] - (when (kbd/enter? event) - (on-leave-as-owner-clicked))) + :on-key-down handle-leave-as-owner-clicked :id "teams-options-leave-team" + :className (stl/css :team-options-item) :data-test "leave-team"} (tr "dashboard.leave-team")] (> (count members) 1) [:> dropdown-menu-item* {:on-click on-leave-clicked - :on-key-down (fn [event] - (when (kbd/enter? event) - (on-leave-clicked))) + :on-key-down handle-on-leave-clicked + :className (stl/css :team-options-item) :id "teams-options-leave-team"} (tr "dashboard.leave-team")]) (when (get-in team [:permissions :is-owner]) [:> dropdown-menu-item* {:on-click on-delete-clicked - :on-key-down (fn [event] - (when (kbd/enter? event) - (on-delete-clicked))) + :on-key-down handle-on-delete-clicked :id "teams-options-delete-team" - :class (stl/css :warning) + :className (stl/css :team-options-item :warning) :data-test "delete-team"} (tr "dashboard.delete-team")])])) @@ -495,6 +578,10 @@ (when first-element (dom/focus! first-element))))))) + close-team-opts-ddwn + (mf/use-fn + #(reset! show-team-opts-ddwn? false)) + handle-show-opts-click (fn [event] (dom/stop-propagation event) @@ -519,34 +606,32 @@ [:div {:class (stl/css :sidebar-team-switch)} [:div {:class (stl/css :switch-content)} - [:button - {:class (stl/css :current-team) - :tab-index "0" - :on-click handle-show-team-click - :on-key-down handle-show-team-keydown} - + [:button {:class (stl/css :current-team) + :on-click handle-show-team-click + :on-key-down handle-show-team-keydown} (if (:is-default team) [:div {:class (stl/css :team-name)} [:span {:class (stl/css :team-icon)} i/logo-icon] [:span {:class (stl/css :team-text)} (tr "dashboard.default-team-name")]] + [:div {:class (stl/css :team-name)} - [:span {:class (stl/css :team-icon)} - [:img {:src (cf/resolve-team-photo-url team) - :alt (:name team)}]] + [:img {:src (cf/resolve-team-photo-url team) + :class (stl/css :team-picture) + :alt (:name team)}] [:span {:class (stl/css :team-text) :title (:name team)} (:name team)]]) [:span {:class (stl/css :switch-icon)} i/arrow-down]] (when-not (:is-default team) - [:button - {:class (stl/css :switch-options) - :on-click handle-show-opts-click - :tab-index "0" - :on-key-down handle-show-opts-keydown} + [:button {:class (stl/css :switch-options) + :on-click handle-show-opts-click + :tab-index "0" + :on-key-down handle-show-opts-keydown} i/actions])] - ;; Teams Dropdown + ;; Teams Dropdown + [:& dropdown-menu {:show @show-teams-ddwn? :on-close handle-close-team :ids ids @@ -557,7 +642,7 @@ :teams teams}]] [:& dropdown-menu {:show @show-team-opts-ddwn? - :on-close #(reset! show-team-opts-ddwn? false) + :on-close close-team-opts-ddwn :ids options-ids :list-class (stl/css :dropdown :options-dropdown)} [:& team-options-dropdown {:team team @@ -577,12 +662,12 @@ (= (:id project) default-project-id)) go-projects - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)}))) go-projects-with-key - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-projects {:team-id (:id team)}) (ts/schedule-on-idle @@ -594,12 +679,12 @@ (dom/set-attribute! projects-title "tabindex" "-1"))))))) go-fonts - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)}))) go-fonts-with-key - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-fonts {:team-id (:id team)}) (ts/schedule-on-idle @@ -610,7 +695,7 @@ (dom/focus! font-title) (dom/set-attribute! font-title "tabindex" "-1"))))))) go-drafts - (mf/use-callback + (mf/use-fn (mf/deps team default-project-id) (fn [] (st/emit! (rt/nav :dashboard-files @@ -618,7 +703,7 @@ :project-id default-project-id})))) go-drafts-with-key - (mf/use-callback + (mf/use-fn (mf/deps team default-project-id) #(st/emit! (rt/nav :dashboard-files {:team-id (:id team) :project-id default-project-id}) @@ -631,12 +716,12 @@ (dom/set-attribute! drafts-title "tabindex" "-1"))))))) go-libs - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)}))) go-libs-with-key - (mf/use-callback + (mf/use-fn (mf/deps team) #(st/emit! (rt/nav :dashboard-libraries {:team-id (:id team)}) (ts/schedule-on-idle @@ -653,45 +738,51 @@ [:div {:class (stl/css :sidebar-content)} [:& sidebar-team-switch {:team team :profile profile}] - [:hr] + [:& sidebar-search {:search-term search-term :team-id (:id team)}] [:div {:class (stl/css :sidebar-content-section)} - [:ul {:class (stl/css :sidebar-nav :no-overflow)} - [:li - {:class (stl/css :recent-projects) - :class-name (when projects? (stl/css :current))} + [:ul {:class (stl/css :sidebar-nav)} + [:li {:class (stl/css-case :recent-projects true + :sidebar-nav-item true + :current projects?)} [:& link {:action go-projects + :class (stl/css :sidebar-link) :keyboard-action go-projects-with-key} [:span {:class (stl/css :element-title)} (tr "labels.projects")]]] - [:li {:class-name (when drafts? (stl/css :current))} + [:li {:class (stl/css-case :current drafts? + :sidebar-nav-item true)} [:& link {:action go-drafts + :class (stl/css :sidebar-link) :keyboard-action go-drafts-with-key} [:span {:class (stl/css :element-title)} (tr "labels.drafts")]]] - [:li {:class-name (when libs? (stl/css :current))} + [:li {:class (stl/css-case :current libs? + :sidebar-nav-item true)} [:& link {:action go-libs + :class (stl/css :sidebar-link) :keyboard-action go-libs-with-key} [:span {:class (stl/css :element-title)} (tr "labels.shared-libraries")]]]]] - [:hr] [:div {:class (stl/css :sidebar-content-section)} - [:ul {:class (stl/css :sidebar-nav :no-overflow)} - [:li {:class-name (when fonts? (stl/css :current))} + [:ul {:class (stl/css :sidebar-nav)} + [:li {:class (stl/css-case :sidebar-nav-item true + :current fonts?)} [:& link {:action go-fonts + :class (stl/css :sidebar-link) :keyboard-action go-fonts-with-key :data-test "fonts"} [:span {:class (stl/css :element-title)} (tr "labels.fonts")]]]]] - [:hr] + [:div {:class (stl/css :sidebar-content-section) :data-test "pinned-projects"} (if (seq pinned-projects) - [:ul {:class (stl/css :sidebar-nav)} + [:ul {:class (stl/css :sidebar-nav :pinned-projects)} (for [item pinned-projects] [:& sidebar-project {:item item @@ -700,25 +791,26 @@ :team-id (:id team) :selected? (= (:id item) (:id project))}])] [:div {:class (stl/css :sidebar-empty-placeholder)} - [:span {:class (stl/css :icon)} i/pin-refactor] - [:span {:class (stl/css :text)} (tr "dashboard.no-projects-placeholder")]])]])) + [:span {:class (stl/css :empty-placeholder-icon)} i/pin-refactor] + [:span {:class (stl/css :empty-text)} (tr "dashboard.no-projects-placeholder")]])]])) (mf/defc profile-section [{:keys [profile team] :as props}] - (let [show (mf/use-state false) + (let [show* (mf/use-state false) + show (deref show*) photo (cf/resolve-profile-photo-url profile) on-click - (mf/use-callback + (mf/use-fn (fn [section event] (dom/stop-propagation event) - (reset! show false) + (reset! show* false) (if (keyword? section) (st/emit! (rt/nav section)) (st/emit! section)))) show-release-notes - (mf/use-callback + (mf/use-fn (fn [event] (let [version (:main cf/version)] (st/emit! (ptk/event ::ev/event {::ev/name "show-release-notes" :version version})) @@ -730,48 +822,48 @@ show-comments? @show-comments* handle-hide-comments - (mf/use-callback + (mf/use-fn (fn [] (reset! show-comments* false))) handle-show-comments - (mf/use-callback + (mf/use-fn (fn [] (reset! show-comments* true))) handle-click - (mf/use-callback + (mf/use-fn (fn [event] (dom/stop-propagation event) - (swap! show not))) + (swap! show* not))) handle-key-down - (mf/use-callback + (mf/use-fn (fn [event] (when (kbd/enter? event) - (reset! show true)))) + (reset! show* true)))) handle-close (fn [event] (dom/stop-propagation event) - (reset! show false)) + (reset! show* false)) handle-key-down-profile - (mf/use-callback + (mf/use-fn (mf/deps on-click) (fn [event] (when (kbd/enter? event) (on-click :settings-profile event)))) handle-click-url - (mf/use-callback + (mf/use-fn (fn [event] (let [url (-> (dom/get-current-target event) (dom/get-data "url"))] (dom/open-new-window url)))) handle-keydown-url - (mf/use-callback + (mf/use-fn (fn [event] (let [url (-> (dom/get-current-target event) (dom/get-data "url"))] @@ -779,35 +871,41 @@ (dom/open-new-window url))))) handle-show-release-notes - (mf/use-callback + (mf/use-fn (mf/deps show-release-notes) (fn [event] (when (kbd/enter? event) (show-release-notes)))) handle-feedback-click - (mf/use-callback + (mf/use-fn (mf/deps on-click) #(on-click :settings-feedback %)) handle-feedback-keydown - (mf/use-callback + (mf/use-fn (mf/deps on-click) (fn [event] (when (kbd/enter? event) (on-click :settings-feedback event)))) handle-logout-click - (mf/use-callback + (mf/use-fn (mf/deps on-click) #(on-click (du/logout) %)) handle-logout-keydown - (mf/use-callback + (mf/use-fn (mf/deps on-click) (fn [event] (when (kbd/enter? event) - (on-click (du/logout) event))))] + (on-click (du/logout) event)))) + + handle-set-profile + (mf/use-fn + (mf/deps on-click) + (fn [event] + (on-click :settings-profile event)))] [:* (when (and team profile) @@ -825,77 +923,89 @@ :on-key-down handle-key-down :data-test "profile-btn"} [:img {:src photo + :class (stl/css :profile-img) :alt (:fullname profile)}] - [:span (:fullname profile)]] + [:span {:class (stl/css :profile-fullname)} (:fullname profile)]] - [:& dropdown-menu {:on-close handle-close :show @show} - [:ul {:class (stl/css :dropdown)} - [:li {:tab-index (if @show "0" "-1") - :on-click (partial on-click :settings-profile) - :on-key-down handle-key-down-profile - :data-test "profile-profile-opt"} - [:span {:class (stl/css :text)} (tr "labels.your-account")]] + [:& dropdown-menu {:on-close handle-close :show show :list-class (stl/css :profile-dropdown)} + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :on-click handle-set-profile + :on-key-down handle-key-down-profile + :data-test "profile-profile-opt"} + (tr "labels.your-account")] - [:li {:class (stl/css :separator) - :tab-index (if @show "0" "-1") - :data-url "https://help.penpot.app" - :on-click handle-click-url - :on-key-down handle-keydown-url - :data-test "help-center-profile-opt"} - [:span {:class (stl/css :text)} (tr "labels.help-center")]] + [:li {:class (stl/css :profile-separator)}] - [:li {:tab-index (if @show "0" "-1") - :data-url "https://community.penpot.app" - :on-click handle-click-url - :on-key-down handle-keydown-url} - [:span {:class (stl/css :text)} (tr "labels.community")]] + [:li {:class (stl/css :profile-dropdown-item) + :tab-index (if show "0" "-1") + :data-url "https://help.penpot.app" + :on-click handle-click-url + :on-key-down handle-keydown-url + :data-test "help-center-profile-opt"} + (tr "labels.help-center")] - [:li {:tab-index (if @show "0" "-1") - :data-url "https://www.youtube.com/c/Penpot" - :on-click handle-click-url - :on-key-down handle-keydown-url} - [:span {:class (stl/css :text)} (tr "labels.tutorials")]] + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :data-url "https://community.penpot.app" + :on-click handle-click-url + :on-key-down handle-keydown-url} + (tr "labels.community")] - [:li {:tab-index (if @show "0" "-1") - :on-click show-release-notes - :on-key-down handle-show-release-notes} - [:span {:class (stl/css :text)} (tr "labels.release-notes")]] + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :data-url "https://www.youtube.com/c/Penpot" + :on-click handle-click-url + :on-key-down handle-keydown-url} + (tr "labels.tutorials")] - [:li {:class (stl/css :separator) - :tab-index (if @show "0" "-1") - :data-url "https://penpot.app/libraries-templates" - :on-click handle-click-url - :on-key-down handle-keydown-url - :data-test "libraries-templates-profile-opt"} - [:span {:class (stl/css :text)} (tr "labels.libraries-and-templates")]] + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :on-click show-release-notes + :on-key-down handle-show-release-notes} + (tr "labels.release-notes")] - [:li {:tab-index (if @show "0" "-1") - :data-url "https://github.com/penpot/penpot" - :on-click handle-click-url - :on-key-down handle-keydown-url} - [:span {:class (stl/css :text)} (tr "labels.github-repo")]] + [:li {:class (stl/css :profile-separator)}] - [:li {:tab-index (if @show "0" "-1") - :data-url "https://penpot.app/terms" - :on-click handle-click-url - :on-key-down handle-keydown-url} - [:span {:class (stl/css :text)} (tr "auth.terms-of-service")]] + [:li {:class (stl/css :profile-dropdown-item) + :tab-index (if show "0" "-1") + :data-url "https://penpot.app/libraries-templates" + :on-click handle-click-url + :on-key-down handle-keydown-url + :data-test "libraries-templates-profile-opt"} + (tr "labels.libraries-and-templates")] - (when (contains? cf/flags :user-feedback) - [:li {:class (stl/css :separator) - :tab-index (if @show "0" "-1") - :on-click handle-feedback-click - :on-key-down handle-feedback-keydown - :data-test "feedback-profile-opt"} - [:span {:class (stl/css :text)} (tr "labels.give-feedback")]]) + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :data-url "https://github.com/penpot/penpot" + :on-click handle-click-url + :on-key-down handle-keydown-url} + (tr "labels.github-repo")] - [:li {:class (stl/css :separator) - :tab-index (if @show "0" "-1") - :on-click handle-logout-click - :on-key-down handle-logout-keydown - :data-test "logout-profile-opt"} - [:span {:class (stl/css :icon)} i/exit] - [:span {:class (stl/css :text)} (tr "labels.logout")]]]] + [:li {:tab-index (if show "0" "-1") + :class (stl/css :profile-dropdown-item) + :data-url "https://penpot.app/terms" + :on-click handle-click-url + :on-key-down handle-keydown-url} + (tr "auth.terms-of-service")] + + [:li {:class (stl/css :profile-separator)}] + + (when (contains? cf/flags :user-feedback) + [:li {:class (stl/css :profile-dropdown-item) + :tab-index (if show "0" "-1") + :on-click handle-feedback-click + :on-key-down handle-feedback-keydown + :data-test "feedback-profile-opt"} + (tr "labels.give-feedback")]) + + [:li {:class (stl/css :profile-dropdown-item :item-with-icon) + :tab-index (if show "0" "-1") + :on-click handle-logout-click + :on-key-down handle-logout-keydown + :data-test "logout-profile-opt"} + [:span {:class (stl/css :exit-icon)} i/exit] + (tr "labels.logout")]] (when (and team profile) [:& comments-icon diff --git a/frontend/src/app/main/ui/dashboard/sidebar.scss b/frontend/src/app/main/ui/dashboard/sidebar.scss index 2623cc516d..4bc58fb777 100644 --- a/frontend/src/app/main/ui/dashboard/sidebar.scss +++ b/frontend/src/app/main/ui/dashboard/sidebar.scss @@ -7,498 +7,393 @@ @use "common/refactor/common-refactor.scss" as *; @use "common/refactor/common-dashboard"; +// SIDEBAR COMPONENT .dashboard-sidebar { grid-row: 1 / span 2; grid-column: 1 / span 2; - - background-color: var(--panel-background-color); - border-right: $s-1 solid $db-quaternary; - margin: 0 $s-16 0 0; + display: grid; + grid-template-rows: 1fr auto; + height: 100%; + width: 100%; padding: $s-16 0 0 0; - + margin: 0 $s-16 0 0; + border-right: $s-1 solid var(--panel-border-color); + background-color: var(--panel-background-color); z-index: $z-index-1; - display: flex; - flex-direction: column; - height: 100%; } +//SIDEBAR CONTENT COMPONENT .sidebar-content { - display: flex; - flex-direction: column; + display: grid; + grid-template-rows: auto auto auto auto 1fr; + gap: $s-24; height: 100%; - overflow-y: auto; padding: 0; - - hr { - border-color: transparent; - margin: $s-12 $s-16; - } + overflow-y: auto; } +// SIDEBAR TEAM SWITCH .sidebar-team-switch { position: relative; - display: flex; margin: $s-4 $s-16; - - .switch-content { - background-color: $db-tertiary; - border-radius: $br-8; - height: $s-48; - display: flex; - width: 100%; - border: $s-1 solid $db-tertiary; - align-items: center; - - svg { - fill: #8f9da3; - } - } - - .switch-icon { - display: flex; - align-items: center; - justify-content: center; - - svg { - fill: $df-secondary; - width: $s-12; - height: $s-12; - } - } - - .current-team { - height: 100%; - cursor: pointer; - display: flex; - align-items: center; - flex-grow: 1; - font-size: $fs-14; - padding: 0 $s-12; - background-color: transparent; - border: none; - } - - .team-name { - flex-grow: 1; - display: flex; - height: $s-40; - align-items: center; - } - - .team-text { - color: $df-primary; - width: $s-144; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - text-align: left; - } - - .team-icon { - display: flex; - align-items: center; - padding-right: $s-12; - - img { - border-radius: 50%; - flex-shrink: 0; - height: $s-24; - width: $s-24; - } - - svg { - width: $s-24; - height: $s-24; - } - } - - .switch-options { - @include buttonStyle; - @include flexCenter; - max-width: $s-24; - min-width: $s-28; - height: 100%; - border-left: $s-1 solid $db-primary; - background-color: transparent; - - svg { - fill: $df-secondary; - width: $s-16; - height: $s-12; - } - } - - .dropdown { - right: $s-2; - top: $s-52; - max-height: $s-480; - &:not(.teams-dropdown) { - min-width: $s-160; - } - } } -.dropdown { - @include menuShadow; - position: absolute; - z-index: $z-index-4; - background-color: $db-tertiary; - border: $s-1 solid $db-quaternary; +.switch-content { + display: grid; + grid-template-columns: 1fr auto; + align-items: center; + height: $s-48; + width: 100%; border-radius: $br-8; + border: $s-1 solid var(--menu-background-color); + background-color: var(--menu-background-color); +} - .separator { - border-color: transparent; - margin-top: $s-12; - } +.current-team { + @include buttonStyle; + display: grid; + align-items: center; + grid-template-columns: 1fr auto; + gap: $s-8; + height: 100%; + padding: 0 $s-12; +} - li { - border-radius: $br-8; - height: $s-40; - margin: $s-6; +.team-name { + display: grid; + align-items: center; + grid-template-columns: auto 1fr; + gap: $s-12; + height: $s-40; +} - display: flex; - align-items: center; - cursor: pointer; - font-size: $fs-14; - padding: $s-6 $s-16; +.team-text { + @include textEllipsis; + @include smallTitleTipography; + width: $s-144; + text-align: left; + color: var(--menu-foreground-color-hover); +} - .warning { - color: var(--element-foreground-warning); - } - - &:hover { - background-color: $db-quaternary; - } - svg { - height: $s-12; - width: $s-12; - } - } - - hr { - border-color: transparent; - margin: 0; - } - - &.options-dropdown { - li { - color: $df-primary; - &.warning { - color: var(--element-foreground-warning); - } - } +.team-icon { + @include flexCenter; + svg { + fill: var(--icon-foreground); + width: $s-24; + height: $s-24; } } +.team-picture { + @include flexCenter; + border-radius: 50%; + height: $s-24; + width: $s-24; +} + +.switch-icon { + @include flexCenter; + svg { + fill: var(--icon-foreground); + width: $s-12; + height: $s-12; + } +} + +.switch-options { + @include buttonStyle; + @include flexCenter; + max-width: $s-24; + min-width: $s-28; + height: 100%; + border-left: $s-1 solid var(--panel-background-color); + background-color: transparent; + + svg { + fill: var(--icon-foreground); + width: $s-16; + height: $s-12; + } +} + +// DROPDOWNS + .teams-dropdown { - background-color: $db-tertiary; - border-radius: $br-8; - border: $s-1 solid $db-quaternary; - min-width: $s-248; - + @extend .menu-dropdown; left: 0; top: $s-52; - + height: fit-content; max-height: $s-480; + min-width: $s-248; + width: 100%; overflow-x: hidden; overflow-y: auto; +} - li { - border-radius: $br-8; - height: $s-40; - padding: 0 $s-6; - margin: $s-6; +.team-dropdown-item { + @extend .menu-item-base; + display: grid; + grid-template-columns: $s-24 1fr auto; + gap: $s-8; + height: $s-40; +} - svg { - fill: $df-secondary; +.team-dropdown-item.action .team-icon { + height: $s-24; + width: $s-24; + padding: $s-6; + margin-right: $s-12; + border-radius: 50%; + background-color: var(--new-team-button-background-color); + + svg { + height: $s-12; + width: $s-12; + } +} + +.team-separator { + border-top: $s-1 solid var(--dropdown-separator-color); + margin: 0; +} + +.check-icon { + @extend .button-icon; + fill: var(--icon-foreground); + svg { + height: 12px; + width: 12px; + } +} + +.options-dropdown { + @extend .menu-dropdown; + right: $s-2; + top: $s-52; + max-height: $s-480; + &:not(.teams-dropdown) { + min-width: $s-160; + } +} + +.team-options-item { + @extend .menu-item-base; + height: $s-40; +} + +.team-option-separator { + height: $s-1; + margin: 0; + border-top: $s-1 solid var(--dropdown-separator-color); +} + +// Sections +.sidebar-nav { + margin: 0; + user-select: none; + overflow: none; +} + +.pinned-projects { + overflow-y: auto; +} + +.sidebar-nav-item { + cursor: pointer; + + svg { + fill: var(--icon-foreground); + margin-right: $s-8; + height: $s-12; + width: $s-12; + } + + &:hover { + background-color: var(--sidebar-element-background-color-hover); + span { + color: var(--sidebar-element-foreground-color-hover); } + } - &:hover { - background-color: $db-quaternary; - .team-icon { - &.new-team { - background-color: $da-primary; - color: $db-primary; - svg { - fill: $db-secondary; - } - } - } - } - .team-icon { - display: flex; - align-items: center; - } - .team-text { - color: $df-primary; - width: $s-168; - } - - &.action { - .team-icon { - background-color: #2e3434; - background-color: var(--new-team-button-background-color); - border-radius: 50%; - height: $s-24; - margin-right: $s-12; - padding: $s-6; - width: $s-24; - - svg { - height: $s-12; - width: $s-12; - } - } + &.current { + background-color: var(--sidebar-element-background-color-selected); + .element-title { + color: var(--sidebar-element-foreground-color-selected); } } } +.recent-projects svg { + fill: var(--main-icon-foreground); +} + +.sidebar-link { + display: block; + padding: $s-8 $s-8 $s-8 $s-24; + font-weight: $fw400; + width: 100%; + &:hover { + text-decoration: none; + } +} + +.project-element { + padding: $s-8 $s-8 $s-8 $s-24; +} + +.element-title { + @include textEllipsis; + color: var(--sidebar-element-foreground-color); + font-size: $fs-14; +} + +// Pinned projects + .sidebar-empty-placeholder { padding: $s-12; - color: $df-secondary; + color: var(--empty-message-foreground-color); display: flex; align-items: center; +} - .icon { - padding: 0 $s-12; - svg { - fill: none; - stroke: currentColor; - width: $s-12; - height: $s-12; - } - } - .text { - font-size: $fs-12; +.empty-placeholder-icon { + padding: 0 $s-12; + svg { + fill: none; + stroke: currentColor; + width: $s-12; + height: $s-12; } } +.empty-text { + font-size: $fs-12; +} + +// Search + .sidebar-search { + position: relative; + display: grid; + grid-template-columns: 1fr; align-items: center; border: $s-1 solid transparent; - display: flex; - margin: $s-6 $s-16; - - background-color: $db-tertiary; + margin: 0 $s-16; border-radius: $br-8; - margin-bottom: $s-32; - margin-top: 0; - position: relative; + background-color: var(--search-bar-input-background-color); +} - .input-text { - background: transparent; - border: 0; - font-size: $fs-14; - margin: 0; - width: 100%; - height: $s-40; +.input-text { + @include smallTitleTipography; + height: $s-40; + width: 100%; + padding: $s-6 $s-12; + margin: 0; + border: transparent; + border-radius: $br-8; + background: transparent; + color: var(--search-bar-foreground-color); - border-radius: $br-8; - color: $df-primary; - max-width: 100%; - padding: $s-6 $s-12; - - &:focus, - &:focus-within { - border: $s-1 solid $da-primary; - } + &:focus, + &:focus-within, + &:focus-visible { + outline: none; + border: $s-1 solid var(--search-bar-input-border-color-focus); } ::placeholder { - color: $df-secondary; - } - - .search, - .clear-search { - align-items: center; - cursor: pointer; - display: flex; - height: $s-24; - margin-left: auto; - padding: 0 $s-8; - width: $s-32; - - position: absolute; - top: calc(50% - $s-12); - right: $s-2; - - svg { - fill: $df-secondary; - height: $s-16; - width: $s-16; - } - } - - .clear-search svg { - transform: rotate(45deg); - - &:hover { - fill: $da-primary; - } + color: var(--search-bar-placeholder-foreground-color); } } -.sidebar-nav { - display: flex; - flex-direction: column; - overflow-y: auto; - margin: 0; - user-select: none; +.search-btn { + @include buttonStyle; + @include flexCenter; + position: absolute; + right: 0; + height: $s-24; + width: $s-32; + padding: 0 $s-8; - &.no-overflow { - overflow: unset; - } - - & > li { - align-items: center; - cursor: pointer; - display: flex; - flex-shrink: 0; - - &.project-element { - padding: $s-8 $s-8 $s-8 $s-24; - } - - a { - padding: $s-8 $s-8 $s-8 $s-24; - font-weight: $fw400; - width: 100%; - &:hover { - text-decoration: none; - } - } - - svg { - fill: $db-secondary; - margin-right: $s-8; - height: $s-12; - width: $s-12; - } - - .element-title { - color: $df-secondary; - font-size: $fs-14; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - &.recent-projects { - svg { - fill: $df-primary; - } - } - - input.element-title { - border: 0; - height: $s-32; - padding: $s-6; - margin: 0; - width: 100%; - background-color: $df-primary; - } - - .close { - background-color: $df-primary; - cursor: pointer; - padding-left: $s-6; - - svg { - fill: $df-secondary; - height: $s-16; - transform: rotate(45deg) translateY(7px); - width: $s-16; - margin: 0; - } - } - - .element-subtitle { - color: $df-secondary; - font-style: italic; - } - - &:hover { - background-color: $db-secondary; - span { - color: $da-primary; - } - } - - &.current { - background-color: $db-quaternary; - .element-title { - color: $da-primary; - } - } + svg { + fill: var(--search-bar-icon-foreground-color); + height: $s-16; + width: $s-16; } } +.clear-search-btn svg { + transform: rotate(45deg); + + &:hover { + fill: var(--search-bar-icon-foreground-color-hover); + } +} + +// Profile .profile-section { - align-items: center; - cursor: pointer; - display: flex; - padding: $s-12 $s-16; position: relative; + display: grid; + grid-template-columns: 1fr auto; + padding: $s-12 $s-16; + border-top: $s-1 solid var(--panel-border-color); + background-color: var(--profile-section-background-color); + cursor: pointer; +} - background-color: $db-tertiary; - border-top: $s-1 solid $db-quaternary; - - .profile { - align-items: center; - cursor: pointer; - display: flex; - flex-grow: 1; - - span { - @include text-ellipsis; - color: $df-primary; - margin: $s-12; - font-size: $fs-14; - max-width: $s-160; - } - - img { - border-radius: 50%; - flex-shrink: 0; - height: $s-40; - width: $s-40; - } - svg { - height: $s-12; - margin-left: auto; - margin-right: $s-8; - width: $s-12; - } - } - - .dropdown { - left: $s-16; - bottom: $s-44; - background-color: var(--profile-drowpdown-background-color); - border: $s-1 solid $db-tertiary; - border-radius: $br-8; - min-width: $s-252; - - @include animation(0, 0.2s, fadeInUp); - - li { - font-size: $fs-14; - padding: $s-8 $s-16; - - svg { - fill: $df-secondary; - margin-right: $s-8; - - height: $s-12; - width: $s-12; - } - - .text { - color: $df-primary; - } - - &.separator { - border-top: $s-1 solid transparent; - } - } +.profile { + display: grid; + grid-template-columns: auto 1fr; + gap: $s-8; + cursor: pointer; + svg { + height: $s-12; + width: $s-12; + margin-left: auto; + margin-right: $s-8; + } +} + +.profile-fullname { + @include smallTitleTipography; + @include text-ellipsis; + align-self: center; + max-width: $s-160; + color: var(--profile-foreground-color); +} + +.profile-img { + height: $s-40; + width: $s-40; + border-radius: $br-circle; +} + +.profile-dropdown { + @extend .menu-dropdown; + left: $s-16; + bottom: $s-72; + min-width: $s-252; + // TODO ADD animation fadeInUp +} + +.profile-dropdown-item { + @extend .menu-item-base; + @include smallTitleTipography; + height: $s-40; + padding: $s-8 $s-16; +} + +.profile-separator { + height: $s-6; +} + +.item-with-icon { + display: grid; + grid-template-columns: auto 1fr; + + svg { + fill: var(--menu-icon-foreground-color); + margin-right: $s-8; + height: $s-12; + width: $s-12; } }