Files
bookorbit/client/src/components/ui/sidebar/Sidebar.vue
T
neon 0686ae6477 refactor: overhaul UI layout and modernize design system
- transition to floating UI with centralized background pattern in AppLayout
- restructure core layout for stable headers and independent view scrolling
- synchronize component radii (scrollers, cards, skeletons) with global settings
- standardize headers and book detail tabs for consistent alignment and height
- enhance AppSidebar, AppHeader, and ViewHeader with refined active states
- center project logo in collapsed sidebar by removing offset padding
- update shadcn components and theme bridge for consistent design system support
2026-03-06 00:17:10 -06:00

90 lines
3.2 KiB
Vue

<script setup lang="ts">
import type { SidebarProps } from '.'
import { cn } from '@/lib/utils'
import { Sheet, SheetContent } from '@/components/ui/sheet'
import SheetDescription from '@/components/ui/sheet/SheetDescription.vue'
import SheetHeader from '@/components/ui/sheet/SheetHeader.vue'
import SheetTitle from '@/components/ui/sheet/SheetTitle.vue'
import { SIDEBAR_WIDTH_MOBILE, useSidebar } from './utils'
defineOptions({
inheritAttrs: false,
})
const props = withDefaults(defineProps<SidebarProps>(), {
side: 'left',
variant: 'sidebar',
collapsible: 'offcanvas',
})
const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
</script>
<template>
<div
v-if="collapsible === 'none'"
data-slot="sidebar"
:class="cn('bg-sidebar/80 backdrop-blur-xl backdrop-saturate-150 text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col', props.class)"
v-bind="$attrs"
>
<slot />
</div>
<Sheet v-else-if="isMobile" :open="openMobile" v-bind="$attrs" @update:open="setOpenMobile">
<SheetContent
data-sidebar="sidebar"
data-slot="sidebar"
data-mobile="true"
:side="side"
class="bg-sidebar/90 backdrop-blur-xl backdrop-saturate-150 text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden"
:style="{
'--sidebar-width': SIDEBAR_WIDTH_MOBILE,
}"
>
<SheetHeader class="sr-only">
<SheetTitle>Sidebar</SheetTitle>
<SheetDescription>Displays the mobile sidebar.</SheetDescription>
</SheetHeader>
<div class="flex h-full w-full flex-col">
<slot />
</div>
</SheetContent>
</Sheet>
<div
v-else
class="group peer text-sidebar-foreground hidden md:block"
data-slot="sidebar"
:data-state="state"
:data-collapsible="state === 'collapsed' ? collapsible : ''"
:data-variant="variant"
:data-side="side"
>
<!-- Zero-width sentinel — keeps the peer element in the DOM for CSS selectors -->
<div aria-hidden="true" class="w-0 shrink-0" />
<div
:class="
cn(
'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex',
side === 'left'
? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
: 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
// Adjust the padding for floating and inset variants.
variant === 'floating' || variant === 'inset'
? 'p-3 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(6))+2px)]'
: 'group-data-[collapsible=icon]:w-(--sidebar-width-icon)',
props.class,
)
"
v-bind="$attrs"
>
<div
data-sidebar="sidebar"
class="bg-sidebar/55 backdrop-blur-2xl backdrop-saturate-200 border-r border-sidebar-border/60 shadow-[1px_0_0_0_oklch(1_0_0/0.04)] group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-xl group-data-[variant=floating]:border group-data-[variant=floating]:shadow-xl group-data-[variant=floating]:shadow-black/5"
>
<slot />
</div>
</div>
</div>
</template>