diff --git a/.changeset/loose-cycles-create.md b/.changeset/loose-cycles-create.md new file mode 100644 index 00000000..30d9c6db --- /dev/null +++ b/.changeset/loose-cycles-create.md @@ -0,0 +1,12 @@ +--- +'@example/ui-playground': patch +'@genseki/react': patch +--- + +Migrate UI to shadcn + +- New `sidebar` component +- New `breadcrumb` component +- New `dropdown-menu` component +- New `skeleton` component +- New `tooltip` component diff --git a/examples/ui-playground/src/app/playground/shadcn/collapsible-section.tsx b/examples/ui-playground/src/app/playground/shadcn/collapsible-section.tsx new file mode 100644 index 00000000..ed8efeb4 --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/collapsible-section.tsx @@ -0,0 +1,418 @@ +import React from 'react' + +import { + CaretDownIcon, + CaretRightIcon, + FileIcon, + FolderIcon, + FolderOpenIcon, + ImageIcon, + MusicNoteIcon, + VideoIcon, +} from '@phosphor-icons/react' + +import { Typography } from '@genseki/react' +import { Button } from '@genseki/react/v2' +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@genseki/react/v2' + +import { PlaygroundCard } from '~/src/components/card' + +// Basic Collapsible +function BasicCollapsible() { + const [isOpen, setIsOpen] = React.useState(false) + + return ( +
+ +
+
+ + + +
+
+ +
+ This is the collapsible content that can be shown or hidden. +
+
+
+
+ ) +} + +// File Tree Style +function FileTreeStyle() { + const [isDocumentsOpen, setIsDocumentsOpen] = React.useState(true) + const [isImagesOpen, setIsImagesOpen] = React.useState(false) + const [isVideosOpen, setIsVideosOpen] = React.useState(false) + + return ( +
+
+ + + + + +
+ + report.pdf +
+
+ + presentation.pptx +
+
+ + notes.txt +
+
+
+ + + + + + +
+ + photo1.jpg +
+
+ + photo2.png +
+
+ + screenshot.png +
+
+
+ + + + + + +
+ + tutorial.mp4 +
+
+ + demo.mov +
+
+ + audio.mp3 +
+
+
+
+
+ ) +} + +// FAQ Style +function FAQStyle() { + const [openItems, setOpenItems] = React.useState([]) + + const toggleItem = (itemId: string) => { + setOpenItems((prev) => + prev.includes(itemId) ? prev.filter((id) => id !== itemId) : [...prev, itemId] + ) + } + + const faqItems = [ + { + id: '1', + question: 'What is this component library?', + answer: + 'This is a comprehensive React component library built with modern design principles and accessibility in mind.', + }, + { + id: '2', + question: 'How do I install the components?', + answer: + 'You can install the components using npm or yarn. Check the documentation for detailed installation instructions.', + }, + { + id: '3', + question: 'Is it free to use?', + answer: + 'Yes, this component library is open source and free to use in both personal and commercial projects.', + }, + ] + + return ( +
+
+ {faqItems.map((item) => ( + toggleItem(item.id)} + > + + + + +
{item.answer}
+
+
+ ))} +
+
+ ) +} + +// Settings Panel Style +function SettingsPanelStyle() { + const [openSections, setOpenSections] = React.useState(['general']) + + const toggleSection = (sectionId: string) => { + setOpenSections((prev) => + prev.includes(sectionId) ? prev.filter((id) => id !== sectionId) : [...prev, sectionId] + ) + } + + const settingsSections = [ + { + id: 'general', + title: 'General Settings', + content: ( +
+
+ Dark Mode + +
+
+ Notifications + +
+
+ Language + +
+
+ ), + }, + { + id: 'privacy', + title: 'Privacy & Security', + content: ( +
+
+ Two-Factor Authentication + +
+
+ Data Export + +
+
+ Account Deletion + +
+
+ ), + }, + { + id: 'advanced', + title: 'Advanced Options', + content: ( +
+
+ Debug Mode + +
+
+ Cache Management + +
+
+ Reset Settings + +
+
+ ), + }, + ] + + return ( +
+
+ {settingsSections.map((section) => ( +
+ toggleSection(section.id)} + > + + + + {section.content} + +
+ ))} +
+
+ ) +} + +// Multiple Independent Collapsibles +function MultipleIndependentCollapsibles() { + const [openStates, setOpenStates] = React.useState>({ + section1: false, + section2: true, + section3: false, + }) + + const toggleSection = (sectionId: string) => { + setOpenStates((prev) => ({ + ...prev, + [sectionId]: !prev[sectionId], + })) + } + + return ( +
+
+ toggleSection('section1')}> + + + + +
+

+ This is the content for section 1. Each collapsible can be controlled independently. +

+
+
+
+ + toggleSection('section2')}> + + + + +
+

+ This section starts open by default. You can see how the state is managed + independently. +

+
+
+
+ + toggleSection('section3')}> + + + + +
+

+ This is the third section. Notice how each collapsible maintains its own state. +

+
+
+
+
+
+ ) +} + +export function CollapsibleSection() { + return ( +
+ + + A simple collapsible component that can show or hide content. + +
+ +
+
+ + + + Collapsible components styled like a file tree with folders and files. + +
+ +
+
+ + + + Frequently asked questions styled as collapsible sections. + +
+ +
+
+ + + + A settings panel with collapsible sections for different categories. + +
+ +
+
+ + + + Multiple collapsible sections that can be controlled independently. + +
+ +
+
+
+ ) +} diff --git a/examples/ui-playground/src/app/playground/shadcn/combobox-section.tsx b/examples/ui-playground/src/app/playground/shadcn/combobox-section.tsx index b7015d98..671ac738 100644 --- a/examples/ui-playground/src/app/playground/shadcn/combobox-section.tsx +++ b/examples/ui-playground/src/app/playground/shadcn/combobox-section.tsx @@ -213,7 +213,7 @@ function CustomTriggerComboboxMultiple() { {(selectedItems) => ( + + + + + Profile + + + + Settings + + + + Favorites + + + + + Delete + + + + + ) +} + +// Dropdown with Icons and Shortcuts +function DropdownWithIconsAndShortcuts() { + return ( +
+ + + + + + + + Edit + ⌘E + + + + Copy + ⌘C + + + + Share + ⌘S + + + + + Download + ⌘D + + + + Delete + ⌘⌫ + + + +
+ ) +} + +// Dropdown with Groups +function DropdownWithGroups() { + return ( +
+ + + + + + File Operations + + + + New File + + + + Open Folder + + + + Save As + + + + Export + + + + Export as PDF + + + + Export as Image + + + + +
+ ) +} + +// Dropdown with Checkboxes +function DropdownWithCheckboxes() { + const [showStatusBar, setShowStatusBar] = React.useState(true) + const [showPanel, setShowPanel] = React.useState(false) + const [showSidebar, setShowSidebar] = React.useState(true) + + return ( +
+ + + + + + View + { + e.preventDefault() + }} + checked={showStatusBar} + onCheckedChange={setShowStatusBar} + > + Status Bar + + { + e.preventDefault() + }} + checked={showPanel} + onCheckedChange={setShowPanel} + > + Panel + + { + e.preventDefault() + }} + checked={showSidebar} + onCheckedChange={setShowSidebar} + > + Sidebar + + + +
+ ) +} + +// Dropdown with Radio Items +function DropdownWithRadioItems() { + const [theme, setTheme] = React.useState('light') + + return ( +
+ + + + + + Choose Theme + + Light + Dark + System + + + +
+ ) +} + +// Dropdown with Submenus +function DropdownWithSubmenus() { + return ( +
+ + + + + + + + Edit + + + + Copy + + + + + + Share + + + Email + Twitter + LinkedIn + + Copy Link + + + + + + Delete + + + +
+ ) +} + +// Context Menu Style +function ContextMenuStyle() { + return ( +
+ + + + + + + + Edit + + + + Duplicate + + + + + Share + + + + Download + + + + + Delete + + + +
+ ) +} + +export function DropdownMenuSection() { + return ( +
+ + + A simple dropdown menu with basic menu items and separators. + +
+ +
+
+ + + + Dropdown menus can include icons and keyboard shortcuts for better UX. + +
+ +
+
+ + + + Organize menu items into logical groups with labels and separators. + +
+ +
+
+ + + + Interactive checkboxes for toggleable options within dropdown menus. + +
+ +
+
+ + + + Radio button groups for selecting one option from multiple choices. + +
+ +
+
+ + + + Nested dropdown menus for organizing complex menu structures. + +
+ +
+
+ + + + A compact dropdown menu suitable for context menus and action buttons. + +
+ +
+
+
+ ) +} diff --git a/examples/ui-playground/src/app/playground/shadcn/page.tsx b/examples/ui-playground/src/app/playground/shadcn/page.tsx index 27dcfeb3..7e72b72a 100644 --- a/examples/ui-playground/src/app/playground/shadcn/page.tsx +++ b/examples/ui-playground/src/app/playground/shadcn/page.tsx @@ -4,11 +4,15 @@ import * as React from 'react' import Link from 'next/link' import { Typography } from '@genseki/react' +import { linkVariants } from '@genseki/react/v2' import { ButtonSection } from './button-section' +import { CollapsibleSection } from './collapsible-section' import { ComboboxSection } from './combobox-section' +import { DropdownMenuSection } from './dropdown-menu-section' import { InputSection } from './input-section' import { LinkSection } from './link-section' +import { TooltipSection } from './tooltip-section' export default function ComboboxPage() { return ( @@ -37,17 +41,83 @@ export default function ComboboxPage() { Link + + + Tooltip + + + + + Dropdown Menu + + + + + Collapsible + +
-
- {'>'} Button +
+ + {'>'} Button + +
+ + {'>'} Combobox + +
+ + {'>'} Input + +
+ + {'>'} Link + +
+ + {'>'} Tooltip +
- {'>'} Combobox + + {'>'} Dropdown Menu +
- {'>'} Input + + {'>'} Collapsible +
- {'>'} Link + + {'>'} Sidebar +
diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx new file mode 100644 index 00000000..98d493ac --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/app-sidebar.tsx @@ -0,0 +1,158 @@ +import * as React from 'react' + +import { + ChartLineUpIcon, + StackIcon, + StorefrontIcon, + TerminalWindowIcon, + TreeStructureIcon, + WaveformIcon, +} from '@phosphor-icons/react' + +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarHeader, + SidebarRail, +} from '@genseki/react/v2' + +import { NavFooter } from './nav-footer' +import { NavHeader } from './nav-header' +import { NavMain } from './nav-main' + +// This is sample data. +const data = { + teams: [ + { + name: 'Acme Inc', + logo: StackIcon, + plan: 'Enterprise', + }, + { + name: 'Acme Corp.', + logo: WaveformIcon, + plan: 'Startup', + }, + { + name: 'Evil Corp.', + logo: TerminalWindowIcon, + plan: 'Free', + }, + ], + navMain: [ + { + title: 'Omni-Channel Management', + url: '#', + icon: TreeStructureIcon, + isActive: true, + items: [ + { + title: 'Bplus Sync', + url: '#', + }, + { + title: 'Product', + url: '#', + }, + { + title: 'Delivery Fee (by Weight)', + url: '#', + }, + { + title: 'Delivery Fee (by Carton)', + url: '#', + }, + { + title: 'Order', + url: '#', + }, + { + title: 'Data export', + url: '#', + }, + { + title: 'Packing', + url: '#', + }, + { + title: 'Inventory', + url: '#', + }, + { + title: 'Inventory transfer', + url: '#', + }, + ], + }, + { + title: 'Dashboard', + url: '#', + icon: ChartLineUpIcon, + isActive: true, + items: [ + { + title: 'User summary', + url: '#', + }, + { + title: 'Sales reports', + url: '#', + }, + { + title: 'Finance overview', + url: '#', + }, + { + title: 'Growth analytics', + url: '#', + }, + { + title: 'Performance metrics', + url: '#', + }, + { + title: 'Engagement insights', + url: '#', + }, + ], + }, + { + title: 'Storefront Management', + url: '#', + icon: StorefrontIcon, + isActive: true, + items: [ + { + title: 'Line shop', + url: '#', + }, + { + title: 'Shopee', + url: '#', + }, + { + title: 'Lazada', + url: '#', + }, + ], + }, + ], +} + +export function AppSidebar({ ...props }: React.ComponentProps) { + return ( + + + + + + + + + + + + + ) +} diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx new file mode 100644 index 00000000..5b7c33ec --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-footer.tsx @@ -0,0 +1,58 @@ +import { CaretUpDownIcon, SignOutIcon, UserIcon } from '@phosphor-icons/react' + +import { Typography } from '@genseki/react' +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, + SidebarMenu, + SidebarMenuItem, +} from '@genseki/react/v2' + +import { cn } from '../../../../../../../../packages/react/src/react/utils/cn' + +function NavFooter() { + return ( + + + + + + + + + + Signout + + + + + + ) +} + +export { NavFooter } diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx new file mode 100644 index 00000000..16bc966b --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-header.tsx @@ -0,0 +1,38 @@ +import { MoonStarsIcon } from '@phosphor-icons/react' + +import { Typography } from '@genseki/react' +import { SidebarMenu, SidebarMenuItem, SidebarTrigger } from '@genseki/react/v2' + +function NavHeader() { + return ( + + +
+
+
+
+
+ +
+ +
+ + BRV + + + 1.0.1 + +
+
+ + +
+ + + ) +} + +export { NavHeader } diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx new file mode 100644 index 00000000..72cf2058 --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/components/nav-main.tsx @@ -0,0 +1,99 @@ +'use client' + +import type { Icon } from '@phosphor-icons/react' +import { CaretRightIcon } from '@phosphor-icons/react' +import Link from 'next/link' + +import { Typography } from '@genseki/react' +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, + SidebarGroup, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarMenuSub, + SidebarMenuSubButton, + SidebarMenuSubItem, +} from '@genseki/react/v2' + +import { cn } from '../../../../../../../../packages/react/src/react/utils/cn' + +function NavMain({ + items, +}: { + items: { + title: string + url: string + icon?: Icon + isActive?: boolean + items?: { + title: string + url: string + }[] + }[] +}) { + return ( + + + {items.map((item) => ( + + + + + {item.icon && ( + + )} + + {item.title} + + + + + + + {item.items?.map((subItem) => ( + + + + + {subItem.title} + + + + + ))} + + + + + ))} + + + ) +} + +export { NavMain } diff --git a/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx b/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx new file mode 100644 index 00000000..23faafa7 --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/sidebar/page.tsx @@ -0,0 +1,56 @@ +'use client' + +import { + Breadcrumb, + BreadcrumbEllipsis, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, + BreadcrumbPage, + BreadcrumbSeparator, + SidebarInset, + SidebarProvider, + SidebarTrigger, +} from '@genseki/react/v2' + +import { AppSidebar } from './components/app-sidebar' + +function DummySidebarPage() { + return ( + + + +
+
+ + + + + + + Building Your Application + + + + + + Data Fetching + + + +
+
+
+
+
+
+
+
+
+
+ + + ) +} + +export default DummySidebarPage diff --git a/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx b/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx new file mode 100644 index 00000000..fed62785 --- /dev/null +++ b/examples/ui-playground/src/app/playground/shadcn/tooltip-section.tsx @@ -0,0 +1,277 @@ +import React from 'react' + +import { + InfoIcon, + MagnifyingGlassIcon, + PaperPlaneRightIcon, + QuestionMarkIcon, + WarningIcon, +} from '@phosphor-icons/react' + +import { Typography } from '@genseki/react' +import { Button } from '@genseki/react/v2' +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@genseki/react/v2' + +import { PlaygroundCard } from '~/src/components/card' + +// Basic Tooltip +function BasicTooltip() { + return ( +
+ + + + + +

This is a basic tooltip

+
+
+
+ ) +} + +// Tooltip with Icon +function TooltipWithIcon() { + return ( +
+ + + + + +

Information tooltip

+
+
+ + + + + + +

Warning tooltip

+
+
+ + + + + + +

Help tooltip

+
+
+
+ ) +} + +// Tooltip Positions +function TooltipPositions() { + return ( +
+
+ + + + + +

Tooltip on top

+
+
+
+ +
+ + + + + +

Tooltip on bottom

+
+
+
+ +
+ + + + + +

Tooltip on left

+
+
+
+ +
+ + + + + +

Tooltip on right

+
+
+
+
+ ) +} + +// Tooltip with Long Content +function TooltipLongContent() { + return ( +
+ + + + + + Send this email to the recipient. This action cannot be undone. + + + + + + + + +

Search through all your documents and files for specific content.

+
+
+
+ ) +} + +// Tooltip Alignment +function TooltipAlignment() { + return ( +
+
+ + + + + +

Aligned to start

+
+
+
+ +
+ + + + + +

Aligned to center

+
+
+
+ +
+ + + + + +

Aligned to end

+
+
+
+
+ ) +} + +// Disabled Tooltip +function DisabledTooltip() { + return ( +
+ + + + + +

This button is disabled

+
+
+ + +
+ ) +} + +export function TooltipSection() { + return ( + +
+ + + A simple tooltip that appears on hover. + +
+ +
+
+ + + + Tooltips can be used with icon buttons to provide additional context. + +
+ +
+
+ + + + Tooltips can be positioned on any side of the trigger element. + +
+ +
+
+ + + + Tooltips can contain longer text content with proper wrapping. + +
+ +
+
+ + + + Control the alignment of tooltips relative to their trigger element. + +
+ +
+
+ + + + Tooltips work with disabled elements to provide helpful information. + +
+ +
+
+
+
+ ) +} diff --git a/packages/react/package.json b/packages/react/package.json index 967c24df..ffdaa89e 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -52,11 +52,14 @@ "@intentui/icons": "^1.10.31", "@internationalized/date": "^3.8.2", "@phosphor-icons/react": "^2.1.8", + "@radix-ui/react-collapsible": "^1.1.12", "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.15", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.0", + "@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-use-controllable-state": "^1.2.2", "@react-aria/i18n": "^3.12.9", "@react-aria/visually-hidden": "^3.8.23", diff --git a/packages/react/src/react/components/primitives/breadcrumbs.tsx b/packages/react/src/react/components/primitives/breadcrumbs.tsx index 50b5a425..71c61b71 100644 --- a/packages/react/src/react/components/primitives/breadcrumbs.tsx +++ b/packages/react/src/react/components/primitives/breadcrumbs.tsx @@ -9,14 +9,29 @@ import { twMerge } from 'tailwind-merge' import { Link } from './link' import { composeTailwindRenderProps } from './primitive' +/** + * + * React Aria component + * + */ + +/** + * @deprecated + */ interface BreadcrumbsContextProps { separator?: 'chevron' | 'slash' | boolean } +/** + * @deprecated + */ const BreadcrumbsProvider = createContext({ separator: 'slash', }) +/** + * @deprecated + */ const Breadcrumbs = ({ className, ...props @@ -28,11 +43,17 @@ const Breadcrumbs = ({ ) } +/** + * @deprecated + */ interface BreadcrumbsItemProps extends BreadcrumbProps, BreadcrumbsContextProps { href?: string trailing?: React.ReactNode } +/** + * @deprecated + */ const BreadcrumbsItem = ({ href, separator = true, @@ -63,6 +84,9 @@ const BreadcrumbsItem = ({ ) } +/** + * @deprecated + */ const Separator = ({ separator = 'slash' }: { separator?: BreadcrumbsItemProps['separator'] }) => { return ( diff --git a/packages/react/src/react/components/primitives/button.tsx b/packages/react/src/react/components/primitives/button.tsx index 8d83521f..a5ff9aac 100644 --- a/packages/react/src/react/components/primitives/button.tsx +++ b/packages/react/src/react/components/primitives/button.tsx @@ -148,7 +148,7 @@ interface ButtonLinkProps /** * @deprecated */ -const AriaButtonLink = React.forwardRef(function ButtonLink( +const ButtonLink = React.forwardRef(function ButtonLink( { className, variant, size, isDisabled = false, isPending = false, children, ...props }, ref ) { @@ -184,4 +184,4 @@ const AriaButtonLink = React.forwardRef(func ) }) -export { AriaButtonLink, Button, type ButtonLinkProps, type ButtonProps } +export { Button, ButtonLink, type ButtonLinkProps, type ButtonProps } diff --git a/packages/react/src/react/components/primitives/sidebar.tsx b/packages/react/src/react/components/primitives/sidebar.tsx index a2b2713f..8073d707 100644 --- a/packages/react/src/react/components/primitives/sidebar.tsx +++ b/packages/react/src/react/components/primitives/sidebar.tsx @@ -34,9 +34,17 @@ import { Tooltip, TooltipContent } from './tooltip' import { BaseIcon } from '../../components/primitives/base-icon' import { useMediaQuery } from '../../hooks/use-media-query' - +/** + * @deprecated + */ const SIDEBAR_COOKIE_NAME = 'sidebar-state' +/** + * @deprecated + */ const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 +/** + * @deprecated + */ type SidebarContextProps = { state: 'expanded' | 'collapsed' open: boolean @@ -47,8 +55,14 @@ type SidebarContextProps = { toggleSidebar: () => void } +/** + * @deprecated + */ const SidebarContext = createContext(null) +/** + * @deprecated + */ const useSidebar = () => { const context = use(SidebarContext) if (!context) { @@ -58,6 +72,9 @@ const useSidebar = () => { return context } +/** + * @deprecated + */ interface SidebarProviderProps extends React.ComponentProps<'div'> { defaultOpen?: boolean isOpen?: boolean @@ -65,6 +82,9 @@ interface SidebarProviderProps extends React.ComponentProps<'div'> { onOpenChange?: (open: boolean) => void } +/** + * @deprecated + */ const SidebarProvider = ({ defaultOpen = true, isOpen: openProp, @@ -149,6 +169,9 @@ const SidebarProvider = ({ ) } +/** + * @deprecated + */ const gap = tv({ base: [ 'w-(--sidebar-width) group-data-[sidebar-collapsible=hidden]/sidebar-container:w-0', @@ -167,6 +190,9 @@ const gap = tv({ }, }) +/** + * @deprecated + */ const sidebar = tv({ base: [ 'fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) not-has-data-sidebar-footer:pb-2 transition-[left,right,width] duration-200 ease-linear md:flex', @@ -198,6 +224,9 @@ const sidebar = tv({ }, }) +/** + * @deprecated + */ interface SidebarProps extends React.ComponentProps<'div'> { intent?: 'default' | 'float' | 'inset' | 'fleet' collapsible?: 'hidden' | 'dock' | 'none' @@ -205,6 +234,9 @@ interface SidebarProps extends React.ComponentProps<'div'> { closeButton?: boolean } +/** + * @deprecated + */ const Sidebar = ({ closeButton = true, collapsible = 'hidden', @@ -281,6 +313,9 @@ const Sidebar = ({ ) } +/** + * @deprecated + */ const header = tv({ base: 'mb-2 flex flex-col **:data-[slot=sidebar-label-mask]:hidden', variants: { @@ -291,6 +326,9 @@ const header = tv({ }, }) +/** + * @deprecated + */ const SidebarHeader = ({ className, ref, ...props }: React.ComponentProps<'div'>) => { const { state } = use(SidebarContext)! return ( @@ -302,7 +340,9 @@ const SidebarHeader = ({ className, ref, ...props }: React.ComponentProps<'div'> /> ) } - +/** + * @deprecated + */ const footer = tv({ base: [ 'mt-auto flex flex-col p-2', @@ -331,7 +371,9 @@ const footer = tv({ }, }, }) - +/** + * @deprecated + */ const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) => { const { state, isMobile } = useSidebar() const collapsed = state === 'collapsed' && !isMobile @@ -348,7 +390,9 @@ const SidebarFooter = ({ className, ...props }: React.ComponentProps<'div'>) => /> ) } - +/** + * @deprecated + */ const SidebarContent = ({ className, ...props }: React.ComponentProps<'div'>) => { const { state } = useSidebar() return ( @@ -363,7 +407,9 @@ const SidebarContent = ({ className, ...props }: React.ComponentProps<'div'>) => /> ) } - +/** + * @deprecated + */ const SidebarSectionGroup = ({ className, ...props }: React.ComponentProps<'section'>) => { const { state, isMobile } = useSidebar() const collapsed = state === 'collapsed' && !isMobile @@ -380,9 +426,15 @@ const SidebarSectionGroup = ({ className, ...props }: React.ComponentProps<'sect ) } +/** + * @deprecated + */ interface SidebarSectionProps extends React.ComponentProps<'div'> { label?: string } +/** + * @deprecated + */ const SidebarSection = ({ className, ...props }: SidebarSectionProps) => { const { state } = useSidebar() return ( @@ -405,6 +457,9 @@ const SidebarSection = ({ className, ...props }: SidebarSectionProps) => { ) } +/** + * @deprecated + */ const sidebarItemStyles = tv({ base: [ 'group/sidebar-item relative col-span-full cursor-pointer overflow-hidden text-sidebar-fg/70 focus-visible:outline-hidden sm:text-sm', @@ -440,6 +495,9 @@ const sidebarItemStyles = tv({ ], }) +/** + * @deprecated + */ interface SidebarItemProps extends Omit, 'children'> { ghost?: boolean isCurrent?: boolean @@ -452,6 +510,9 @@ interface SidebarItemProps extends Omit, 'chil badge?: string | number | undefined } +/** + * @deprecated + */ const SidebarItem = ({ isCurrent, tooltip, @@ -523,6 +584,9 @@ const SidebarItem = ({ ) } +/** + * @deprecated + */ const sidebarLink = tv({ base: 'col-span-full items-center focus:outline-hidden', variants: { @@ -534,8 +598,14 @@ const sidebarLink = tv({ }, }) +/** + * @deprecated + */ interface SidebarLinkProps extends LinkProps {} +/** + * @deprecated + */ const SidebarLink = React.forwardRef( ({ className, ...props }, ref) => { const { state, isMobile } = useSidebar() @@ -556,6 +626,9 @@ const SidebarLink = React.forwardRef( } ) +/** + * @deprecated + */ const SidebarInset = ({ className, ref, ...props }: React.ComponentProps<'main'>) => { return (
) } +/** + * @deprecated + */ interface SidebarDisclosureGroupProps extends DisclosureGroupProps {} + +/** + * @deprecated + */ const SidebarDisclosureGroup = ({ allowsMultipleExpanded = true, className, @@ -587,8 +667,14 @@ const SidebarDisclosureGroup = ({ ) } +/** + * @deprecated + */ interface SidebarDisclosureProps extends DisclosureProps {} +/** + * @deprecated + */ const SidebarDisclosure = React.forwardRef>( ({ className, ...props }, ref) => { const { state } = useSidebar() @@ -606,6 +692,9 @@ const SidebarDisclosure = React.forwardRef( ({ className, onClick, ...props }, ref) => { const { state, isMobile, toggleSidebar } = useSidebar() @@ -670,6 +765,9 @@ const SidebarDisclosureTrigger = React.forwardRef) => { return ( { return ( { ) } +/** + * @deprecated + */ const SidebarTrigger = ({ onPress, children, @@ -724,6 +828,9 @@ const SidebarTrigger = ({ ) } +/** + * @deprecated + */ const SidebarRail = ({ className, ref, ...props }: React.ComponentProps<'button'>) => { const { toggleSidebar } = useSidebar() @@ -748,8 +855,14 @@ const SidebarRail = ({ className, ref, ...props }: React.ComponentProps<'button' ) } +/** + * @deprecated + */ type SidebarLabelProps = React.ComponentProps +/** + * @deprecated + */ const SidebarLabel = ({ className, ref, ...props }: SidebarLabelProps) => { const { state, isMobile } = useSidebar() const collapsed = state === 'collapsed' && !isMobile @@ -772,6 +885,9 @@ const SidebarLabel = ({ className, ref, ...props }: SidebarLabelProps) => { return null } +/** + * @deprecated + */ const nav = tv({ base: [ 'isolate flex h-[3.2rem] items-center justify-between gap-x-2 px-4 text-navbar-fg sm:justify-start md:w-full', @@ -784,10 +900,16 @@ const nav = tv({ }, }) +/** + * @deprecated + */ interface SidebarNavProps extends React.ComponentProps<'nav'> { isSticky?: boolean } +/** + * @deprecated + */ const SidebarNav = ({ isSticky = false, className, ...props }: SidebarNavProps) => { return