Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ui/desktop/src/components/RecipeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import ParameterInput from './parameter/ParameterInput';
import { saveRecipe, generateRecipeFilename } from '../recipe/recipeStorage';
import { toastSuccess, toastError } from '../toasts';
import { Button } from './ui/button';
import { useEscapeKey } from '../hooks/useEscapeKey';

interface RecipeEditorProps {
config?: Recipe;
Expand Down Expand Up @@ -129,6 +130,12 @@ export default function RecipeEditor({ config }: RecipeEditorProps) {
setParameters(allParams);
}, [instructions, prompt]);

// Handle Esc key for Save Recipe Dialog
useEscapeKey(showSaveDialog, () => {
setShowSaveDialog(false);
setSaveRecipeName('');
});

const getCurrentConfig = useCallback((): Recipe => {
// Transform the internal parameters state into the desired output format.
const formattedParameters = parameters.map((param) => {
Expand Down
18 changes: 18 additions & 0 deletions ui/desktop/src/components/RecipesView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { Skeleton } from './ui/skeleton';
import { MainPanelLayout } from './Layout/MainPanelLayout';
import { Recipe, decodeRecipe } from '../recipe';
import { toastSuccess, toastError } from '../toasts';
import { useEscapeKey } from '../hooks/useEscapeKey';

interface RecipesViewProps {
onLoadRecipe?: (recipe: Recipe) => void;
Expand Down Expand Up @@ -58,6 +59,23 @@ export default function RecipesView({ _onLoadRecipe }: RecipesViewProps = {}) {
loadSavedRecipes();
}, []);

// Handle Esc key for modals
useEscapeKey(showPreview, () => setShowPreview(false));
useEscapeKey(showImportDialog, () => {
setShowImportDialog(false);
setImportDeeplink('');
setImportRecipeName('');
});
useEscapeKey(showCreateDialog, () => {
setShowCreateDialog(false);
setCreateTitle('');
setCreateDescription('');
setCreateInstructions('');
setCreatePrompt('');
setCreateActivities('');
setCreateRecipeName('');
});

// Minimum loading time to prevent skeleton flash
useEffect(() => {
if (!loading && showSkeleton) {
Expand Down
23 changes: 23 additions & 0 deletions ui/desktop/src/hooks/useEscapeKey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useEffect } from 'react';

/**
* Custom hook to handle Esc key press for closing modals
* @param isActive - Whether the hook should be active (typically when modal is open)
* @param onEscape - Callback function to execute when Esc key is pressed
*/
export function useEscapeKey(isActive: boolean, onEscape: () => void) {
useEffect(() => {
if (!isActive) return;

const handleEscKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
onEscape();
}
};

document.addEventListener('keydown', handleEscKey);
return () => {
document.removeEventListener('keydown', handleEscKey);
};
}, [isActive, onEscape]);
}
Loading