Added first sidebar draft
This commit is contained in:
28
app.vue
28
app.vue
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ConfigProvider } from "radix-vue"
|
import { ConfigProvider } from "radix-vue"
|
||||||
|
import { cn } from "./lib/utils";
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
titleTemplate: (titleChunk) => {
|
titleTemplate: (titleChunk) => {
|
||||||
@@ -26,6 +27,8 @@ useHead({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const useIdFunction = () => useId()
|
const useIdFunction = () => useId()
|
||||||
|
|
||||||
|
const { isSidebarOpened } = storeToRefs(useUiStore())
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -34,10 +37,18 @@ const useIdFunction = () => useId()
|
|||||||
|
|
||||||
<NuxtLayout>
|
<NuxtLayout>
|
||||||
<ConfigProvider :use-id="useIdFunction">
|
<ConfigProvider :use-id="useIdFunction">
|
||||||
<div class="h-full grid grid-cols-[auto_1fr] dark:bg-black transition-colors">
|
<div
|
||||||
|
class="h-full grid md:grid-cols-[auto_1fr] dark:bg-black shadow-body-light dark:shadow-body-dark transition-colors after:absolute after:transition-colors"
|
||||||
|
:class="cn({
|
||||||
|
'max-md:after:bg-transparent': isSidebarOpened,
|
||||||
|
'has-sidebar max-md:after:bg-black/20 md:after:opacity-0 md:after:pointer-events-none': isSidebarOpened
|
||||||
|
})"
|
||||||
|
>
|
||||||
<Sidebar />
|
<Sidebar />
|
||||||
|
|
||||||
<div class="wrapper max-h-screen shadow-body-light dark:shadow-body-dark transition-all">
|
<div
|
||||||
|
class="wrapper max-h-screen transition-all"
|
||||||
|
>
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,4 +65,17 @@ const useIdFunction = () => useId()
|
|||||||
.wrapper > * {
|
.wrapper > * {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.has-sidebar {
|
||||||
|
position: relative;
|
||||||
|
isolation: isolate;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 30;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
|
import { breakpointsTailwind, useBreakpoints } from "@vueuse/core"
|
||||||
import { PhMagnifyingGlass } from "@phosphor-icons/vue"
|
import { PhMagnifyingGlass } from "@phosphor-icons/vue"
|
||||||
|
|
||||||
const { revealAdvancedSearch, } = useCalendar()
|
const { revealAdvancedSearch } = useCalendar()
|
||||||
|
|
||||||
const breakpoints = useBreakpoints(
|
const breakpoints = useBreakpoints(
|
||||||
breakpointsTailwind
|
breakpointsTailwind
|
||||||
|
|||||||
@@ -16,7 +16,10 @@ const { isReadOnly, defaultDate } = storeToRefs(useCalendar())
|
|||||||
<li>
|
<li>
|
||||||
<LazyCalendarDialogQuickCreateEvent v-if="!isReadOnly" />
|
<LazyCalendarDialogQuickCreateEvent v-if="!isReadOnly" />
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li class="md:hidden">
|
||||||
|
<SidebarToggle />
|
||||||
|
</li>
|
||||||
|
<li class="max-md:hidden">
|
||||||
<LazyCalendarMenuToday v-if="defaultDate" />
|
<LazyCalendarMenuToday v-if="defaultDate" />
|
||||||
</li>
|
</li>
|
||||||
<li class="ml-4">
|
<li class="ml-4">
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ function toFutureFar(): void {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<div class="grid items-end w-40 px-4 py-2 bg-white dark:bg-black border-border border-x-[1px] border-t-[1px] rounded-t-sm text-sm transition-colors">
|
<div class="grid items-center w-40 px-3 md:px-4 py-2 bg-white dark:bg-black border-border border-x-[1px] border-t-[1px] rounded-t-sm text-sm max-md:text-xs transition-colors">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<span>{{ currentDate.currentDateTitle }}</span>
|
<span>{{ currentDate.currentDateTitle }}</span>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PhCompass, PhGlobeHemisphereEast, PhHurricane, PhList } from "@phosphor-icons/vue"
|
import { PhCompass, PhGlobeHemisphereEast, PhHurricane, PhX } from "@phosphor-icons/vue"
|
||||||
import type { SidebarMenuActionType, SidebarMenuIcon } from "./SidebarProps";
|
import type { SidebarMenuActionType, SidebarMenuIcon } from "./SidebarProps";
|
||||||
|
import { cn } from "~/lib/utils";
|
||||||
|
|
||||||
const { revealAdvancedSearch } = useCalendar()
|
const { revealAdvancedSearch } = useCalendar()
|
||||||
const { currentMenu } = storeToRefs(useUiStore())
|
const { toggleSidebar } = useUiStore()
|
||||||
|
const { currentMenu, isSidebarOpened } = storeToRefs(useUiStore())
|
||||||
|
|
||||||
function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
function handleMenuItemAction(actionType: SidebarMenuActionType) {
|
||||||
if (actionType === "event-search") {
|
if (actionType === "event-search") {
|
||||||
@@ -21,14 +23,32 @@ function computeMenuItemIcon(iconString: SidebarMenuIcon) {
|
|||||||
return PhCompass
|
return PhCompass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const sidebarRef = ref(null)
|
||||||
|
|
||||||
|
// onClickOutside(sidebarRef, () => {
|
||||||
|
// isSidebarOpened.value = false
|
||||||
|
// })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<nav class="w-16 py-6 border-r-[1px] bg-indigo-700 dark:bg-black text-white border-r-indigo-700 dark:border-r-indigo-950 grid grid-rows-[1fr_auto] justify-center transition-colors after:opacity-50 after:contrast-125 dark:after:opacity-75 dark:after:contrast-175 after:-hue-rotate-60">
|
<nav
|
||||||
|
ref="sidebarRef"
|
||||||
|
:class="cn(
|
||||||
|
['md:relative md:isolate w-16 py-6 grid grid-rows-[1fr_auto] justify-center transition-all'], // Base appearance
|
||||||
|
['after:opacity-50 after:contrast-125 dark:after:opacity-75 dark:after:contrast-175 after:-hue-rotate-60'], // After styling
|
||||||
|
['border-r-[1px] bg-indigo-700 dark:bg-black text-white border-r-indigo-700 dark:border-r-indigo-950 shadow-navbar-light dark:shadow-navbar-dark'], // Colours
|
||||||
|
['max-md:absolute max-md:left-0 max-md:inset-0 max-md:z-50'], // Responsive behaviours
|
||||||
|
{
|
||||||
|
'max-md:-translate-x-16': !isSidebarOpened,
|
||||||
|
'max-md:-translate-x-0 shadow-navbar-dark dark:bg-slate-950': isSidebarOpened
|
||||||
|
}
|
||||||
|
)"
|
||||||
|
>
|
||||||
<menu class="flex flex-col gap-4">
|
<menu class="flex flex-col gap-4">
|
||||||
<li class="mb-12">
|
<li class="mb-12">
|
||||||
<UiButton variant="ghost" size="icon" class="rounded-full" @click="console.log">
|
<UiButton variant="ghost" size="icon" class="rounded-full" @click="toggleSidebar">
|
||||||
<PhList size="27" />
|
<PhX size="24" />
|
||||||
</UiButton>
|
</UiButton>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
@@ -86,15 +106,14 @@ function computeMenuItemIcon(iconString: SidebarMenuIcon) {
|
|||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
|
<div ref="userMenuRef">
|
||||||
<UserCTA />
|
<UserCTA />
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
nav {
|
nav {
|
||||||
position: relative;
|
|
||||||
isolation: isolate;
|
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
display: block;
|
display: block;
|
||||||
content: '';
|
content: '';
|
||||||
|
|||||||
15
components/global/sidebar/SidebarToggle.vue
Normal file
15
components/global/sidebar/SidebarToggle.vue
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { PhList } from "@phosphor-icons/vue"
|
||||||
|
|
||||||
|
const { toggleSidebar } = useUiStore()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UiButton
|
||||||
|
size="icon"
|
||||||
|
variant="outline"
|
||||||
|
@click="toggleSidebar"
|
||||||
|
>
|
||||||
|
<PhList size="19" weight="light" />
|
||||||
|
</UiButton>
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
|
import { breakpointsTailwind } from "@vueuse/core"
|
||||||
import type { SidebarMenuItem } from "~/components/global/sidebar/SidebarProps"
|
import type { SidebarMenuItem } from "~/components/global/sidebar/SidebarProps"
|
||||||
|
|
||||||
|
const breakpoints = useBreakpoints(
|
||||||
|
breakpointsTailwind
|
||||||
|
)
|
||||||
|
|
||||||
export const useUiStore = defineStore("ui", () => {
|
export const useUiStore = defineStore("ui", () => {
|
||||||
const currentMenu: Ref<SidebarMenuItem[]> = ref<SidebarMenuItem[]>([])
|
const currentMenu = ref<SidebarMenuItem[]>([])
|
||||||
|
const isSidebarOpened = ref<boolean>(false)
|
||||||
|
|
||||||
function setCurrentMenu(items: SidebarMenuItem[]) {
|
function setCurrentMenu(items: SidebarMenuItem[]) {
|
||||||
currentMenu.value = items
|
currentMenu.value = items
|
||||||
@@ -11,9 +17,35 @@ export const useUiStore = defineStore("ui", () => {
|
|||||||
currentMenu.value = []
|
currentMenu.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openSidebar() {
|
||||||
|
if (breakpoints.isGreater("md")) return
|
||||||
|
|
||||||
|
isSidebarOpened.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeSidebar() {
|
||||||
|
if (breakpoints.isGreater("md")) return
|
||||||
|
|
||||||
|
isSidebarOpened.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleSidebar() {
|
||||||
|
if (breakpoints.isGreater("md")) return
|
||||||
|
|
||||||
|
isSidebarOpened.value = !isSidebarOpened.value
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(breakpoints.md, () => {
|
||||||
|
isSidebarOpened.value = false
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentMenu,
|
currentMenu,
|
||||||
setCurrentMenu,
|
setCurrentMenu,
|
||||||
resetMenu
|
resetMenu,
|
||||||
|
isSidebarOpened,
|
||||||
|
openSidebar,
|
||||||
|
closeSidebar,
|
||||||
|
toggleSidebar
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ module.exports = {
|
|||||||
boxShadow: {
|
boxShadow: {
|
||||||
"body-dark": "hsla(250, 50%, 10%, 0.75) 0 0 32px 2px inset",
|
"body-dark": "hsla(250, 50%, 10%, 0.75) 0 0 32px 2px inset",
|
||||||
"body-light": "hsl(250, 60%, 85%) 0 0 18px 3px inset",
|
"body-light": "hsl(250, 60%, 85%) 0 0 18px 3px inset",
|
||||||
|
"navbar-dark": "hsla(250, 50%, 10%, 0.75) 0 0 32px 2px",
|
||||||
|
"navbar-light": "hsl(250, 60%, 85%) 0 0 18px 3px",
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
xl: "calc(var(--radius) + 4px)",
|
xl: "calc(var(--radius) + 4px)",
|
||||||
|
|||||||
Reference in New Issue
Block a user