From a2775060c7732eacce67d7a3de0dc2020ccc10f8 Mon Sep 17 00:00:00 2001 From: thomasabishop Date: Fri, 18 Jul 2025 13:49:46 +0100 Subject: [PATCH] refactor: restructure component architecture --- src/App.tsx | 5 +- .../{app-header.tsx => AppHeader.tsx} | 0 src/components/app-sidebar.tsx | 141 -- src/components/ui/sidebar.tsx | 1148 ++++++++--------- src/containers/AppSidebar.tsx | 141 ++ src/containers/page.tsx | 53 - src/hooks/use-mobile.ts | 22 +- src/layouts/layout.tsx | 14 - src/pages/home.tsx | 25 + src/templates/Main.tsx | 17 + 10 files changed, 754 insertions(+), 812 deletions(-) rename src/components/{app-header.tsx => AppHeader.tsx} (100%) delete mode 100644 src/components/app-sidebar.tsx create mode 100644 src/containers/AppSidebar.tsx delete mode 100644 src/containers/page.tsx delete mode 100644 src/layouts/layout.tsx create mode 100644 src/pages/home.tsx create mode 100644 src/templates/Main.tsx diff --git a/src/App.tsx b/src/App.tsx index f90266c..4a1caf9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -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 ( <> - + ) } diff --git a/src/components/app-header.tsx b/src/components/AppHeader.tsx similarity index 100% rename from src/components/app-header.tsx rename to src/components/AppHeader.tsx diff --git a/src/components/app-sidebar.tsx b/src/components/app-sidebar.tsx deleted file mode 100644 index 8f402b2..0000000 --- a/src/components/app-sidebar.tsx +++ /dev/null @@ -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 ( - - - - - - - - Eólas - - - - - - - - - - - - - - Graph - - - - - - - - - - Entries - - - - - - - {mockEntries.map((item) => ( - - - {item.title} - - - ))} - - - - - - - - - - - Tags - - - - - - - {mockTags.map((item) => ( - - - {item.title} - - - ))} - - - - - - - - - - - - - {footerMenu.map((item) => ( - - - - - {item.title} - - - - ))} - - - - - - ) -} diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index 2239314..1450e84 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -9,19 +9,14 @@ import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { Separator } from "@/components/ui/separator" import { - Sheet, - SheetContent, - SheetDescription, - SheetHeader, - SheetTitle, + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + 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 @@ -31,694 +26,667 @@ const SIDEBAR_WIDTH_ICON = "3rem" const SIDEBAR_KEYBOARD_SHORTCUT = "b" type SidebarContextProps = { - state: "expanded" | "collapsed" - open: boolean - setOpen: (open: boolean) => void - openMobile: boolean - setOpenMobile: (open: boolean) => void - isMobile: boolean - toggleSidebar: () => void + state: "expanded" | "collapsed" + open: boolean + setOpen: (open: boolean) => void + openMobile: boolean + setOpenMobile: (open: boolean) => void + isMobile: boolean + toggleSidebar: () => void } const SidebarContext = React.createContext(null) function useSidebar() { - const context = React.useContext(SidebarContext) - if (!context) { - throw new Error("useSidebar must be used within a SidebarProvider.") - } + const context = React.useContext(SidebarContext) + if (!context) { + throw new Error("useSidebar must be used within a SidebarProvider.") + } - return context + return context } function SidebarProvider({ - defaultOpen = true, - open: openProp, - onOpenChange: setOpenProp, - className, - style, - children, - ...props + defaultOpen = true, + open: openProp, + onOpenChange: setOpenProp, + className, + style, + children, + ...props }: React.ComponentProps<"div"> & { - defaultOpen?: boolean - open?: boolean - onOpenChange?: (open: boolean) => void + defaultOpen?: boolean + open?: boolean + onOpenChange?: (open: boolean) => void }) { - const isMobile = useIsMobile() - const [openMobile, setOpenMobile] = React.useState(false) + const isMobile = useIsMobile() + const [openMobile, setOpenMobile] = React.useState(false) - // This is the internal state of the sidebar. - // We use openProp and setOpenProp for control from outside the component. - const [_open, _setOpen] = React.useState(defaultOpen) - const open = openProp ?? _open - const setOpen = React.useCallback( - (value: boolean | ((value: boolean) => boolean)) => { - const openState = typeof value === "function" ? value(open) : value - if (setOpenProp) { - setOpenProp(openState) - } else { - _setOpen(openState) - } + // This is the internal state of the sidebar. + // We use openProp and setOpenProp for control from outside the component. + const [_open, _setOpen] = React.useState(defaultOpen) + const open = openProp ?? _open + const setOpen = React.useCallback( + (value: boolean | ((value: boolean) => boolean)) => { + const openState = typeof value === "function" ? value(open) : value + if (setOpenProp) { + setOpenProp(openState) + } else { + _setOpen(openState) + } - // This sets the cookie to keep the sidebar state. - document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` - }, - [setOpenProp, open] - ) + // This sets the cookie to keep the sidebar state. + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` + }, + [setOpenProp, open], + ) - // Helper to toggle the sidebar. - const toggleSidebar = React.useCallback(() => { - return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open) - }, [isMobile, setOpen, setOpenMobile]) + // Helper to toggle the sidebar. + const toggleSidebar = React.useCallback(() => { + return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open) + }, [isMobile, setOpen, setOpenMobile]) - // Adds a keyboard shortcut to toggle the sidebar. - React.useEffect(() => { - const handleKeyDown = (event: KeyboardEvent) => { - if ( - event.key === SIDEBAR_KEYBOARD_SHORTCUT && - (event.metaKey || event.ctrlKey) - ) { - event.preventDefault() - toggleSidebar() - } - } + // Adds a keyboard shortcut to toggle the sidebar. + React.useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) { + event.preventDefault() + toggleSidebar() + } + } - window.addEventListener("keydown", handleKeyDown) - return () => window.removeEventListener("keydown", handleKeyDown) - }, [toggleSidebar]) + window.addEventListener("keydown", handleKeyDown) + return () => window.removeEventListener("keydown", handleKeyDown) + }, [toggleSidebar]) - // We add a state so that we can do data-state="expanded" or "collapsed". - // This makes it easier to style the sidebar with Tailwind classes. - const state = open ? "expanded" : "collapsed" + // We add a state so that we can do data-state="expanded" or "collapsed". + // This makes it easier to style the sidebar with Tailwind classes. + const state = open ? "expanded" : "collapsed" - const contextValue = React.useMemo( - () => ({ - state, - open, - setOpen, - isMobile, - openMobile, - setOpenMobile, - toggleSidebar, - }), - [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] - ) + const contextValue = React.useMemo( + () => ({ + state, + open, + setOpen, + isMobile, + openMobile, + setOpenMobile, + toggleSidebar, + }), + [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar], + ) - return ( - - -
- {children} -
-
-
- ) + return ( + + +
+ {children} +
+
+
+ ) } function Sidebar({ - side = "left", - variant = "sidebar", - collapsible = "offcanvas", - className, - children, - ...props + side = "left", + variant = "sidebar", + collapsible = "offcanvas", + className, + children, + ...props }: React.ComponentProps<"div"> & { - side?: "left" | "right" - variant?: "sidebar" | "floating" | "inset" - collapsible?: "offcanvas" | "icon" | "none" + side?: "left" | "right" + variant?: "sidebar" | "floating" | "inset" + collapsible?: "offcanvas" | "icon" | "none" }) { - const { isMobile, state, openMobile, setOpenMobile } = useSidebar() + const { isMobile, state, openMobile, setOpenMobile } = useSidebar() - if (collapsible === "none") { - return ( -
- {children} -
- ) - } + if (collapsible === "none") { + return ( +
+ {children} +
+ ) + } - if (isMobile) { - return ( - - - - Sidebar - Displays the mobile sidebar. - -
{children}
-
-
- ) - } + if (isMobile) { + return ( + + + + Sidebar + Displays the mobile sidebar. + +
{children}
+
+
+ ) + } - return ( -
- {/* This is what handles the sidebar gap on desktop */} -
- -
- ) + return ( +
+ {/* This is what handles the sidebar gap on desktop */} +
+ +
+ ) } -function SidebarTrigger({ - className, - onClick, - ...props -}: React.ComponentProps) { - const { toggleSidebar } = useSidebar() +function SidebarTrigger({ className, onClick, ...props }: React.ComponentProps) { + const { toggleSidebar } = useSidebar() - return ( - - ) + return ( + + ) } function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { - const { toggleSidebar } = useSidebar() + const { toggleSidebar } = useSidebar() - return ( -