From 094775a3a08b125f52cedbb36b09ec035bbd0bde Mon Sep 17 00:00:00 2001 From: Lars Hampe Date: Sun, 20 Oct 2024 09:34:09 +0200 Subject: [PATCH] feat(ui): add sidebar component --- bun.lockb | Bin 486632 -> 487304 bytes packages/ui/package.json | 3 + packages/ui/src/avatar.tsx | 48 ++ packages/ui/src/collapsible.tsx | 9 + packages/ui/src/global.css | 22 +- packages/ui/src/hooks/useIsMobile.tsx | 19 + packages/ui/src/index.ts | 5 + packages/ui/src/separator.tsx | 29 + packages/ui/src/sidebar.tsx | 762 ++++++++++++++++++++++++++ packages/ui/src/skeleton.tsx | 15 + 10 files changed, 911 insertions(+), 1 deletion(-) create mode 100644 packages/ui/src/avatar.tsx create mode 100644 packages/ui/src/collapsible.tsx create mode 100644 packages/ui/src/hooks/useIsMobile.tsx create mode 100644 packages/ui/src/separator.tsx create mode 100644 packages/ui/src/sidebar.tsx create mode 100644 packages/ui/src/skeleton.tsx diff --git a/bun.lockb b/bun.lockb index 1e9e72c2da2b6fc21d82e5d74e69751dd23080b1..978d1b4b31e9cc6f10e4159349bc9fb18e59fcbf 100755 GIT binary patch delta 43899 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≦2s~MB^GD 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 FH2^vB=d^ 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, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/packages/ui/src/collapsible.tsx b/packages/ui/src/collapsible.tsx new file mode 100644 index 0000000..7cee61e --- /dev/null +++ b/packages/ui/src/collapsible.tsx @@ -0,0 +1,9 @@ +import * as CollapsiblePrimitive from '@radix-ui/react-collapsible' + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/packages/ui/src/global.css b/packages/ui/src/global.css index 95d8cab..3836550 100644 --- a/packages/ui/src/global.css +++ b/packages/ui/src/global.css @@ -34,6 +34,15 @@ --ring: 215 20.2% 65.1%; --radius: 0.5rem; + + --sidebar-background: 0 0% 98%; + --sidebar-foreground: 240 5.3% 26.1%; + --sidebar-primary: 240 5.9% 10%; + --sidebar-primary-foreground: 0 0% 98%; + --sidebar-accent: 240 4.8% 95.9%; + --sidebar-accent-foreground: 240 5.9% 10%; + --sidebar-border: 220 13% 91%; + --sidebar-ring: 217.2 91.2% 59.8%; } .dark { @@ -67,6 +76,15 @@ --ring: 216 34% 17%; --radius: 0.5rem; + + --sidebar-background: 240 5.9% 10%; + --sidebar-foreground: 240 4.8% 95.9%; + --sidebar-primary: 224.3 76.3% 48%; + --sidebar-primary-foreground: 0 0% 100%; + --sidebar-accent: 240 3.7% 15.9%; + --sidebar-accent-foreground: 240 4.8% 95.9%; + --sidebar-border: 240 3.7% 15.9%; + --sidebar-ring: 217.2 91.2% 59.8%; } } @@ -76,6 +94,8 @@ } body { @apply bg-background text-foreground; - font-feature-settings: "rlig" 1, "calt" 1; + font-feature-settings: + "rlig" 1, + "calt" 1; } } diff --git a/packages/ui/src/hooks/useIsMobile.tsx b/packages/ui/src/hooks/useIsMobile.tsx new file mode 100644 index 0000000..4331d5c --- /dev/null +++ b/packages/ui/src/hooks/useIsMobile.tsx @@ -0,0 +1,19 @@ +import * as React from 'react' + +const MOBILE_BREAKPOINT = 768 + +export function useIsMobile() { + const [isMobile, setIsMobile] = React.useState(undefined) + + React.useEffect(() => { + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) + const onChange = () => { + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + } + mql.addEventListener('change', onChange) + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) + return () => mql.removeEventListener('change', onChange) + }, []) + + return !!isMobile +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 8426db4..48c4bd8 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -19,3 +19,8 @@ export * from './popover' export * from './calendar' export * from './date-picker' export * from './alert' +export * from './separator' +export * from './skeleton' +export * from './sidebar' +export * from './collapsible' +export * from './avatar' diff --git a/packages/ui/src/separator.tsx b/packages/ui/src/separator.tsx new file mode 100644 index 0000000..842667f --- /dev/null +++ b/packages/ui/src/separator.tsx @@ -0,0 +1,29 @@ +import * as SeparatorPrimitive from '@radix-ui/react-separator' +import * as React from 'react' + +import { cn } from './lib/cn' + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = 'horizontal', decorative = true, ...props }, + ref, + ) => ( + + ), +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/packages/ui/src/sidebar.tsx b/packages/ui/src/sidebar.tsx new file mode 100644 index 0000000..341e8b7 --- /dev/null +++ b/packages/ui/src/sidebar.tsx @@ -0,0 +1,762 @@ +import { Slot } from '@radix-ui/react-slot' +import { type VariantProps, cva } from 'class-variance-authority' +import { PanelLeft } from 'lucide-react' +import * as React from 'react' + +import { Button } from './button' +import { useIsMobile } from './hooks/useIsMobile' +import { Input } from './input' +import { cn } from './lib/cn' +import { Separator } from './separator' +import { Sheet, SheetContent } from './sheet' +import { Skeleton } from './skeleton' +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from './tooltip' + +const SIDEBAR_COOKIE_NAME = 'sidebar:state' +const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 +const SIDEBAR_WIDTH = '16rem' +const SIDEBAR_WIDTH_MOBILE = '18rem' +const SIDEBAR_WIDTH_ICON = '3rem' +const SIDEBAR_KEYBOARD_SHORTCUT = 'b' + +type SidebarContext = { + 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 Sidebar.') + } + + return context +} + +const SidebarProvider = React.forwardRef< + HTMLDivElement, + React.ComponentProps<'div'> & { + defaultOpen?: boolean + open?: boolean + onOpenChange?: (open: boolean) => void + } +>( + ( + { + defaultOpen = true, + open: openProp, + onOpenChange: setOpenProp, + className, + style, + children, + ...props + }, + ref, + ) => { + 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)) => { + if (setOpenProp) { + return setOpenProp?.( + typeof value === 'function' ? value(open) : value, + ) + } + + _setOpen(value) + + // This sets the cookie to keep the sidebar state. + document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; 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]) + + // 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]) + + // 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, toggleSidebar], + ) + + return ( + + +
+ {children} +
+
+
+ ) + }, +) +SidebarProvider.displayName = 'SidebarProvider' + +const Sidebar = React.forwardRef< + HTMLDivElement, + React.ComponentProps<'div'> & { + side?: 'left' | 'right' + variant?: 'sidebar' | 'floating' | 'inset' + collapsible?: 'offcanvas' | 'icon' | 'none' + } +>( + ( + { + side = 'left', + variant = 'sidebar', + collapsible = 'offcanvas', + className, + children, + ...props + }, + ref, + ) => { + const { isMobile, state, openMobile, setOpenMobile } = useSidebar() + + if (collapsible === 'none') { + return ( +
+ {children} +
+ ) + } + + if (isMobile) { + return ( + + +
{children}
+
+
+ ) + } + + return ( +
+ {/* This is what handles the sidebar gap on desktop */} +
+ +
+ ) + }, +) +Sidebar.displayName = 'Sidebar' + +const SidebarTrigger = React.forwardRef< + React.ElementRef, + React.ComponentProps +>(({ className, onClick, ...props }, ref) => { + const { toggleSidebar } = useSidebar() + + return ( + + ) +}) +SidebarTrigger.displayName = 'SidebarTrigger' + +const SidebarRail = React.forwardRef< + HTMLButtonElement, + React.ComponentProps<'button'> +>(({ className, ...props }, ref) => { + const { toggleSidebar } = useSidebar() + + return ( +