fix: cleanup of tag icon in action bar

This commit is contained in:
2026-02-21 16:07:43 +01:00
parent cdf064b6a1
commit 69007ef393
3 changed files with 121 additions and 7 deletions

View File

@@ -66,8 +66,8 @@ export const ActivityBar: React.FC = () => {
// Check if settings view is active (either tab or sidebar) // Check if settings view is active (either tab or sidebar)
const isSettingsActive = (activeView === 'settings' && sidebarVisible) || isSettingsTabActive; const isSettingsActive = (activeView === 'settings' && sidebarVisible) || isSettingsTabActive;
// Check if tags tab is currently active // Check if tags sidebar is active
const isTagsTabActive = tabs.some(t => t.type === 'tags' && t.id === activeTabId); const isTagsActive = activeView === 'tags' && sidebarVisible;
// Check if chat sidebar is active (activeView === 'chat' and sidebar is visible) // Check if chat sidebar is active (activeView === 'chat' and sidebar is visible)
const isChatActive = activeView === 'chat' && sidebarVisible; const isChatActive = activeView === 'chat' && sidebarVisible;
@@ -108,8 +108,16 @@ export const ActivityBar: React.FC = () => {
}; };
const handleTagsClick = () => { const handleTagsClick = () => {
// Open tags as a dedicated (non-transient) tab // Toggle sidebar if tags is already active, otherwise switch to tags
openTab({ type: 'tags', id: 'tags', isTransient: false }); if (activeView === 'tags' && sidebarVisible) {
toggleSidebar();
} else {
openTab({ type: 'tags', id: 'tags', isTransient: false });
setActiveView('tags');
if (!sidebarVisible) {
toggleSidebar();
}
}
}; };
const handleImportClick = () => { const handleImportClick = () => {
@@ -148,9 +156,9 @@ export const ActivityBar: React.FC = () => {
<MediaIcon /> <MediaIcon />
</button> </button>
<button <button
className={`activity-bar-item ${isTagsTabActive ? 'active' : ''}`} className={`activity-bar-item ${isTagsActive ? 'active' : ''}`}
onClick={handleTagsClick} onClick={handleTagsClick}
title={t('activity.tags')} title={`${t('activity.tags')} ${t('activity.toggleHint')}`}
> >
<TagsIcon /> <TagsIcon />
</button> </button>

View File

@@ -1223,11 +1223,19 @@ import { scrollToTagsSection, TagsCategory } from '../TagsView';
const TagsNav: React.FC = () => { const TagsNav: React.FC = () => {
const { t } = useI18n(); const { t } = useI18n();
const { tabs, activeTabId, openTab } = useAppStore();
const [activeSection, setActiveSection] = useState<TagsCategory | null>(null); const [activeSection, setActiveSection] = useState<TagsCategory | null>(null);
const isTagsTabActive = tabs.some(t => t.type === 'tags' && t.id === activeTabId);
const handleNavClick = (category: TagsCategory) => { const handleNavClick = (category: TagsCategory) => {
if (!isTagsTabActive) {
openTab({ type: 'tags', id: 'tags', isTransient: false });
}
setActiveSection(category); setActiveSection(category);
scrollToTagsSection(category); setTimeout(() => {
scrollToTagsSection(category);
}, isTagsTabActive ? 0 : 100);
}; };
return ( return (

View File

@@ -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(
<I18nProvider>
<ActivityBar />
</I18nProvider>
);
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(
<I18nProvider>
<ActivityBar />
</I18nProvider>
);
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(
<I18nProvider>
<ActivityBar />
</I18nProvider>
);
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(
<I18nProvider>
<ActivityBar />
</I18nProvider>
);
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(
<I18nProvider>
<ActivityBar />
</I18nProvider>
);
expect(screen.getByTitle('Tags (click again to toggle sidebar)')).toBeInTheDocument();
});
});