Skip to content

Instantly share code, notes, and snippets.

@Gerbuuun
Last active September 21, 2024 20:15
Show Gist options
  • Save Gerbuuun/bb6ca1306b0fcd8800e7943a8edbe17c to your computer and use it in GitHub Desktop.
Save Gerbuuun/bb6ca1306b0fcd8800e7943a8edbe17c to your computer and use it in GitHub Desktop.
Supabase Dashboard Sidebar Nuxt UI
<script setup lang="ts">
import type { DashboardSidebarLink } from '#ui-pro/types';
defineProps<{
links: DashboardSidebarLink[][];
}>();
const open = ref(false);
const userDropdownOpen = ref(false);
</script>
<template>
<div class="w-14 h-full flex flex-col">
<nav
:data-state="open ? 'expanded' : 'collapsed'"
:class="[
'group z-10 h-full w-14 data-[state=expanded]:w-[13rem]',
'border-r bg-background border-gray-200 dark:border-gray-800 data-[state=expanded]:shadow-xl',
'transition-width duration-200',
'hide-scrollbar flex flex-col overflow-y-auto overflow-x-hidden'
]"
@mouseenter="() => open = true"
@mouseleave="() => open = false || userDropdownOpen"
>
<ul class="flex flex-col gap-y-1 justify-start relative px-2 pt-2">
<template v-for="group, index in links" :key="index">
<SidebarItem
v-for="item in group"
:key="item.label"
:item="item"
:open="open"
@navigate="open = false"
/>
<UDivider />
</template>
</ul>
</nav>
</div>
</template>
<style scoped>
.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
.hide-scrollbar::-webkit-scrollbar {
display: none;
}
</style>
<script setup lang="ts">
import type { DashboardSidebarLink } from '#ui-pro/types';
const props = defineProps<{
item: DashboardSidebarLink;
open: boolean;
}>();
defineEmits<{
navigate: [];
}>();
const route = useRoute();
const isActive = computed(() => props.item.exact ? route.path === props.item.to : route.path.startsWith(props.item.to as string));
</script>
<template>
<NuxtLink
:to="item.to"
:exact="item.exact"
:class="[
'relative',
'size-10 group-data-[state=expanded]:w-full',
'transition-[width] duration-200',
'flex items-center rounded-md',
'group-data-[state=collapsed]:justify-center',
'group-data-[state=expanded]:-space-x-2',
isActive
? 'text-gray-900 hover:text-gray-900 dark:text-white dark:hover:text-white bg-gray-100 dark:bg-gray-800'
: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:bg-gray-50 dark:hover:bg-gray-800/50',
'group/item',
]"
@click="() => $emit('navigate')"
>
<span
:class="[
'absolute left-0 top-0 flex items-center size-10 items-center justify-center',
isActive ? 'text-gray-900 dark:text-white' : 'text-gray-400 dark:text-gray-500 group-hover/item:text-gray-700 dark:group-hover/item:text-gray-200',
]"
>
<UIcon v-if="item.icon" :name="item.icon" class="size-5" />
</span>
<span
:aria-hidden="open || undefined"
:class="[
'min-w-[128px] text-sm',
'absolute left-7 group-data-[state=expanded]:left-12',
'opacity-0 group-data-[state=expanded]:opacity-100',
'transition-[left,opacity,margin]',
]"
>
{{ item.label }}
</span>
</NuxtLink>
</template>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment