diff --git a/src/components/Openings/OpeningSelectionModal.tsx b/src/components/Openings/OpeningSelectionModal.tsx index 70065d5f..f8c998c6 100644 --- a/src/components/Openings/OpeningSelectionModal.tsx +++ b/src/components/Openings/OpeningSelectionModal.tsx @@ -347,7 +347,7 @@ const TabNavigation: React.FC<{ const { isMobile } = useContext(WindowSizeContext) return ( -
+
{/* Queue */} -
+

Queue @@ -1308,7 +1308,7 @@ const SelectedPanel: React.FC<{ showTargetSlider, }) => (

@@ -2648,7 +2648,7 @@ export const OpeningSelectionModal: React.FC = ({ /> {/* Main Content - Responsive Layout */} -
+
= ({
{/* Mobile-only Selected Panel */} -
+
() => { + document + .getElementById(id) + ?.dispatchEvent(new MouseEvent('click', { bubbles: true })) +} + +const openingDrillTourSteps = (): TourStep[] => { + const isMobile = typeof window !== 'undefined' && window.innerWidth < 1024 + + return [ + { + id: 'opening-drill-overview', + title: 'Welcome to Opening Drills', + description: + 'Practice your openings by drilling specific openings against Maia. First select the openings you want to practice, configure drill settings, and practice them repeatedly until they become second nature. You can track your progress and analyze your performance after each drill.', + targetId: 'opening-drill-modal', + placement: 'bottom', + }, + { + id: 'opening-drill-selection', + title: 'Select Openings', + description: + 'Browse and select the openings you want to practice. You can search for specific variations and add them using the + button.', + targetId: 'opening-drill-browse', + placement: isMobile ? 'bottom' : 'right', + ...(isMobile && { beforeAction: clickTab('opening-drill-browse') }), + }, + { + id: 'opening-drill-start', + title: 'Start Drilling', + description: + 'Customize your drills by choosing the Maia opponent strength, how many moves in each drill, and how many drills to do. Click "Start Drilling" to start!', + targetId: isMobile ? 'opening-drill-selected' : 'opening-drill-preview', + placement: isMobile ? 'bottom' : 'left', + ...(isMobile && { beforeAction: clickTab('opening-drill-selected') }), + }, + { + id: 'opening-drill-gameplay', + title: 'Drill Experience', + description: + "During drilling, you'll play through your selected openings against Maia until reaching the target move count. After each drill, you can analyze the moves you played, see how the Maia and Stockfish evaluations changed throughout the game, and learn from your insights.", + targetId: isMobile + ? 'opening-drill-selected-panel' + : 'opening-drill-queue', + placement: isMobile ? 'bottom' : 'left', + ...(isMobile && { beforeAction: clickTab('opening-drill-selected') }), + }, + ] +} export const tourConfigs = { analysis: { @@ -199,6 +214,6 @@ export const tourConfigs = { openingDrill: { id: 'openingDrill', name: 'Opening Drill Tour', - steps: openingDrillTourSteps, + steps: openingDrillTourSteps(), }, } diff --git a/src/contexts/TourContext.tsx b/src/contexts/TourContext.tsx index a5a32680..a5edb150 100644 --- a/src/contexts/TourContext.tsx +++ b/src/contexts/TourContext.tsx @@ -16,6 +16,7 @@ export interface TourStep { targetId: string placement?: 'top' | 'bottom' | 'left' | 'right' offset?: { x: number; y: number } + beforeAction?: () => void | Promise } export interface TourState { @@ -497,6 +498,10 @@ export const TourProvider: React.FC = ({ children }) => { const handleNext = useCallback(async () => { if (tourState.currentStep < tourState.steps.length - 1) { const nextStepIndex = tourState.currentStep + 1 + const nextStepData = tourState.steps[nextStepIndex] + if (nextStepData?.beforeAction) { + await nextStepData.beforeAction() + } await preScrollToTarget(nextStepIndex) nextStep() } else { @@ -504,7 +509,7 @@ export const TourProvider: React.FC = ({ children }) => { } }, [ tourState.currentStep, - tourState.steps.length, + tourState.steps, nextStep, endTour, preScrollToTarget, @@ -513,10 +518,14 @@ export const TourProvider: React.FC = ({ children }) => { const handlePrevious = useCallback(async () => { if (tourState.currentStep > 0) { const prevStepIndex = tourState.currentStep - 1 + const prevStepData = tourState.steps[prevStepIndex] + if (prevStepData?.beforeAction) { + await prevStepData.beforeAction() + } await preScrollToTarget(prevStepIndex) prevStep() } - }, [tourState.currentStep, prevStep, preScrollToTarget]) + }, [tourState.currentStep, tourState.steps, prevStep, preScrollToTarget]) // Update Joyride steps when tour state changes useEffect(() => {