diff --git a/src/App.tsx b/src/App.tsx
index f58fdfb8fc..1c25994259 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -28,7 +28,7 @@ import LibraryView from './components/views/LibraryView';
import { ContextMenuProvider } from './context/ContextMenuContext';
import { useSettingsStore } from './store/useSettingsStore';
-import { useUIStore } from './store/useUIStore';
+import { MIN_SIDE_PANEL_WIDTH, useUIStore } from './store/useUIStore';
import { useLibraryStore } from './store/useLibraryStore';
import { useEditorStore } from './store/useEditorStore';
import { useProcessStore } from './store/useProcessStore';
@@ -116,6 +116,8 @@ function App() {
isLibraryExportPanelVisible,
leftPanelWidth,
rightPanelWidth,
+ leftPanelVisible,
+ rightPanelVisible,
compactEditorPanelHeightOverride,
activePanel,
activeLayoutDragItem,
@@ -135,6 +137,8 @@ function App() {
isLibraryExportPanelVisible: state.isLibraryExportPanelVisible,
leftPanelWidth: state.leftPanelWidth,
rightPanelWidth: state.rightPanelWidth,
+ leftPanelVisible: state.leftPanelVisible,
+ rightPanelVisible: state.rightPanelVisible,
compactEditorPanelHeightOverride: state.compactEditorPanelHeightOverride,
activePanel: state.activePanel,
activeLayoutDragItem: state.activeLayoutDragItem,
@@ -503,14 +507,20 @@ function App() {
if (stateKey === 'left') {
let w = startSize + (moveEvent.clientX - startX);
- if (w < 200) w = 48;
- else if (w > 600) w = 600;
- setUI({ leftPanelWidth: Math.round(w) });
+ if (w < MIN_SIDE_PANEL_WIDTH) {
+ setUI({ leftPanelWidth: startSize, leftPanelVisible: false });
+ } else {
+ if (w > 600) w = 600;
+ setUI({ leftPanelWidth: Math.round(w), leftPanelVisible: true });
+ }
} else if (stateKey === 'right') {
let w = startSize - (moveEvent.clientX - startX);
- if (w < 200) w = 48;
- else if (w > 600) w = 600;
- setUI({ rightPanelWidth: Math.round(w) });
+ if (w < MIN_SIDE_PANEL_WIDTH) {
+ setUI({ rightPanelWidth: startSize, rightPanelVisible: false });
+ } else {
+ if (w > 600) w = 600;
+ setUI({ rightPanelWidth: Math.round(w), rightPanelVisible: true });
+ }
} else if (stateKey === 'bottom') {
const newHeight = startSize - (moveEvent.clientY - startY);
if (newHeight < 100) {
@@ -729,7 +739,7 @@ function App() {
isFullScreen ? 'max-h-0 opacity-0 pointer-events-none' : 'max-h-15 opacity-100',
)}
>
- {appSettings?.decorations || (!isWindowFullScreen && )}
+ {appSettings?.decorations || (!isWindowFullScreen && )}
)}
= {
[Panel.FolderTree]: 'library.folders.sourcesTitle',
};
-function PanelTab({ panel, region, side }: { panel: Panel; region: PanelRegion; side: 'left' | 'right' }) {
+function PanelTab({ panel, region }: { panel: Panel; region: PanelRegion }) {
const { t } = useTranslation();
const activePanels = useUIStore((s) => s.activePanels);
const setActivePanel = useUIStore((s) => s.setActivePanel);
- const setUI = useUIStore((s) => s.setUI);
- const leftPanelWidth = useUIStore((s) => s.leftPanelWidth);
- const rightPanelWidth = useUIStore((s) => s.rightPanelWidth);
const isInstantTransition = useUIStore((s) => s.isInstantTransition);
const isActive = activePanels[region] === panel;
@@ -58,12 +55,6 @@ function PanelTab({ panel, region, side }: { panel: Panel; region: PanelRegion;
const handleClick = () => {
setActivePanel(region, panel);
- if (side === 'left' && leftPanelWidth < 200) {
- setUI({ leftPanelWidth: 320 });
- }
- if (side === 'right' && rightPanelWidth < 200) {
- setUI({ rightPanelWidth: 320 });
- }
};
return (
@@ -94,15 +85,7 @@ function PanelTab({ panel, region, side }: { panel: Panel; region: PanelRegion;
);
}
-export default function PanelSwitcher({
- region,
- side,
- placement,
-}: {
- region: PanelRegion;
- side: 'left' | 'right';
- placement: SwitcherPlacement;
-}) {
+export default function PanelSwitcher({ region, placement }: { region: PanelRegion; placement: SwitcherPlacement }) {
const panelLayout = useUIStore((s) => s.panelLayout);
const panels = panelLayout[region];
const movePanelToIndex = useUIStore((s) => s.movePanelToIndex);
@@ -230,7 +213,7 @@ export default function PanelSwitcher({
{panels.map((id) => (
-
+
))}
diff --git a/src/components/panel/SidePanelArea.tsx b/src/components/panel/SidePanelArea.tsx
index bcfb7c1973..74ab60d272 100644
--- a/src/components/panel/SidePanelArea.tsx
+++ b/src/components/panel/SidePanelArea.tsx
@@ -7,11 +7,10 @@ import { SwitcherPlacement, useUIStore } from '../../store/useUIStore';
import { Panel, PanelRegion } from '../ui/AppProperties';
import PanelSwitcher from './PanelSwitcher';
-const COLLAPSE_THRESHOLD = 200;
-
interface SidePanelAreaProps {
side: 'left' | 'right';
width: number;
+ isVisible: boolean;
topRegion: PanelRegion;
bottomRegion: PanelRegion;
renderPanel: (panel: Panel) => React.ReactNode;
@@ -23,14 +22,14 @@ function RegionDroppableContainer({
region,
side,
renderPanel,
- width,
+ isVisible,
isInstantTransition,
isResizing,
}: {
region: PanelRegion;
side: 'left' | 'right';
renderPanel: (panel: Panel) => React.ReactNode;
- width: number;
+ isVisible: boolean;
isInstantTransition: boolean;
isResizing: boolean;
}) {
@@ -111,8 +110,6 @@ function RegionDroppableContainer({
const isFlexRow = placement === 'left' || placement === 'right';
const showSwitcherFirst = placement === 'left' || placement === 'top';
- const isCollapsed = width < COLLAPSE_THRESHOLD;
-
return (
- {showSwitcherFirst &&
}
+ {showSwitcherFirst &&
}
@@ -180,7 +177,7 @@ function RegionDroppableContainer({
- {!showSwitcherFirst &&
}
+ {!showSwitcherFirst &&
}
);
@@ -306,6 +303,7 @@ function SplitOverlayDropzone({
export default function SidePanelArea({
side,
width,
+ isVisible,
topRegion,
bottomRegion,
renderPanel,
@@ -371,19 +369,20 @@ export default function SidePanelArea({
const topSplitIsTop = topPlacement === 'bottom';
const bottomSplitIsTop = bottomPlacement !== 'top';
- const isCollapsed = width < COLLAPSE_THRESHOLD;
- const shouldAnimateWidth = !isInstantTransition && (!isResizing || isCollapsed);
+ const shouldAnimateWidth = !isInstantTransition && !isResizing;
return (
- {side === 'right' && (
+ {side === 'right' && isVisible && (
)}
@@ -397,7 +396,7 @@ export default function SidePanelArea({
region={topRegion}
side={side}
renderPanel={renderPanel}
- width={width}
+ isVisible={isVisible}
isInstantTransition={isInstantTransition}
isResizing={isResizing}
/>
@@ -426,7 +425,7 @@ export default function SidePanelArea({
region={bottomRegion}
side={side}
renderPanel={renderPanel}
- width={width}
+ isVisible={isVisible}
isInstantTransition={isInstantTransition}
isResizing={isResizing}
/>
@@ -439,7 +438,7 @@ export default function SidePanelArea({
region={topRegion}
side={side}
renderPanel={renderPanel}
- width={width}
+ isVisible={isVisible}
isInstantTransition={isInstantTransition}
isResizing={isResizing}
/>
@@ -447,7 +446,7 @@ export default function SidePanelArea({
)}
- {side === 'left' && (
+ {side === 'left' && isVisible && (
)}
diff --git a/src/components/ui/AppProperties.tsx b/src/components/ui/AppProperties.tsx
index d70db261d0..7e527cdfc5 100644
--- a/src/components/ui/AppProperties.tsx
+++ b/src/components/ui/AppProperties.tsx
@@ -167,6 +167,8 @@ export enum ThumbnailAspectRatio {
export interface WorkspaceState {
leftPanelWidth: number;
rightPanelWidth: number;
+ leftPanelVisible?: boolean;
+ rightPanelVisible?: boolean;
leftTopHeight: number;
rightTopHeight: number;
panelLayout: Record;
diff --git a/src/hooks/useAppInitialization.ts b/src/hooks/useAppInitialization.ts
index 87b88ff4ba..9a046cdf99 100644
--- a/src/hooks/useAppInitialization.ts
+++ b/src/hooks/useAppInitialization.ts
@@ -2,7 +2,7 @@ import { useEffect, useRef } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { useShallow } from 'zustand/react/shallow';
import { useSettingsStore } from '../store/useSettingsStore';
-import { useUIStore } from '../store/useUIStore';
+import { DEFAULT_SIDE_PANEL_WIDTH, MIN_SIDE_PANEL_WIDTH, useUIStore } from '../store/useUIStore';
import { useLibraryStore } from '../store/useLibraryStore';
import { useEditorStore } from '../store/useEditorStore';
import { useProcessStore } from '../store/useProcessStore';
@@ -91,6 +91,8 @@ export const useAppInitialization = ({
useShallow((state) => ({
leftPanelWidth: state.leftPanelWidth,
rightPanelWidth: state.rightPanelWidth,
+ leftPanelVisible: state.leftPanelVisible,
+ rightPanelVisible: state.rightPanelVisible,
leftTopHeight: state.leftTopHeight,
rightTopHeight: state.rightTopHeight,
panelLayout: state.panelLayout,
@@ -191,9 +193,18 @@ export const useAppInitialization = ({
}
if (settings?.workspace) {
+ const savedLeftPanelWidth = settings.workspace.leftPanelWidth;
+ const savedRightPanelWidth = settings.workspace.rightPanelWidth;
+ const leftPanelWasCollapsed =
+ typeof savedLeftPanelWidth === 'number' && savedLeftPanelWidth < MIN_SIDE_PANEL_WIDTH;
+ const rightPanelWasCollapsed =
+ typeof savedRightPanelWidth === 'number' && savedRightPanelWidth < MIN_SIDE_PANEL_WIDTH;
+
setUI({
- leftPanelWidth: settings.workspace.leftPanelWidth,
- rightPanelWidth: settings.workspace.rightPanelWidth,
+ leftPanelWidth: leftPanelWasCollapsed ? DEFAULT_SIDE_PANEL_WIDTH : savedLeftPanelWidth,
+ rightPanelWidth: rightPanelWasCollapsed ? DEFAULT_SIDE_PANEL_WIDTH : savedRightPanelWidth,
+ leftPanelVisible: settings.workspace.leftPanelVisible ?? !leftPanelWasCollapsed,
+ rightPanelVisible: settings.workspace.rightPanelVisible ?? !rightPanelWasCollapsed,
leftTopHeight: settings.workspace.leftTopHeight,
rightTopHeight: settings.workspace.rightTopHeight,
panelLayout: settings.workspace.panelLayout,
diff --git a/src/hooks/useKeyboardShortcuts.ts b/src/hooks/useKeyboardShortcuts.ts
index 65b5fa4ff3..6c4d4b0fad 100644
--- a/src/hooks/useKeyboardShortcuts.ts
+++ b/src/hooks/useKeyboardShortcuts.ts
@@ -305,6 +305,20 @@ export const useKeyboardShortcuts = ({
s.editor.setEditor({ showOriginal: !s.editor.showOriginal });
},
},
+ toggle_left_panel: {
+ shouldFire: () => true,
+ execute: (e: KeyboardEvent, s: ReturnType) => {
+ e.preventDefault();
+ s.ui.toggleLeftPanel();
+ },
+ },
+ toggle_right_panel: {
+ shouldFire: () => true,
+ execute: (e: KeyboardEvent, s: ReturnType) => {
+ e.preventDefault();
+ s.ui.toggleRightPanel();
+ },
+ },
toggle_adjustments: {
shouldFire: () => true,
execute: (e: any, s: any) => {
diff --git a/src/i18n/locales/ca.json b/src/i18n/locales/ca.json
index bdb4ddb688..3aa45f070c 100644
--- a/src/i18n/locales/ca.json
+++ b/src/i18n/locales/ca.json
@@ -1529,6 +1529,8 @@
"toggle_export": "Alternar tauler d'Exportació",
"toggle_folder_tree": "Alternar tauler d'arbre de carpetes",
"toggle_fullscreen": "Alternar pantalla completa",
+ "toggle_left_panel": "Alternar el tauler esquerre",
+ "toggle_right_panel": "Alternar el tauler dret",
"toggle_library_exif": "Alternar superposició EXIF",
"toggle_masks": "Alternar tauler de Màscares",
"toggle_metadata": "Alternar tauler de Metadades",
diff --git a/src/i18n/locales/de.json b/src/i18n/locales/de.json
index ef6454dfdc..be8a170265 100644
--- a/src/i18n/locales/de.json
+++ b/src/i18n/locales/de.json
@@ -1529,6 +1529,8 @@
"toggle_export": "Exportieren-Panel ein-/ausblenden",
"toggle_folder_tree": "Ordnerstruktur-Panel ein-/ausblenden",
"toggle_fullscreen": "Vollbild umschalten",
+ "toggle_left_panel": "Linkes Bedienfeld ein-/ausblenden",
+ "toggle_right_panel": "Rechtes Bedienfeld ein-/ausblenden",
"toggle_library_exif": "EXIF-Überlagerung ein-/ausblenden",
"toggle_masks": "Maskieren-Panel ein-/ausblenden",
"toggle_metadata": "Metadaten-Panel ein-/ausblenden",
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index d1c2a8d433..d8d44bdc5b 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -1529,6 +1529,8 @@
"toggle_export": "Toggle Export panel",
"toggle_folder_tree": "Toggle Folder Tree panel",
"toggle_fullscreen": "Toggle fullscreen",
+ "toggle_left_panel": "Toggle left panel",
+ "toggle_right_panel": "Toggle right panel",
"toggle_library_exif": "Toggle EXIF overlay",
"toggle_masks": "Toggle Masks panel",
"toggle_metadata": "Toggle Metadata panel",
diff --git a/src/i18n/locales/es.json b/src/i18n/locales/es.json
index f45bb40ee7..bda9ebdda8 100644
--- a/src/i18n/locales/es.json
+++ b/src/i18n/locales/es.json
@@ -1562,6 +1562,8 @@
"toggle_export": "Alternar panel de Exportación",
"toggle_folder_tree": "Alternar panel de árbol de carpetas",
"toggle_fullscreen": "Alternar pantalla completa",
+ "toggle_left_panel": "Alternar panel izquierdo",
+ "toggle_right_panel": "Alternar panel derecho",
"toggle_library_exif": "Alternar superposición EXIF",
"toggle_masks": "Alternar panel de Máscaras",
"toggle_metadata": "Alternar panel de Metadatos",
diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json
index d66fa1b021..327e536b7a 100644
--- a/src/i18n/locales/fr.json
+++ b/src/i18n/locales/fr.json
@@ -1562,6 +1562,8 @@
"toggle_export": "Basculer le panneau d'exportation",
"toggle_folder_tree": "Afficher/Masquer le panneau d'arborescence des dossiers",
"toggle_fullscreen": "Basculer en plein écran",
+ "toggle_left_panel": "Afficher ou masquer le panneau gauche",
+ "toggle_right_panel": "Afficher ou masquer le panneau droit",
"toggle_library_exif": "Basculer la superposition EXIF",
"toggle_masks": "Basculer le panneau des masques",
"toggle_metadata": "Basculer le panneau des métadonnées",
diff --git a/src/i18n/locales/it.json b/src/i18n/locales/it.json
index 35b016e6ad..b864b199e8 100644
--- a/src/i18n/locales/it.json
+++ b/src/i18n/locales/it.json
@@ -1562,6 +1562,8 @@
"toggle_export": "Attiva/Disattiva pannello Esportazione",
"toggle_folder_tree": "Mostra/Nascondi pannello albero delle cartelle",
"toggle_fullscreen": "Attiva/Disattiva schermo intero",
+ "toggle_left_panel": "Attiva/disattiva pannello sinistro",
+ "toggle_right_panel": "Attiva/disattiva pannello destro",
"toggle_library_exif": "Attiva/Disattiva overlay EXIF",
"toggle_masks": "Attiva/Disattiva pannello Maschere",
"toggle_metadata": "Attiva/Disattiva pannello Metadati",
diff --git a/src/i18n/locales/ja.json b/src/i18n/locales/ja.json
index 5f4a3b7803..86d68b6ba1 100644
--- a/src/i18n/locales/ja.json
+++ b/src/i18n/locales/ja.json
@@ -1527,6 +1527,8 @@
"toggle_export": "書き出しパネルの表示/非表示",
"toggle_folder_tree": "フォルダーツリーパネルの切り替え",
"toggle_fullscreen": "全画面表示の切り替え",
+ "toggle_left_panel": "左パネルの表示/非表示",
+ "toggle_right_panel": "右パネルの表示/非表示",
"toggle_library_exif": "EXIF重ね合わせ表示の表示/非表示",
"toggle_masks": "マスクパネルの表示/非表示",
"toggle_metadata": "メタデータパネルの表示/非表示",
diff --git a/src/i18n/locales/ko.json b/src/i18n/locales/ko.json
index 1a2fbc8f70..981c6bb478 100644
--- a/src/i18n/locales/ko.json
+++ b/src/i18n/locales/ko.json
@@ -1527,6 +1527,8 @@
"toggle_export": "내보내기 패널 전환",
"toggle_folder_tree": "폴더 트리 패널 토글",
"toggle_fullscreen": "전체 화면 전환",
+ "toggle_left_panel": "왼쪽 패널 전환",
+ "toggle_right_panel": "오른쪽 패널 전환",
"toggle_library_exif": "EXIF 오버레이 전환",
"toggle_masks": "마스크 패널 전환",
"toggle_metadata": "메타데이터 패널 전환",
diff --git a/src/i18n/locales/pl.json b/src/i18n/locales/pl.json
index e7ba2241ce..93ad1eae22 100644
--- a/src/i18n/locales/pl.json
+++ b/src/i18n/locales/pl.json
@@ -1595,6 +1595,8 @@
"toggle_export": "Przełącz panel Eksport",
"toggle_folder_tree": "Przełącz panel drzewa folderów",
"toggle_fullscreen": "Przełącz tryb pełnoekranowy",
+ "toggle_left_panel": "Przełącz lewy panel",
+ "toggle_right_panel": "Przełącz prawy panel",
"toggle_library_exif": "Przełącz nakładkę EXIF",
"toggle_masks": "Przełącz panel Maski",
"toggle_metadata": "Przełącz panel Metadane",
diff --git a/src/i18n/locales/pt.json b/src/i18n/locales/pt.json
index 5371655958..b2d3c78803 100644
--- a/src/i18n/locales/pt.json
+++ b/src/i18n/locales/pt.json
@@ -1562,6 +1562,8 @@
"toggle_export": "Alternar painel de Exportação",
"toggle_folder_tree": "Alternar painel da árvore de pastas",
"toggle_fullscreen": "Alternar tela cheia",
+ "toggle_left_panel": "Alternar painel esquerdo",
+ "toggle_right_panel": "Alternar painel direito",
"toggle_library_exif": "Alternar sobreposição EXIF",
"toggle_masks": "Alternar painel de Máscaras",
"toggle_metadata": "Alternar painel de Metadados",
diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json
index 13548cc904..c76392a297 100644
--- a/src/i18n/locales/ru.json
+++ b/src/i18n/locales/ru.json
@@ -1595,6 +1595,8 @@
"toggle_export": "Панель экспорта",
"toggle_folder_tree": "Показать/скрыть панель дерева папок",
"toggle_fullscreen": "Полноэкранный режим",
+ "toggle_left_panel": "Показать или скрыть левую панель",
+ "toggle_right_panel": "Показать или скрыть правую панель",
"toggle_library_exif": "Информация EXIF поверх сетки",
"toggle_masks": "Панель масок",
"toggle_metadata": "Панель метаданных",
diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json
index a926ce0de4..4ec990428a 100644
--- a/src/i18n/locales/zh-CN.json
+++ b/src/i18n/locales/zh-CN.json
@@ -1527,6 +1527,8 @@
"toggle_export": "切换导出面板",
"toggle_folder_tree": "切换文件夹树面板",
"toggle_fullscreen": "切换全屏",
+ "toggle_left_panel": "切换左侧面板",
+ "toggle_right_panel": "切换右侧面板",
"toggle_library_exif": "切换 EXIF 叠加",
"toggle_masks": "切换蒙版面板",
"toggle_metadata": "切换元数据面板",
diff --git a/src/i18n/locales/zh-TW.json b/src/i18n/locales/zh-TW.json
index 5e355ac6df..ee91fbd39b 100644
--- a/src/i18n/locales/zh-TW.json
+++ b/src/i18n/locales/zh-TW.json
@@ -1527,6 +1527,8 @@
"toggle_export": "切換匯出面板",
"toggle_folder_tree": "切換資料夾樹面板",
"toggle_fullscreen": "切換全屏",
+ "toggle_left_panel": "切換左側面板",
+ "toggle_right_panel": "切換右側面板",
"toggle_library_exif": "切換 EXIF 疊加",
"toggle_masks": "切換遮色片面板",
"toggle_metadata": "切換後設資料面板",
diff --git a/src/store/useUIStore.ts b/src/store/useUIStore.ts
index 52ddcf899c..2ca33c12e7 100644
--- a/src/store/useUIStore.ts
+++ b/src/store/useUIStore.ts
@@ -1,6 +1,9 @@
import { create } from 'zustand';
import { ImageFile, Panel, UiVisibility, CullingSuggestions, PanelRegion } from '../components/ui/AppProperties';
+export const DEFAULT_SIDE_PANEL_WIDTH = 320;
+export const MIN_SIDE_PANEL_WIDTH = 200;
+
export type SwitcherPlacement = 'bottom' | 'right' | 'left' | 'top';
export interface CollapsibleSectionsState {
@@ -79,6 +82,8 @@ interface UIState {
leftPanelWidth: number;
rightPanelWidth: number;
+ leftPanelVisible: boolean;
+ rightPanelVisible: boolean;
bottomPanelHeight: number;
leftTopHeight: number;
rightTopHeight: number;
@@ -124,6 +129,8 @@ interface UIState {
collageModalState: CollageModalState;
setUI: (updater: Partial | ((state: UIState) => Partial)) => void;
+ toggleLeftPanel: () => void;
+ toggleRightPanel: () => void;
setPanel: (panel: Panel | null) => void;
customEscapeHandler: (() => void) | null;
setCustomEscapeHandler: (handler: (() => void) | null) => void;
@@ -141,8 +148,10 @@ export const useUIStore = create((set, get) => ({
isLibraryExportPanelVisible: false,
isSettingsOpen: false,
- leftPanelWidth: 320,
- rightPanelWidth: 320,
+ leftPanelWidth: DEFAULT_SIDE_PANEL_WIDTH,
+ rightPanelWidth: DEFAULT_SIDE_PANEL_WIDTH,
+ leftPanelVisible: true,
+ rightPanelVisible: true,
bottomPanelHeight: 144,
leftTopHeight: 450,
rightTopHeight: 450,
@@ -224,6 +233,9 @@ export const useUIStore = create((set, get) => ({
setUI: (updater) => set((state) => (typeof updater === 'function' ? updater(state) : updater)),
+ toggleLeftPanel: () => set((state) => ({ leftPanelVisible: !state.leftPanelVisible })),
+ toggleRightPanel: () => set((state) => ({ rightPanelVisible: !state.rightPanelVisible })),
+
setLayoutDragItem: (panel) => set({ activeLayoutDragItem: panel }),
movePanel: (panel, toRegion) =>
@@ -318,7 +330,10 @@ export const useUIStore = create((set, get) => ({
break;
}
}
- if (targetRegion) state.setActivePanel(targetRegion, panelId);
+ if (targetRegion) {
+ state.setActivePanel(targetRegion, panelId);
+ set(targetRegion.startsWith('left') ? { leftPanelVisible: true } : { rightPanelVisible: true });
+ }
},
customEscapeHandler: null,
diff --git a/src/utils/keyboardUtils.ts b/src/utils/keyboardUtils.ts
index 2771063f8f..9a7b126030 100644
--- a/src/utils/keyboardUtils.ts
+++ b/src/utils/keyboardUtils.ts
@@ -163,6 +163,18 @@ export const KEYBIND_DEFINITIONS: KeybindDefinition[] = [
defaultCombo: ['shift', 'Digit5'],
section: 'rating',
},
+ {
+ action: 'toggle_left_panel',
+ description: 'settings.keybinds.actions.toggle_left_panel',
+ defaultCombo: ['ctrl', 'KeyB'],
+ section: 'panels',
+ },
+ {
+ action: 'toggle_right_panel',
+ description: 'settings.keybinds.actions.toggle_right_panel',
+ defaultCombo: ['ctrl', 'shift', 'KeyB'],
+ section: 'panels',
+ },
{
action: 'toggle_adjustments',
description: 'settings.keybinds.actions.toggle_adjustments',
diff --git a/src/window/TitleBar.tsx b/src/window/TitleBar.tsx
index bcd75f341b..110fef7375 100644
--- a/src/window/TitleBar.tsx
+++ b/src/window/TitleBar.tsx
@@ -1,7 +1,10 @@
import { useCallback, useState, useEffect } from 'react';
import { platform } from '@tauri-apps/plugin-os';
import { getCurrentWindow } from '@tauri-apps/api/window';
-import { Minus, Square, X } from 'lucide-react';
+import { useTranslation } from 'react-i18next';
+import clsx from 'clsx';
+import { Minus, PanelLeft, PanelRight, Square, X } from 'lucide-react';
+import { useUIStore } from '../store/useUIStore';
const RestoreDownIcon = ({ size = 14, className = '' }) => (
);
-export default function TitleBar() {
+export default function TitleBar({ showPanelControls = false }: { showPanelControls?: boolean }) {
+ const { t } = useTranslation();
const [osPlatform, setOsPlatform] = useState('');
const [isMaximized, setIsMaximized] = useState(false);
+ const leftPanelVisible = useUIStore((state) => state.leftPanelVisible);
+ const rightPanelVisible = useUIStore((state) => state.rightPanelVisible);
+ const toggleLeftPanel = useUIStore((state) => state.toggleLeftPanel);
+ const toggleRightPanel = useUIStore((state) => state.toggleRightPanel);
const appWindow = getCurrentWindow();
@@ -120,6 +128,41 @@ export default function TitleBar() {
+ {showPanelControls && (
+
+ )}
+
{isLinux && (