chore(VerticalNavigation): update with preset

This commit is contained in:
Benjamin Canac
2021-12-21 15:32:10 +01:00
parent 8d7f041377
commit 05558e95ef
3 changed files with 86 additions and 95 deletions

View File

@@ -12,10 +12,13 @@
</template> </template>
<script> <script>
import { computed } from 'vue'
import { RouterLink } from 'vue-router' import { RouterLink } from 'vue-router'
import { useRoute } from '#imports'
export default { export default {
name: 'Link', name: 'Link',
inheritAttrs: false,
props: { props: {
...RouterLink.props, ...RouterLink.props,
inactiveClass: { inactiveClass: {
@@ -27,13 +30,18 @@ export default {
default: false default: false
} }
}, },
computed: { setup (props) {
isActive () { const route = useRoute()
if (!this.exact) { const isActive = computed(() => {
return !!this.$route.path.startsWith(this.to) if (props.exact) {
return [props.to, `${props.to}/`].includes(route.path)
} else { } else {
return this.$route.path === this.to || this.$route.path === `${this.to}/` return !!route.path.startsWith(props.to)
} }
})
return {
isActive
} }
} }
} }

View File

@@ -1,65 +1,40 @@
<template> <template>
<nav> <nav class="space-y-1">
<h3 <Link
v-if="title || $slots.title" v-for="link of links"
class="flex items-center justify-between px-2 mb-1 text-xs font-semibold tracking-wider uppercase u-text-gray-500" v-slot="{ isActive }"
:key="link.to || link.label"
:to="link.to"
:exact="link.exact"
:class="baseClass"
:active-class="activeClass"
:inactive-class="inactiveClass"
@click="link.click && link.click()"
@keyup.enter="$event.target.blur()"
> >
<slot name="title"> <slot name="icon" :link="link">
{{ title }} <Icon
v-if="link.icon"
:name="link.icon"
:class="[iconBaseClass, isActive ? iconActiveClass : iconInactiveClass]"
/>
</slot> </slot>
</h3> <slot :link="link">
<span class="truncate">{{ link.label }}</span>
<div class="space-y-1"> </slot>
<Link <slot name="badge" :link="link">
v-for="link of links" <span v-if="link.badge" :class="[badgeBaseClass, isActive ? badgeActiveClass : badgeInactiveClass]">
v-slot="{ isActive }" {{ link.badge }}
:key="link.to || link.label"
:to="link.to"
:exact="link.exact"
class="flex items-center px-2 py-2 text-sm font-medium rounded-md group focus:outline-none"
:active-class="activeVariantClass"
:inactive-class="variantClass"
@click="link.click && link.click()"
@keyup.enter="$event.target.blur()"
>
<slot name="icon" :link="link">
<Icon
v-if="link.icon"
:name="link.icon"
class="w-6 h-6 mr-3"
:class="isActive ? activeIconClass : iconClass"
/>
</slot>
<slot :link="link">
<span class="truncate">{{ link.label }}</span>
</slot>
<div v-if="link.shortcuts" class="hidden ml-3 space-x-1 lg:flex">
<span v-for="shortcut of link.shortcuts" :key="shortcut" class="flex items-center justify-center w-4 h-4 font-normal bg-gray-200 rounded text-xxs dark:bg-gray-700 u-text-gray-600">
{{ shortcut }}
</span>
</div>
<span class="inline-block ml-auto">
<slot name="badge" :link="link">
<span
v-if="link.badge"
class="ml-auto inline-block py-0.5 px-3 text-xs rounded-full"
:class="{
'u-bg-gray-50': isActive,
'bg-gray-200 dark:bg-gray-700 u-text-gray-600': !isActive
}"
>
{{ link.badge }}
</span>
</slot>
</span> </span>
</Link> </slot>
</div> </Link>
</nav> </nav>
</template> </template>
<script> <script>
import Icon from '../elements/Icon' import Icon from '../elements/Icon'
import Link from '../elements/Link' import Link from '../elements/Link'
import $ui from '#build/ui'
export default { export default {
components: { components: {
@@ -71,50 +46,41 @@ export default {
type: Array, type: Array,
required: true required: true
}, },
title: { baseClass: {
type: String, type: String,
default: null default: () => $ui.verticalNavigation.base
}, },
variant: { activeClass: {
type: String, type: String,
default: 'white', default: () => $ui.verticalNavigation.active
validator (value) {
return ['white', 'gray'].includes(value)
}
}
},
computed: {
options () {
return this.links.map(link => ({ value: link.to, text: link.label }))
}, },
variantClass () { inactiveClass: {
return ({ type: String,
white: 'u-text-gray-600 hover:u-text-gray-900 hover:u-bg-gray-50 focus:u-bg-gray-50', default: () => $ui.verticalNavigation.inactive
gray: 'u-text-gray-600 hover:u-text-gray-900 hover:u-bg-gray-50 focus:u-bg-gray-50'
})[this.variant]
}, },
activeVariantClass () { iconBaseClass: {
return ({ type: String,
white: 'u-text-gray-900 u-bg-gray-100 hover:u-text-gray-900 hover:u-bg-gray-100 focus:u-bg-gray-100', default: () => $ui.verticalNavigation.icon.base
gray: 'u-text-gray-900 bg-gray-200 dark:bg-gray-800 hover:u-text-gray-900 hover:bg-gray-200 dark:hover:bg-gray-800 focus:bg-gray-200 dark:focus:bg-gray-800'
})[this.variant]
}, },
iconClass () { iconActiveClass: {
return ({ type: String,
white: 'u-text-gray-400 group-hover:u-text-gray-500', default: () => $ui.verticalNavigation.icon.active
gray: 'u-text-gray-400 group-hover:u-text-gray-500'
})[this.variant]
}, },
activeIconClass () { iconInactiveClass: {
return ({ type: String,
white: 'u-text-gray-500 group-hover:u-text-gray-500', default: () => $ui.verticalNavigation.icon.inactive
gray: 'u-text-gray-500 group-hover:u-text-gray-500' },
})[this.variant] badgeBaseClass: {
} type: String,
}, default: () => $ui.verticalNavigation.badge.base
methods: { },
changeRoute (to) { badgeActiveClass: {
this.$router.push(to) type: String,
default: () => $ui.verticalNavigation.badge.active
},
badgeInactiveClass: {
type: String,
default: () => $ui.verticalNavigation.badge.inactive
} }
} }
} }

View File

@@ -219,6 +219,22 @@ const container = {
constrained: 'max-w-7xl' constrained: 'max-w-7xl'
} }
const verticalNavigation = {
base: 'flex items-center px-3 py-2 text-sm font-medium rounded-md',
active: 'u-text-gray-900 u-bg-gray-100',
inactive: 'u-text-gray-600 hover:u-text-gray-900 hover:u-bg-gray-50 focus:u-bg-gray-50',
icon: {
base: 'flex-shrink-0 -ml-1 mr-3 h-6 w-6',
active: 'u-text-gray-500',
inactive: 'u-text-gray-400 group-hover:u-text-gray-500'
},
badge: {
base: 'ml-auto inline-block py-0.5 px-3 text-xs rounded-full',
active: 'u-bg-white',
inactive: 'u-bg-gray-100 group-hove:u-bg'
}
}
export default { export default {
button, button,
formGroup, formGroup,
@@ -228,5 +244,6 @@ export default {
checkbox, checkbox,
radio, radio,
card, card,
container container,
verticalNavigation
} }