diff --git a/.env.example b/.env.example deleted file mode 100644 index 6937031..0000000 --- a/.env.example +++ /dev/null @@ -1,4 +0,0 @@ -# Update these with your Supabase details from your project settings > API -# https://app.supabase.com/project/_/settings/api -NEXT_PUBLIC_SUPABASE_URL=your-project-url -NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx new file mode 100644 index 0000000..2d2390b --- /dev/null +++ b/app/dashboard/page.tsx @@ -0,0 +1,61 @@ +import { AppSidebar } from "@/components/app-sidebar"; +import { NavActions } from "@/components/nav-actions"; +import { + Breadcrumb, + BreadcrumbItem, + BreadcrumbList, + BreadcrumbPage, +} from "@/components/ui/breadcrumb"; +import { Separator } from "@/components/ui/separator"; +import { + SidebarInset, + SidebarProvider, + SidebarTrigger, +} from "@/components/ui/sidebar"; +import { createClient } from "@/utils/supabase/server"; +import { redirect } from "next/navigation"; + +export default async function Page() { + const supabase = await createClient(); + + const { + data: { user }, + } = await supabase.auth.getUser(); + + if (!user) { + return redirect("/login"); + } + + return ( + + + +
+
+ + + + + + + Project Management & Task Tracking + + + + +
+
+ +
+
+
+
+
+
+ + + ); +} diff --git a/app/globals.css b/app/globals.css index f450d1e..a356309 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,67 +1,121 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; +@import "tailwindcss"; +@import "tw-animate-css"; -@layer base { - :root { - --background: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --radius: 0.5rem; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - } +@custom-variant dark (&:is(.dark *)); - .dark { - --background: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; - } +:root { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --destructive-foreground: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.205 0 0); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); +} + +.dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.145 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.145 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.985 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.396 0.141 25.723); + --destructive-foreground: oklch(0.637 0.237 25.331); + --border: oklch(0.269 0 0); + --input: oklch(0.269 0 0); + --ring: oklch(0.439 0 0); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.985 0 0); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(0.269 0 0); + --sidebar-ring: oklch(0.439 0 0); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); } @layer base { * { - @apply border-border; + @apply border-border outline-ring/50; } body { @apply bg-background text-foreground; diff --git a/app/layout.tsx b/app/layout.tsx index 8f6dcb7..d81c446 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -37,39 +37,8 @@ export default function RootLayout({ enableSystem disableTransitionOnChange > -
-
- -
- {children} -
- - -
-
+ {children} + diff --git a/app/login/page.tsx b/app/login/page.tsx new file mode 100644 index 0000000..94b501b --- /dev/null +++ b/app/login/page.tsx @@ -0,0 +1,19 @@ +import { Brain, BrainCircuit, GalleryVerticalEnd } from "lucide-react"; + +import { LoginForm } from "@/components/login-form"; + +export default function LoginPage() { + return ( + + ); +} diff --git a/app/page.tsx b/app/page.tsx index 9144694..9ed9260 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -2,15 +2,19 @@ import Hero from "@/components/hero"; import ConnectSupabaseSteps from "@/components/tutorial/connect-supabase-steps"; import SignUpUserSteps from "@/components/tutorial/sign-up-user-steps"; import { hasEnvVars } from "@/utils/supabase/check-env-vars"; +import { createClient } from "@/utils/supabase/server"; +import { redirect } from "next/navigation"; export default async function Home() { - return ( - <> - -
-

Next steps

- {hasEnvVars ? : } -
- - ); + const supabase = await createClient(); + + const { + data: { user }, + } = await supabase.auth.getUser(); + + if (!user) { + return redirect("/login"); + } else { + return redirect("/documents"); + } } diff --git a/app/protected/page.tsx b/app/protected/page.tsx deleted file mode 100644 index 5508aba..0000000 --- a/app/protected/page.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import FetchDataSteps from "@/components/tutorial/fetch-data-steps"; -import { createClient } from "@/utils/supabase/server"; -import { InfoIcon } from "lucide-react"; -import { redirect } from "next/navigation"; - -export default async function ProtectedPage() { - const supabase = await createClient(); - - const { - data: { user }, - } = await supabase.auth.getUser(); - - if (!user) { - return redirect("/sign-in"); - } - - return ( -
-
-
- - This is a protected page that you can only see as an authenticated - user -
-
-
-

Your user details

-
-          {JSON.stringify(user, null, 2)}
-        
-
-
-

Next steps

- -
-
- ); -} diff --git a/app/protected/reset-password/page.tsx b/app/protected/reset-password/page.tsx deleted file mode 100644 index 9cd7084..0000000 --- a/app/protected/reset-password/page.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { resetPasswordAction } from "@/app/actions"; -import { FormMessage, Message } from "@/components/form-message"; -import { SubmitButton } from "@/components/submit-button"; -import { Input } from "@/components/ui/input"; -import { Label } from "@/components/ui/label"; - -export default async function ResetPassword(props: { - searchParams: Promise; -}) { - const searchParams = await props.searchParams; - return ( -
-

Reset password

-

- Please enter your new password below. -

- - - - - - Reset password - - - - ); -} diff --git a/bun.lockb b/bun.lockb index 709b069..36eaec4 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx new file mode 100644 index 0000000..741a40b --- /dev/null +++ b/components/app-sidebar.tsx @@ -0,0 +1,276 @@ +"use client" + +import * as React from "react" +import { + AudioWaveform, + Blocks, + Calendar, + Command, + Home, + Inbox, + MessageCircleQuestion, + Search, + Settings2, + Sparkles, + Trash2, +} from "lucide-react" + +import { NavFavorites } from "@/components/nav-favorites" +import { NavMain } from "@/components/nav-main" +import { NavSecondary } from "@/components/nav-secondary" +import { NavWorkspaces } from "@/components/nav-workspaces" +import { TeamSwitcher } from "@/components/team-switcher" +import { + Sidebar, + SidebarContent, + SidebarHeader, + SidebarRail, +} from "@/components/ui/sidebar" + +// This is sample data. +const data = { + teams: [ + { + name: "Acme Inc", + logo: Command, + plan: "Enterprise", + }, + { + name: "Acme Corp.", + logo: AudioWaveform, + plan: "Startup", + }, + { + name: "Evil Corp.", + logo: Command, + plan: "Free", + }, + ], + navMain: [ + { + title: "Search", + url: "#", + icon: Search, + }, + { + title: "Ask AI", + url: "#", + icon: Sparkles, + }, + { + title: "Home", + url: "#", + icon: Home, + isActive: true, + }, + { + title: "Inbox", + url: "#", + icon: Inbox, + badge: "10", + }, + ], + navSecondary: [ + { + title: "Calendar", + url: "#", + icon: Calendar, + }, + { + title: "Settings", + url: "#", + icon: Settings2, + }, + { + title: "Templates", + url: "#", + icon: Blocks, + }, + { + title: "Trash", + url: "#", + icon: Trash2, + }, + { + title: "Help", + url: "#", + icon: MessageCircleQuestion, + }, + ], + favorites: [ + { + name: "Project Management & Task Tracking", + url: "#", + emoji: "πŸ“Š", + }, + { + name: "Family Recipe Collection & Meal Planning", + url: "#", + emoji: "🍳", + }, + { + name: "Fitness Tracker & Workout Routines", + url: "#", + emoji: "πŸ’ͺ", + }, + { + name: "Book Notes & Reading List", + url: "#", + emoji: "πŸ“š", + }, + { + name: "Sustainable Gardening Tips & Plant Care", + url: "#", + emoji: "🌱", + }, + { + name: "Language Learning Progress & Resources", + url: "#", + emoji: "πŸ—£οΈ", + }, + { + name: "Home Renovation Ideas & Budget Tracker", + url: "#", + emoji: "🏠", + }, + { + name: "Personal Finance & Investment Portfolio", + url: "#", + emoji: "πŸ’°", + }, + { + name: "Movie & TV Show Watchlist with Reviews", + url: "#", + emoji: "🎬", + }, + { + name: "Daily Habit Tracker & Goal Setting", + url: "#", + emoji: "βœ…", + }, + ], + workspaces: [ + { + name: "Personal Life Management", + emoji: "🏠", + pages: [ + { + name: "Daily Journal & Reflection", + url: "#", + emoji: "πŸ“”", + }, + { + name: "Health & Wellness Tracker", + url: "#", + emoji: "🍏", + }, + { + name: "Personal Growth & Learning Goals", + url: "#", + emoji: "🌟", + }, + ], + }, + { + name: "Professional Development", + emoji: "πŸ’Ό", + pages: [ + { + name: "Career Objectives & Milestones", + url: "#", + emoji: "🎯", + }, + { + name: "Skill Acquisition & Training Log", + url: "#", + emoji: "🧠", + }, + { + name: "Networking Contacts & Events", + url: "#", + emoji: "🀝", + }, + ], + }, + { + name: "Creative Projects", + emoji: "🎨", + pages: [ + { + name: "Writing Ideas & Story Outlines", + url: "#", + emoji: "✍️", + }, + { + name: "Art & Design Portfolio", + url: "#", + emoji: "πŸ–ΌοΈ", + }, + { + name: "Music Composition & Practice Log", + url: "#", + emoji: "🎡", + }, + ], + }, + { + name: "Home Management", + emoji: "🏑", + pages: [ + { + name: "Household Budget & Expense Tracking", + url: "#", + emoji: "πŸ’°", + }, + { + name: "Home Maintenance Schedule & Tasks", + url: "#", + emoji: "πŸ”§", + }, + { + name: "Family Calendar & Event Planning", + url: "#", + emoji: "πŸ“…", + }, + ], + }, + { + name: "Travel & Adventure", + emoji: "🧳", + pages: [ + { + name: "Trip Planning & Itineraries", + url: "#", + emoji: "πŸ—ΊοΈ", + }, + { + name: "Travel Bucket List & Inspiration", + url: "#", + emoji: "🌎", + }, + { + name: "Travel Journal & Photo Gallery", + url: "#", + emoji: "πŸ“Έ", + }, + ], + }, + ], +} + +export function AppSidebar({ ...props }: React.ComponentProps) { + return ( + + + + + + + + + + + + + ) +} diff --git a/components/login-form.tsx b/components/login-form.tsx new file mode 100644 index 0000000..44add0e --- /dev/null +++ b/components/login-form.tsx @@ -0,0 +1,67 @@ +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + +export function LoginForm({ + className, + ...props +}: React.ComponentProps<"div">) { + return ( +
+ + + Welcome back + Login with your Google account + + +
+
+
+ +
+
+ + Or continue with + +
+
+
+ + +
+ +
+
+
+
+
+
+ ); +} diff --git a/components/nav-actions.tsx b/components/nav-actions.tsx new file mode 100644 index 0000000..867c85a --- /dev/null +++ b/components/nav-actions.tsx @@ -0,0 +1,153 @@ +"use client" + +import * as React from "react" +import { + ArrowDown, + ArrowUp, + Bell, + Copy, + CornerUpLeft, + CornerUpRight, + FileText, + GalleryVerticalEnd, + LineChart, + Link, + MoreHorizontal, + Settings2, + Star, + Trash, + Trash2, +} from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover" +import { + Sidebar, + SidebarContent, + SidebarGroup, + SidebarGroupContent, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +const data = [ + [ + { + label: "Customize Page", + icon: Settings2, + }, + { + label: "Turn into wiki", + icon: FileText, + }, + ], + [ + { + label: "Copy Link", + icon: Link, + }, + { + label: "Duplicate", + icon: Copy, + }, + { + label: "Move to", + icon: CornerUpRight, + }, + { + label: "Move to Trash", + icon: Trash2, + }, + ], + [ + { + label: "Undo", + icon: CornerUpLeft, + }, + { + label: "View analytics", + icon: LineChart, + }, + { + label: "Version History", + icon: GalleryVerticalEnd, + }, + { + label: "Show delete pages", + icon: Trash, + }, + { + label: "Notifications", + icon: Bell, + }, + ], + [ + { + label: "Import", + icon: ArrowUp, + }, + { + label: "Export", + icon: ArrowDown, + }, + ], +] + +export function NavActions() { + const [isOpen, setIsOpen] = React.useState(false) + + React.useEffect(() => { + setIsOpen(true) + }, []) + + return ( +
+
+ Edit Oct 08 +
+ + + + + + + + + {data.map((group, index) => ( + + + + {group.map((item, index) => ( + + + {item.label} + + + ))} + + + + ))} + + + + +
+ ) +} diff --git a/components/nav-favorites.tsx b/components/nav-favorites.tsx new file mode 100644 index 0000000..34e2aea --- /dev/null +++ b/components/nav-favorites.tsx @@ -0,0 +1,94 @@ +"use client" + +import { + ArrowUpRight, + Link, + MoreHorizontal, + StarOff, + Trash2, +} from "lucide-react" + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { + SidebarGroup, + SidebarGroupLabel, + SidebarMenu, + SidebarMenuAction, + SidebarMenuButton, + SidebarMenuItem, + useSidebar, +} from "@/components/ui/sidebar" + +export function NavFavorites({ + favorites, +}: { + favorites: { + name: string + url: string + emoji: string + }[] +}) { + const { isMobile } = useSidebar() + + return ( + + Favorites + + {favorites.map((item) => ( + + + + {item.emoji} + {item.name} + + + + + + + More + + + + + + Remove from Favorites + + + + + Copy Link + + + + Open in New Tab + + + + + Delete + + + + + ))} + + + + More + + + + + ) +} diff --git a/components/nav-main.tsx b/components/nav-main.tsx new file mode 100644 index 0000000..31edc97 --- /dev/null +++ b/components/nav-main.tsx @@ -0,0 +1,35 @@ +"use client" + +import { type LucideIcon } from "lucide-react" + +import { + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +export function NavMain({ + items, +}: { + items: { + title: string + url: string + icon: LucideIcon + isActive?: boolean + }[] +}) { + return ( + + {items.map((item) => ( + + + + + {item.title} + + + + ))} + + ) +} diff --git a/components/nav-secondary.tsx b/components/nav-secondary.tsx new file mode 100644 index 0000000..71d2ebf --- /dev/null +++ b/components/nav-secondary.tsx @@ -0,0 +1,43 @@ +import React from "react" +import { type LucideIcon } from "lucide-react" + +import { + SidebarGroup, + SidebarGroupContent, + SidebarMenu, + SidebarMenuBadge, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +export function NavSecondary({ + items, + ...props +}: { + items: { + title: string + url: string + icon: LucideIcon + badge?: React.ReactNode + }[] +} & React.ComponentPropsWithoutRef) { + return ( + + + + {items.map((item) => ( + + + + + {item.title} + + + {item.badge && {item.badge}} + + ))} + + + + ) +} diff --git a/components/nav-workspaces.tsx b/components/nav-workspaces.tsx new file mode 100644 index 0000000..70ade7f --- /dev/null +++ b/components/nav-workspaces.tsx @@ -0,0 +1,85 @@ +import { ChevronRight, MoreHorizontal, Plus } from "lucide-react" + +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible" +import { + SidebarGroup, + SidebarGroupContent, + SidebarGroupLabel, + SidebarMenu, + SidebarMenuAction, + SidebarMenuButton, + SidebarMenuItem, + SidebarMenuSub, + SidebarMenuSubButton, + SidebarMenuSubItem, +} from "@/components/ui/sidebar" + +export function NavWorkspaces({ + workspaces, +}: { + workspaces: { + name: string + emoji: React.ReactNode + pages: { + name: string + emoji: React.ReactNode + }[] + }[] +}) { + return ( + + Workspaces + + + {workspaces.map((workspace) => ( + + + + + {workspace.emoji} + {workspace.name} + + + + + + + + + + + + + {workspace.pages.map((page) => ( + + + + {page.emoji} + {page.name} + + + + ))} + + + + + ))} + + + + More + + + + + + ) +} diff --git a/components/team-switcher.tsx b/components/team-switcher.tsx new file mode 100644 index 0000000..76144b2 --- /dev/null +++ b/components/team-switcher.tsx @@ -0,0 +1,83 @@ +"use client" + +import * as React from "react" +import { ChevronDown, Plus } from "lucide-react" + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, +} from "@/components/ui/sidebar" + +export function TeamSwitcher({ + teams, +}: { + teams: { + name: string + logo: React.ElementType + plan: string + }[] +}) { + const [activeTeam, setActiveTeam] = React.useState(teams[0]) + + if (!activeTeam) { + return null + } + + return ( + + + + + +
+ +
+ {activeTeam.name} + +
+
+ + + Teams + + {teams.map((team, index) => ( + setActiveTeam(team)} + className="gap-2 p-2" + > +
+ +
+ {team.name} + ⌘{index + 1} +
+ ))} + + +
+ +
+
Add team
+
+
+
+
+
+ ) +} diff --git a/components/ui/breadcrumb.tsx b/components/ui/breadcrumb.tsx new file mode 100644 index 0000000..eb88f32 --- /dev/null +++ b/components/ui/breadcrumb.tsx @@ -0,0 +1,109 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { ChevronRight, MoreHorizontal } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { + return