From 02482720fa0b2a71b7853d261b7427de6abb32f0 Mon Sep 17 00:00:00 2001 From: Patrick Mulligan Date: Sat, 3 Jan 2026 12:14:15 +0100 Subject: [PATCH] feat(layout): Replace top navbar with sidebar layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add new sidebar-based layout components: - AppLayout.vue: Main layout wrapper with sidebar + topbar - AppSidebar.vue: Desktop sidebar with navigation, theme, language - AppTopBar.vue: Top bar with notifications, cart, profile - MobileDrawer.vue: Slide-out drawer for mobile navigation - Add Shadcn Sheet component for mobile drawer - Update App.vue to use new AppLayout (except login page) - Rename old Navbar.vue to Navbar.old.vue for reference Layout structure: - Desktop: Fixed 288px sidebar + offset content area - Mobile: Hidden sidebar with drawer triggered from top bar - Cart only shown when market module is enabled - Combined notifications (chat unread count) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- package-lock.json | 8 +- package.json | 2 +- src/App.vue | 34 +-- src/components/layout/AppLayout.vue | 38 +++ src/components/layout/AppSidebar.vue | 135 ++++++++++ src/components/layout/AppTopBar.vue | 242 ++++++++++++++++++ src/components/layout/MobileDrawer.vue | 158 ++++++++++++ .../layout/{Navbar.vue => Navbar.old.vue} | 10 + src/components/ui/sheet/Sheet.vue | 15 ++ src/components/ui/sheet/SheetClose.vue | 12 + src/components/ui/sheet/SheetContent.vue | 53 ++++ src/components/ui/sheet/SheetDescription.vue | 20 ++ src/components/ui/sheet/SheetFooter.vue | 19 ++ src/components/ui/sheet/SheetHeader.vue | 16 ++ src/components/ui/sheet/SheetTitle.vue | 20 ++ src/components/ui/sheet/SheetTrigger.vue | 12 + src/components/ui/sheet/index.ts | 32 +++ 17 files changed, 799 insertions(+), 27 deletions(-) create mode 100644 src/components/layout/AppLayout.vue create mode 100644 src/components/layout/AppSidebar.vue create mode 100644 src/components/layout/AppTopBar.vue create mode 100644 src/components/layout/MobileDrawer.vue rename src/components/layout/{Navbar.vue => Navbar.old.vue} (97%) create mode 100644 src/components/ui/sheet/Sheet.vue create mode 100644 src/components/ui/sheet/SheetClose.vue create mode 100644 src/components/ui/sheet/SheetContent.vue create mode 100644 src/components/ui/sheet/SheetDescription.vue create mode 100644 src/components/ui/sheet/SheetFooter.vue create mode 100644 src/components/ui/sheet/SheetHeader.vue create mode 100644 src/components/ui/sheet/SheetTitle.vue create mode 100644 src/components/ui/sheet/SheetTrigger.vue create mode 100644 src/components/ui/sheet/index.ts diff --git a/package-lock.json b/package-lock.json index b1a2cf4..3486759 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,7 @@ "qr-scanner": "^1.4.2", "qrcode": "^1.5.4", "radix-vue": "^1.9.13", - "reka-ui": "^2.5.0", + "reka-ui": "^2.7.0", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "unique-names-generator": "^4.7.1", @@ -12172,9 +12172,9 @@ } }, "node_modules/reka-ui": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.5.0.tgz", - "integrity": "sha512-81aMAmJeVCy2k0E6x7n1kypDY6aM1ldLis5+zcdV1/JtoAlSDck5OBsyLRJU9CfgbrQp1ImnRnBSmC4fZ2fkZQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.7.0.tgz", + "integrity": "sha512-m+XmxQN2xtFzBP3OAdIafKq7C8OETo2fqfxcIIxYmNN2Ch3r5oAf6yEYCIJg5tL/yJU2mHqF70dCCekUkrAnXA==", "license": "MIT", "dependencies": { "@floating-ui/dom": "^1.6.13", diff --git a/package.json b/package.json index 304528e..00b5554 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "qr-scanner": "^1.4.2", "qrcode": "^1.5.4", "radix-vue": "^1.9.13", - "reka-ui": "^2.5.0", + "reka-ui": "^2.7.0", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", "unique-names-generator": "^4.7.1", diff --git a/src/App.vue b/src/App.vue index 127cdd6..559d0bf 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,7 @@ + + diff --git a/src/components/layout/AppSidebar.vue b/src/components/layout/AppSidebar.vue new file mode 100644 index 0000000..351ef6a --- /dev/null +++ b/src/components/layout/AppSidebar.vue @@ -0,0 +1,135 @@ + + + diff --git a/src/components/layout/AppTopBar.vue b/src/components/layout/AppTopBar.vue new file mode 100644 index 0000000..3fae1d2 --- /dev/null +++ b/src/components/layout/AppTopBar.vue @@ -0,0 +1,242 @@ + + + diff --git a/src/components/layout/MobileDrawer.vue b/src/components/layout/MobileDrawer.vue new file mode 100644 index 0000000..20c4dad --- /dev/null +++ b/src/components/layout/MobileDrawer.vue @@ -0,0 +1,158 @@ + + + diff --git a/src/components/layout/Navbar.vue b/src/components/layout/Navbar.old.vue similarity index 97% rename from src/components/layout/Navbar.vue rename to src/components/layout/Navbar.old.vue index 07fbba1..6eb160f 100644 --- a/src/components/layout/Navbar.vue +++ b/src/components/layout/Navbar.old.vue @@ -1,3 +1,13 @@ + + + diff --git a/src/components/ui/sheet/SheetClose.vue b/src/components/ui/sheet/SheetClose.vue new file mode 100644 index 0000000..0295976 --- /dev/null +++ b/src/components/ui/sheet/SheetClose.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/components/ui/sheet/SheetContent.vue b/src/components/ui/sheet/SheetContent.vue new file mode 100644 index 0000000..50f3de6 --- /dev/null +++ b/src/components/ui/sheet/SheetContent.vue @@ -0,0 +1,53 @@ + + + diff --git a/src/components/ui/sheet/SheetDescription.vue b/src/components/ui/sheet/SheetDescription.vue new file mode 100644 index 0000000..455c2f4 --- /dev/null +++ b/src/components/ui/sheet/SheetDescription.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/ui/sheet/SheetFooter.vue b/src/components/ui/sheet/SheetFooter.vue new file mode 100644 index 0000000..5f481e5 --- /dev/null +++ b/src/components/ui/sheet/SheetFooter.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/components/ui/sheet/SheetHeader.vue b/src/components/ui/sheet/SheetHeader.vue new file mode 100644 index 0000000..f97d24a --- /dev/null +++ b/src/components/ui/sheet/SheetHeader.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/ui/sheet/SheetTitle.vue b/src/components/ui/sheet/SheetTitle.vue new file mode 100644 index 0000000..5870787 --- /dev/null +++ b/src/components/ui/sheet/SheetTitle.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/ui/sheet/SheetTrigger.vue b/src/components/ui/sheet/SheetTrigger.vue new file mode 100644 index 0000000..a4fc3ee --- /dev/null +++ b/src/components/ui/sheet/SheetTrigger.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/components/ui/sheet/index.ts b/src/components/ui/sheet/index.ts new file mode 100644 index 0000000..a370633 --- /dev/null +++ b/src/components/ui/sheet/index.ts @@ -0,0 +1,32 @@ +import type { VariantProps } from "class-variance-authority" +import { cva } from "class-variance-authority" + +export { default as Sheet } from "./Sheet.vue" +export { default as SheetClose } from "./SheetClose.vue" +export { default as SheetContent } from "./SheetContent.vue" +export { default as SheetDescription } from "./SheetDescription.vue" +export { default as SheetFooter } from "./SheetFooter.vue" +export { default as SheetHeader } from "./SheetHeader.vue" +export { default as SheetTitle } from "./SheetTitle.vue" +export { default as SheetTrigger } from "./SheetTrigger.vue" + +export const sheetVariants = cva( + "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500", + { + variants: { + side: { + top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", + bottom: + "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", + left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", + right: + "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", + }, + }, + defaultVariants: { + side: "right", + }, + }, +) + +export type SheetVariants = VariantProps