diff --git a/src/renderer/components/ActivityBar/ActivityBar.tsx b/src/renderer/components/ActivityBar/ActivityBar.tsx index 4effda6..425bc6e 100644 --- a/src/renderer/components/ActivityBar/ActivityBar.tsx +++ b/src/renderer/components/ActivityBar/ActivityBar.tsx @@ -66,8 +66,8 @@ export const ActivityBar: React.FC = () => { // Check if settings view is active (either tab or sidebar) const isSettingsActive = (activeView === 'settings' && sidebarVisible) || isSettingsTabActive; - // Check if tags tab is currently active - const isTagsTabActive = tabs.some(t => t.type === 'tags' && t.id === activeTabId); + // Check if tags sidebar is active + const isTagsActive = activeView === 'tags' && sidebarVisible; // Check if chat sidebar is active (activeView === 'chat' and sidebar is visible) const isChatActive = activeView === 'chat' && sidebarVisible; @@ -108,8 +108,16 @@ export const ActivityBar: React.FC = () => { }; const handleTagsClick = () => { - // Open tags as a dedicated (non-transient) tab - openTab({ type: 'tags', id: 'tags', isTransient: false }); + // Toggle sidebar if tags is already active, otherwise switch to tags + if (activeView === 'tags' && sidebarVisible) { + toggleSidebar(); + } else { + openTab({ type: 'tags', id: 'tags', isTransient: false }); + setActiveView('tags'); + if (!sidebarVisible) { + toggleSidebar(); + } + } }; const handleImportClick = () => { @@ -148,9 +156,9 @@ export const ActivityBar: React.FC = () => { diff --git a/src/renderer/components/Sidebar/Sidebar.tsx b/src/renderer/components/Sidebar/Sidebar.tsx index efec9cc..1b48ce0 100644 --- a/src/renderer/components/Sidebar/Sidebar.tsx +++ b/src/renderer/components/Sidebar/Sidebar.tsx @@ -1223,11 +1223,19 @@ import { scrollToTagsSection, TagsCategory } from '../TagsView'; const TagsNav: React.FC = () => { const { t } = useI18n(); + const { tabs, activeTabId, openTab } = useAppStore(); const [activeSection, setActiveSection] = useState(null); + const isTagsTabActive = tabs.some(t => t.type === 'tags' && t.id === activeTabId); + const handleNavClick = (category: TagsCategory) => { + if (!isTagsTabActive) { + openTab({ type: 'tags', id: 'tags', isTransient: false }); + } setActiveSection(category); - scrollToTagsSection(category); + setTimeout(() => { + scrollToTagsSection(category); + }, isTagsTabActive ? 0 : 100); }; return ( diff --git a/tests/renderer/components/ActivityBar.test.tsx b/tests/renderer/components/ActivityBar.test.tsx new file mode 100644 index 0000000..b70ee9a --- /dev/null +++ b/tests/renderer/components/ActivityBar.test.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { beforeEach, describe, expect, it } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; +import { ActivityBar } from '../../../src/renderer/components/ActivityBar/ActivityBar'; +import { I18nProvider } from '../../../src/renderer/i18n'; +import { useAppStore } from '../../../src/renderer/store'; + +describe('ActivityBar tags behavior', () => { + beforeEach(() => { + useAppStore.setState({ + activeView: 'posts', + sidebarVisible: true, + tabs: [], + activeTabId: null, + }); + }); + + it('opens tags tab and switches sidebar to tags view when clicking Tags', () => { + render( + + + + ); + + fireEvent.click(screen.getByTitle('Tags (click again to toggle sidebar)')); + + const state = useAppStore.getState(); + expect(state.activeView).toBe('tags'); + expect(state.sidebarVisible).toBe(true); + expect(state.activeTabId).toBe('tags'); + expect(state.tabs).toContainEqual({ type: 'tags', id: 'tags', isTransient: false }); + }); + + it('toggles tags sidebar off when tags view is already active', () => { + useAppStore.setState({ + activeView: 'tags', + sidebarVisible: true, + tabs: [{ type: 'tags', id: 'tags', isTransient: false }], + activeTabId: 'tags', + }); + + render( + + + + ); + + fireEvent.click(screen.getByTitle('Tags (click again to toggle sidebar)')); + + expect(useAppStore.getState().sidebarVisible).toBe(false); + }); + + it('shows tags sidebar when hidden and tags view is active', () => { + useAppStore.setState({ + activeView: 'tags', + sidebarVisible: false, + tabs: [{ type: 'tags', id: 'tags', isTransient: false }], + activeTabId: 'tags', + }); + + render( + + + + ); + + fireEvent.click(screen.getByTitle('Tags (click again to toggle sidebar)')); + + expect(useAppStore.getState().sidebarVisible).toBe(true); + }); + + it('does not mark tags icon active when tags editor tab is open but another sidebar is active', () => { + useAppStore.setState({ + activeView: 'posts', + sidebarVisible: true, + tabs: [{ type: 'tags', id: 'tags', isTransient: false }], + activeTabId: 'tags', + }); + + render( + + + + ); + + expect(screen.getByTitle('Tags (click again to toggle sidebar)')).not.toHaveClass('active'); + }); + + it('uses the shared toggle hint in the tags activity button title', () => { + render( + + + + ); + + expect(screen.getByTitle('Tags (click again to toggle sidebar)')).toBeInTheDocument(); + }); +});