diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 9a4511ec10..42291b47fb 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -32,6 +32,7 @@
"deleteBoardAndImages": "Delete Board and Images",
"deleteBoardOnly": "Delete Board Only",
"deletedBoardsCannotbeRestored": "Deleted boards cannot be restored",
+ "hideBoards": "Hide Boards",
"loading": "Loading...",
"menuItemAutoAdd": "Auto-add to this Board",
"move": "Move",
@@ -47,6 +48,7 @@
"topMessage": "This board contains images used in the following features:",
"unarchiveBoard": "Unarchive Board",
"uncategorized": "Uncategorized",
+ "viewBoards": "View Boards",
"downloadBoard": "Download Board",
"imagesWithCount_one": "{{count}} image",
"imagesWithCount_other": "{{count}} images",
diff --git a/invokeai/frontend/web/src/features/gallery/components/Gallery.tsx b/invokeai/frontend/web/src/features/gallery/components/Gallery.tsx
index f538832b70..7a320099ee 100644
--- a/invokeai/frontend/web/src/features/gallery/components/Gallery.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/Gallery.tsx
@@ -1,10 +1,11 @@
import type { ChakraProps } from '@invoke-ai/ui-library';
-import { Box, Collapse, Flex, IconButton, Spacer, Tab, TabList, Tabs, useDisclosure } from '@invoke-ai/ui-library';
+import { Box, Collapse, Flex, IconButton, Tab, TabList, Tabs, Text, useDisclosure } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { galleryViewChanged, searchTermChanged } from 'features/gallery/store/gallerySlice';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { MdSearch, MdSearchOff } from 'react-icons/md';
+import { useBoardName } from 'services/api/hooks/useBoardName';
import { COLLAPSE_STYLES } from './ImageGalleryContent';
import GalleryImageGrid from './ImageGrid/GalleryImageGrid';
@@ -47,17 +48,26 @@ export const Gallery = () => {
}
}, [searchTerm, dispatch, searchDisclosure]);
+ const selectedBoardId = useAppSelector((s) => s.gallery.selectedBoardId);
+ const boardName = useBoardName(selectedBoardId);
+
return (
-
-
-
- {t('parameters.images')}
-
-
- {t('gallery.assets')}
-
-
+
+
+ {boardName}
+
+
+
+
+
+ {t('parameters.images')}
+
+
+ {t('gallery.assets')}
+
+
+
{
variant="link"
/>
-
-
+
+
+
diff --git a/invokeai/frontend/web/src/features/gallery/components/GalleryHeader.tsx b/invokeai/frontend/web/src/features/gallery/components/GalleryHeader.tsx
index 69c2c8fe35..a7f5d3d891 100644
--- a/invokeai/frontend/web/src/features/gallery/components/GalleryHeader.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/GalleryHeader.tsx
@@ -3,13 +3,7 @@ import { useStore } from '@nanostores/react';
import { $projectName, $projectUrl } from 'app/store/nanostores/projectId';
import { memo } from 'react';
-import GalleryBoardName from './GalleryBoardName';
-
-type Props = {
- onClickBoardName: () => void;
-};
-
-export const GalleryHeader = memo((props: Props) => {
+export const GalleryHeader = memo(() => {
const projectName = useStore($projectName);
const projectUrl = useStore($projectUrl);
@@ -19,16 +13,11 @@ export const GalleryHeader = memo((props: Props) => {
{projectName}
-
);
}
- return (
-
-
-
- );
+ return <>>;
});
GalleryHeader.displayName = 'GalleryHeader';
diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
index 577e5b6f87..be87ffb918 100644
--- a/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/ImageGalleryContent.tsx
@@ -1,13 +1,14 @@
-import { Box, Collapse, Divider, Flex, IconButton, useDisclosure } from '@invoke-ai/ui-library';
+import { Button, Collapse, Divider, Flex, IconButton, useDisclosure } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { GalleryHeader } from 'features/gallery/components/GalleryHeader';
import { boardSearchTextChanged } from 'features/gallery/store/gallerySlice';
import ResizeHandle from 'features/ui/components/tabs/ResizeHandle';
import { usePanel, type UsePanelOptions } from 'features/ui/hooks/usePanel';
import type { CSSProperties } from 'react';
-import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
+import { memo, useCallback, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { MdSearch, MdSearchOff } from 'react-icons/md';
+import { PiCaretDownBold, PiCaretUpBold } from 'react-icons/pi';
import type { ImperativePanelGroupHandle } from 'react-resizable-panels';
import { Panel, PanelGroup } from 'react-resizable-panels';
@@ -41,36 +42,50 @@ const ImageGalleryContent = () => {
const handleClickBoardSearch = useCallback(() => {
if (boardSearchText.length) {
dispatch(boardSearchTextChanged(''));
- boardSearchDisclosure.onToggle();
- } else {
- boardSearchDisclosure.onToggle();
}
+ boardSearchDisclosure.onToggle();
}, [boardSearchText, dispatch, boardSearchDisclosure]);
- useEffect(() => {
- if (boardSearchDisclosure.isOpen) {
- boardsListPanel.expand();
+ const handleToggleBoardPanel = useCallback(() => {
+ if (boardSearchText.length) {
+ dispatch(boardSearchTextChanged(''));
}
- }, [boardSearchDisclosure, boardsListPanel]);
+
+ boardsListPanel.toggle();
+ }, [boardSearchText, dispatch, boardsListPanel]);
return (
-
-
-
-
- : }
- variant="link"
- />
-
+
+
+
+ : }
+ >
+ {boardsListPanel.isCollapsed ? t('boards.viewBoards') : t('boards.hideBoards')}
+
+
+
+
+ : }
+ variant="link"
+ />
+
+
+