diff --git a/packages/web/src/pages/CookingMode.tsx b/packages/web/src/pages/CookingMode.tsx index df06c3c..798cf5b 100644 --- a/packages/web/src/pages/CookingMode.tsx +++ b/packages/web/src/pages/CookingMode.tsx @@ -20,6 +20,9 @@ function CookingMode() { const [showInlineIngredients, setShowInlineIngredients] = useState(true); const [completedSteps, setCompletedSteps] = useState>(new Set()); const [isFullscreen, setIsFullscreen] = useState(false); + const [ingredientsCollapsed, setIngredientsCollapsed] = useState(false); + const [collapsedSteps, setCollapsedSteps] = useState>(new Set()); + const [autoCollapseOnComplete, setAutoCollapseOnComplete] = useState(false); useEffect(() => { if (id) { @@ -71,12 +74,34 @@ function CookingMode() { const newCompleted = new Set(completedSteps); if (newCompleted.has(stepNumber)) { newCompleted.delete(stepNumber); + // When unchecking, expand the step + if (autoCollapseOnComplete) { + const newCollapsed = new Set(collapsedSteps); + newCollapsed.delete(stepNumber); + setCollapsedSteps(newCollapsed); + } } else { newCompleted.add(stepNumber); + // When checking, auto-collapse if enabled + if (autoCollapseOnComplete) { + const newCollapsed = new Set(collapsedSteps); + newCollapsed.add(stepNumber); + setCollapsedSteps(newCollapsed); + } } setCompletedSteps(newCompleted); }; + const toggleStepCollapse = (stepNumber: number) => { + const newCollapsed = new Set(collapsedSteps); + if (newCollapsed.has(stepNumber)) { + newCollapsed.delete(stepNumber); + } else { + newCollapsed.add(stepNumber); + } + setCollapsedSteps(newCollapsed); + }; + const exitCookingMode = () => { if (document.fullscreenElement) { document.exitFullscreen(); @@ -219,6 +244,15 @@ function CookingMode() { Show ingredients with steps + + @@ -243,32 +277,43 @@ function CookingMode() { {/* Ingredients Section */}
-

Ingredients

+

setIngredientsCollapsed(!ingredientsCollapsed)} + className="collapsible-header" + style={{ cursor: 'pointer' }} + > + {ingredientsCollapsed ? '▶' : '▼'} + Ingredients +

- {recipe.sections && recipe.sections.length > 0 ? ( + {!ingredientsCollapsed && ( <> - {recipe.sections.map(section => ( -
-

{section.name}

- {section.timing &&

{section.timing}

} -
    - {section.ingredients?.map((ingredient) => ( -
  • - {getScaledIngredientText(ingredient)} -
  • - ))} -
-
- ))} + {recipe.sections && recipe.sections.length > 0 ? ( + <> + {recipe.sections.map(section => ( +
+

{section.name}

+ {section.timing &&

{section.timing}

} +
    + {section.ingredients?.map((ingredient) => ( +
  • + {getScaledIngredientText(ingredient)} +
  • + ))} +
+
+ ))} + + ) : ( +
    + {allIngredients.map((ingredient) => ( +
  • + {getScaledIngredientText(ingredient)} +
  • + ))} +
+ )} - ) : ( -
    - {allIngredients.map((ingredient) => ( -
  • - {getScaledIngredientText(ingredient)} -
  • - ))} -
)}
@@ -292,25 +337,101 @@ function CookingMode() { {section.timing && {section.timing}} - {sectionInstructions.map(({ instruction, matchedIngredients }) => ( -
-
- - {instruction.timing && ( - {instruction.timing} + {sectionInstructions.map(({ instruction, matchedIngredients }) => { + const isCollapsed = collapsedSteps.has(instruction.step); + return ( +
+
+ + {instruction.timing && ( + {instruction.timing} + )} +
+ + {!isCollapsed && ( + <> +
{instruction.text}
+ + {instruction.imageUrl && ( + {`Step + )} + + {showInlineIngredients && matchedIngredients.length > 0 && ( +
+ Ingredients needed: +
    + {matchedIngredients.map((ingredient) => ( +
  • + + {getScaledIngredientText(ingredient)} + +
  • + ))} +
+
+ )} + )}
+ ); + })} +
+ ); + })} + + ) : ( + <> + {instructionsWithIngredients.map(({ instruction, matchedIngredients }) => { + const isCollapsed = collapsedSteps.has(instruction.step); + return ( +
+
+ + {instruction.timing && ( + {instruction.timing} + )} +
+ {!isCollapsed && ( + <>
{instruction.text}
{instruction.imageUrl && ( @@ -335,60 +456,12 @@ function CookingMode() {
)} -
- ))} + + )} ); })} - ) : ( - <> - {instructionsWithIngredients.map(({ instruction, matchedIngredients }) => ( -
-
- - {instruction.timing && ( - {instruction.timing} - )} -
- -
{instruction.text}
- - {instruction.imageUrl && ( - {`Step - )} - - {showInlineIngredients && matchedIngredients.length > 0 && ( -
- Ingredients needed: -
    - {matchedIngredients.map((ingredient) => ( -
  • - - {getScaledIngredientText(ingredient)} - -
  • - ))} -
-
- )} -
- ))} - )} diff --git a/packages/web/src/styles/CookingMode.css b/packages/web/src/styles/CookingMode.css index 0a4d5fc..783f628 100644 --- a/packages/web/src/styles/CookingMode.css +++ b/packages/web/src/styles/CookingMode.css @@ -423,3 +423,52 @@ border: 1px solid #ccc; } } + +/* Collapsible Elements */ +.collapsible-header { + display: flex; + align-items: center; + gap: 0.5rem; + user-select: none; +} + +.collapse-icon { + display: inline-block; + font-size: 0.9em; + margin-right: 0.25rem; + transition: transform 0.2s ease; +} + +.step-number { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.instruction-step.collapsed { + opacity: 0.6; +} + +.instruction-step.collapsed .step-header { + margin-bottom: 0; +} + +/* Toggle auto-collapse checkbox */ +.toggle-auto-collapse { + display: flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; + user-select: none; + background-color: white; + padding: 0.75rem 1rem; + border-radius: 8px; + border: 2px solid #e0e0e0; + font-size: 1rem; +} + +.toggle-auto-collapse input[type="checkbox"] { + width: 1.25rem; + height: 1.25rem; + cursor: pointer; +}