Files
Rocketmc/packages/ui/src/components/base/PopoutMenu.vue
Prospector 6a70acef25 Updated ad placeholder graphics, update Modrinth App sidebar to mockup designs (#4584)
* Update ad placeholders to new green graphic

* Remove rounded corners from app ad frame

* Improve web ad placeholder styling

* Revamp app sidebar to match mockups more closely, greatly improve friends UX, fix up context menus and typify shit

* only show overflow on hover

* lint

* intl:extract

* clean up the inline code in FriendsSection
2025-10-19 23:26:17 +00:00

103 lines
1.7 KiB
Vue

<template>
<Dropdown
ref="dropdown"
no-auto-focus
:aria-id="dropdownId || null"
:placement="placement"
:class="dropdownClass"
@apply-hide="focusTrigger"
@apply-show="focusMenuChild"
>
<button ref="trigger" v-bind="$attrs" v-tooltip="tooltip">
<slot></slot>
</button>
<template #popper="{ hide: hideFunction }">
<button class="dummy-button" @focusin="hideAndFocusTrigger(hideFunction)"></button>
<div ref="menu" class="contents">
<slot name="menu"> </slot>
</div>
<button class="dummy-button" @focusin="hideAndFocusTrigger(hideFunction)"></button>
</template>
</Dropdown>
</template>
<script setup>
import { Dropdown } from 'floating-vue'
import { ref } from 'vue'
const trigger = ref()
const menu = ref()
const dropdown = ref()
defineProps({
dropdownId: {
type: String,
default: null,
required: false,
},
dropdownClass: {
type: String,
default: null,
required: false,
},
tooltip: {
type: String,
default: null,
required: false,
},
placement: {
type: String,
default: 'bottom-end',
required: false,
},
})
function focusMenuChild() {
setTimeout(() => {
if (menu.value && menu.value.children && menu.value.children.length > 0) {
menu.value.children[0].focus()
}
}, 50)
}
function hideAndFocusTrigger(hide) {
hide()
focusTrigger()
}
function focusTrigger() {
trigger.value.focus()
}
defineOptions({
inheritAttrs: false,
})
function hide() {
dropdown.value.hide()
}
function show() {
dropdown.value.show()
}
defineExpose({
show,
hide,
})
</script>
<style scoped>
.dummy-button {
position: absolute;
width: 0;
height: 0;
margin: 0;
padding: 0;
border: none;
overflow: hidden;
clip: rect(0 0 0 0);
white-space: nowrap;
outline: none;
}
</style>