mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 03:51:37 +02:00
✨Add new layers panel UI design
This commit is contained in:
parent
90fb619dfc
commit
86b0e95458
191 changed files with 3998 additions and 1037 deletions
|
@ -4,12 +4,14 @@
|
|||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.context-menu-a11y
|
||||
(ns app.main.ui.components.context-menu-a11y.context-menu-a11y
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.components.dropdown :refer [dropdown']]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -36,15 +38,15 @@
|
|||
on-click (gobj/get props "on-click")
|
||||
on-key-down (gobj/get props "on-key-down")
|
||||
id (gobj/get props "id")
|
||||
klass (gobj/get props "klass")
|
||||
key (gobj/get props "key")
|
||||
klass (gobj/get props "class")
|
||||
key-index (gobj/get props "key-index")
|
||||
data-test (gobj/get props "data-test")]
|
||||
[:li {:id id
|
||||
:class klass
|
||||
:tab-index "0"
|
||||
:on-key-down on-key-down
|
||||
:on-click on-click
|
||||
:key key
|
||||
:key key-index
|
||||
:role "menuitem"
|
||||
:data-test data-test}
|
||||
children]))
|
||||
|
@ -54,22 +56,24 @@
|
|||
[props]
|
||||
(assert (fn? (gobj/get props "on-close")) "missing `on-close` prop")
|
||||
(assert (boolean? (gobj/get props "show")) "missing `show` prop")
|
||||
(assert (vector? (gobj/get props "options")) "missing `options` prop")
|
||||
(let [open? (gobj/get props "show")
|
||||
on-close (gobj/get props "on-close")
|
||||
options (gobj/get props "options")
|
||||
is-selectable (gobj/get props "selectable")
|
||||
selected (gobj/get props "selected")
|
||||
top (gobj/get props "top" 0)
|
||||
left (gobj/get props "left" 0)
|
||||
fixed? (gobj/get props "fixed?" false)
|
||||
min-width? (gobj/get props "min-width?" false)
|
||||
origin (gobj/get props "origin")
|
||||
route (mf/deref refs/route)
|
||||
in-dashboard? (= :dashboard-projects (:name (:data route)))
|
||||
local (mf/use-state {:offset-y 0
|
||||
:offset-x 0
|
||||
:levels nil})
|
||||
(assert (vector? (gobj/get props "options")) "missing `options` prop")
|
||||
(let [open? (gobj/get props "show")
|
||||
on-close (gobj/get props "on-close")
|
||||
options (gobj/get props "options")
|
||||
is-selectable (gobj/get props "selectable")
|
||||
selected (gobj/get props "selected")
|
||||
top (gobj/get props "top" 0)
|
||||
left (gobj/get props "left" 0)
|
||||
fixed? (gobj/get props "fixed?" false)
|
||||
min-width? (gobj/get props "min-width?" false)
|
||||
workspace? (gobj/get props "workspace?" false)
|
||||
origin (gobj/get props "origin")
|
||||
route (mf/deref refs/route)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
in-dashboard? (= :dashboard-projects (:name (:data route)))
|
||||
local (mf/use-state {:offset-y 0
|
||||
:offset-x 0
|
||||
:levels nil})
|
||||
|
||||
on-local-close
|
||||
(mf/use-callback
|
||||
|
@ -79,7 +83,7 @@
|
|||
(on-close)))
|
||||
|
||||
props (obj/merge props #js {:on-close on-local-close})
|
||||
|
||||
|
||||
ids (generate-ids-group (:options (last (:levels @local))) (:parent-option (last (:levels @local))))
|
||||
check-menu-offscreen
|
||||
(mf/use-callback
|
||||
|
@ -190,64 +194,100 @@
|
|||
|
||||
(when (and open? (some? (:levels @local)))
|
||||
[:> dropdown' props
|
||||
|
||||
|
||||
(let [level (-> @local :levels peek)
|
||||
original-options (:options level)
|
||||
parent-original (:parent-option level)]
|
||||
[:div.context-menu {:class (dom/classnames :is-open open?
|
||||
:fixed fixed?
|
||||
:is-selectable is-selectable)
|
||||
:style {:top (+ top (:offset-y @local))
|
||||
:left (+ left (:offset-x @local))}
|
||||
:on-key-down (on-key-down original-options parent-original)}
|
||||
(let [level (-> @local :levels peek)]
|
||||
[:ul.context-menu-items {:class (dom/classnames :min-width min-width?)
|
||||
:role "menu"
|
||||
:ref check-menu-offscreen}
|
||||
(when-let [parent-option (:parent-option level)]
|
||||
[:*
|
||||
[:& context-menu-a11y-item
|
||||
{:id "go-back-sub-option"
|
||||
:tab-index "0"
|
||||
:on-key-down (fn [event]
|
||||
(dom/prevent-default event))}
|
||||
[:div.context-menu-action.submenu-back
|
||||
{:data-no-close true
|
||||
:on-click exit-submenu}
|
||||
[:span i/arrow-slide]
|
||||
parent-option]]
|
||||
[:li.separator]])
|
||||
(for [[index option] (d/enumerate (:options level))]
|
||||
[:div {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :is-selectable) is-selectable
|
||||
(css :context-menu) true
|
||||
(css :is-open) open?
|
||||
(css :fixed) fixed?)
|
||||
(dom/classnames :is-selectable is-selectable
|
||||
:context-menu true
|
||||
:is-open open?
|
||||
:fixed fixed?))
|
||||
:style {:top (+ top (:offset-y @local))
|
||||
:left (+ left (:offset-x @local))}
|
||||
:on-key-down (on-key-down original-options parent-original)}
|
||||
(let [level (-> @local :levels peek)]
|
||||
[:ul {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :min-width) min-width?
|
||||
(css :context-menu-items) true)
|
||||
(dom/classnames :min-width min-width?
|
||||
:context-menu-items true))
|
||||
:role "menu"
|
||||
:ref check-menu-offscreen}
|
||||
(when-let [parent-option (:parent-option level)]
|
||||
[:*
|
||||
[:& context-menu-a11y-item
|
||||
{:id "go-back-sub-option"
|
||||
:class (dom/classnames (css :context-menu-item) (and new-css-system workspace?))
|
||||
:tab-index "0"
|
||||
:on-key-down (fn [event]
|
||||
(dom/prevent-default event))}
|
||||
[:div {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :context-menu-action) true
|
||||
(css :submenu-back) true)
|
||||
(dom/classnames :context-menu-action true
|
||||
:submenu-back true))
|
||||
:data-no-close true
|
||||
:on-click exit-submenu}
|
||||
[:span {:class (dom/classnames (css :submenu-icon-back) (and new-css-system workspace?))}
|
||||
(if (and new-css-system workspace?)
|
||||
i/arrow-refactor
|
||||
i/arrow-slide)]
|
||||
parent-option]]
|
||||
[:li {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :separator) true)
|
||||
(dom/classnames :separator true))}]])
|
||||
(for [[index option] (d/enumerate (:options level))]
|
||||
(let [option-name (:option-name option)
|
||||
id (:id option)
|
||||
sub-options (:sub-options option)
|
||||
option-handler (:option-handler option)
|
||||
data-test (:data-test option)]
|
||||
(when option-name
|
||||
(if (= option-name :separator)
|
||||
[:li {:key (dm/str "context-item-" index)
|
||||
:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :separator) true)
|
||||
(dom/classnames :separator true))}]
|
||||
[:& context-menu-a11y-item
|
||||
{:id id
|
||||
:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :is-selected) (and selected (= option-name selected))
|
||||
(css :context-menu-item) true)
|
||||
(dom/classnames :is-selected (and selected (= option-name selected))))
|
||||
:key-index (dm/str "context-item-" index)
|
||||
:tab-index "0"
|
||||
:on-key-down (fn [event]
|
||||
(dom/prevent-default event))}
|
||||
(if-not sub-options
|
||||
[:a {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :context-menu-action) true)
|
||||
(dom/classnames :context-menu-action true))
|
||||
:on-click #(do (dom/stop-propagation %)
|
||||
(on-close)
|
||||
(option-handler %))
|
||||
:data-test data-test}
|
||||
(if (and in-dashboard? (= option-name "Default"))
|
||||
(tr "dashboard.default-team-name")
|
||||
option-name)]
|
||||
[:a {:class (if (and new-css-system workspace?)
|
||||
(dom/classnames (css :context-menu-action) true
|
||||
(css :submenu) true)
|
||||
(dom/classnames :context-menu-action true
|
||||
:submenu true))
|
||||
:data-no-close true
|
||||
:on-click (enter-submenu option-name sub-options)
|
||||
:data-test data-test}
|
||||
option-name
|
||||
[:span {:class (dom/classnames (css :submenu-icon) (and new-css-system workspace?))}
|
||||
(if (and new-css-system workspace?)
|
||||
i/arrow-refactor
|
||||
i/arrow-slide)]])]))))])])])))
|
||||
|
||||
(let [option-name (:option-name option)
|
||||
id (:id option)
|
||||
sub-options (:sub-options option)
|
||||
option-handler (:option-handler option)
|
||||
data-test (:data-test option)]
|
||||
(when option-name
|
||||
(if (= option-name :separator)
|
||||
[:li.separator {:key (dm/str "context-item-" index)}]
|
||||
[:& context-menu-a11y-item
|
||||
{:id id
|
||||
:class (dom/classnames :is-selected (and selected (= option-name selected)))
|
||||
:key (dm/str "context-item-" index)
|
||||
:tab-index "0"
|
||||
:on-key-down (fn [event]
|
||||
(dom/prevent-default event))}
|
||||
(if-not sub-options
|
||||
[:a.context-menu-action {:on-click #(do (dom/stop-propagation %)
|
||||
(on-close)
|
||||
(option-handler %))
|
||||
:data-test data-test}
|
||||
(if (and in-dashboard? (= option-name "Default"))
|
||||
(tr "dashboard.default-team-name")
|
||||
option-name)]
|
||||
[:a.context-menu-action.submenu
|
||||
{:data-no-close true
|
||||
:on-click (enter-submenu option-name sub-options)
|
||||
:data-test data-test}
|
||||
option-name
|
||||
[:span i/arrow-slide]])]))))])])])))
|
||||
|
||||
(mf/defc context-menu-a11y
|
||||
{::mf/wrap-props false}
|
||||
|
@ -255,6 +295,6 @@
|
|||
(assert (fn? (gobj/get props "on-close")) "missing `on-close` prop")
|
||||
(assert (boolean? (gobj/get props "show")) "missing `show` prop")
|
||||
(assert (vector? (gobj/get props "options")) "missing `options` prop")
|
||||
|
||||
|
||||
(when (gobj/get props "show")
|
||||
(mf/element context-menu-a11y' props)))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"context_menu_a11y_context_menu_a11y_button-primary_-nqKB","button-secondary":"context_menu_a11y_context_menu_a11y_button-secondary_3sivR","button-icon":"context_menu_a11y_context_menu_a11y_button-icon_45j80","button-icon-small":"context_menu_a11y_context_menu_a11y_button-icon-small_TNORx","context-menu":"context_menu_a11y_context_menu_a11y_context-menu_HLzPl","context-menu-items":"context_menu_a11y_context_menu_a11y_context-menu-items_r2JIA","context-menu-item":"context_menu_a11y_context_menu_a11y_context-menu-item_KB64Q","context-menu-action":"context_menu_a11y_context_menu_a11y_context-menu-action_x7nPU","submenu-back":"context_menu_a11y_context_menu_a11y_submenu-back_8iOw0","submenu-icon-back":"context_menu_a11y_context_menu_a11y_submenu-icon-back_vlCP7","submenu":"context_menu_a11y_context_menu_a11y_submenu_pUX19","submenu-icon":"context_menu_a11y_context_menu_a11y_submenu-icon_mlof4","is-open":"context_menu_a11y_context_menu_a11y_is-open_ASqQk","fixed":"context_menu_a11y_context_menu_a11y_fixed_5h8sL","separator":"context_menu_a11y_context_menu_a11y_separator_b1CzA","min-width":"context_menu_a11y_context_menu_a11y_min-width_jirG8","is-selected":"context_menu_a11y_context_menu_a11y_is-selected_jihDn","is-selectable":"context_menu_a11y_context_menu_a11y_is-selectable_wqvJa"}
|
|
@ -0,0 +1,127 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.context-menu {
|
||||
position: relative;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
z-index: $z-index-2;
|
||||
|
||||
&.is-open {
|
||||
position: relative;
|
||||
display: block;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.context-menu-items {
|
||||
position: absolute;
|
||||
top: $s-12;
|
||||
left: calc(-1 * $s-6);
|
||||
max-height: $s-480;
|
||||
min-width: $s-96;
|
||||
margin: 0;
|
||||
padding: $s-4;
|
||||
border-radius: $br8;
|
||||
background-color: var(--menu-background-color);
|
||||
box-shadow: 0px 0px $s-12 0px var(--menu-shadow-color);
|
||||
overflow: auto;
|
||||
& .separator {
|
||||
height: $s-12;
|
||||
}
|
||||
|
||||
&.min-width {
|
||||
min-width: $s-192;
|
||||
}
|
||||
|
||||
.context-menu-item {
|
||||
display: flex;
|
||||
.context-menu-action {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
padding: $s-6;
|
||||
border-radius: $br8;
|
||||
white-space: nowrap;
|
||||
color: var(--menu-foreground-color);
|
||||
&.submenu {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.submenu-icon {
|
||||
margin-left: 0.5rem;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.submenu-back {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: $fw700;
|
||||
.submenu-icon-back svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--menu-foreground-color);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover .context-menu-action {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
text-decoration: none;
|
||||
color: var(--menu-foreground-color-hover);
|
||||
&.submenu .submenu-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
&.submenu-back .submenu-icon-back svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
.context-menu-action {
|
||||
border: 1px solid var(--menu-border-color-focus);
|
||||
background-color: var(--menu-background-color-focus);
|
||||
text-decoration: none;
|
||||
color: var(--menu-foreground-color-focus);
|
||||
&.submenu .submenu-icon svg {
|
||||
stroke: var(--menu-foreground-color-focus);
|
||||
}
|
||||
|
||||
&.submenu-back .submenu-icon-back svg {
|
||||
stroke: var(--menu-foreground-color-focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.is-selected .context-menu-action {
|
||||
padding-left: $s-28;
|
||||
background-image: url(/images/icons/tick.svg);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 5% 48%;
|
||||
background-size: $s-12;
|
||||
font-weight: $fw700;
|
||||
}
|
||||
}
|
||||
&.is-selectable {
|
||||
.context-menu-action {
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
63
frontend/src/app/main/ui/components/shape_icon_refactor.cljs
Normal file
63
frontend/src/app/main/ui/components/shape_icon_refactor.cljs
Normal file
|
@ -0,0 +1,63 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.shape-icon-refactor
|
||||
(:require
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.ui.icons :as i]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
||||
(mf/defc element-icon-refactor
|
||||
[{:keys [shape main-instance?] :as props}]
|
||||
(if (ctk/instance-root? shape)
|
||||
(if main-instance?
|
||||
i/component-refactor
|
||||
i/copy-refactor)
|
||||
(case (:type shape)
|
||||
:frame (cond
|
||||
(and (ctl/flex-layout? shape) (ctl/col? shape))
|
||||
i/flex-vertical-refactor
|
||||
|
||||
(and (ctl/flex-layout? shape) (ctl/row? shape))
|
||||
i/flex-horizontal-refactor
|
||||
|
||||
;; TODO: GRID ICON
|
||||
|
||||
:else
|
||||
i/board-refactor)
|
||||
;; TODO -> THUMBNAIL ICON
|
||||
:image i/img-refactor
|
||||
:line i/path-refactor
|
||||
:circle i/elipse-refactor
|
||||
:path i/path-refactor
|
||||
:rect i/rectangle-refactor
|
||||
:text i/text-refactor
|
||||
:group (if (:masked-group? shape)
|
||||
i/mask-refactor
|
||||
i/group-refactor)
|
||||
:bool (case (:bool-type shape)
|
||||
:difference i/boolean-difference-refactor
|
||||
:exclude i/boolean-exclude-refactor
|
||||
:intersection i/boolean-intersection-refactor
|
||||
#_:default i/boolean-union-refactor)
|
||||
:svg-raw i/file-svg
|
||||
nil)))
|
||||
|
||||
|
||||
(mf/defc element-icon-refactor-by-type
|
||||
[{:keys [type main-instance?] :as props}]
|
||||
(if main-instance?
|
||||
i/component-refactor
|
||||
(case type
|
||||
:frame i/board-refactor
|
||||
:image i/img-refactor
|
||||
:shape i/path-refactor
|
||||
:text i/text-refactor
|
||||
:mask i/mask-refactor
|
||||
:group i/group-refactor
|
||||
nil)))
|
|
@ -0,0 +1,89 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.tab-container.tab-container
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc tab-element
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (unchecked-get props "children")
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-element) true)
|
||||
(dom/classnames :tab-element true))}
|
||||
children]))
|
||||
|
||||
(mf/defc tab-container
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (->>
|
||||
(unchecked-get props "children")
|
||||
(filter some?))
|
||||
selected (unchecked-get props "selected")
|
||||
on-change (unchecked-get props "on-change-tab")
|
||||
collapsable? (unchecked-get props "collapsable?")
|
||||
handle-collapse (unchecked-get props "handle-collapse")
|
||||
|
||||
state (mf/use-state #(or selected (-> children first .-props .-id)))
|
||||
selected (or selected @state)
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
select-fn
|
||||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn [event]
|
||||
(let [id (d/read-string (.. event -target -dataset -id))]
|
||||
(reset! state id)
|
||||
(when (fn? on-change) (on-change id)))))]
|
||||
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container) true)
|
||||
(dom/classnames :tab-container true))}
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container-tabs) true)
|
||||
(dom/classnames :tab-container-tabs true))}
|
||||
(when (and new-css-system collapsable?)
|
||||
[:button
|
||||
{:on-click handle-collapse
|
||||
:class (dom/classnames (css :collapse-sidebar) true)
|
||||
:aria-label (tr "workspace.sidebar.collapse")}
|
||||
i/arrow-refactor])
|
||||
(if new-css-system
|
||||
[:div {:class (dom/classnames (css :tab-container-tab-wrapper) new-css-system)}
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:on-click select-fn
|
||||
:class (dom/classnames (css :tab-container-tab-title) true
|
||||
(css :current) (= selected id))}
|
||||
title]))]
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div.tab-container-tab-title
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:on-click select-fn
|
||||
:class (when (= selected id) "current")}
|
||||
title])))]
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-container-content) true)
|
||||
(dom/classnames :tab-container-content true))}
|
||||
(d/seek #(= selected (-> % .-props .-id)) children)]]))
|
|
@ -0,0 +1 @@
|
|||
{"button-primary":"tab_container_tab_container_button-primary_83Zqm","button-secondary":"tab_container_tab_container_button-secondary_lnkfT","button-icon":"tab_container_tab_container_button-icon_9pt7Y","button-icon-small":"tab_container_tab_container_button-icon-small_A8MNz","tab-container":"tab_container_tab_container_tab-container_UElWL","tab-container-content":"tab_container_tab_container_tab-container-content_5dioy","tab-element":"tab_container_tab_container_tab-element_ehGDK","tab-container-tabs":"tab_container_tab_container_tab-container-tabs_Vrl6C","tab-container-tab-wrapper":"tab_container_tab_container_tab-container-tab-wrapper_-g0lU","tab-container-tab-title":"tab_container_tab_container_tab-container-tab-title_lR2I4","current":"tab_container_tab_container_current_jHyvE","collapse-sidebar":"tab_container_tab_container_collapse-sidebar_cuRC2","collapsed":"tab_container_tab_container_collapsed_KWhAl"}
|
|
@ -0,0 +1,89 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.tab-container {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
grid-template-columns: 100%;
|
||||
height: 100%;
|
||||
|
||||
.tab-container-content {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.tab-element {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.tab-container-tabs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: $s-2;
|
||||
height: $s-32;
|
||||
margin: $s-2 $s-2 0 $s-2;
|
||||
padding: $s-2;
|
||||
border-radius: $br8;
|
||||
background: var(--color-background-secondary);
|
||||
cursor: pointer;
|
||||
font-size: $fs12;
|
||||
.tab-container-tab-wrapper {
|
||||
@include flexCenter;
|
||||
flex-direction: row;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
gap: $s-2;
|
||||
.tab-container-tab-title {
|
||||
@include flexCenter;
|
||||
@include tabTitleTipography;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-radius: $br5;
|
||||
background-color: transparent;
|
||||
color: var(--tab-foreground-color);
|
||||
|
||||
&.current,
|
||||
&.current:hover {
|
||||
background: var(--tab-background-color-selected);
|
||||
color: var(--tab-foreground-color-selected);
|
||||
}
|
||||
&:hover {
|
||||
color: var(--tab-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.collapse-sidebar {
|
||||
@include flexCenter;
|
||||
@include buttonStyle;
|
||||
height: 100%;
|
||||
width: $s-24;
|
||||
padding: 0;
|
||||
border-radius: $br5;
|
||||
svg {
|
||||
@include flexCenter;
|
||||
height: 12px;
|
||||
width: 16px;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(180deg);
|
||||
fill: none;
|
||||
color: transparent;
|
||||
}
|
||||
&:hover {
|
||||
svg {
|
||||
stroke: var(--icon-foreground-hover);
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
svg {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,20 +4,20 @@
|
|||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.tab-container
|
||||
(ns app.main.ui.components.tabs-container
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc tab-element
|
||||
(mf/defc tabs-element
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (unchecked-get props "children")]
|
||||
[:div.tab-element
|
||||
[:div.tab-element-content children]]))
|
||||
|
||||
(mf/defc tab-container
|
||||
(mf/defc tabs-container
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [children (->>
|
|
@ -0,0 +1,23 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.tests.test-component
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require
|
||||
[app.util.keyboard :as kbd]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc test-component [{:keys [action icon name ]}]
|
||||
[:button.test-component
|
||||
{:class (css :button)
|
||||
:tab-index "0"
|
||||
:on-click action
|
||||
:on-key-down (fn [event]
|
||||
(when (kbd/enter? event)
|
||||
(action event)))}
|
||||
|
||||
(when icon [:span.logo icon])
|
||||
name])
|
|
@ -0,0 +1 @@
|
|||
{"button":"tests_test_component_button_8MQZj"}
|
|
@ -0,0 +1,4 @@
|
|||
.button {
|
||||
color: var(--button-foreground-active);
|
||||
background-color: var(--button-background-active);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue