refactor: restructure component architecture
This commit is contained in:
parent
12132bc660
commit
a2775060c7
10 changed files with 754 additions and 812 deletions
|
|
@ -1,11 +1,10 @@
|
|||
import Home from "@/pages/home"
|
||||
import "./App.css"
|
||||
import Page from "./containers/page"
|
||||
import Layout from "./layouts/layout"
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<>
|
||||
<Page />
|
||||
<Home />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,141 +0,0 @@
|
|||
import {
|
||||
FileText,
|
||||
Waypoints,
|
||||
SquareLibrary,
|
||||
Settings,
|
||||
Tags,
|
||||
Info,
|
||||
ChevronRight,
|
||||
} from "lucide-react"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarHeader,
|
||||
SidebarFooter,
|
||||
SidebarMenuSub,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { Collapsible, CollapsibleTrigger } from "@radix-ui/react-collapsible"
|
||||
import { CollapsibleContent } from "./ui/collapsible"
|
||||
import { mockEntries } from "@/mock-data/mock-entries"
|
||||
import { mockTags } from "@/mock-data/mock-tags"
|
||||
|
||||
const footerMenu = [
|
||||
{
|
||||
title: "About",
|
||||
url: "#",
|
||||
icon: Info,
|
||||
},
|
||||
|
||||
{
|
||||
title: "Settings",
|
||||
url: "#",
|
||||
icon: Settings,
|
||||
},
|
||||
]
|
||||
|
||||
export function AppSidebar() {
|
||||
return (
|
||||
<Sidebar>
|
||||
<SidebarHeader className="border-b h-12">
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild className="data-[slot=sidebar-menu-button]:!p-1.5">
|
||||
<a href="#">
|
||||
<SquareLibrary className="h-5 w-5" />
|
||||
<span className="text-base font-semibold">Eólas</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem key="graph">
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<Waypoints />
|
||||
<span>Graph</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<Collapsible className="group/collapsible">
|
||||
<SidebarMenuItem key="entries">
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<FileText />
|
||||
<span>Entries</span>
|
||||
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{mockEntries.map((item) => (
|
||||
<SidebarMenuItem>
|
||||
<a href={item.url}>
|
||||
<span className="text-xs">{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
<Collapsible className="group/collapsible">
|
||||
<SidebarMenuItem key="entries">
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<Tags />
|
||||
<span>Tags</span>
|
||||
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{mockTags.map((item) => (
|
||||
<SidebarMenuItem>
|
||||
<a href={item.url}>
|
||||
<span className="text-xs">{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{footerMenu.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
)
|
||||
}
|
||||
|
|
@ -16,12 +16,7 @@ import {
|
|||
SheetTitle,
|
||||
} from "@/components/ui/sheet"
|
||||
import { Skeleton } from "@/components/ui/skeleton"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip"
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
|
||||
const SIDEBAR_COOKIE_NAME = "sidebar_state"
|
||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
||||
|
|
@ -83,7 +78,7 @@ function SidebarProvider({
|
|||
// This sets the cookie to keep the sidebar state.
|
||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
|
||||
},
|
||||
[setOpenProp, open]
|
||||
[setOpenProp, open],
|
||||
)
|
||||
|
||||
// Helper to toggle the sidebar.
|
||||
|
|
@ -94,10 +89,7 @@ function SidebarProvider({
|
|||
// Adds a keyboard shortcut to toggle the sidebar.
|
||||
React.useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (
|
||||
event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
|
||||
(event.metaKey || event.ctrlKey)
|
||||
) {
|
||||
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
||||
event.preventDefault()
|
||||
toggleSidebar()
|
||||
}
|
||||
|
|
@ -121,7 +113,7 @@ function SidebarProvider({
|
|||
setOpenMobile,
|
||||
toggleSidebar,
|
||||
}),
|
||||
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
||||
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
@ -138,7 +130,7 @@ function SidebarProvider({
|
|||
}
|
||||
className={cn(
|
||||
"group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -169,7 +161,7 @@ function Sidebar({
|
|||
data-slot="sidebar"
|
||||
className={cn(
|
||||
"bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -221,7 +213,7 @@ function Sidebar({
|
|||
"group-data-[side=right]:rotate-180",
|
||||
variant === "floating" || variant === "inset"
|
||||
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]"
|
||||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
||||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon)",
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
|
|
@ -235,7 +227,7 @@ function Sidebar({
|
|||
variant === "floating" || variant === "inset"
|
||||
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]"
|
||||
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
|
|
@ -251,11 +243,7 @@ function Sidebar({
|
|||
)
|
||||
}
|
||||
|
||||
function SidebarTrigger({
|
||||
className,
|
||||
onClick,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps<typeof Button>) {
|
||||
const { toggleSidebar } = useSidebar()
|
||||
|
||||
return (
|
||||
|
|
@ -295,7 +283,7 @@ function SidebarRail({ className, ...props }: React.ComponentProps<"button">) {
|
|||
"hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
|
||||
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
||||
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -309,17 +297,14 @@ function SidebarInset({ className, ...props }: React.ComponentProps<"main">) {
|
|||
className={cn(
|
||||
"bg-background relative flex w-full flex-1 flex-col",
|
||||
"md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarInput({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Input>) {
|
||||
function SidebarInput({ className, ...props }: React.ComponentProps<typeof Input>) {
|
||||
return (
|
||||
<Input
|
||||
data-slot="sidebar-input"
|
||||
|
|
@ -352,10 +337,7 @@ function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|||
)
|
||||
}
|
||||
|
||||
function SidebarSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof Separator>) {
|
||||
function SidebarSeparator({ className, ...props }: React.ComponentProps<typeof Separator>) {
|
||||
return (
|
||||
<Separator
|
||||
data-slot="sidebar-separator"
|
||||
|
|
@ -373,7 +355,7 @@ function SidebarContent({ className, ...props }: React.ComponentProps<"div">) {
|
|||
data-sidebar="content"
|
||||
className={cn(
|
||||
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -405,7 +387,7 @@ function SidebarGroupLabel({
|
|||
className={cn(
|
||||
"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
||||
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -428,17 +410,14 @@ function SidebarGroupAction({
|
|||
// Increases the hit area of the button on mobile.
|
||||
"after:absolute after:-inset-2 md:after:hidden",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarGroupContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div">) {
|
||||
function SidebarGroupContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="sidebar-group-content"
|
||||
|
|
@ -490,7 +469,7 @@ const sidebarMenuButtonVariants = cva(
|
|||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function SidebarMenuButton({
|
||||
|
|
@ -568,17 +547,14 @@ function SidebarMenuAction({
|
|||
"group-data-[collapsible=icon]:hidden",
|
||||
showOnHover &&
|
||||
"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarMenuBadge({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div">) {
|
||||
function SidebarMenuBadge({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="sidebar-menu-badge"
|
||||
|
|
@ -590,7 +566,7 @@ function SidebarMenuBadge({
|
|||
"peer-data-[size=default]/menu-button:top-1.5",
|
||||
"peer-data-[size=lg]/menu-button:top-2.5",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -616,12 +592,7 @@ function SidebarMenuSkeleton({
|
|||
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
||||
{...props}
|
||||
>
|
||||
{showIcon && (
|
||||
<Skeleton
|
||||
className="size-4 rounded-md"
|
||||
data-sidebar="menu-skeleton-icon"
|
||||
/>
|
||||
)}
|
||||
{showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
|
||||
<Skeleton
|
||||
className="h-4 max-w-(--skeleton-width) flex-1"
|
||||
data-sidebar="menu-skeleton-text"
|
||||
|
|
@ -643,17 +614,14 @@ function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) {
|
|||
className={cn(
|
||||
"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SidebarMenuSubItem({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"li">) {
|
||||
function SidebarMenuSubItem({ className, ...props }: React.ComponentProps<"li">) {
|
||||
return (
|
||||
<li
|
||||
data-slot="sidebar-menu-sub-item"
|
||||
|
|
@ -689,7 +657,7 @@ function SidebarMenuSubButton({
|
|||
size === "sm" && "text-xs",
|
||||
size === "md" && "text-sm",
|
||||
"group-data-[collapsible=icon]:hidden",
|
||||
className
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
|
|
|
|||
141
src/containers/AppSidebar.tsx
Normal file
141
src/containers/AppSidebar.tsx
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
import {
|
||||
FileText,
|
||||
Waypoints,
|
||||
SquareLibrary,
|
||||
Settings,
|
||||
Tags,
|
||||
Info,
|
||||
ChevronRight,
|
||||
} from "lucide-react"
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
SidebarHeader,
|
||||
SidebarFooter,
|
||||
SidebarMenuSub,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { Collapsible, CollapsibleTrigger } from "@radix-ui/react-collapsible"
|
||||
import { CollapsibleContent } from "../components/ui/collapsible"
|
||||
import { mockEntries } from "@/mock-data/mock-entries"
|
||||
import { mockTags } from "@/mock-data/mock-tags"
|
||||
|
||||
const footerMenu = [
|
||||
{
|
||||
title: "About",
|
||||
url: "#",
|
||||
icon: Info,
|
||||
},
|
||||
|
||||
{
|
||||
title: "Settings",
|
||||
url: "#",
|
||||
icon: Settings,
|
||||
},
|
||||
]
|
||||
|
||||
export function AppSidebar() {
|
||||
return (
|
||||
<Sidebar>
|
||||
<SidebarHeader className="border-b h-12">
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild className="data-[slot=sidebar-menu-button]:!p-1.5">
|
||||
<a href="#">
|
||||
<SquareLibrary className="h-5 w-5" />
|
||||
<span className="text-base font-semibold">Eólas</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarHeader>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem key="graph">
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<Waypoints />
|
||||
<span>Graph</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<Collapsible className="group/collapsible">
|
||||
<SidebarMenuItem key="entries">
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<FileText />
|
||||
<span>Entries</span>
|
||||
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{mockEntries.map((item) => (
|
||||
<SidebarMenuItem>
|
||||
<a href={item.url}>
|
||||
<span className="text-xs">{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
<Collapsible className="group/collapsible">
|
||||
<SidebarMenuItem key="entries">
|
||||
<CollapsibleTrigger asChild>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href="#">
|
||||
<Tags />
|
||||
<span>Tags</span>
|
||||
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent>
|
||||
<SidebarMenuSub>
|
||||
{mockTags.map((item) => (
|
||||
<SidebarMenuItem>
|
||||
<a href={item.url}>
|
||||
<span className="text-xs">{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenuSub>
|
||||
</CollapsibleContent>
|
||||
</SidebarMenuItem>
|
||||
</Collapsible>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{footerMenu.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<a href={item.url}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</a>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import AppHeader from "@/components/app-header"
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
|
||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<AppSidebar variant="inset" />
|
||||
<SidebarInset>
|
||||
<AppHeader pageTitle="Home" />
|
||||
<div className="flex-1 flex flex-col overflow-auto">
|
||||
<div className="@container/main flex flex-col">
|
||||
<div className="p-4 lg:p-6 flex-1 flex">
|
||||
<Card className="border rounded-sm shadow-none w-auto">
|
||||
<CardContent className="p-4 overflow-auto">
|
||||
<p className="leading-7 [&:not(:first-child)]:mt-6 font-normal">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eget
|
||||
justo non ipsum venenatis suscipit. In eu viverra nisl. Pellentesque
|
||||
vel tincidunt arcu. Sed congue consequat dapibus. Suspendisse
|
||||
imperdiet faucibus velit, in porta massa. Vivamus ornare, justo
|
||||
pulvinar hendrerit accumsan, nisl massa tempus orci, id iaculis metus
|
||||
mi pellentesque nibh. Quisque mollis id massa malesuada sagittis. Nunc
|
||||
massa est, maximus sit amet sollicitudin in, ultrices at tellus.
|
||||
Curabitur vel odio varius, faucibus quam sed, sollicitudin nunc. Ut
|
||||
pretium, risus et malesuada mattis, urna neque maximus est, in
|
||||
pellentesque eros neque nec mi. Aenean aliquet auctor dolor, quis
|
||||
condimentum urna vehicula quis.
|
||||
</p>
|
||||
<p className="leading-7 [&:not(:first-child)]:mt-6">
|
||||
Vestibulum bibendum dui sit amet quam molestie gravida. Integer turpis
|
||||
est, ultricies sed imperdiet vitae, ultricies sed purus. Nulla
|
||||
facilisi. Nullam ultricies imperdiet urna, id convallis massa commodo
|
||||
in. Pellentesque dapibus malesuada turpis nec sollicitudin. Duis ante
|
||||
nunc, faucibus et ornare vitae, posuere quis mi. Sed vitae varius
|
||||
turpis. Sed fringilla, libero id varius volutpat, eros nibh auctor
|
||||
purus, sit amet tincidunt enim quam ac libero. Cras congue posuere
|
||||
dolor, eget rutrum lacus accumsan sed. Etiam sit amet lectus neque.
|
||||
Morbi dignissim elit tortor, ut porta dolor aliquet at. Ut commodo
|
||||
interdum malesuada. Nulla velit sem, maximus et ultricies et,
|
||||
vulputate ac tortor. Maecenas lobortis tellus in mi tristique
|
||||
fringilla. Morbi ullamcorper et diam et condim
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import AppHeader from "@/components/app-header"
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import { SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar"
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
<SidebarProvider>
|
||||
<AppSidebar />
|
||||
<main>{children}</main>
|
||||
</SidebarProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
25
src/pages/home.tsx
Normal file
25
src/pages/home.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import Main from "@/templates/Main"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<Main pageTitle="Home">
|
||||
<div className="flex-1 flex flex-col overflow-auto">
|
||||
<div className="@container/main flex flex-col">
|
||||
<div className="p-4 lg:p-6 flex-1 flex">
|
||||
<Card className="border rounded-sm shadow-none w-full">
|
||||
<CardContent className="p-4 overflow-auto">
|
||||
<p className="leading-7 [&:not(:first-child)]:mt-6 font-normal">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eget
|
||||
justo non ipsum venenatis suscipit.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
17
src/templates/Main.tsx
Normal file
17
src/templates/Main.tsx
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import AppHeader from "@/components/AppHeader"
|
||||
import { AppSidebar } from "@/containers/AppSidebar"
|
||||
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"
|
||||
|
||||
export default function Main({ children, pageTitle }) {
|
||||
return (
|
||||
<>
|
||||
<SidebarProvider variant="inset">
|
||||
<AppSidebar />
|
||||
<SidebarInset>
|
||||
<AppHeader pageTitle={pageTitle} />
|
||||
<main>{children}</main>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue