chore: use the <dropdown> and <dropdown-item> components everywhere
Resolves https://kolaente.dev/vikunja/frontend/issues/2176
This commit is contained in:
@ -1,25 +1,95 @@
|
||||
<template>
|
||||
<router-link
|
||||
<component
|
||||
:is="componentNodeName"
|
||||
v-bind="elementBindings"
|
||||
:to="to"
|
||||
class="dropdown-item">
|
||||
<span class="icon" v-if="icon !== ''">
|
||||
<span class="icon" v-if="icon">
|
||||
<icon :icon="icon"/>
|
||||
</span>
|
||||
<span>
|
||||
<slot></slot>
|
||||
</span>
|
||||
</router-link>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps({
|
||||
to: {
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
import {ref, useAttrs, watchEffect} from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
to?: object,
|
||||
icon?: string | string[],
|
||||
}>()
|
||||
|
||||
const componentNodeName = ref<Node['nodeName']>('a')
|
||||
const elementBindings = ref({})
|
||||
|
||||
const attrs = useAttrs()
|
||||
watchEffect(() => {
|
||||
let nodeName = 'a'
|
||||
|
||||
if (props.to) {
|
||||
nodeName = 'router-link'
|
||||
}
|
||||
|
||||
if ('href' in attrs) {
|
||||
nodeName = 'BaseButton'
|
||||
}
|
||||
|
||||
componentNodeName.value = nodeName
|
||||
elementBindings.value = {
|
||||
...attrs,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.dropdown-item {
|
||||
color: var(--text);
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
padding: $item-padding;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
a.dropdown-item,
|
||||
button.dropdown-item {
|
||||
text-align: inherit;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: left !important;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--grey-100) !important;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: var(--link);
|
||||
color: var(--link-invert);
|
||||
}
|
||||
|
||||
.icon {
|
||||
padding-right: .5rem;
|
||||
}
|
||||
|
||||
.icon:not(.has-text-success) {
|
||||
color: var(--grey-300) !important;
|
||||
}
|
||||
|
||||
&.has-text-danger .icon {
|
||||
color: var(--danger) !important;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
cursor: not-allowed;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="dropdown is-right is-active" ref="dropdown">
|
||||
<div class="dropdown" ref="dropdown">
|
||||
<slot name="trigger" :close="close" :toggleOpen="toggleOpen">
|
||||
<BaseButton class="dropdown-trigger is-flex" @click="toggleOpen">
|
||||
<icon :icon="triggerIcon" class="icon"/>
|
||||
@ -51,7 +51,36 @@ onClickOutside(dropdown, (e: Event) => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dropdown-menu .dropdown-content {
|
||||
.dropdown {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
min-width: 12rem;
|
||||
padding-top: 4px;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
z-index: 20;
|
||||
display: block;
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
background-color: var(--scheme-main);
|
||||
border-radius: $radius;
|
||||
padding-bottom: .5rem;
|
||||
padding-top: .5rem;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
</style>
|
||||
|
||||
.dropdown-divider {
|
||||
background-color: var(--border-light);
|
||||
border: none;
|
||||
display: block;
|
||||
height: 1px;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<x-button
|
||||
v-if="isButton"
|
||||
v-if="type === 'button'"
|
||||
variant="secondary"
|
||||
:icon="iconName"
|
||||
v-tooltip="tooltipText"
|
||||
@ -9,6 +9,15 @@
|
||||
>
|
||||
{{ buttonText }}
|
||||
</x-button>
|
||||
<DropdownItem
|
||||
v-else-if="type === 'dropdown'"
|
||||
v-tooltip="tooltipText"
|
||||
@click="changeSubscription"
|
||||
:class="{'is-disabled': disabled}"
|
||||
:icon="iconName"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</DropdownItem>
|
||||
<BaseButton
|
||||
v-else
|
||||
v-tooltip="tooltipText"
|
||||
@ -27,6 +36,7 @@ import {computed, shallowRef} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import BaseButton from '@/components/base/BaseButton.vue'
|
||||
import DropdownItem from '@/components/misc/dropdown-item.vue'
|
||||
|
||||
import SubscriptionService from '@/services/subscription'
|
||||
import SubscriptionModel from '@/models/subscription'
|
||||
@ -34,15 +44,15 @@ import SubscriptionModel from '@/models/subscription'
|
||||
import {success} from '@/message'
|
||||
|
||||
interface Props {
|
||||
entity: string
|
||||
entityId: number
|
||||
subscription: SubscriptionModel | null
|
||||
isButton?: boolean
|
||||
entity: string
|
||||
entityId: number
|
||||
subscription: SubscriptionModel | null
|
||||
type?: 'button' | 'dropdown' | null
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
isButton: true,
|
||||
subscription: null,
|
||||
type: 'button',
|
||||
})
|
||||
|
||||
const subscriptionEntity = computed<string | null>(() => props.subscription?.entity ?? null)
|
||||
|
Reference in New Issue
Block a user