diff --git a/frontend/src/components/ui-new/containers/ProcessListContainer.tsx b/frontend/src/components/ui-new/containers/ProcessListContainer.tsx
index ded07b74..dd07bec6 100644
--- a/frontend/src/components/ui-new/containers/ProcessListContainer.tsx
+++ b/frontend/src/components/ui-new/containers/ProcessListContainer.tsx
@@ -2,9 +2,10 @@ import { useEffect, useMemo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useExecutionProcessesContext } from '@/contexts/ExecutionProcessesContext';
import { ProcessListItem } from '../primitives/ProcessListItem';
-import { SectionHeader } from '../primitives/SectionHeader';
+import { CollapsibleSectionHeader } from '../primitives/CollapsibleSectionHeader';
import { InputField } from '../primitives/InputField';
import { CaretUpIcon, CaretDownIcon } from '@phosphor-icons/react';
+import { PERSIST_KEYS } from '@/stores/useUiPreferencesStore';
interface ProcessListContainerProps {
selectedProcessId: string | null;
@@ -124,8 +125,11 @@ export function ProcessListContainer({
return (
-
-
+
{sortedProcesses.length === 0 ? (
{t('processes.noProcesses')}
@@ -144,7 +148,7 @@ export function ProcessListContainer({
))}
)}
-
+
{searchBar}
);
diff --git a/frontend/src/components/ui-new/primitives/CollapsibleSectionHeader.tsx b/frontend/src/components/ui-new/primitives/CollapsibleSectionHeader.tsx
new file mode 100644
index 00000000..67bebd24
--- /dev/null
+++ b/frontend/src/components/ui-new/primitives/CollapsibleSectionHeader.tsx
@@ -0,0 +1,76 @@
+import type { Icon } from '@phosphor-icons/react';
+import { CaretDownIcon } from '@phosphor-icons/react';
+import { cn } from '@/lib/utils';
+import {
+ usePersistedExpanded,
+ type PersistKey,
+} from '@/stores/useUiPreferencesStore';
+
+interface CollapsibleSectionHeaderProps {
+ persistKey: PersistKey;
+ title: string;
+ defaultExpanded?: boolean;
+ icon?: Icon;
+ onIconClick?: () => void;
+ children?: React.ReactNode;
+ className?: string;
+ contentClassName?: string;
+}
+
+export function CollapsibleSectionHeader({
+ persistKey,
+ title,
+ defaultExpanded = true,
+ icon: IconComponent,
+ onIconClick,
+ children,
+ className,
+ contentClassName,
+}: CollapsibleSectionHeaderProps) {
+ const [expanded, toggle] = usePersistedExpanded(persistKey, defaultExpanded);
+
+ const handleIconClick = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ onIconClick?.();
+ };
+
+ return (
+
+
+ {expanded &&
{children}
}
+
+ );
+}
diff --git a/frontend/src/components/ui-new/views/FileTree.tsx b/frontend/src/components/ui-new/views/FileTree.tsx
index bf76250d..0fa89eb3 100644
--- a/frontend/src/components/ui-new/views/FileTree.tsx
+++ b/frontend/src/components/ui-new/views/FileTree.tsx
@@ -3,7 +3,8 @@ import { cn } from '@/lib/utils';
import { FileTreeSearchBar } from './FileTreeSearchBar';
import { FileTreeNode } from './FileTreeNode';
import type { TreeNode } from '../types/fileTree';
-import { SectionHeader } from '../primitives/SectionHeader';
+import { CollapsibleSectionHeader } from '../primitives/CollapsibleSectionHeader';
+import { PERSIST_KEYS } from '@/stores/useUiPreferencesStore';
interface FileTreeProps {
nodes: TreeNode[];
@@ -66,24 +67,31 @@ export function FileTree({
return (
-
-
-
-
-
- {nodes.length > 0 ? (
- renderNodes(nodes)
- ) : (
-
- {searchQuery ? t('common:fileTree.noResults') : 'No changed files'}
-
- )}
-
+
+
+
+
+
+ {nodes.length > 0 ? (
+ renderNodes(nodes)
+ ) : (
+
+ {searchQuery
+ ? t('common:fileTree.noResults')
+ : 'No changed files'}
+
+ )}
+
+
);
}
diff --git a/frontend/src/components/ui-new/views/GitPanel.tsx b/frontend/src/components/ui-new/views/GitPanel.tsx
index 45bd42bd..c7cd66e5 100644
--- a/frontend/src/components/ui-new/views/GitPanel.tsx
+++ b/frontend/src/components/ui-new/views/GitPanel.tsx
@@ -6,9 +6,9 @@ import {
type RepoAction,
} from '@/components/ui-new/primitives/RepoCard';
import { InputField } from '@/components/ui-new/primitives/InputField';
-import { SectionHeader } from '@/components/ui-new/primitives/SectionHeader';
import { ErrorAlert } from '@/components/ui-new/primitives/ErrorAlert';
import { CollapsibleSection } from '../primitives/CollapsibleSection';
+import { CollapsibleSectionHeader } from '../primitives/CollapsibleSectionHeader';
import { PERSIST_KEYS } from '@/stores/useUiPreferencesStore';
export interface RepoInfo {
@@ -56,8 +56,11 @@ export function GitPanel({
)}
>
{error && }
-
-
+
{repos.map((repo) => (
-
+
);
}
diff --git a/frontend/src/components/ui-new/views/GitPanelCreate.tsx b/frontend/src/components/ui-new/views/GitPanelCreate.tsx
index 65de19ff..42b8333a 100644
--- a/frontend/src/components/ui-new/views/GitPanelCreate.tsx
+++ b/frontend/src/components/ui-new/views/GitPanelCreate.tsx
@@ -1,12 +1,13 @@
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
-import { SectionHeader } from '@/components/ui-new/primitives/SectionHeader';
+import { CollapsibleSectionHeader } from '@/components/ui-new/primitives/CollapsibleSectionHeader';
import { SelectedReposList } from '@/components/ui-new/primitives/SelectedReposList';
import { ProjectSelectorContainer } from '@/components/ui-new/containers/ProjectSelectorContainer';
import { RecentReposListContainer } from '@/components/ui-new/containers/RecentReposListContainer';
import { BrowseRepoButtonContainer } from '@/components/ui-new/containers/BrowseRepoButtonContainer';
import { CreateRepoButtonContainer } from '@/components/ui-new/containers/CreateRepoButtonContainer';
import { WarningIcon } from '@phosphor-icons/react';
+import { PERSIST_KEYS } from '@/stores/useUiPreferencesStore';
import type { Project, GitBranch, Repo } from 'shared/types';
interface GitPanelCreateProps {
@@ -50,8 +51,11 @@ export function GitPanelCreate({
className
)}
>
-
-
+
-
-
+
{hasNoRepos ? (
@@ -79,9 +86,12 @@ export function GitPanelCreate({
onBranchChange={onBranchChange}
/>
)}
-
-
-
+
+
{t('common:sections.recent')}
@@ -94,7 +104,7 @@ export function GitPanelCreate({
-
+
);
}
diff --git a/frontend/src/components/ui-new/views/PreviewControls.tsx b/frontend/src/components/ui-new/views/PreviewControls.tsx
index 55820001..bc5b2af0 100644
--- a/frontend/src/components/ui-new/views/PreviewControls.tsx
+++ b/frontend/src/components/ui-new/views/PreviewControls.tsx
@@ -8,12 +8,13 @@ import {
} from '@phosphor-icons/react';
import { useTranslation } from 'react-i18next';
import { cn } from '@/lib/utils';
-import { SectionHeader } from '../primitives/SectionHeader';
+import { CollapsibleSectionHeader } from '../primitives/CollapsibleSectionHeader';
import { PrimaryButton } from '../primitives/PrimaryButton';
import {
VirtualizedProcessLogs,
type LogEntry,
} from '../VirtualizedProcessLogs';
+import { PERSIST_KEYS } from '@/stores/useUiPreferencesStore';
interface PreviewControlsProps {
logs: LogEntry[];
@@ -56,9 +57,11 @@ export function PreviewControls({
className
)}
>
-
-
-
+
{/* Controls row: URL bar + Start/Stop button */}
{url && (
@@ -139,7 +142,7 @@ export function PreviewControls({
)}
-
+
);
}
diff --git a/frontend/src/stores/useUiPreferencesStore.ts b/frontend/src/stores/useUiPreferencesStore.ts
index a6fa29c6..3b2a5e63 100644
--- a/frontend/src/stores/useUiPreferencesStore.ts
+++ b/frontend/src/stores/useUiPreferencesStore.ts
@@ -16,9 +16,18 @@ export const PERSIST_KEYS = {
// Sidebar sections
workspacesSidebarActive: 'workspaces-sidebar-active',
workspacesSidebarArchived: 'workspaces-sidebar-archived',
- // Git panel
+ // Git panel sections
gitAdvancedSettings: 'git-advanced-settings',
gitPanelCreateAddRepo: 'git-panel-create-add-repo',
+ gitPanelRepositories: 'git-panel-repositories',
+ gitPanelProject: 'git-panel-project',
+ gitPanelAddRepositories: 'git-panel-add-repositories',
+ // Process panel sections
+ processesSection: 'processes-section',
+ // Changes panel sections
+ changesSection: 'changes-section',
+ // Preview panel sections
+ devServerSection: 'dev-server-section',
// Context bar
contextBarPosition: 'context-bar-position',
// Pane sizes
@@ -35,6 +44,12 @@ export type PersistKey =
| typeof PERSIST_KEYS.workspacesSidebarArchived
| typeof PERSIST_KEYS.gitAdvancedSettings
| typeof PERSIST_KEYS.gitPanelCreateAddRepo
+ | typeof PERSIST_KEYS.gitPanelRepositories
+ | typeof PERSIST_KEYS.gitPanelProject
+ | typeof PERSIST_KEYS.gitPanelAddRepositories
+ | typeof PERSIST_KEYS.processesSection
+ | typeof PERSIST_KEYS.changesSection
+ | typeof PERSIST_KEYS.devServerSection
| typeof PERSIST_KEYS.sidebarWidth
| typeof PERSIST_KEYS.gitPanelWidth
| typeof PERSIST_KEYS.changesPanelWidth