Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Add hover menus and fix ProjectCard issue with omitted properties (#166)
Browse files Browse the repository at this point in the history
* Adds hover menus

* Allow ProjectCard props to be omitted

* Bump version
  • Loading branch information
Prospector authored Dec 6, 2023
1 parent ca2336a commit 94db8ce
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 63 deletions.
21 changes: 21 additions & 0 deletions docs/components/popout-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,24 @@
</template>
</PopoutMenu>
```

# Popout Menu on hover
<DemoContainer>
<PopoutMenu class="btn btn-dropdown-animation" position="bottom" direction="right" allow-hover>
Hover me! <DropdownIcon />
<template #menu>
Menu contents!
Menu contents!
Menu contents!
</template>
</PopoutMenu>
</DemoContainer>

```vue
<PopoutMenu class="btn" position="bottom" direction="right" allow-hover>
Hover me!
<template #menu>
Menu contents!
</template>
</PopoutMenu>
```
5 changes: 5 additions & 0 deletions lib/components/base/OverflowMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:disabled="disabled"
:position="position"
:direction="direction"
:allow-hover="allowHover"
>
<slot></slot>
<template #menu>
Expand Down Expand Up @@ -66,6 +67,10 @@ defineProps({
type: String,
default: 'left',
},
allowHover: {
type: Boolean,
default: false,
},
})
defineOptions({
inheritAttrs: false,
Expand Down
200 changes: 143 additions & 57 deletions lib/components/base/PopoutMenu.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
<template>
<div ref="dropdown" class="popup-container" tabindex="-1" :aria-expanded="dropdownVisible">
<div
ref="dropdown"
class="popup-container"
tabindex="-1"
:aria-expanded="dropdownVisible"
:class="{ 'allow-hover': allowHover }"
>
<button
v-bind="$attrs"
ref="dropdownButton"
Expand All @@ -9,6 +15,11 @@
>
<slot></slot>
</button>
<div
v-if="allowHover"
class="hover-bounding-box"
:class="`position-${position}-${direction}`"
></div>
<div
class="popup-menu"
:class="`position-${position}-${direction} ${dropdownVisible ? 'visible' : ''}`"
Expand All @@ -34,6 +45,10 @@ const props = defineProps({
type: String,
default: 'left',
},
allowHover: {
type: Boolean,
default: false,
},
})
defineOptions({
inheritAttrs: false,
Expand Down Expand Up @@ -90,6 +105,133 @@ onBeforeUnmount(() => {
.popup-container {
position: relative;
&.allow-hover .hover-bounding-box {
position: absolute;
inset: 0;
border-radius: var(--radius-md);
z-index: 1;
// Debug properties
// background-color: red;
// opacity: 0.1;
// Q: Why is this here and also below?
// A: For the few browsers that do not yet support :has(), this at least
// makes it mostly functional.
&:hover {
&.position-bottom-left,
&.position-bottom-right {
bottom: -1rem;
}
&.position-top-left,
&.position-top-right {
top: -1rem;
}
&.position-left-up,
&.position-left-down {
left: -1rem;
}
&.position-right-up,
&.position-right-down {
right: -1rem;
}
}
}
&:not(.allow-hover) .popup-menu:not(.visible):not(:focus-within),
&.allow-hover:not(:has(.hover-bounding-box:hover)):not(:has(.popup-menu:hover))
.popup-menu:not(.visible):not(:focus-within) {
pointer-events: none;
*,
::before,
::after {
pointer-events: none;
}
}
&.allow-hover:has(.hover-bounding-box:hover),
&.allow-hover:has(.popup-menu:hover),
:has(.popup-menu.visible),
:has(.popup-menu:focus-within) {
:deep(.btn-dropdown-animation svg:last-child) {
transform: rotate(180deg);
}
.hover-bounding-box {
&.position-bottom-left,
&.position-bottom-right {
bottom: -1rem;
}
&.position-top-left,
&.position-top-right {
top: -1rem;
}
&.position-left-up,
&.position-left-down {
left: -1rem;
}
&.position-right-up,
&.position-right-down {
right: -1rem;
}
}
}
&.allow-hover .hover-bounding-box:hover + .popup-menu,
&.allow-hover .popup-menu:hover,
.popup-menu.visible,
.popup-menu:focus-within {
opacity: 1;
scale: 1;
&.position-bottom-left {
top: calc(100% + var(--gap-sm));
right: 0;
}
&.position-bottom-right {
top: calc(100% + var(--gap-sm));
left: 0;
}
&.position-top-left {
bottom: calc(100% + var(--gap-sm));
right: 0;
}
&.position-top-right {
bottom: calc(100% + var(--gap-sm));
left: 0;
}
&.position-left-up {
bottom: 0rem;
right: calc(100% + var(--gap-sm));
}
&.position-left-down {
top: 0rem;
right: calc(100% + var(--gap-sm));
}
&.position-right-up {
bottom: 0rem;
left: calc(100% + var(--gap-sm));
}
&.position-right-down {
top: 0rem;
left: calc(100% + var(--gap-sm));
}
}
.popup-menu {
--_animation-offset: -1rem;
position: absolute;
Expand Down Expand Up @@ -149,62 +291,6 @@ onBeforeUnmount(() => {
left: calc(100% + var(--gap-sm) - 1rem);
}
&:not(.visible):not(:focus-within) {
pointer-events: none;
*,
::before,
::after {
pointer-events: none;
}
}
&.visible,
&:focus-within {
opacity: 1;
scale: 1;
&.position-bottom-left {
top: calc(100% + var(--gap-sm));
right: 0;
}
&.position-bottom-right {
top: calc(100% + var(--gap-sm));
left: 0;
}
&.position-top-left {
bottom: calc(100% + var(--gap-sm));
right: 0;
}
&.position-top-right {
bottom: calc(100% + var(--gap-sm));
left: 0;
}
&.position-left-up {
bottom: 0rem;
right: calc(100% + var(--gap-sm));
}
&.position-left-down {
top: 0rem;
right: calc(100% + var(--gap-sm));
}
&.position-right-up {
bottom: 0rem;
left: calc(100% + var(--gap-sm));
}
&.position-right-down {
top: 0rem;
left: calc(100% + var(--gap-sm));
}
}
.btn {
white-space: nowrap;
}
Expand Down
14 changes: 9 additions & 5 deletions lib/components/base/ProjectCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,23 @@
<div class="summary">{{ description }}</div>
<div class="stats">
<span
v-if="downloads"
v-tooltip="formatMessage(messages.downloads, { count: formatNumber(downloads, false) })"
class="stat consumes-click"
>
<span class="label"><DownloadIcon /></span>
<span class="value">{{ formatNumber(downloads) }}</span>
</span>
<span
v-if="follows"
v-tooltip="formatMessage(messages.followers, { count: formatNumber(follows, false) })"
class="stat consumes-click"
>
<span class="label"><HeartIcon /></span>
<span class="value">{{ formatNumber(follows) }}</span>
</span>
<span
v-if="showUpdatedDate"
v-if="showUpdatedDate && updatedAt"
v-tooltip="
formatMessage(messages.updated, {
date: dayjs(updatedAt).format('MMMM D, YYYY [at] h:mm A'),
Expand All @@ -48,7 +50,7 @@
<span class="value">{{ fromNow(updatedAt) }}</span>
</span>
<span
v-else
v-else-if="createdAt"
v-tooltip="
formatMessage(messages.published, {
date: dayjs(createdAt).format('MMMM D, YYYY [at] h:mm A'),
Expand All @@ -60,8 +62,10 @@
<span class="value">{{ fromNow(createdAt) }}</span>
</span>
<div class="tags">
<TagIcon />
<Categories :type="type" :categories="categories" />
<template v-if="categories && categories.length > 0">
<TagIcon />
<Categories :type="type" :categories="categories" />
</template>
</div>
</div>
</article>
Expand Down Expand Up @@ -145,7 +149,7 @@ defineProps({
},
createdAt: {
type: String,
default: '0000-00-00',
default: null,
},
updatedAt: {
type: String,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "omorphia",
"type": "module",
"version": "0.9.2",
"version": "0.9.3",
"files": [
"dist",
"locales"
Expand Down

0 comments on commit 94db8ce

Please sign in to comment.