From f923c3a428df6d46be499f3a335c3ac423637c11 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Thu, 13 Mar 2025 13:21:36 -0600 Subject: [PATCH] sortable sidebar collapse --- .../features/sidebars/SidebarPrimary.tsx | 4 ++++ web/src/components/ui/sidebar/Sidebar.tsx | 19 +++++++++---------- .../ui/sidebar/SidebarCollapsible.stories.tsx | 7 +++++-- .../ui/sidebar/SidebarCollapsible.tsx | 9 +++++++-- web/src/components/ui/sidebar/interfaces.ts | 1 + 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/web/src/components/features/sidebars/SidebarPrimary.tsx b/web/src/components/features/sidebars/SidebarPrimary.tsx index 47166e7dc..4c66a8c8b 100644 --- a/web/src/components/features/sidebars/SidebarPrimary.tsx +++ b/web/src/components/features/sidebars/SidebarPrimary.tsx @@ -209,6 +209,10 @@ GlobalModals.displayName = 'GlobalModals'; const favoritesDropdown = (favorites: BusterUserFavorite[]): ISidebarGroup => { return { label: 'Favorites', + isSortable: true, + onItemsReorder: (itemIds) => { + console.warn('onItemsReorder', itemIds); + }, items: favorites.map((favorite) => { const Icon = assetTypeToIcon(favorite.asset_type); const route = assetTypeToRoute(favorite.asset_type, favorite.id); diff --git a/web/src/components/ui/sidebar/Sidebar.tsx b/web/src/components/ui/sidebar/Sidebar.tsx index 6bbb8b028..ed5b1da82 100644 --- a/web/src/components/ui/sidebar/Sidebar.tsx +++ b/web/src/components/ui/sidebar/Sidebar.tsx @@ -2,21 +2,21 @@ import React from 'react'; import { ISidebarGroup, ISidebarList, SidebarProps } from './interfaces'; import { SidebarCollapsible } from './SidebarCollapsible'; import { SidebarItem } from './SidebarItem'; +import { useMemoizedFn } from '@/hooks'; export const Sidebar: React.FC = React.memo( - ({ header, content, footer, activeItem, isSortable = false }) => { + ({ header, content, footer, activeItem }) => { + const onItemsReorder = useMemoizedFn((ids: string[], contentIndex: number) => { + console.log('onItemsReorder', ids); + }); + return (
{header}
{content.map((item, index) => ( - + ))}
@@ -31,10 +31,9 @@ Sidebar.displayName = 'Sidebar'; const ContentSelector: React.FC<{ content: SidebarProps['content'][number]; activeItem: SidebarProps['activeItem']; - isSortable: SidebarProps['isSortable']; -}> = React.memo(({ content, activeItem, isSortable }) => { +}> = React.memo(({ content, activeItem }) => { if (isSidebarGroup(content)) { - return ; + return ; } return ; diff --git a/web/src/components/ui/sidebar/SidebarCollapsible.stories.tsx b/web/src/components/ui/sidebar/SidebarCollapsible.stories.tsx index bb5d31271..ef067f60a 100644 --- a/web/src/components/ui/sidebar/SidebarCollapsible.stories.tsx +++ b/web/src/components/ui/sidebar/SidebarCollapsible.stories.tsx @@ -3,6 +3,7 @@ import { SidebarCollapsible } from './SidebarCollapsible'; import { HouseModern, MapSettings, User } from '../icons/NucleoIconOutlined'; import { BusterRoutes } from '../../../routes'; import React from 'react'; +import { fn } from '@storybook/test'; const meta: Meta = { title: 'UI/Sidebar/SidebarCollapsible', @@ -50,7 +51,9 @@ export const Default: Story = { export const Sortable: Story = { args: { - ...Default.args, - isSortable: true + label: 'Sortable', + isSortable: true, + items: Default.args!.items!, + onItemsReorder: fn() } }; diff --git a/web/src/components/ui/sidebar/SidebarCollapsible.tsx b/web/src/components/ui/sidebar/SidebarCollapsible.tsx index 73580f6a6..cb9221c67 100644 --- a/web/src/components/ui/sidebar/SidebarCollapsible.tsx +++ b/web/src/components/ui/sidebar/SidebarCollapsible.tsx @@ -100,12 +100,15 @@ const SortableSidebarItem: React.FC = React.memo(({ it SortableSidebarItem.displayName = 'SortableSidebarItem'; -export const SidebarCollapsible: React.FC = React.memo( +export const SidebarCollapsible: React.FC< + ISidebarGroup & { activeItem?: string; onItemsReorder?: (ids: string[]) => void } +> = React.memo( ({ label, items, isSortable = false, activeItem, + onItemsReorder, variant = 'collapsible', icon, defaultOpen = true @@ -133,7 +136,9 @@ export const SidebarCollapsible: React.FC { const oldIndex = items.findIndex((item) => item.id === active.id); const newIndex = items.findIndex((item) => item.id === over?.id); - return arrayMove(items, oldIndex, newIndex); + const moveddArray = arrayMove(items, oldIndex, newIndex); + onItemsReorder?.(moveddArray.map((item) => item.id)); + return moveddArray; }); } }); diff --git a/web/src/components/ui/sidebar/interfaces.ts b/web/src/components/ui/sidebar/interfaces.ts index 1935e81b3..a09a177b8 100644 --- a/web/src/components/ui/sidebar/interfaces.ts +++ b/web/src/components/ui/sidebar/interfaces.ts @@ -18,6 +18,7 @@ export interface ISidebarGroup { variant?: 'collapsible' | 'icon'; //default is collapsible defaultOpen?: boolean; //will default to true isSortable?: boolean; + onItemsReorder?: (ids: string[]) => void; } export interface ISidebarList {