Files
vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx

46 lines
1.4 KiB
TypeScript
Raw Normal View History

2026-01-08 22:14:38 +00:00
import { ReactNode, useRef } from 'react';
import { PortalContainerContext } from '@/contexts/PortalContainerContext';
Fix CommandBar input and navigation issues with state machine refactor (Vibe Kanban) (#1885) * Done! I've removed all 7 `shortcut` properties from the action definitions in `index.ts`: - `NewWorkspace`: removed `shortcut: 'N'` - `Settings`: removed `shortcut: ','` - `ToggleSidebar`: removed `shortcut: '['` - `ToggleGitPanel`: removed `shortcut: ']'` - `ToggleChangesMode`: removed `shortcut: 'C'` - `ToggleLogsMode`: removed `shortcut: 'L'` - `TogglePreviewMode`: removed `shortcut: 'P'` The `ActionDefinition` type (and its base `ActionBase` interface) were left unchanged as requested. * fix tailwind nto auto creating styles * I've successfully completed all the changes. Here's a summary of what was done: ## Summary of Changes ### 1. `ActionExecutorContext` (index.ts) - Made all properties non-optional - Removed `gitRepoId` from context (now passed as action parameter) - Properties now use `| null` for values that may not exist ### 2. New `GitActionDefinition` Type (index.ts) - Added new action type with `requiresTarget: 'git'` - Git actions now explicitly require `repoId` as a parameter ### 3. Git Actions Updated (index.ts) - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` function takes `repoId` as third parameter - Simplified implementations (no more fallback repo fetching logic) ### 4. `ActionsContext` Provider (ActionsContext.tsx) - Now calls `useDevServer()` to get dev server state - Provides all required context properties - `executeAction` handles three action types: global, workspace, and git - Removed `contextOverride` pattern ### 5. `ContextBarContainer` (ContextBarContainer.tsx) - Simplified significantly - no longer builds extended context - Uses executor context directly from provider - Removed `containerPath` prop ### 6. `ActionVisibilityContext` (index.ts + useActionVisibility.ts) - Made `editorType`, `devServerState`, `runningDevServerId` required - Visibility hook now provides all values from hooks ### 7. Updated Call Sites - `WorkspacesLayout`: Git actions now pass `repoId` as third parameter - `WorkspacesMain`: Removed `containerPath` prop from ContextBarContainer * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * All changes are complete and type checks pass. Here's a summary of the changes made: ## Summary of Changes ### 1. `ActionExecutorContext` - Made all properties non-optional - Removed `?` from all properties - Removed `gitRepoId` (moved to per-action parameter) - Changed nullable properties to use `| null` type ### 2. New `GitActionDefinition` type - Added new action type with `requiresTarget: 'git'` - Takes `repoId` as explicit third parameter ### 3. Git actions updated - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` receives `repoId` as parameter ### 4. `ActionsContext` provider centralized - Now calls `useDevServer()` to provide dev server state - Provides all required context properties from hooks - `executeAction` handles three action types: global, workspace, git - Removed `contextOverride` pattern ### 5. `ActionVisibilityContext` - Made dev server properties required - `editorType`, `devServerState`, `runningDevServerId` now required - `useActionVisibilityContext` hook provides all values ### 6. `ContextBarContainer` simplified - Removed extended context creation - Uses executor context directly from provider ### 7. Provider order fix - Moved `ExecutionProcessesProvider` up to `NewDesignScope` - Required because `useDevServer` depends on `ExecutionProcessesContext` ### Files Modified: - `vibe-kanban/frontend/src/components/ui-new/actions/index.ts` - `vibe-kanban/frontend/src/components/ui-new/actions/useActionVisibility.ts` - `vibe-kanban/frontend/src/contexts/ActionsContext.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/ContextBarContainer.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` - `vibe-kanban/frontend/src/components/ui-new/views/WorkspacesMain.tsx` - `vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx` * The implementation is complete. Let me summarize what was changed: ## Summary of Changes ### `pages.ts` - Added `'selectRepo'` to `PageId` type for dynamic repo selection page - Created `StaticPageId` type (excludes `selectRepo`) for static page records - Added `RepoItem` interface for repo selection items - Extended `ResolvedGroupItem` union type to include `{ type: 'repo'; repo: RepoItem }` - Updated `Pages` record and `getPageActions` to use `StaticPageId` ### `CommandBarDialog.tsx` - Added `repos` from `useWorkspaceContext()` - Added `pendingGitAction` state to track git actions awaiting repo selection - Reset `pendingGitAction` when dialog opens/closes - Modified `getPageWithItems` to generate dynamic `selectRepo` page with repo list - Updated `handleSelect` to: - Execute git actions immediately with single repo - Navigate to `selectRepo` page when multiple repos exist - Execute pending git action when user selects a repo - Clear `pendingGitAction` when navigating back from `selectRepo` page ### `CommandBar.tsx` - Added `FolderIcon` import - Added rendering for `'repo'` item type with folder icon ## Behavior 1. **Single repo**: When user selects a git action (e.g., "Create Pull Request") and the workspace has only one git repo, the action executes immediately with that repo's ID. 2. **Multiple repos**: When workspace has multiple repos, selecting a git action navigates to a "Select Repository" page where the user can choose which repo to use, then the action executes with the selected repo. 3. **Back navigation**: Pressing back from the repo selection page clears the pending action and returns to the previous page. * Done! The `CommandBarDialog` has been refactored to use a state machine pattern with `useReducer`. Here's a summary of the changes: ## Summary of Changes **State Machine Types (lines 38-67):** - `CommandBarState`: Discriminated union with `browsing` and `selectingRepo` states - `CommandBarEvent`: `RESET`, `SEARCH_CHANGE`, `GO_BACK`, `SELECT_ITEM` - `CommandBarEffect`: Side effects returned from reducer (`none` or `execute`) **Reducer (lines 73-201):** - Pure function returning `[newState, effect]` tuple - Handles all state transitions based on current state and event - Git action flow: single repo → execute, multiple repos → transition to `selectingRepo` **Component Changes:** - Replaced 4 `useState` calls with single `useReducer` - `currentPage` is now derived from state (line 249-250) - `handleSelect` computes effect from reducer, dispatches event, then handles effect (lines 456-475) - `goBack` and `handleSearchChange` simply dispatch events (lines 446-453) **Benefits:** - All state transitions in one place (the reducer) - State transitions are pure and testable - Clear separation between state updates and side effects - Impossible states are unrepresentable (e.g., can't have `pendingAction` while `browsing`) * Done! Here's the final result: ## Summary **Before:** 520 lines in 1 file (after initial state machine refactor) **After:** 487 lines across 4 files | File | Lines | Purpose | |------|-------|---------| | `CommandBarDialog.tsx` | 101 | Thin orchestration (down from 520) | | `useCommandBarState.ts` | 177 | State machine hook | | `useResolvedPage.ts` | 150 | Page building logic | | `injectSearchMatches.ts` | 59 | DRY search helper | **Key wins:** - Main component: **520 → 101 lines** (80% reduction) - Search injection code: **100 → 59 lines** (4× duplication eliminated) - Each file has single responsibility - State machine is testable in isolation - Page building logic is reusable * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * Done! Here are the final results: ## Final Summary | File | Before | After | Reduction | |------|--------|-------|-----------| | `CommandBarDialog.tsx` | 101 | 106 | +5 (linter formatting) | | `useCommandBarState.ts` | 177 | 95 | **-82 (46%)** | | `useResolvedPage.ts` | 150 | 95 | **-55 (37%)** | | `injectSearchMatches.ts` | 59 | 42 | **-17 (29%)** | | **Total** | **487** | **338** | **-149 (31%)** | **Original single file:** 398 lines **Final 4 files:** 338 lines (15% less code overall) Key wins: - Main component is now just 106 lines of thin orchestration - State machine is flattened (if statements instead of nested switch/case) - Page resolution is simplified with reused types - Search injection uses reduce() instead of for-loop - All files pass type check * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * I've fixed both issues with the CommandBar. Here's a summary of what was wrong and how I fixed it: ## Root Causes ### Issue 1: Nested `<Command>` Components The `CommandDialog` component was wrapping children in a `<Command>` component, and `CommandBar` also rendered its own `<Command>`. This nested cmdk context caused conflicts with state management. **Fix:** Removed the `<Command>` wrapper from `CommandDialog` in `Command.tsx:26-44`, and moved the styling classes to `CommandBar`'s `<Command>` component. ### Issue 2: Unstable `dispatch` Function Causing Infinite RESET Loop In `useCommandBarState.ts`, the `dispatch` function had `[state, repoCount]` in its `useCallback` dependency array. This caused `dispatch` to be recreated on every state change. In `CommandBarDialog.tsx`, the `useEffect` that resets state when the modal opens had `dispatch` in its dependency array: ```tsx useEffect(() => { if (modal.visible) { dispatch({ type: 'RESET', page }); } }, [modal.visible, page, dispatch]); // dispatch changes → useEffect runs → RESET ``` This created an infinite loop: 1. User types → state updates → `dispatch` recreated 2. `dispatch` changed → `useEffect` runs → `RESET` dispatched 3. State resets to empty → repeat **Fix:** Made `dispatch` stable by using refs instead of state in dependencies: ```tsx const stateRef = useRef<CommandBarState>(browsing(initialPage)); const repoCountRef = useRef(repoCount); const dispatch = useCallback( (event: CommandBarEvent): CommandBarEffect => { const [, effect] = reducer(stateRef.current, event, repoCountRef.current); rawDispatch(event); return effect; }, [] // No dependencies - uses refs for current values ); ``` ## Files Changed 1. `vibe-kanban/frontend/src/components/ui-new/primitives/Command.tsx` - Removed nested `<Command>` wrapper from `CommandDialog` 2. `vibe-kanban/frontend/src/components/ui-new/primitives/CommandBar.tsx` - Added styling classes that were on the removed wrapper 3. `vibe-kanban/frontend/src/components/ui-new/dialogs/commandBar/useCommandBarState.ts` - Made `dispatch` stable using refs
2026-01-09 16:25:42 +00:00
import {
WorkspaceProvider,
useWorkspaceContext,
} from '@/contexts/WorkspaceContext';
2026-01-08 22:14:38 +00:00
import { ActionsProvider } from '@/contexts/ActionsContext';
Fix CommandBar input and navigation issues with state machine refactor (Vibe Kanban) (#1885) * Done! I've removed all 7 `shortcut` properties from the action definitions in `index.ts`: - `NewWorkspace`: removed `shortcut: 'N'` - `Settings`: removed `shortcut: ','` - `ToggleSidebar`: removed `shortcut: '['` - `ToggleGitPanel`: removed `shortcut: ']'` - `ToggleChangesMode`: removed `shortcut: 'C'` - `ToggleLogsMode`: removed `shortcut: 'L'` - `TogglePreviewMode`: removed `shortcut: 'P'` The `ActionDefinition` type (and its base `ActionBase` interface) were left unchanged as requested. * fix tailwind nto auto creating styles * I've successfully completed all the changes. Here's a summary of what was done: ## Summary of Changes ### 1. `ActionExecutorContext` (index.ts) - Made all properties non-optional - Removed `gitRepoId` from context (now passed as action parameter) - Properties now use `| null` for values that may not exist ### 2. New `GitActionDefinition` Type (index.ts) - Added new action type with `requiresTarget: 'git'` - Git actions now explicitly require `repoId` as a parameter ### 3. Git Actions Updated (index.ts) - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` function takes `repoId` as third parameter - Simplified implementations (no more fallback repo fetching logic) ### 4. `ActionsContext` Provider (ActionsContext.tsx) - Now calls `useDevServer()` to get dev server state - Provides all required context properties - `executeAction` handles three action types: global, workspace, and git - Removed `contextOverride` pattern ### 5. `ContextBarContainer` (ContextBarContainer.tsx) - Simplified significantly - no longer builds extended context - Uses executor context directly from provider - Removed `containerPath` prop ### 6. `ActionVisibilityContext` (index.ts + useActionVisibility.ts) - Made `editorType`, `devServerState`, `runningDevServerId` required - Visibility hook now provides all values from hooks ### 7. Updated Call Sites - `WorkspacesLayout`: Git actions now pass `repoId` as third parameter - `WorkspacesMain`: Removed `containerPath` prop from ContextBarContainer * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * All changes are complete and type checks pass. Here's a summary of the changes made: ## Summary of Changes ### 1. `ActionExecutorContext` - Made all properties non-optional - Removed `?` from all properties - Removed `gitRepoId` (moved to per-action parameter) - Changed nullable properties to use `| null` type ### 2. New `GitActionDefinition` type - Added new action type with `requiresTarget: 'git'` - Takes `repoId` as explicit third parameter ### 3. Git actions updated - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` receives `repoId` as parameter ### 4. `ActionsContext` provider centralized - Now calls `useDevServer()` to provide dev server state - Provides all required context properties from hooks - `executeAction` handles three action types: global, workspace, git - Removed `contextOverride` pattern ### 5. `ActionVisibilityContext` - Made dev server properties required - `editorType`, `devServerState`, `runningDevServerId` now required - `useActionVisibilityContext` hook provides all values ### 6. `ContextBarContainer` simplified - Removed extended context creation - Uses executor context directly from provider ### 7. Provider order fix - Moved `ExecutionProcessesProvider` up to `NewDesignScope` - Required because `useDevServer` depends on `ExecutionProcessesContext` ### Files Modified: - `vibe-kanban/frontend/src/components/ui-new/actions/index.ts` - `vibe-kanban/frontend/src/components/ui-new/actions/useActionVisibility.ts` - `vibe-kanban/frontend/src/contexts/ActionsContext.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/ContextBarContainer.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` - `vibe-kanban/frontend/src/components/ui-new/views/WorkspacesMain.tsx` - `vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx` * The implementation is complete. Let me summarize what was changed: ## Summary of Changes ### `pages.ts` - Added `'selectRepo'` to `PageId` type for dynamic repo selection page - Created `StaticPageId` type (excludes `selectRepo`) for static page records - Added `RepoItem` interface for repo selection items - Extended `ResolvedGroupItem` union type to include `{ type: 'repo'; repo: RepoItem }` - Updated `Pages` record and `getPageActions` to use `StaticPageId` ### `CommandBarDialog.tsx` - Added `repos` from `useWorkspaceContext()` - Added `pendingGitAction` state to track git actions awaiting repo selection - Reset `pendingGitAction` when dialog opens/closes - Modified `getPageWithItems` to generate dynamic `selectRepo` page with repo list - Updated `handleSelect` to: - Execute git actions immediately with single repo - Navigate to `selectRepo` page when multiple repos exist - Execute pending git action when user selects a repo - Clear `pendingGitAction` when navigating back from `selectRepo` page ### `CommandBar.tsx` - Added `FolderIcon` import - Added rendering for `'repo'` item type with folder icon ## Behavior 1. **Single repo**: When user selects a git action (e.g., "Create Pull Request") and the workspace has only one git repo, the action executes immediately with that repo's ID. 2. **Multiple repos**: When workspace has multiple repos, selecting a git action navigates to a "Select Repository" page where the user can choose which repo to use, then the action executes with the selected repo. 3. **Back navigation**: Pressing back from the repo selection page clears the pending action and returns to the previous page. * Done! The `CommandBarDialog` has been refactored to use a state machine pattern with `useReducer`. Here's a summary of the changes: ## Summary of Changes **State Machine Types (lines 38-67):** - `CommandBarState`: Discriminated union with `browsing` and `selectingRepo` states - `CommandBarEvent`: `RESET`, `SEARCH_CHANGE`, `GO_BACK`, `SELECT_ITEM` - `CommandBarEffect`: Side effects returned from reducer (`none` or `execute`) **Reducer (lines 73-201):** - Pure function returning `[newState, effect]` tuple - Handles all state transitions based on current state and event - Git action flow: single repo → execute, multiple repos → transition to `selectingRepo` **Component Changes:** - Replaced 4 `useState` calls with single `useReducer` - `currentPage` is now derived from state (line 249-250) - `handleSelect` computes effect from reducer, dispatches event, then handles effect (lines 456-475) - `goBack` and `handleSearchChange` simply dispatch events (lines 446-453) **Benefits:** - All state transitions in one place (the reducer) - State transitions are pure and testable - Clear separation between state updates and side effects - Impossible states are unrepresentable (e.g., can't have `pendingAction` while `browsing`) * Done! Here's the final result: ## Summary **Before:** 520 lines in 1 file (after initial state machine refactor) **After:** 487 lines across 4 files | File | Lines | Purpose | |------|-------|---------| | `CommandBarDialog.tsx` | 101 | Thin orchestration (down from 520) | | `useCommandBarState.ts` | 177 | State machine hook | | `useResolvedPage.ts` | 150 | Page building logic | | `injectSearchMatches.ts` | 59 | DRY search helper | **Key wins:** - Main component: **520 → 101 lines** (80% reduction) - Search injection code: **100 → 59 lines** (4× duplication eliminated) - Each file has single responsibility - State machine is testable in isolation - Page building logic is reusable * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * Done! Here are the final results: ## Final Summary | File | Before | After | Reduction | |------|--------|-------|-----------| | `CommandBarDialog.tsx` | 101 | 106 | +5 (linter formatting) | | `useCommandBarState.ts` | 177 | 95 | **-82 (46%)** | | `useResolvedPage.ts` | 150 | 95 | **-55 (37%)** | | `injectSearchMatches.ts` | 59 | 42 | **-17 (29%)** | | **Total** | **487** | **338** | **-149 (31%)** | **Original single file:** 398 lines **Final 4 files:** 338 lines (15% less code overall) Key wins: - Main component is now just 106 lines of thin orchestration - State machine is flattened (if statements instead of nested switch/case) - Page resolution is simplified with reused types - Search injection uses reduce() instead of for-loop - All files pass type check * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * I've fixed both issues with the CommandBar. Here's a summary of what was wrong and how I fixed it: ## Root Causes ### Issue 1: Nested `<Command>` Components The `CommandDialog` component was wrapping children in a `<Command>` component, and `CommandBar` also rendered its own `<Command>`. This nested cmdk context caused conflicts with state management. **Fix:** Removed the `<Command>` wrapper from `CommandDialog` in `Command.tsx:26-44`, and moved the styling classes to `CommandBar`'s `<Command>` component. ### Issue 2: Unstable `dispatch` Function Causing Infinite RESET Loop In `useCommandBarState.ts`, the `dispatch` function had `[state, repoCount]` in its `useCallback` dependency array. This caused `dispatch` to be recreated on every state change. In `CommandBarDialog.tsx`, the `useEffect` that resets state when the modal opens had `dispatch` in its dependency array: ```tsx useEffect(() => { if (modal.visible) { dispatch({ type: 'RESET', page }); } }, [modal.visible, page, dispatch]); // dispatch changes → useEffect runs → RESET ``` This created an infinite loop: 1. User types → state updates → `dispatch` recreated 2. `dispatch` changed → `useEffect` runs → `RESET` dispatched 3. State resets to empty → repeat **Fix:** Made `dispatch` stable by using refs instead of state in dependencies: ```tsx const stateRef = useRef<CommandBarState>(browsing(initialPage)); const repoCountRef = useRef(repoCount); const dispatch = useCallback( (event: CommandBarEvent): CommandBarEffect => { const [, effect] = reducer(stateRef.current, event, repoCountRef.current); rawDispatch(event); return effect; }, [] // No dependencies - uses refs for current values ); ``` ## Files Changed 1. `vibe-kanban/frontend/src/components/ui-new/primitives/Command.tsx` - Removed nested `<Command>` wrapper from `CommandDialog` 2. `vibe-kanban/frontend/src/components/ui-new/primitives/CommandBar.tsx` - Added styling classes that were on the removed wrapper 3. `vibe-kanban/frontend/src/components/ui-new/dialogs/commandBar/useCommandBarState.ts` - Made `dispatch` stable using refs
2026-01-09 16:25:42 +00:00
import { ExecutionProcessesProvider } from '@/contexts/ExecutionProcessesContext';
2026-01-08 22:14:38 +00:00
import NiceModal from '@ebay/nice-modal-react';
import '@/styles/new/index.css';
interface NewDesignScopeProps {
children: ReactNode;
}
Fix CommandBar input and navigation issues with state machine refactor (Vibe Kanban) (#1885) * Done! I've removed all 7 `shortcut` properties from the action definitions in `index.ts`: - `NewWorkspace`: removed `shortcut: 'N'` - `Settings`: removed `shortcut: ','` - `ToggleSidebar`: removed `shortcut: '['` - `ToggleGitPanel`: removed `shortcut: ']'` - `ToggleChangesMode`: removed `shortcut: 'C'` - `ToggleLogsMode`: removed `shortcut: 'L'` - `TogglePreviewMode`: removed `shortcut: 'P'` The `ActionDefinition` type (and its base `ActionBase` interface) were left unchanged as requested. * fix tailwind nto auto creating styles * I've successfully completed all the changes. Here's a summary of what was done: ## Summary of Changes ### 1. `ActionExecutorContext` (index.ts) - Made all properties non-optional - Removed `gitRepoId` from context (now passed as action parameter) - Properties now use `| null` for values that may not exist ### 2. New `GitActionDefinition` Type (index.ts) - Added new action type with `requiresTarget: 'git'` - Git actions now explicitly require `repoId` as a parameter ### 3. Git Actions Updated (index.ts) - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` function takes `repoId` as third parameter - Simplified implementations (no more fallback repo fetching logic) ### 4. `ActionsContext` Provider (ActionsContext.tsx) - Now calls `useDevServer()` to get dev server state - Provides all required context properties - `executeAction` handles three action types: global, workspace, and git - Removed `contextOverride` pattern ### 5. `ContextBarContainer` (ContextBarContainer.tsx) - Simplified significantly - no longer builds extended context - Uses executor context directly from provider - Removed `containerPath` prop ### 6. `ActionVisibilityContext` (index.ts + useActionVisibility.ts) - Made `editorType`, `devServerState`, `runningDevServerId` required - Visibility hook now provides all values from hooks ### 7. Updated Call Sites - `WorkspacesLayout`: Git actions now pass `repoId` as third parameter - `WorkspacesMain`: Removed `containerPath` prop from ContextBarContainer * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * All changes are complete and type checks pass. Here's a summary of the changes made: ## Summary of Changes ### 1. `ActionExecutorContext` - Made all properties non-optional - Removed `?` from all properties - Removed `gitRepoId` (moved to per-action parameter) - Changed nullable properties to use `| null` type ### 2. New `GitActionDefinition` type - Added new action type with `requiresTarget: 'git'` - Takes `repoId` as explicit third parameter ### 3. Git actions updated - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` receives `repoId` as parameter ### 4. `ActionsContext` provider centralized - Now calls `useDevServer()` to provide dev server state - Provides all required context properties from hooks - `executeAction` handles three action types: global, workspace, git - Removed `contextOverride` pattern ### 5. `ActionVisibilityContext` - Made dev server properties required - `editorType`, `devServerState`, `runningDevServerId` now required - `useActionVisibilityContext` hook provides all values ### 6. `ContextBarContainer` simplified - Removed extended context creation - Uses executor context directly from provider ### 7. Provider order fix - Moved `ExecutionProcessesProvider` up to `NewDesignScope` - Required because `useDevServer` depends on `ExecutionProcessesContext` ### Files Modified: - `vibe-kanban/frontend/src/components/ui-new/actions/index.ts` - `vibe-kanban/frontend/src/components/ui-new/actions/useActionVisibility.ts` - `vibe-kanban/frontend/src/contexts/ActionsContext.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/ContextBarContainer.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` - `vibe-kanban/frontend/src/components/ui-new/views/WorkspacesMain.tsx` - `vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx` * The implementation is complete. Let me summarize what was changed: ## Summary of Changes ### `pages.ts` - Added `'selectRepo'` to `PageId` type for dynamic repo selection page - Created `StaticPageId` type (excludes `selectRepo`) for static page records - Added `RepoItem` interface for repo selection items - Extended `ResolvedGroupItem` union type to include `{ type: 'repo'; repo: RepoItem }` - Updated `Pages` record and `getPageActions` to use `StaticPageId` ### `CommandBarDialog.tsx` - Added `repos` from `useWorkspaceContext()` - Added `pendingGitAction` state to track git actions awaiting repo selection - Reset `pendingGitAction` when dialog opens/closes - Modified `getPageWithItems` to generate dynamic `selectRepo` page with repo list - Updated `handleSelect` to: - Execute git actions immediately with single repo - Navigate to `selectRepo` page when multiple repos exist - Execute pending git action when user selects a repo - Clear `pendingGitAction` when navigating back from `selectRepo` page ### `CommandBar.tsx` - Added `FolderIcon` import - Added rendering for `'repo'` item type with folder icon ## Behavior 1. **Single repo**: When user selects a git action (e.g., "Create Pull Request") and the workspace has only one git repo, the action executes immediately with that repo's ID. 2. **Multiple repos**: When workspace has multiple repos, selecting a git action navigates to a "Select Repository" page where the user can choose which repo to use, then the action executes with the selected repo. 3. **Back navigation**: Pressing back from the repo selection page clears the pending action and returns to the previous page. * Done! The `CommandBarDialog` has been refactored to use a state machine pattern with `useReducer`. Here's a summary of the changes: ## Summary of Changes **State Machine Types (lines 38-67):** - `CommandBarState`: Discriminated union with `browsing` and `selectingRepo` states - `CommandBarEvent`: `RESET`, `SEARCH_CHANGE`, `GO_BACK`, `SELECT_ITEM` - `CommandBarEffect`: Side effects returned from reducer (`none` or `execute`) **Reducer (lines 73-201):** - Pure function returning `[newState, effect]` tuple - Handles all state transitions based on current state and event - Git action flow: single repo → execute, multiple repos → transition to `selectingRepo` **Component Changes:** - Replaced 4 `useState` calls with single `useReducer` - `currentPage` is now derived from state (line 249-250) - `handleSelect` computes effect from reducer, dispatches event, then handles effect (lines 456-475) - `goBack` and `handleSearchChange` simply dispatch events (lines 446-453) **Benefits:** - All state transitions in one place (the reducer) - State transitions are pure and testable - Clear separation between state updates and side effects - Impossible states are unrepresentable (e.g., can't have `pendingAction` while `browsing`) * Done! Here's the final result: ## Summary **Before:** 520 lines in 1 file (after initial state machine refactor) **After:** 487 lines across 4 files | File | Lines | Purpose | |------|-------|---------| | `CommandBarDialog.tsx` | 101 | Thin orchestration (down from 520) | | `useCommandBarState.ts` | 177 | State machine hook | | `useResolvedPage.ts` | 150 | Page building logic | | `injectSearchMatches.ts` | 59 | DRY search helper | **Key wins:** - Main component: **520 → 101 lines** (80% reduction) - Search injection code: **100 → 59 lines** (4× duplication eliminated) - Each file has single responsibility - State machine is testable in isolation - Page building logic is reusable * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * Done! Here are the final results: ## Final Summary | File | Before | After | Reduction | |------|--------|-------|-----------| | `CommandBarDialog.tsx` | 101 | 106 | +5 (linter formatting) | | `useCommandBarState.ts` | 177 | 95 | **-82 (46%)** | | `useResolvedPage.ts` | 150 | 95 | **-55 (37%)** | | `injectSearchMatches.ts` | 59 | 42 | **-17 (29%)** | | **Total** | **487** | **338** | **-149 (31%)** | **Original single file:** 398 lines **Final 4 files:** 338 lines (15% less code overall) Key wins: - Main component is now just 106 lines of thin orchestration - State machine is flattened (if statements instead of nested switch/case) - Page resolution is simplified with reused types - Search injection uses reduce() instead of for-loop - All files pass type check * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * I've fixed both issues with the CommandBar. Here's a summary of what was wrong and how I fixed it: ## Root Causes ### Issue 1: Nested `<Command>` Components The `CommandDialog` component was wrapping children in a `<Command>` component, and `CommandBar` also rendered its own `<Command>`. This nested cmdk context caused conflicts with state management. **Fix:** Removed the `<Command>` wrapper from `CommandDialog` in `Command.tsx:26-44`, and moved the styling classes to `CommandBar`'s `<Command>` component. ### Issue 2: Unstable `dispatch` Function Causing Infinite RESET Loop In `useCommandBarState.ts`, the `dispatch` function had `[state, repoCount]` in its `useCallback` dependency array. This caused `dispatch` to be recreated on every state change. In `CommandBarDialog.tsx`, the `useEffect` that resets state when the modal opens had `dispatch` in its dependency array: ```tsx useEffect(() => { if (modal.visible) { dispatch({ type: 'RESET', page }); } }, [modal.visible, page, dispatch]); // dispatch changes → useEffect runs → RESET ``` This created an infinite loop: 1. User types → state updates → `dispatch` recreated 2. `dispatch` changed → `useEffect` runs → `RESET` dispatched 3. State resets to empty → repeat **Fix:** Made `dispatch` stable by using refs instead of state in dependencies: ```tsx const stateRef = useRef<CommandBarState>(browsing(initialPage)); const repoCountRef = useRef(repoCount); const dispatch = useCallback( (event: CommandBarEvent): CommandBarEffect => { const [, effect] = reducer(stateRef.current, event, repoCountRef.current); rawDispatch(event); return effect; }, [] // No dependencies - uses refs for current values ); ``` ## Files Changed 1. `vibe-kanban/frontend/src/components/ui-new/primitives/Command.tsx` - Removed nested `<Command>` wrapper from `CommandDialog` 2. `vibe-kanban/frontend/src/components/ui-new/primitives/CommandBar.tsx` - Added styling classes that were on the removed wrapper 3. `vibe-kanban/frontend/src/components/ui-new/dialogs/commandBar/useCommandBarState.ts` - Made `dispatch` stable using refs
2026-01-09 16:25:42 +00:00
// Wrapper component to get workspaceId from context for ExecutionProcessesProvider
function ExecutionProcessesProviderWrapper({
children,
}: {
children: ReactNode;
}) {
const { workspaceId } = useWorkspaceContext();
return (
<ExecutionProcessesProvider attemptId={workspaceId}>
{children}
</ExecutionProcessesProvider>
);
}
2026-01-08 22:14:38 +00:00
export function NewDesignScope({ children }: NewDesignScopeProps) {
const ref = useRef<HTMLDivElement>(null);
return (
<div ref={ref} className="new-design h-full">
<PortalContainerContext.Provider value={ref}>
<WorkspaceProvider>
Fix CommandBar input and navigation issues with state machine refactor (Vibe Kanban) (#1885) * Done! I've removed all 7 `shortcut` properties from the action definitions in `index.ts`: - `NewWorkspace`: removed `shortcut: 'N'` - `Settings`: removed `shortcut: ','` - `ToggleSidebar`: removed `shortcut: '['` - `ToggleGitPanel`: removed `shortcut: ']'` - `ToggleChangesMode`: removed `shortcut: 'C'` - `ToggleLogsMode`: removed `shortcut: 'L'` - `TogglePreviewMode`: removed `shortcut: 'P'` The `ActionDefinition` type (and its base `ActionBase` interface) were left unchanged as requested. * fix tailwind nto auto creating styles * I've successfully completed all the changes. Here's a summary of what was done: ## Summary of Changes ### 1. `ActionExecutorContext` (index.ts) - Made all properties non-optional - Removed `gitRepoId` from context (now passed as action parameter) - Properties now use `| null` for values that may not exist ### 2. New `GitActionDefinition` Type (index.ts) - Added new action type with `requiresTarget: 'git'` - Git actions now explicitly require `repoId` as a parameter ### 3. Git Actions Updated (index.ts) - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` function takes `repoId` as third parameter - Simplified implementations (no more fallback repo fetching logic) ### 4. `ActionsContext` Provider (ActionsContext.tsx) - Now calls `useDevServer()` to get dev server state - Provides all required context properties - `executeAction` handles three action types: global, workspace, and git - Removed `contextOverride` pattern ### 5. `ContextBarContainer` (ContextBarContainer.tsx) - Simplified significantly - no longer builds extended context - Uses executor context directly from provider - Removed `containerPath` prop ### 6. `ActionVisibilityContext` (index.ts + useActionVisibility.ts) - Made `editorType`, `devServerState`, `runningDevServerId` required - Visibility hook now provides all values from hooks ### 7. Updated Call Sites - `WorkspacesLayout`: Git actions now pass `repoId` as third parameter - `WorkspacesMain`: Removed `containerPath` prop from ContextBarContainer * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * All changes are complete and type checks pass. Here's a summary of the changes made: ## Summary of Changes ### 1. `ActionExecutorContext` - Made all properties non-optional - Removed `?` from all properties - Removed `gitRepoId` (moved to per-action parameter) - Changed nullable properties to use `| null` type ### 2. New `GitActionDefinition` type - Added new action type with `requiresTarget: 'git'` - Takes `repoId` as explicit third parameter ### 3. Git actions updated - `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'` - Each action's `execute` receives `repoId` as parameter ### 4. `ActionsContext` provider centralized - Now calls `useDevServer()` to provide dev server state - Provides all required context properties from hooks - `executeAction` handles three action types: global, workspace, git - Removed `contextOverride` pattern ### 5. `ActionVisibilityContext` - Made dev server properties required - `editorType`, `devServerState`, `runningDevServerId` now required - `useActionVisibilityContext` hook provides all values ### 6. `ContextBarContainer` simplified - Removed extended context creation - Uses executor context directly from provider ### 7. Provider order fix - Moved `ExecutionProcessesProvider` up to `NewDesignScope` - Required because `useDevServer` depends on `ExecutionProcessesContext` ### Files Modified: - `vibe-kanban/frontend/src/components/ui-new/actions/index.ts` - `vibe-kanban/frontend/src/components/ui-new/actions/useActionVisibility.ts` - `vibe-kanban/frontend/src/contexts/ActionsContext.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/ContextBarContainer.tsx` - `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx` - `vibe-kanban/frontend/src/components/ui-new/views/WorkspacesMain.tsx` - `vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx` * The implementation is complete. Let me summarize what was changed: ## Summary of Changes ### `pages.ts` - Added `'selectRepo'` to `PageId` type for dynamic repo selection page - Created `StaticPageId` type (excludes `selectRepo`) for static page records - Added `RepoItem` interface for repo selection items - Extended `ResolvedGroupItem` union type to include `{ type: 'repo'; repo: RepoItem }` - Updated `Pages` record and `getPageActions` to use `StaticPageId` ### `CommandBarDialog.tsx` - Added `repos` from `useWorkspaceContext()` - Added `pendingGitAction` state to track git actions awaiting repo selection - Reset `pendingGitAction` when dialog opens/closes - Modified `getPageWithItems` to generate dynamic `selectRepo` page with repo list - Updated `handleSelect` to: - Execute git actions immediately with single repo - Navigate to `selectRepo` page when multiple repos exist - Execute pending git action when user selects a repo - Clear `pendingGitAction` when navigating back from `selectRepo` page ### `CommandBar.tsx` - Added `FolderIcon` import - Added rendering for `'repo'` item type with folder icon ## Behavior 1. **Single repo**: When user selects a git action (e.g., "Create Pull Request") and the workspace has only one git repo, the action executes immediately with that repo's ID. 2. **Multiple repos**: When workspace has multiple repos, selecting a git action navigates to a "Select Repository" page where the user can choose which repo to use, then the action executes with the selected repo. 3. **Back navigation**: Pressing back from the repo selection page clears the pending action and returns to the previous page. * Done! The `CommandBarDialog` has been refactored to use a state machine pattern with `useReducer`. Here's a summary of the changes: ## Summary of Changes **State Machine Types (lines 38-67):** - `CommandBarState`: Discriminated union with `browsing` and `selectingRepo` states - `CommandBarEvent`: `RESET`, `SEARCH_CHANGE`, `GO_BACK`, `SELECT_ITEM` - `CommandBarEffect`: Side effects returned from reducer (`none` or `execute`) **Reducer (lines 73-201):** - Pure function returning `[newState, effect]` tuple - Handles all state transitions based on current state and event - Git action flow: single repo → execute, multiple repos → transition to `selectingRepo` **Component Changes:** - Replaced 4 `useState` calls with single `useReducer` - `currentPage` is now derived from state (line 249-250) - `handleSelect` computes effect from reducer, dispatches event, then handles effect (lines 456-475) - `goBack` and `handleSearchChange` simply dispatch events (lines 446-453) **Benefits:** - All state transitions in one place (the reducer) - State transitions are pure and testable - Clear separation between state updates and side effects - Impossible states are unrepresentable (e.g., can't have `pendingAction` while `browsing`) * Done! Here's the final result: ## Summary **Before:** 520 lines in 1 file (after initial state machine refactor) **After:** 487 lines across 4 files | File | Lines | Purpose | |------|-------|---------| | `CommandBarDialog.tsx` | 101 | Thin orchestration (down from 520) | | `useCommandBarState.ts` | 177 | State machine hook | | `useResolvedPage.ts` | 150 | Page building logic | | `injectSearchMatches.ts` | 59 | DRY search helper | **Key wins:** - Main component: **520 → 101 lines** (80% reduction) - Search injection code: **100 → 59 lines** (4× duplication eliminated) - Each file has single responsibility - State machine is testable in isolation - Page building logic is reusable * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * Done! Here are the final results: ## Final Summary | File | Before | After | Reduction | |------|--------|-------|-----------| | `CommandBarDialog.tsx` | 101 | 106 | +5 (linter formatting) | | `useCommandBarState.ts` | 177 | 95 | **-82 (46%)** | | `useResolvedPage.ts` | 150 | 95 | **-55 (37%)** | | `injectSearchMatches.ts` | 59 | 42 | **-17 (29%)** | | **Total** | **487** | **338** | **-149 (31%)** | **Original single file:** 398 lines **Final 4 files:** 338 lines (15% less code overall) Key wins: - Main component is now just 106 lines of thin orchestration - State machine is flattened (if statements instead of nested switch/case) - Page resolution is simplified with reused types - Search injection uses reduce() instead of for-loop - All files pass type check * Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497 * I've fixed both issues with the CommandBar. Here's a summary of what was wrong and how I fixed it: ## Root Causes ### Issue 1: Nested `<Command>` Components The `CommandDialog` component was wrapping children in a `<Command>` component, and `CommandBar` also rendered its own `<Command>`. This nested cmdk context caused conflicts with state management. **Fix:** Removed the `<Command>` wrapper from `CommandDialog` in `Command.tsx:26-44`, and moved the styling classes to `CommandBar`'s `<Command>` component. ### Issue 2: Unstable `dispatch` Function Causing Infinite RESET Loop In `useCommandBarState.ts`, the `dispatch` function had `[state, repoCount]` in its `useCallback` dependency array. This caused `dispatch` to be recreated on every state change. In `CommandBarDialog.tsx`, the `useEffect` that resets state when the modal opens had `dispatch` in its dependency array: ```tsx useEffect(() => { if (modal.visible) { dispatch({ type: 'RESET', page }); } }, [modal.visible, page, dispatch]); // dispatch changes → useEffect runs → RESET ``` This created an infinite loop: 1. User types → state updates → `dispatch` recreated 2. `dispatch` changed → `useEffect` runs → `RESET` dispatched 3. State resets to empty → repeat **Fix:** Made `dispatch` stable by using refs instead of state in dependencies: ```tsx const stateRef = useRef<CommandBarState>(browsing(initialPage)); const repoCountRef = useRef(repoCount); const dispatch = useCallback( (event: CommandBarEvent): CommandBarEffect => { const [, effect] = reducer(stateRef.current, event, repoCountRef.current); rawDispatch(event); return effect; }, [] // No dependencies - uses refs for current values ); ``` ## Files Changed 1. `vibe-kanban/frontend/src/components/ui-new/primitives/Command.tsx` - Removed nested `<Command>` wrapper from `CommandDialog` 2. `vibe-kanban/frontend/src/components/ui-new/primitives/CommandBar.tsx` - Added styling classes that were on the removed wrapper 3. `vibe-kanban/frontend/src/components/ui-new/dialogs/commandBar/useCommandBarState.ts` - Made `dispatch` stable using refs
2026-01-09 16:25:42 +00:00
<ExecutionProcessesProviderWrapper>
<ActionsProvider>
<NiceModal.Provider>{children}</NiceModal.Provider>
</ActionsProvider>
</ExecutionProcessesProviderWrapper>
2026-01-08 22:14:38 +00:00
</WorkspaceProvider>
</PortalContainerContext.Provider>
</div>
);
}