From 342b5aa5542703a4e26361502f2487f4d442b63b Mon Sep 17 00:00:00 2001
From: 409 <409dev@protonmail.com>
Date: Fri, 11 Jul 2025 01:44:13 +0200
Subject: [PATCH] sidebar + basic layout
---
app.vue | 9 +-
bun.lock | 13 ++-
components/AppSidebar.vue | 43 +++++++++
components/ui/breadcrumb/Breadcrumb.vue | 17 ++++
.../ui/breadcrumb/BreadcrumbEllipsis.vue | 23 +++++
components/ui/breadcrumb/BreadcrumbItem.vue | 17 ++++
components/ui/breadcrumb/BreadcrumbLink.vue | 20 ++++
components/ui/breadcrumb/BreadcrumbList.vue | 17 ++++
components/ui/breadcrumb/BreadcrumbPage.vue | 20 ++++
.../ui/breadcrumb/BreadcrumbSeparator.vue | 22 +++++
components/ui/breadcrumb/index.ts | 7 ++
components/ui/button/Button.vue | 34 +++----
components/ui/button/index.ts | 63 ++++++------
components/ui/input/Input.vue | 33 +++++++
components/ui/input/index.ts | 1 +
components/ui/separator/Separator.vue | 28 ++++++
components/ui/separator/index.ts | 1 +
components/ui/sheet/Sheet.vue | 17 ++++
components/ui/sheet/SheetClose.vue | 14 +++
components/ui/sheet/SheetContent.vue | 63 ++++++++++++
components/ui/sheet/SheetDescription.vue | 20 ++++
components/ui/sheet/SheetFooter.vue | 16 ++++
components/ui/sheet/SheetHeader.vue | 15 +++
components/ui/sheet/SheetOverlay.vue | 20 ++++
components/ui/sheet/SheetTitle.vue | 20 ++++
components/ui/sheet/SheetTrigger.vue | 14 +++
components/ui/sheet/index.ts | 8 ++
components/ui/sidebar/Sidebar.vue | 96 +++++++++++++++++++
components/ui/sidebar/SidebarContent.vue | 18 ++++
components/ui/sidebar/SidebarFooter.vue | 18 ++++
components/ui/sidebar/SidebarGroup.vue | 18 ++++
components/ui/sidebar/SidebarGroupAction.vue | 27 ++++++
components/ui/sidebar/SidebarGroupContent.vue | 18 ++++
components/ui/sidebar/SidebarGroupLabel.vue | 25 +++++
components/ui/sidebar/SidebarHeader.vue | 18 ++++
components/ui/sidebar/SidebarInput.vue | 22 +++++
components/ui/sidebar/SidebarInset.vue | 21 ++++
components/ui/sidebar/SidebarMenu.vue | 18 ++++
components/ui/sidebar/SidebarMenuAction.vue | 34 +++++++
components/ui/sidebar/SidebarMenuBadge.vue | 26 +++++
components/ui/sidebar/SidebarMenuButton.vue | 47 +++++++++
.../ui/sidebar/SidebarMenuButtonChild.vue | 34 +++++++
components/ui/sidebar/SidebarMenuItem.vue | 18 ++++
components/ui/sidebar/SidebarMenuSkeleton.vue | 34 +++++++
components/ui/sidebar/SidebarMenuSub.vue | 22 +++++
.../ui/sidebar/SidebarMenuSubButton.vue | 36 +++++++
components/ui/sidebar/SidebarMenuSubItem.vue | 18 ++++
components/ui/sidebar/SidebarProvider.vue | 81 ++++++++++++++++
components/ui/sidebar/SidebarRail.vue | 33 +++++++
components/ui/sidebar/SidebarSeparator.vue | 19 ++++
components/ui/sidebar/SidebarTrigger.vue | 27 ++++++
components/ui/sidebar/index.ts | 60 ++++++++++++
components/ui/sidebar/utils.ts | 19 ++++
components/ui/skeleton/Skeleton.vue | 17 ++++
components/ui/skeleton/index.ts | 1 +
components/ui/tooltip/Tooltip.vue | 17 ++++
components/ui/tooltip/TooltipContent.vue | 33 +++++++
components/ui/tooltip/TooltipProvider.vue | 13 +++
components/ui/tooltip/TooltipTrigger.vue | 14 +++
components/ui/tooltip/index.ts | 4 +
layouts/default.vue | 44 +++++++++
nuxt.config.ts | 15 +++
package.json | 4 +-
pages/about.vue | 5 +
pages/index.vue | 5 +
65 files changed, 1498 insertions(+), 56 deletions(-)
create mode 100644 components/AppSidebar.vue
create mode 100644 components/ui/breadcrumb/Breadcrumb.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbEllipsis.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbItem.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbLink.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbList.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbPage.vue
create mode 100644 components/ui/breadcrumb/BreadcrumbSeparator.vue
create mode 100644 components/ui/breadcrumb/index.ts
create mode 100644 components/ui/input/Input.vue
create mode 100644 components/ui/input/index.ts
create mode 100644 components/ui/separator/Separator.vue
create mode 100644 components/ui/separator/index.ts
create mode 100644 components/ui/sheet/Sheet.vue
create mode 100644 components/ui/sheet/SheetClose.vue
create mode 100644 components/ui/sheet/SheetContent.vue
create mode 100644 components/ui/sheet/SheetDescription.vue
create mode 100644 components/ui/sheet/SheetFooter.vue
create mode 100644 components/ui/sheet/SheetHeader.vue
create mode 100644 components/ui/sheet/SheetOverlay.vue
create mode 100644 components/ui/sheet/SheetTitle.vue
create mode 100644 components/ui/sheet/SheetTrigger.vue
create mode 100644 components/ui/sheet/index.ts
create mode 100644 components/ui/sidebar/Sidebar.vue
create mode 100644 components/ui/sidebar/SidebarContent.vue
create mode 100644 components/ui/sidebar/SidebarFooter.vue
create mode 100644 components/ui/sidebar/SidebarGroup.vue
create mode 100644 components/ui/sidebar/SidebarGroupAction.vue
create mode 100644 components/ui/sidebar/SidebarGroupContent.vue
create mode 100644 components/ui/sidebar/SidebarGroupLabel.vue
create mode 100644 components/ui/sidebar/SidebarHeader.vue
create mode 100644 components/ui/sidebar/SidebarInput.vue
create mode 100644 components/ui/sidebar/SidebarInset.vue
create mode 100644 components/ui/sidebar/SidebarMenu.vue
create mode 100644 components/ui/sidebar/SidebarMenuAction.vue
create mode 100644 components/ui/sidebar/SidebarMenuBadge.vue
create mode 100644 components/ui/sidebar/SidebarMenuButton.vue
create mode 100644 components/ui/sidebar/SidebarMenuButtonChild.vue
create mode 100644 components/ui/sidebar/SidebarMenuItem.vue
create mode 100644 components/ui/sidebar/SidebarMenuSkeleton.vue
create mode 100644 components/ui/sidebar/SidebarMenuSub.vue
create mode 100644 components/ui/sidebar/SidebarMenuSubButton.vue
create mode 100644 components/ui/sidebar/SidebarMenuSubItem.vue
create mode 100644 components/ui/sidebar/SidebarProvider.vue
create mode 100644 components/ui/sidebar/SidebarRail.vue
create mode 100644 components/ui/sidebar/SidebarSeparator.vue
create mode 100644 components/ui/sidebar/SidebarTrigger.vue
create mode 100644 components/ui/sidebar/index.ts
create mode 100644 components/ui/sidebar/utils.ts
create mode 100644 components/ui/skeleton/Skeleton.vue
create mode 100644 components/ui/skeleton/index.ts
create mode 100644 components/ui/tooltip/Tooltip.vue
create mode 100644 components/ui/tooltip/TooltipContent.vue
create mode 100644 components/ui/tooltip/TooltipProvider.vue
create mode 100644 components/ui/tooltip/TooltipTrigger.vue
create mode 100644 components/ui/tooltip/index.ts
create mode 100644 layouts/default.vue
create mode 100644 pages/about.vue
create mode 100644 pages/index.vue
diff --git a/app.vue b/app.vue
index 2d82e7a..5f2f87d 100644
--- a/app.vue
+++ b/app.vue
@@ -1,6 +1,7 @@
-
-
-
-
+
+
+
+
+
diff --git a/bun.lock b/bun.lock
index 0f3e791..8ece64c 100644
--- a/bun.lock
+++ b/bun.lock
@@ -10,6 +10,7 @@
"@nuxt/image": "1.10.0",
"@nuxt/test-utils": "3.19.2",
"@tailwindcss/vite": "^4.1.11",
+ "@vueuse/core": "^13.5.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"eslint": "^9.0.0",
@@ -561,11 +562,11 @@
"@vue/shared": ["@vue/shared@3.5.17", "", {}, "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg=="],
- "@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="],
+ "@vueuse/core": ["@vueuse/core@13.5.0", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "13.5.0", "@vueuse/shared": "13.5.0" }, "peerDependencies": { "vue": "^3.5.0" } }, "sha512-wV7z0eUpifKmvmN78UBZX8T7lMW53Nrk6JP5+6hbzrB9+cJ3jr//hUlhl9TZO/03bUkMK6gGkQpqOPWoabr72g=="],
- "@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="],
+ "@vueuse/metadata": ["@vueuse/metadata@13.5.0", "", {}, "sha512-euhItU3b0SqXxSy8u1XHxUCdQ8M++bsRs+TYhOLDU/OykS7KvJnyIFfep0XM5WjIFry9uAPlVSjmVHiqeshmkw=="],
- "@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="],
+ "@vueuse/shared": ["@vueuse/shared@13.5.0", "", { "peerDependencies": { "vue": "^3.5.0" } }, "sha512-K7GrQIxJ/ANtucxIXbQlUHdB0TPA8c+q5i+zbrjxuhJCnJ9GtBg75sBSnvmLSxHKPg2Yo8w62PWksl9kwH0Q8g=="],
"@whatwg-node/disposablestack": ["@whatwg-node/disposablestack@0.0.6", "", { "dependencies": { "@whatwg-node/promise-helpers": "^1.0.0", "tslib": "^2.6.3" } }, "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw=="],
@@ -2145,6 +2146,10 @@
"regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="],
+ "reka-ui/@vueuse/core": ["@vueuse/core@12.8.2", "", { "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" } }, "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ=="],
+
+ "reka-ui/@vueuse/shared": ["@vueuse/shared@12.8.2", "", { "dependencies": { "vue": "^3.5.13" } }, "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w=="],
+
"rollup-plugin-visualizer/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
"shadcn-nuxt/oxc-parser": ["oxc-parser@0.72.3", "", { "dependencies": { "@oxc-project/types": "^0.72.3" }, "optionalDependencies": { "@oxc-parser/binding-darwin-arm64": "0.72.3", "@oxc-parser/binding-darwin-x64": "0.72.3", "@oxc-parser/binding-freebsd-x64": "0.72.3", "@oxc-parser/binding-linux-arm-gnueabihf": "0.72.3", "@oxc-parser/binding-linux-arm-musleabihf": "0.72.3", "@oxc-parser/binding-linux-arm64-gnu": "0.72.3", "@oxc-parser/binding-linux-arm64-musl": "0.72.3", "@oxc-parser/binding-linux-riscv64-gnu": "0.72.3", "@oxc-parser/binding-linux-s390x-gnu": "0.72.3", "@oxc-parser/binding-linux-x64-gnu": "0.72.3", "@oxc-parser/binding-linux-x64-musl": "0.72.3", "@oxc-parser/binding-wasm32-wasi": "0.72.3", "@oxc-parser/binding-win32-arm64-msvc": "0.72.3", "@oxc-parser/binding-win32-x64-msvc": "0.72.3" } }, "sha512-JYQeJKDcUTTZ/uTdJ+fZBGFjAjkLD1h0p3Tf44ZYXRcoMk+57d81paNPFAAwzrzzqhZmkGvKKXDxwyhJXYZlpg=="],
@@ -2313,6 +2318,8 @@
"readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
+ "reka-ui/@vueuse/core/@vueuse/metadata": ["@vueuse/metadata@12.8.2", "", {}, "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A=="],
+
"rollup-plugin-visualizer/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
"rollup-plugin-visualizer/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
diff --git a/components/AppSidebar.vue b/components/AppSidebar.vue
new file mode 100644
index 0000000..415ab7c
--- /dev/null
+++ b/components/AppSidebar.vue
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ Application
+
+
+
+
+
+ {{ item.title }}
+
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/Breadcrumb.vue b/components/ui/breadcrumb/Breadcrumb.vue
new file mode 100644
index 0000000..b99dcea
--- /dev/null
+++ b/components/ui/breadcrumb/Breadcrumb.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbEllipsis.vue b/components/ui/breadcrumb/BreadcrumbEllipsis.vue
new file mode 100644
index 0000000..b147851
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbEllipsis.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ More
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbItem.vue b/components/ui/breadcrumb/BreadcrumbItem.vue
new file mode 100644
index 0000000..f50f69d
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbItem.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbLink.vue b/components/ui/breadcrumb/BreadcrumbLink.vue
new file mode 100644
index 0000000..c94995e
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbLink.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbList.vue b/components/ui/breadcrumb/BreadcrumbList.vue
new file mode 100644
index 0000000..3a92c48
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbList.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbPage.vue b/components/ui/breadcrumb/BreadcrumbPage.vue
new file mode 100644
index 0000000..cc667bc
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbPage.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/BreadcrumbSeparator.vue b/components/ui/breadcrumb/BreadcrumbSeparator.vue
new file mode 100644
index 0000000..7ee2d01
--- /dev/null
+++ b/components/ui/breadcrumb/BreadcrumbSeparator.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/ui/breadcrumb/index.ts b/components/ui/breadcrumb/index.ts
new file mode 100644
index 0000000..0590983
--- /dev/null
+++ b/components/ui/breadcrumb/index.ts
@@ -0,0 +1,7 @@
+export { default as Breadcrumb } from './Breadcrumb.vue'
+export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue'
+export { default as BreadcrumbItem } from './BreadcrumbItem.vue'
+export { default as BreadcrumbLink } from './BreadcrumbLink.vue'
+export { default as BreadcrumbList } from './BreadcrumbList.vue'
+export { default as BreadcrumbPage } from './BreadcrumbPage.vue'
+export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue'
diff --git a/components/ui/button/Button.vue b/components/ui/button/Button.vue
index d984fb4..ecf3fe3 100644
--- a/components/ui/button/Button.vue
+++ b/components/ui/button/Button.vue
@@ -1,27 +1,27 @@
-
-
-
+
+
+
diff --git a/components/ui/button/index.ts b/components/ui/button/index.ts
index 4df6784..616d1d3 100644
--- a/components/ui/button/index.ts
+++ b/components/ui/button/index.ts
@@ -1,35 +1,36 @@
-import { cva, type VariantProps } from 'class-variance-authority';
+import { cva, type VariantProps } from 'class-variance-authority'
-export { default as Button } from './Button.vue';
+export { default as Button } from './Button.vue'
export const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
- {
- variants: {
- variant: {
- default:
- 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
- destructive:
- 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
- outline:
- 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
- secondary:
- 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
- ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
- link: 'text-primary underline-offset-4 hover:underline',
- },
- size: {
- default: 'h-9 px-4 py-2 has-[>svg]:px-3',
- sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
- lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
- icon: 'size-9',
- },
- },
- defaultVariants: {
- variant: 'default',
- size: 'default',
- },
- }
-);
+ 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*=\'size-\'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
+ {
+ variants: {
+ variant: {
+ default:
+ 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
+ destructive:
+ 'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
+ outline:
+ 'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
+ secondary:
+ 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
+ ghost:
+ 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
+ link: 'text-primary underline-offset-4 hover:underline',
+ },
+ size: {
+ default: 'h-9 px-4 py-2 has-[>svg]:px-3',
+ sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
+ lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
+ icon: 'size-9',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ },
+)
-export type ButtonVariants = VariantProps;
+export type ButtonVariants = VariantProps
diff --git a/components/ui/input/Input.vue b/components/ui/input/Input.vue
new file mode 100644
index 0000000..b82c9d0
--- /dev/null
+++ b/components/ui/input/Input.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/components/ui/input/index.ts b/components/ui/input/index.ts
new file mode 100644
index 0000000..a691dd6
--- /dev/null
+++ b/components/ui/input/index.ts
@@ -0,0 +1 @@
+export { default as Input } from './Input.vue'
diff --git a/components/ui/separator/Separator.vue b/components/ui/separator/Separator.vue
new file mode 100644
index 0000000..d397e08
--- /dev/null
+++ b/components/ui/separator/Separator.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
diff --git a/components/ui/separator/index.ts b/components/ui/separator/index.ts
new file mode 100644
index 0000000..2287bcb
--- /dev/null
+++ b/components/ui/separator/index.ts
@@ -0,0 +1 @@
+export { default as Separator } from './Separator.vue'
diff --git a/components/ui/sheet/Sheet.vue b/components/ui/sheet/Sheet.vue
new file mode 100644
index 0000000..e2a3374
--- /dev/null
+++ b/components/ui/sheet/Sheet.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetClose.vue b/components/ui/sheet/SheetClose.vue
new file mode 100644
index 0000000..05077ea
--- /dev/null
+++ b/components/ui/sheet/SheetClose.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetContent.vue b/components/ui/sheet/SheetContent.vue
new file mode 100644
index 0000000..8e55613
--- /dev/null
+++ b/components/ui/sheet/SheetContent.vue
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
diff --git a/components/ui/sheet/SheetDescription.vue b/components/ui/sheet/SheetDescription.vue
new file mode 100644
index 0000000..e3682d3
--- /dev/null
+++ b/components/ui/sheet/SheetDescription.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetFooter.vue b/components/ui/sheet/SheetFooter.vue
new file mode 100644
index 0000000..d2ac823
--- /dev/null
+++ b/components/ui/sheet/SheetFooter.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetHeader.vue b/components/ui/sheet/SheetHeader.vue
new file mode 100644
index 0000000..ab20557
--- /dev/null
+++ b/components/ui/sheet/SheetHeader.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetOverlay.vue b/components/ui/sheet/SheetOverlay.vue
new file mode 100644
index 0000000..3f27a86
--- /dev/null
+++ b/components/ui/sheet/SheetOverlay.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetTitle.vue b/components/ui/sheet/SheetTitle.vue
new file mode 100644
index 0000000..262fb5b
--- /dev/null
+++ b/components/ui/sheet/SheetTitle.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/SheetTrigger.vue b/components/ui/sheet/SheetTrigger.vue
new file mode 100644
index 0000000..5981f8e
--- /dev/null
+++ b/components/ui/sheet/SheetTrigger.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sheet/index.ts b/components/ui/sheet/index.ts
new file mode 100644
index 0000000..ee33431
--- /dev/null
+++ b/components/ui/sheet/index.ts
@@ -0,0 +1,8 @@
+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'
diff --git a/components/ui/sidebar/Sidebar.vue b/components/ui/sidebar/Sidebar.vue
new file mode 100644
index 0000000..c75db5d
--- /dev/null
+++ b/components/ui/sidebar/Sidebar.vue
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarContent.vue b/components/ui/sidebar/SidebarContent.vue
new file mode 100644
index 0000000..3b7536c
--- /dev/null
+++ b/components/ui/sidebar/SidebarContent.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarFooter.vue b/components/ui/sidebar/SidebarFooter.vue
new file mode 100644
index 0000000..c324dff
--- /dev/null
+++ b/components/ui/sidebar/SidebarFooter.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarGroup.vue b/components/ui/sidebar/SidebarGroup.vue
new file mode 100644
index 0000000..57a099f
--- /dev/null
+++ b/components/ui/sidebar/SidebarGroup.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarGroupAction.vue b/components/ui/sidebar/SidebarGroupAction.vue
new file mode 100644
index 0000000..eb9a3ec
--- /dev/null
+++ b/components/ui/sidebar/SidebarGroupAction.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarGroupContent.vue b/components/ui/sidebar/SidebarGroupContent.vue
new file mode 100644
index 0000000..5d5e2dd
--- /dev/null
+++ b/components/ui/sidebar/SidebarGroupContent.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarGroupLabel.vue b/components/ui/sidebar/SidebarGroupLabel.vue
new file mode 100644
index 0000000..8e1c1e3
--- /dev/null
+++ b/components/ui/sidebar/SidebarGroupLabel.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarHeader.vue b/components/ui/sidebar/SidebarHeader.vue
new file mode 100644
index 0000000..00673f7
--- /dev/null
+++ b/components/ui/sidebar/SidebarHeader.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarInput.vue b/components/ui/sidebar/SidebarInput.vue
new file mode 100644
index 0000000..ecaa977
--- /dev/null
+++ b/components/ui/sidebar/SidebarInput.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarInset.vue b/components/ui/sidebar/SidebarInset.vue
new file mode 100644
index 0000000..386c622
--- /dev/null
+++ b/components/ui/sidebar/SidebarInset.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenu.vue b/components/ui/sidebar/SidebarMenu.vue
new file mode 100644
index 0000000..59ec071
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenu.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuAction.vue b/components/ui/sidebar/SidebarMenuAction.vue
new file mode 100644
index 0000000..4852f28
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuAction.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuBadge.vue b/components/ui/sidebar/SidebarMenuBadge.vue
new file mode 100644
index 0000000..3984b33
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuBadge.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuButton.vue b/components/ui/sidebar/SidebarMenuButton.vue
new file mode 100644
index 0000000..1d934b2
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuButton.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ tooltip }}
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuButtonChild.vue b/components/ui/sidebar/SidebarMenuButtonChild.vue
new file mode 100644
index 0000000..82998df
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuButtonChild.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuItem.vue b/components/ui/sidebar/SidebarMenuItem.vue
new file mode 100644
index 0000000..b7b4d3f
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuItem.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuSkeleton.vue b/components/ui/sidebar/SidebarMenuSkeleton.vue
new file mode 100644
index 0000000..6302c35
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuSkeleton.vue
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuSub.vue b/components/ui/sidebar/SidebarMenuSub.vue
new file mode 100644
index 0000000..11aec64
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuSub.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuSubButton.vue b/components/ui/sidebar/SidebarMenuSubButton.vue
new file mode 100644
index 0000000..f9fae8f
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuSubButton.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarMenuSubItem.vue b/components/ui/sidebar/SidebarMenuSubItem.vue
new file mode 100644
index 0000000..f0c35bc
--- /dev/null
+++ b/components/ui/sidebar/SidebarMenuSubItem.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarProvider.vue b/components/ui/sidebar/SidebarProvider.vue
new file mode 100644
index 0000000..2e08dec
--- /dev/null
+++ b/components/ui/sidebar/SidebarProvider.vue
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarRail.vue b/components/ui/sidebar/SidebarRail.vue
new file mode 100644
index 0000000..07e59be
--- /dev/null
+++ b/components/ui/sidebar/SidebarRail.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarSeparator.vue b/components/ui/sidebar/SidebarSeparator.vue
new file mode 100644
index 0000000..1803bff
--- /dev/null
+++ b/components/ui/sidebar/SidebarSeparator.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/components/ui/sidebar/SidebarTrigger.vue b/components/ui/sidebar/SidebarTrigger.vue
new file mode 100644
index 0000000..59f29b9
--- /dev/null
+++ b/components/ui/sidebar/SidebarTrigger.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/components/ui/sidebar/index.ts b/components/ui/sidebar/index.ts
new file mode 100644
index 0000000..48da274
--- /dev/null
+++ b/components/ui/sidebar/index.ts
@@ -0,0 +1,60 @@
+import type { VariantProps } from 'class-variance-authority'
+import type { HTMLAttributes } from 'vue'
+import { cva } from 'class-variance-authority'
+
+export interface SidebarProps {
+ side?: 'left' | 'right'
+ variant?: 'sidebar' | 'floating' | 'inset'
+ collapsible?: 'offcanvas' | 'icon' | 'none'
+ class?: HTMLAttributes['class']
+}
+
+export { default as Sidebar } from './Sidebar.vue'
+export { default as SidebarContent } from './SidebarContent.vue'
+export { default as SidebarFooter } from './SidebarFooter.vue'
+export { default as SidebarGroup } from './SidebarGroup.vue'
+export { default as SidebarGroupAction } from './SidebarGroupAction.vue'
+export { default as SidebarGroupContent } from './SidebarGroupContent.vue'
+export { default as SidebarGroupLabel } from './SidebarGroupLabel.vue'
+export { default as SidebarHeader } from './SidebarHeader.vue'
+export { default as SidebarInput } from './SidebarInput.vue'
+export { default as SidebarInset } from './SidebarInset.vue'
+export { default as SidebarMenu } from './SidebarMenu.vue'
+export { default as SidebarMenuAction } from './SidebarMenuAction.vue'
+export { default as SidebarMenuBadge } from './SidebarMenuBadge.vue'
+export { default as SidebarMenuButton } from './SidebarMenuButton.vue'
+export { default as SidebarMenuItem } from './SidebarMenuItem.vue'
+export { default as SidebarMenuSkeleton } from './SidebarMenuSkeleton.vue'
+export { default as SidebarMenuSub } from './SidebarMenuSub.vue'
+export { default as SidebarMenuSubButton } from './SidebarMenuSubButton.vue'
+export { default as SidebarMenuSubItem } from './SidebarMenuSubItem.vue'
+export { default as SidebarProvider } from './SidebarProvider.vue'
+export { default as SidebarRail } from './SidebarRail.vue'
+export { default as SidebarSeparator } from './SidebarSeparator.vue'
+export { default as SidebarTrigger } from './SidebarTrigger.vue'
+
+export { useSidebar } from './utils'
+
+export const sidebarMenuButtonVariants = cva(
+ 'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
+ {
+ variants: {
+ variant: {
+ default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
+ outline:
+ 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',
+ },
+ size: {
+ default: 'h-8 text-sm',
+ sm: 'h-7 text-xs',
+ lg: 'h-12 text-sm group-data-[collapsible=icon]:p-0!',
+ },
+ },
+ defaultVariants: {
+ variant: 'default',
+ size: 'default',
+ },
+ },
+)
+
+export type SidebarMenuButtonVariants = VariantProps
diff --git a/components/ui/sidebar/utils.ts b/components/ui/sidebar/utils.ts
new file mode 100644
index 0000000..6edb140
--- /dev/null
+++ b/components/ui/sidebar/utils.ts
@@ -0,0 +1,19 @@
+import type { ComputedRef, Ref } from 'vue'
+import { createContext } from 'reka-ui'
+
+export const SIDEBAR_COOKIE_NAME = 'sidebar_state'
+export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
+export const SIDEBAR_WIDTH = '16rem'
+export const SIDEBAR_WIDTH_MOBILE = '18rem'
+export const SIDEBAR_WIDTH_ICON = '3rem'
+export const SIDEBAR_KEYBOARD_SHORTCUT = 'b'
+
+export const [useSidebar, provideSidebarContext] = createContext<{
+ state: ComputedRef<'expanded' | 'collapsed'>
+ open: Ref
+ setOpen: (value: boolean) => void
+ isMobile: Ref
+ openMobile: Ref
+ setOpenMobile: (value: boolean) => void
+ toggleSidebar: () => void
+}>('Sidebar')
diff --git a/components/ui/skeleton/Skeleton.vue b/components/ui/skeleton/Skeleton.vue
new file mode 100644
index 0000000..153fe2c
--- /dev/null
+++ b/components/ui/skeleton/Skeleton.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/components/ui/skeleton/index.ts b/components/ui/skeleton/index.ts
new file mode 100644
index 0000000..be21fad
--- /dev/null
+++ b/components/ui/skeleton/index.ts
@@ -0,0 +1 @@
+export { default as Skeleton } from './Skeleton.vue'
diff --git a/components/ui/tooltip/Tooltip.vue b/components/ui/tooltip/Tooltip.vue
new file mode 100644
index 0000000..3ebeecc
--- /dev/null
+++ b/components/ui/tooltip/Tooltip.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/components/ui/tooltip/TooltipContent.vue b/components/ui/tooltip/TooltipContent.vue
new file mode 100644
index 0000000..62712e6
--- /dev/null
+++ b/components/ui/tooltip/TooltipContent.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ui/tooltip/TooltipProvider.vue b/components/ui/tooltip/TooltipProvider.vue
new file mode 100644
index 0000000..4b4203e
--- /dev/null
+++ b/components/ui/tooltip/TooltipProvider.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/components/ui/tooltip/TooltipTrigger.vue b/components/ui/tooltip/TooltipTrigger.vue
new file mode 100644
index 0000000..36253c6
--- /dev/null
+++ b/components/ui/tooltip/TooltipTrigger.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/components/ui/tooltip/index.ts b/components/ui/tooltip/index.ts
new file mode 100644
index 0000000..5ab9653
--- /dev/null
+++ b/components/ui/tooltip/index.ts
@@ -0,0 +1,4 @@
+export { default as Tooltip } from './Tooltip.vue'
+export { default as TooltipContent } from './TooltipContent.vue'
+export { default as TooltipProvider } from './TooltipProvider.vue'
+export { default as TooltipTrigger } from './TooltipTrigger.vue'
diff --git a/layouts/default.vue b/layouts/default.vue
new file mode 100644
index 0000000..db04e7e
--- /dev/null
+++ b/layouts/default.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/nuxt.config.ts b/nuxt.config.ts
index 18b7e86..bb320e0 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -36,4 +36,19 @@ export default defineNuxtConfig({
colorMode: {
classSuffix: '',
},
+
+ icon: {
+ mode: 'svg',
+ },
+
+ app: {
+ head: {
+ title: 'Warren',
+ htmlAttrs: {
+ lang: 'en',
+ },
+ },
+ },
+
+ ssr: false,
});
diff --git a/package.json b/package.json
index 797b5d7..2d0c03e 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
- "postinstall": "nuxt prepare"
+ "postinstall": "nuxt prepare",
+ "format": "bunx --bun prettier --write ."
},
"dependencies": {
"@nuxt/eslint": "1.5.2",
@@ -16,6 +17,7 @@
"@nuxt/image": "1.10.0",
"@nuxt/test-utils": "3.19.2",
"@tailwindcss/vite": "^4.1.11",
+ "@vueuse/core": "^13.5.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"eslint": "^9.0.0",
diff --git a/pages/about.vue b/pages/about.vue
new file mode 100644
index 0000000..5b3a9b8
--- /dev/null
+++ b/pages/about.vue
@@ -0,0 +1,5 @@
+
+
+
diff --git a/pages/index.vue b/pages/index.vue
new file mode 100644
index 0000000..c627fc4
--- /dev/null
+++ b/pages/index.vue
@@ -0,0 +1,5 @@
+
+
+
/
+
+