feat: Tidying up kanban board#1900
Conversation
…sh header bar and Show Archived button Changes made: - Removed refresh header bar from KanbanBoard component - Removed Show Archived toggle button from Done column - Removed unused imports (useViewState, RefreshCw icon, Tooltip, archiveTasks) - Updated KanbanBoardProps interface to remove onRefresh and isRefreshing props - Updated DroppableColumnProps interface to remove archivedCount, showArchived, and onToggleArchived props - Removed archived-related state and logic (archivedCount, filteredTasks, showArchived) - Updated tasksByStatus to use tasks directly instead of filteredTasks - Cleaned up App.tsx by removing unused isRefreshingTasks state and handleRefreshTasks function 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…h and Show Archived buttons with tooltips, add tooltip to + button
…e settings icon from active tab
…nglish and French - Added refreshTasks and addNewProject keys to en/common.json - Added refreshTasks and addNewProject keys to fr/common.json - Tooltips will display for Refresh and Add Project buttons in tab bar 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
…to ProjectTabBar - Added showArchived state management to App component - Created handleRefreshTasks handler to reload tasks from store - Created handleToggleArchived handler to toggle archived visibility - Added archivedCount calculation based on tasks with archivedAt metadata - Updated ProjectTabBarWithContext interface to include new props - Passed all new props (onRefresh, isRefreshing, showArchived, onToggleArchived, archivedCount) to ProjectTabBar This completes the UI reorganization by lifting the refresh and archived state management from KanbanBoard to the parent component and passing it through to the ProjectTabBar where the controls now reside.
Fixes: - Show Archived button now only appears when archivedCount > 0 - Changed icons from Eye/EyeOff to Archive - Added badge with count on button (not in tooltip) - Added active state styling (primary background when enabled) - Added aria-pressed attribute for accessibility - Fixed + button tooltip to use "Add new project" translation Verified: - All QA issues from QA_FIX_REQUEST.md addressed - Implementation now matches spec requirements exactly QA Fix Session: 1
Fixes: - Show Archived button functionality: Added showArchived prop to KanbanBoard and filter archived tasks - + icon positioning: Moved buttons into same flex container as tabs for proper alignment Verified: - Show Archived button now properly filters archived tasks - Buttons (Refresh, Show Archived, +) appear directly to the right of tabs - Added flex-shrink-0 to prevent button shrinking QA Fix Session: 1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Reorganize ProjectTabBar layout so that Add Project button stays next to the project tabs while Refresh Tasks and Show Archived buttons are anchored to the right side of the bar. Also fixes refresh tooltip to use correct translation key and adds missing archiveTasks import. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Follows established codebase pattern for cross-namespace translation access. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove redundant undefined check since archivedCount defaults to 0. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…board Resolved conflicts by: - Keeping all new develop features (selection, collapse, resize, lock columns, bulk actions) - Preserving our feature: Kanban controls moved to ProjectTabBar - Removed archived-related props from Done column (moved to tab bar) - Kept Expand All button, removed duplicate Refresh button from Kanban header - Used isRefreshingTasks state for refresh spinner - Updated to use filteredTasks for archive filtering - Added Tooltip imports to KanbanBoard.tsx Note: TypeScript errors for rehype-* modules will be resolved when dependencies are installed in the main repository. These come from develop branch changes. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Import Tooltip, TooltipContent, TooltipTrigger for column header buttons - Add .secretsignore to allow test files and checksums in commits Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Summary of ChangesHello @fireapache, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly tidies up the Kanban board interface by reorganizing key UI elements. The 'Add Project' button is now more intuitively placed, and controls for refreshing tasks and viewing archived items have been elevated to the project tab bar. This change aims to streamline the user experience, making the Kanban board itself less cluttered while providing essential actions in a more accessible location. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
📝 WalkthroughWalkthroughThis PR refactors component state management by moving archive visibility to a shared ViewState context, removes per-component refresh UI from KanbanBoard, consolidates refresh and archive controls into ProjectTabBar, eliminates per-tab settings controls, and adds corresponding internationalization strings. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request effectively tidies up the Kanban board and project tab bar by relocating the 'add project', 'refresh', and 'show archived' controls. The changes improve UI layout and visibility as intended.
My review includes a few suggestions for improvement:
- Removing an unused variable in
App.tsx. - Optimizing a calculation by using
useMemofor better performance. - Cleaning up an unused prop in
SortableProjectTab.tsxfollowing the refactor.
These changes will help improve code clarity and performance. Overall, this is a good step forward for the UI.
apps/frontend/src/renderer/App.tsx
Outdated
| const setActiveProject = useProjectStore((state) => state.setActiveProject); | ||
| const reorderTabs = useProjectStore((state) => state.reorderTabs); | ||
| const tasks = useTaskStore((state) => state.tasks); | ||
| const isLoadingTasks = useTaskStore((state) => state.isLoading); |
apps/frontend/src/renderer/App.tsx
Outdated
| const archivedCount = tasks.filter( | ||
| (task) => task.metadata?.archivedAt | ||
| ).length; |
There was a problem hiding this comment.
To optimize performance, this calculation of archivedCount should be memoized using useMemo, similar to how it was implemented in KanbanBoard.tsx before this refactoring. This will prevent re-calculating on every render, which can be expensive if the tasks array is large. Please also remember to import useMemo from react.
| const archivedCount = tasks.filter( | |
| (task) => task.metadata?.archivedAt | |
| ).length; | |
| const archivedCount = useMemo(() => tasks.filter( | |
| (task) => task.metadata?.archivedAt | |
| ).length, [tasks]); |
| import { useSortable } from '@dnd-kit/sortable'; | ||
| import { CSS } from '@dnd-kit/utilities'; | ||
| import { useTranslation } from 'react-i18next'; | ||
| import { Settings2 } from 'lucide-react'; |
There was a problem hiding this comment.
Since the settings button and its usage via onSettingsClick have been removed from this component, the onSettingsClick prop is now unused. To improve code clarity, please remove the onSettingsClick prop from the SortableProjectTabProps interface (line 16) and from the component's destructuring (line 30). Also, remove it from the parent component ProjectTabBar.tsx where it's being passed to SortableProjectTab.
Fixes: - Remove unused isLoadingTasks variable from App.tsx - Memoize archivedCount calculation for performance optimization - Remove unused onSettingsClick prop from SortableProjectTab and ProjectTabBar - Remove unused AlertCircle and RefreshCw imports from KanbanBoard Verified: - TypeScript type checking passes - All unused code removed per PR AndyMik90#1900 review comments QA Fix Session: 0 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
fireapache
left a comment
There was a problem hiding this comment.
🤖 Auto Claude PR Review
Merge Verdict: 🔴 BLOCKED
🔴 Blocked - 2 CI check(s) failing. Fix CI before merge.
Blocked: 2 CI check(s) failing. Fix CI before merge.
Risk Assessment
| Factor | Level | Notes |
|---|---|---|
| Complexity | Medium | Based on lines changed |
| Security Impact | None | Based on security findings |
| Scope Coherence | Good | Based on structural review |
🚨 Blocking Issues (Must Fix)
- CI Failed: CI Complete
- CI Failed: test-frontend (windows-latest)
Findings Summary
- High: 1 issue(s)
- Low: 2 issue(s)
Generated by Auto Claude PR Review
Findings (3 selected of 3 total)
🟠 [cb1add393993] [HIGH] Duplicate showArchived state breaks ViewStateContext cross-view sync
📁 apps/frontend/src/renderer/App.tsx:158
The PR introduces a new useState(false) for showArchived in App.tsx (line 158), but the codebase already has ViewStateContext (contexts/ViewStateContext.tsx) which provides this exact state via useViewState(). The ViewStateProvider is still rendered in App.tsx (line 851), and the Ideation component (ideation/Ideation.tsx:22) still reads showArchived from useViewState(). This means KanbanBoard now uses the local App.tsx state while Ideation uses the ViewStateContext state — they are no longer synced. The ViewStateContext JSDoc explicitly states it manages 'view state that needs to be shared across different project pages (kanban, ideation, etc.)'. The PR should either use ViewStateContext consistently (passing its values to ProjectTabBar) or update Ideation to also use the new approach. | The showArchived state was moved from ViewStateContext to App.tsx local state (useState(false) at line 158). However, the Ideation component (Ideation.tsx:22) still reads showArchived from ViewStateContext via useViewState() (comment says 'Get showArchived from shared context for cross-page sync'). Since the kanban's archived toggle now controls App.tsx's local state instead of the context, the ViewStateContext's showArchived is permanently stuck at false — nothing ever calls toggleShowArchived() or setShowArchived() on it anymore. This means: (1) If Ideation was supposed to react to kanban's archived toggle, it won't. (2) The ViewStateProvider wrapping the entire app (App.tsx:851) is now dead code for its only purpose (showArchived). Either remove the context and manage archived state per-view independently, or keep using the context so state stays synced.
Suggested fix:
Either (a) continue using ViewStateContext by consuming `useViewState()` in the component that passes props to ProjectTabBar, or (b) remove ViewStateContext usage from Ideation and pipe the App.tsx state down. Option (a) is preferred as it preserves the existing architectural pattern.
🔵 [2a8034dd862b] [LOW] Repetitive ternary pattern for conditional prop passing
📁 apps/frontend/src/renderer/App.tsx:881
Five consecutive props use the same activeView === 'kanban' ? value : undefined ternary pattern. This is verbose and error-prone if new kanban-only controls are added later.
Suggested fix:
Consider computing `const isKanban = activeView === 'kanban';` once and using spread: `{...(isKanban && { onRefresh: handleRefreshTasks, isRefreshing: isRefreshingTasks, showArchived, onToggleArchived: handleToggleArchived, archivedCount })}`
🔵 [4eae1bc52317] [LOW] [NEEDS REVIEW] Archive All button lost showArchived guard, may re-archive tasks
📁 apps/frontend/src/renderer/components/KanbanBoard.tsx:514
The old code had !showArchived as a condition for showing the Archive All button in the Done column (line 514). This guard was removed. When showArchived=true, the Done column includes already-archived tasks (via filteredTasks at line 682-687 which returns all tasks when showArchived is true). The handleArchiveAll at line 870 archives ALL tasksByStatus.done tasks without checking if they're already archived. This means clicking 'Archive All' when archived tasks are visible will redundantly re-archive already-archived tasks. While likely idempotent, it's unnecessary API calls and could confuse users seeing an 'Archive All' button when viewing archived content.
Suggested fix:
Either restore the `!showArchived` guard on the button visibility, or filter out already-archived tasks in handleArchiveAll: `const doneTaskIds = tasksByStatus.done.filter(t => !t.metadata?.archivedAt).map(t => t.id);`
This review was generated by Auto Claude.
Fixes:
- Use ViewStateContext instead of local showArchived state for cross-view sync
- Simplify repetitive ternary pattern using spread operator
- Add showArchived guard to Archive All button to prevent re-archiving
Details:
1. HIGH: Duplicate showArchived state breaks ViewStateContext cross-view sync
- Removed local showArchived state from App.tsx
- Updated ProjectTabBarWithContext to use useViewState() hook
- Updated KanbanBoard to use useViewState() instead of prop
- Removed unused showArchived/onToggleArchived/archivedCount from DroppableColumnProps
- Now KanbanBoard and Ideation share the same ViewStateContext state
2. LOW: Repetitive ternary pattern for conditional prop passing
- Computed isKanban once and created kanbanOnlyProps object
- Used spread operator {...kanbanOnlyProps} for cleaner code
3. LOW: Archive All button lost showArchived guard
- Added useViewState() hook in DroppableColumn
- Added !showArchived guard to Archive All button condition
- Prevents re-archiving already-archived tasks
Verified:
- TypeScript type checking passes
- All PR review issues resolved
PR Review: AndyMik90#1900
QA Fix Session: 1
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/frontend/src/renderer/App.tsx (1)
79-122: 🛠️ Refactor suggestion | 🟠 MajorMigrate
showArchivedstate from React context to a Zustand store.
ProjectTabBarWithContextreadsshowArchivedfromViewStateContext, a plain React context atapps/frontend/src/renderer/contexts/ViewStateContext.tsx. Per coding guidelines, all frontend state management must use Zustand stores insrc/renderer/stores/. SinceshowArchivedis cross-view shared state (used across Kanban, Ideation, and other views), it belongs in a domain store such asui-store.tsor within an existing domain store liketask-store.ts.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/frontend/src/renderer/App.tsx` around lines 79 - 122, Replace the React context usage in ProjectTabBarWithContext by reading and mutating the archived flag from the Zustand UI/domain store instead of useViewState: remove the useViewState() call and instead import and call the appropriate store hook (e.g., useUiStore or useTaskStore) to select showArchived and the toggle action (e.g., const { showArchived, toggleShowArchived } = useUiStore(s => ({ showArchived: s.showArchived, toggleShowArchived: s.toggleShowArchived }))). Keep the archivedCount computation using tasks unchanged, and pass the store-derived showArchived and toggleShowArchived into ProjectTabBar (props showArchived and onToggleArchived). Ensure you add the selector shape/name that matches the chosen store (create one if needed in the store file) so ProjectTabBarWithContext references the correct functions/fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/frontend/src/renderer/App.tsx`:
- Line 73: Replace the relative import for the ViewState context with the
project path alias: change the import of ViewStateProvider and useViewState in
App.tsx to use the "@/..." alias (referencing the same module that currently
exports ViewStateProvider and useViewState) so imports use the renderer path
alias per tsconfig instead of a relative path.
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx`:
- Around line 1393-1409: The Expand All button is only rendered when
collapsedColumnCount >= 3 so it’s hidden when 1–2 columns are collapsed; change
the conditional in the KanbanBoard JSX to use a lower threshold (e.g.,
collapsedColumnCount >= 1 or >= 2) so the Button (onClick={handleExpandAll},
label t('tasks:kanban.expandAll')) is shown earlier, and update the surrounding
comment string that currently says "appears when 3+ columns are collapsed" to
reflect the new threshold.
In `@apps/frontend/src/renderer/components/ProjectTabBar.tsx`:
- Line 40: Remove the unused 'tasks' namespace from the useTranslation call in
ProjectTabBar.tsx: update the useTranslation invocation (const { t } =
useTranslation(['common', 'tasks'])) to only request the 'common' namespace
since all t() usages are prefixed with 'common:' and 'tasks' is never
referenced; this will eliminate the unnecessary bundle import while leaving the
t binding and its existing calls unchanged.
- Around line 167-194: The toggle disappears when archivedCount === 0 but
showArchived may still be true; update the render condition in ProjectTabBar so
the Archived Button is shown if onToggleArchived is present and either
archivedCount > 0 or showArchived is true (i.e. replace the current conditional
with onToggleArchived && (archivedCount > 0 || showArchived)). Also ensure the
badge/number span renders only when archivedCount > 0 so it doesn't display "0"
when there are no archived items.
---
Outside diff comments:
In `@apps/frontend/src/renderer/App.tsx`:
- Around line 79-122: Replace the React context usage in
ProjectTabBarWithContext by reading and mutating the archived flag from the
Zustand UI/domain store instead of useViewState: remove the useViewState() call
and instead import and call the appropriate store hook (e.g., useUiStore or
useTaskStore) to select showArchived and the toggle action (e.g., const {
showArchived, toggleShowArchived } = useUiStore(s => ({ showArchived:
s.showArchived, toggleShowArchived: s.toggleShowArchived }))). Keep the
archivedCount computation using tasks unchanged, and pass the store-derived
showArchived and toggleShowArchived into ProjectTabBar (props showArchived and
onToggleArchived). Ensure you add the selector shape/name that matches the
chosen store (create one if needed in the store file) so
ProjectTabBarWithContext references the correct functions/fields.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json,!**/package-lock.json
📒 Files selected for processing (7)
.secretsignoreapps/frontend/src/renderer/App.tsxapps/frontend/src/renderer/components/KanbanBoard.tsxapps/frontend/src/renderer/components/ProjectTabBar.tsxapps/frontend/src/renderer/components/SortableProjectTab.tsxapps/frontend/src/shared/i18n/locales/en/common.jsonapps/frontend/src/shared/i18n/locales/fr/common.json
| import { ProjectTabBar } from './components/ProjectTabBar'; | ||
| import { AddProjectModal } from './components/AddProjectModal'; | ||
| import { ViewStateProvider } from './contexts/ViewStateContext'; | ||
| import { ViewStateProvider, useViewState } from './contexts/ViewStateContext'; |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Use the @/* path alias instead of a relative path.
Line 73 introduces a new relative import in the renderer. Per coding guidelines, all renderer imports should use the @/* path alias.
♻️ Proposed fix
-import { ViewStateProvider, useViewState } from './contexts/ViewStateContext';
+import { ViewStateProvider, useViewState } from '@/contexts/ViewStateContext';As per coding guidelines: "Use path aliases from tsconfig.json in frontend code: @/* for renderer".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { ViewStateProvider, useViewState } from './contexts/ViewStateContext'; | |
| import { ViewStateProvider, useViewState } from '@/contexts/ViewStateContext'; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/renderer/App.tsx` at line 73, Replace the relative import
for the ViewState context with the project path alias: change the import of
ViewStateProvider and useViewState in App.tsx to use the "@/..." alias
(referencing the same module that currently exports ViewStateProvider and
useViewState) so imports use the renderer path alias per tsconfig instead of a
relative path.
| {/* Kanban header with expand all button */} | ||
| {collapsedColumnCount >= 3 && ( | ||
| <div className="flex items-center justify-between px-6 pt-4 pb-2"> | ||
| <div className="flex items-center gap-2"> | ||
| {/* Expand All button - appears when 3+ columns are collapsed */} | ||
| {collapsedColumnCount >= 3 && ( | ||
| <Button | ||
| variant="outline" | ||
| size="sm" | ||
| onClick={handleExpandAll} | ||
| className="gap-2 text-muted-foreground hover:text-foreground" | ||
| > | ||
| <ChevronsRight className="h-4 w-4" /> | ||
| {t('tasks:kanban.expandAll')} | ||
| </Button> | ||
| )} | ||
| </div> | ||
| <div className="flex items-center gap-2"> | ||
| {onRefresh && ( | ||
| <Button | ||
| variant="ghost" | ||
| size="sm" | ||
| onClick={onRefresh} | ||
| disabled={isRefreshing} | ||
| className="gap-2 text-muted-foreground hover:text-foreground" | ||
| > | ||
| <RefreshCw className={cn("h-4 w-4", isRefreshing && "animate-spin")} /> | ||
| {isRefreshing ? t('common:buttons.refreshing') : t('tasks:refreshTasks')} | ||
| </Button> | ||
| )} | ||
| <Button | ||
| variant="outline" | ||
| size="sm" | ||
| onClick={handleExpandAll} | ||
| className="gap-2 text-muted-foreground hover:text-foreground" | ||
| > | ||
| <ChevronsRight className="h-4 w-4" /> | ||
| {t('tasks:kanban.expandAll')} | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
Minor UX gap: "Expand All" is hidden when fewer than 3 columns are collapsed.
With 1 or 2 columns collapsed, collapsedColumnCount >= 3 evaluates to false and the entire header (including the only available "Expand All" shortcut) is hidden. Users must expand each collapsed column individually via the per-column button. Consider lowering the threshold to >= 1 or >= 2 to surface the convenience button earlier.
💡 Suggested threshold adjustment
- {collapsedColumnCount >= 3 && (
+ {collapsedColumnCount >= 1 && (🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/renderer/components/KanbanBoard.tsx` around lines 1393 -
1409, The Expand All button is only rendered when collapsedColumnCount >= 3 so
it’s hidden when 1–2 columns are collapsed; change the conditional in the
KanbanBoard JSX to use a lower threshold (e.g., collapsedColumnCount >= 1 or >=
2) so the Button (onClick={handleExpandAll}, label t('tasks:kanban.expandAll'))
is shown earlier, and update the surrounding comment string that currently says
"appears when 3+ columns are collapsed" to reflect the new threshold.
| archivedCount = 0 | ||
| }: ProjectTabBarProps) { | ||
| const { t } = useTranslation('common'); | ||
| const { t } = useTranslation(['common', 'tasks']); |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Remove the unused 'tasks' namespace from useTranslation.
Every t() call in this file uses the 'common:' prefix. The 'tasks' namespace is never referenced and adds an unnecessary bundle import.
♻️ Proposed fix
- const { t } = useTranslation(['common', 'tasks']);
+ const { t } = useTranslation(['common']);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { t } = useTranslation(['common', 'tasks']); | |
| const { t } = useTranslation(['common']); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/renderer/components/ProjectTabBar.tsx` at line 40, Remove
the unused 'tasks' namespace from the useTranslation call in ProjectTabBar.tsx:
update the useTranslation invocation (const { t } = useTranslation(['common',
'tasks'])) to only request the 'common' namespace since all t() usages are
prefixed with 'common:' and 'tasks' is never referenced; this will eliminate the
unnecessary bundle import while leaving the t binding and its existing calls
unchanged.
| {/* Show Archived button */} | ||
| {onToggleArchived && archivedCount > 0 && ( | ||
| <Tooltip delayDuration={200}> | ||
| <TooltipTrigger asChild> | ||
| <Button | ||
| variant="ghost" | ||
| size="icon" | ||
| className={cn( | ||
| "h-8 w-8 relative flex-shrink-0", | ||
| showArchived | ||
| ? "text-primary bg-primary/10 hover:bg-primary/20" | ||
| : "hover:bg-muted-foreground/10 hover:text-muted-foreground" | ||
| )} | ||
| onClick={onToggleArchived} | ||
| aria-pressed={showArchived} | ||
| aria-label={t('common:accessibility.toggleShowArchivedAriaLabel')} | ||
| > | ||
| <Archive className="h-4 w-4" /> | ||
| <span className="absolute -top-1 -right-1 text-[10px] font-medium bg-muted rounded-full min-w-[14px] h-[14px] flex items-center justify-center"> | ||
| {archivedCount} | ||
| </span> | ||
| </Button> | ||
| </TooltipTrigger> | ||
| <TooltipContent side="bottom"> | ||
| <span>{showArchived ? t('common:projectTab.hideArchived') : t('common:projectTab.showArchived')}</span> | ||
| </TooltipContent> | ||
| </Tooltip> | ||
| )} |
There was a problem hiding this comment.
showArchived state persists invisibly when archivedCount drops to zero.
When showArchived is true (archived tasks are shown) but all archived tasks are then deleted or un-archived, archivedCount becomes 0, causing the toggle to disappear. The context state remains showArchived = true, but there is no visible control to reset it. If new tasks are later archived they will immediately be visible, which is the correct behavior — but the user has no affordance to opt out of archived mode while archivedCount === 0.
Consider either rendering the toggle regardless of archivedCount when showArchived is true, or resetting showArchived when archivedCount reaches zero.
💡 Option: always render when already active
- {onToggleArchived && archivedCount > 0 && (
+ {onToggleArchived && (archivedCount > 0 || showArchived) && (📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {/* Show Archived button */} | |
| {onToggleArchived && archivedCount > 0 && ( | |
| <Tooltip delayDuration={200}> | |
| <TooltipTrigger asChild> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className={cn( | |
| "h-8 w-8 relative flex-shrink-0", | |
| showArchived | |
| ? "text-primary bg-primary/10 hover:bg-primary/20" | |
| : "hover:bg-muted-foreground/10 hover:text-muted-foreground" | |
| )} | |
| onClick={onToggleArchived} | |
| aria-pressed={showArchived} | |
| aria-label={t('common:accessibility.toggleShowArchivedAriaLabel')} | |
| > | |
| <Archive className="h-4 w-4" /> | |
| <span className="absolute -top-1 -right-1 text-[10px] font-medium bg-muted rounded-full min-w-[14px] h-[14px] flex items-center justify-center"> | |
| {archivedCount} | |
| </span> | |
| </Button> | |
| </TooltipTrigger> | |
| <TooltipContent side="bottom"> | |
| <span>{showArchived ? t('common:projectTab.hideArchived') : t('common:projectTab.showArchived')}</span> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} | |
| {/* Show Archived button */} | |
| {onToggleArchived && (archivedCount > 0 || showArchived) && ( | |
| <Tooltip delayDuration={200}> | |
| <TooltipTrigger asChild> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className={cn( | |
| "h-8 w-8 relative flex-shrink-0", | |
| showArchived | |
| ? "text-primary bg-primary/10 hover:bg-primary/20" | |
| : "hover:bg-muted-foreground/10 hover:text-muted-foreground" | |
| )} | |
| onClick={onToggleArchived} | |
| aria-pressed={showArchived} | |
| aria-label={t('common:accessibility.toggleShowArchivedAriaLabel')} | |
| > | |
| <Archive className="h-4 w-4" /> | |
| <span className="absolute -top-1 -right-1 text-[10px] font-medium bg-muted rounded-full min-w-[14px] h-[14px] flex items-center justify-center"> | |
| {archivedCount} | |
| </span> | |
| </Button> | |
| </TooltipTrigger> | |
| <TooltipContent side="bottom"> | |
| <span>{showArchived ? t('common:projectTab.hideArchived') : t('common:projectTab.showArchived')}</span> | |
| </TooltipContent> | |
| </Tooltip> | |
| )} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/frontend/src/renderer/components/ProjectTabBar.tsx` around lines 167 -
194, The toggle disappears when archivedCount === 0 but showArchived may still
be true; update the render condition in ProjectTabBar so the Archived Button is
shown if onToggleArchived is present and either archivedCount > 0 or
showArchived is true (i.e. replace the current conditional with onToggleArchived
&& (archivedCount > 0 || showArchived)). Also ensure the badge/number span
renders only when archivedCount > 0 so it doesn't display "0" when there are no
archived items.
Base Branch
developbranch (required for all feature/fix PRs)main(hotfix only - maintainers)Description
Type of Change
Area
AI Disclosure
Tool(s) used:
Testing level:
Untested -- AI output not yet verified
Lightly tested -- ran the app / spot-checked key paths
Fully tested -- all tests pass, manually verified behavior
I understand what this PR does and how the underlying code works
Checklist
developbranchPlatform Testing Checklist
CRITICAL: This project supports Windows, macOS, and Linux. Platform-specific bugs are a common source of breakage.
platform/module instead of directprocess.platformchecksfindExecutable()or platform abstractions)If you only have access to one OS: CI now tests on all platforms. Ensure all checks pass before submitting.
CI/Testing Requirements
Screenshots
Feature Toggle
use_feature_nameBreaking Changes
Breaking: No
Summary by CodeRabbit
Release Notes
New Features
Improvements
Chores