Add styled scrollbars (#231)
This commit is contained in:
parent
ece23e7c5f
commit
cd5e36af28
|
|
@ -41,7 +41,7 @@
|
||||||
// TODO: Replace with CSS color() function to calculate alpha when browsers support it
|
// TODO: Replace with CSS color() function to calculate alpha when browsers support it
|
||||||
// See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color() and https://caniuse.com/css-color-function
|
// See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color() and https://caniuse.com/css-color-function
|
||||||
// E6 = 90% alpha
|
// E6 = 90% alpha
|
||||||
--floating-menu-opacity-color-2-mildblack: #222222e6;
|
--floating-menu-opacity-color-2-mildblack: #222222f2;
|
||||||
--floating-menu-shadow: rgba(0, 0, 0, 50%);
|
--floating-menu-shadow: rgba(0, 0, 0, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,6 +69,72 @@ img {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scrollable,
|
||||||
|
.scrollable-x,
|
||||||
|
.scrollable-y {
|
||||||
|
// Standard
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-width: 6px;
|
||||||
|
scrollbar-gutter: 6px;
|
||||||
|
scrollbar-color: var(--color-5-dullgray) transparent;
|
||||||
|
|
||||||
|
&:not(:hover) {
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebKit
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: calc(2px + 6px + 2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:hover)::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
box-shadow: inset 0 0 0 1px var(--color-5-dullgray);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: inset 0 0 0 1px var(--color-6-lowergray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-clip: padding-box;
|
||||||
|
background-color: var(--color-5-dullgray);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 2px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-6-lowergray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollable {
|
||||||
|
// Standard
|
||||||
|
overflow: auto;
|
||||||
|
// WebKit
|
||||||
|
overflow: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollable-x {
|
||||||
|
// Standard
|
||||||
|
overflow-x: auto;
|
||||||
|
// WebKit
|
||||||
|
overflow-x: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scrollable-y {
|
||||||
|
// Standard
|
||||||
|
overflow-y: auto;
|
||||||
|
// WebKit
|
||||||
|
overflow-y: overlay;
|
||||||
|
}
|
||||||
|
|
||||||
// For placeholder messages (remove eventually)
|
// For placeholder messages (remove eventually)
|
||||||
.floating-menu {
|
.floating-menu {
|
||||||
h1,
|
h1,
|
||||||
|
|
@ -117,12 +183,12 @@ img {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: var(--color-6-lowergray);
|
background: var(--color-6-lowergray);
|
||||||
color: var(--color-f-white);
|
color: var(--color-f-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background-color: var(--color-accent-hover);
|
background: var(--color-accent-hover);
|
||||||
color: var(--color-f-white);
|
color: var(--color-f-white);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
<p>More blend and compositing options will be here</p>
|
<p>More blend and compositing options will be here</p>
|
||||||
</PopoverButton>
|
</PopoverButton>
|
||||||
</LayoutRow>
|
</LayoutRow>
|
||||||
<LayoutRow :class="'layer-tree'">
|
<LayoutRow :class="'layer-tree scrollable-y'">
|
||||||
<LayoutCol :class="'list'">
|
<LayoutCol :class="'list'">
|
||||||
<div class="layer-row" v-for="layer in layers" :key="layer.path">
|
<div class="layer-row" v-for="layer in layers" :key="layer.path">
|
||||||
<div class="layer-visibility">
|
<div class="layer-visibility">
|
||||||
|
|
@ -62,8 +62,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.layer-tree {
|
.layer-tree {
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
.layer-row {
|
.layer-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="floating-menu" :class="[direction.toLowerCase(), type.toLowerCase()]" v-if="open" ref="floatingMenu">
|
<div class="floating-menu" :class="[direction.toLowerCase(), type.toLowerCase()]" v-if="open" ref="floatingMenu">
|
||||||
<div class="tail" v-if="type === MenuType.Popover"></div>
|
<div class="tail" v-if="type === MenuType.Popover"></div>
|
||||||
<div class="floating-menu-container" ref="floatingMenuContainer">
|
<div class="floating-menu-container" ref="floatingMenuContainer">
|
||||||
<div class="floating-menu-content" ref="floatingMenuContent" :style="floatingMenuContentStyle">
|
<div class="floating-menu-content" :class="{ 'scrollable-y': scrollable }" ref="floatingMenuContent" :style="floatingMenuContentStyle">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -193,6 +193,7 @@ export default defineComponent({
|
||||||
type: { type: String, required: true },
|
type: { type: String, required: true },
|
||||||
windowEdgeMargin: { type: Number, default: 8 },
|
windowEdgeMargin: { type: Number, default: 8 },
|
||||||
minWidth: { type: Number, default: 0 },
|
minWidth: { type: Number, default: 0 },
|
||||||
|
scrollable: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<FloatingMenu :class="'menu-list'" :direction="direction" :type="MenuType.Dropdown" ref="floatingMenu" :windowEdgeMargin="0" data-hover-menu-keep-open>
|
<FloatingMenu :class="'menu-list'" :direction="direction" :type="MenuType.Dropdown" ref="floatingMenu" :windowEdgeMargin="0" :scrollable="scrollable" data-hover-menu-keep-open>
|
||||||
<template v-for="(section, sectionIndex) in menuEntries" :key="sectionIndex">
|
<template v-for="(section, sectionIndex) in menuEntries" :key="sectionIndex">
|
||||||
<Separator :type="SeparatorType.List" :direction="SeparatorDirection.Vertical" v-if="sectionIndex > 0" />
|
<Separator :type="SeparatorType.List" :direction="SeparatorDirection.Vertical" v-if="sectionIndex > 0" />
|
||||||
<div
|
<div
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
v-model:active-entry="currentEntry"
|
v-model:active-entry="currentEntry"
|
||||||
:minWidth="minWidth"
|
:minWidth="minWidth"
|
||||||
:drawIcon="drawIcon"
|
:drawIcon="drawIcon"
|
||||||
|
:scrollable="scrollable"
|
||||||
:ref="(ref) => setEntryRefs(entry, ref)"
|
:ref="(ref) => setEntryRefs(entry, ref)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -144,8 +145,10 @@ const MenuList = defineComponent({
|
||||||
direction: { type: String as PropType<MenuDirection>, default: MenuDirection.Bottom },
|
direction: { type: String as PropType<MenuDirection>, default: MenuDirection.Bottom },
|
||||||
menuEntries: { type: Array as PropType<SectionsOfMenuListEntries>, required: true },
|
menuEntries: { type: Array as PropType<SectionsOfMenuListEntries>, required: true },
|
||||||
activeEntry: { type: Object as PropType<MenuListEntry>, required: false },
|
activeEntry: { type: Object as PropType<MenuListEntry>, required: false },
|
||||||
|
defaultAction: { type: Function as PropType<Function | undefined>, required: false },
|
||||||
minWidth: { type: Number, default: 0 },
|
minWidth: { type: Number, default: 0 },
|
||||||
drawIcon: { type: Boolean, default: false },
|
drawIcon: { type: Boolean, default: false },
|
||||||
|
scrollable: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setEntryRefs(menuEntry: MenuListEntry, ref: typeof FloatingMenu) {
|
setEntryRefs(menuEntry: MenuListEntry, ref: typeof FloatingMenu) {
|
||||||
|
|
@ -154,32 +157,27 @@ const MenuList = defineComponent({
|
||||||
handleEntryClick(menuEntry: MenuListEntry) {
|
handleEntryClick(menuEntry: MenuListEntry) {
|
||||||
(this.$refs.floatingMenu as typeof FloatingMenu).setClosed();
|
(this.$refs.floatingMenu as typeof FloatingMenu).setClosed();
|
||||||
|
|
||||||
if (menuEntry.action) {
|
if (menuEntry.action) menuEntry.action();
|
||||||
menuEntry.action();
|
else if (this.defaultAction) this.defaultAction();
|
||||||
} else {
|
else this.$emit("update:activeEntry", menuEntry);
|
||||||
this.$emit("update:activeEntry", menuEntry);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
handleEntryMouseEnter(menuEntry: MenuListEntry) {
|
handleEntryMouseEnter(menuEntry: MenuListEntry) {
|
||||||
if (!menuEntry.children || !menuEntry.children.length) return;
|
if (!menuEntry.children || !menuEntry.children.length) return;
|
||||||
|
|
||||||
if (menuEntry.ref) {
|
if (menuEntry.ref) menuEntry.ref.setOpen();
|
||||||
menuEntry.ref.setOpen();
|
else throw new Error("The menu bar floating menu has no associated ref");
|
||||||
} else throw new Error("The menu bar floating menu has no associated ref");
|
|
||||||
},
|
},
|
||||||
handleEntryMouseLeave(menuEntry: MenuListEntry) {
|
handleEntryMouseLeave(menuEntry: MenuListEntry) {
|
||||||
if (!menuEntry.children || !menuEntry.children.length) return;
|
if (!menuEntry.children || !menuEntry.children.length) return;
|
||||||
|
|
||||||
if (menuEntry.ref) {
|
if (menuEntry.ref) menuEntry.ref.setClosed();
|
||||||
menuEntry.ref.setClosed();
|
else throw new Error("The menu bar floating menu has no associated ref");
|
||||||
} else throw new Error("The menu bar floating menu has no associated ref");
|
|
||||||
},
|
},
|
||||||
isMenuEntryOpen(menuEntry: MenuListEntry): boolean {
|
isMenuEntryOpen(menuEntry: MenuListEntry): boolean {
|
||||||
if (!menuEntry.children || !menuEntry.children.length) return false;
|
if (!menuEntry.children || !menuEntry.children.length) return false;
|
||||||
|
|
||||||
if (menuEntry.ref) {
|
if (menuEntry.ref) return menuEntry.ref.isOpen();
|
||||||
return menuEntry.ref.isOpen();
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
setOpen() {
|
setOpen() {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,15 @@
|
||||||
<span>{{ activeEntry.label }}</span>
|
<span>{{ activeEntry.label }}</span>
|
||||||
<Icon :class="'dropdown-arrow'" :icon="'DropdownArrow'" />
|
<Icon :class="'dropdown-arrow'" :icon="'DropdownArrow'" />
|
||||||
</div>
|
</div>
|
||||||
<MenuList :menuEntries="menuEntries" v-model:active-entry="activeEntry" :direction="MenuDirection.Bottom" @width-changed="onWidthChanged" :drawIcon="drawIcon" ref="menuList" />
|
<MenuList
|
||||||
|
:menuEntries="menuEntries"
|
||||||
|
v-model:active-entry="activeEntry"
|
||||||
|
:direction="MenuDirection.Bottom"
|
||||||
|
@width-changed="onWidthChanged"
|
||||||
|
:drawIcon="drawIcon"
|
||||||
|
:scrollable="true"
|
||||||
|
ref="menuList"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -62,7 +70,6 @@
|
||||||
|
|
||||||
.menu-list .floating-menu-container .floating-menu-content {
|
.menu-list .floating-menu-container .floating-menu-content {
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,7 @@
|
||||||
<Icon :icon="entry.icon" v-if="entry.icon" />
|
<Icon :icon="entry.icon" v-if="entry.icon" />
|
||||||
<span v-if="entry.label">{{ entry.label }}</span>
|
<span v-if="entry.label">{{ entry.label }}</span>
|
||||||
</div>
|
</div>
|
||||||
<MenuList
|
<MenuList :menuEntries="entry.children" :direction="MenuDirection.Bottom" :minWidth="240" :drawIcon="true" :defaultAction="actionNotImplemented" :ref="(ref) => setEntryRefs(entry, ref)" />
|
||||||
:ourEntry="entry"
|
|
||||||
:menuEntries="entry.children"
|
|
||||||
:direction="MenuDirection.Bottom"
|
|
||||||
:minWidth="240"
|
|
||||||
:drawIcon="true"
|
|
||||||
:defaultAction="actionNotImplemented"
|
|
||||||
:ref="(ref) => setEntryRefs(entry, ref)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue