diff --git a/client/web/src/search/home/SearchPageInput.tsx b/client/web/src/search/home/SearchPageInput.tsx index b542bef05b6..3df3d727527 100644 --- a/client/web/src/search/home/SearchPageInput.tsx +++ b/client/web/src/search/home/SearchPageInput.tsx @@ -1,5 +1,5 @@ import * as H from 'history' -import React, { useState, useCallback, useEffect, useMemo } from 'react' +import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react' import { Form } from 'reactstrap' import { ActivationProps } from '@sourcegraph/shared/src/components/activation/Activation' @@ -80,11 +80,14 @@ export const SearchPageInput: React.FunctionComponent = (props: Props) => ]) const showOnboardingTour = props.showOnboardingTour && isHomepage + const tourContainer = useRef(null) + const { shouldFocusQueryInput, ...onboardingTourQueryInputProps } = useSearchOnboardingTour({ ...props, showOnboardingTour, queryState: userQueryState, setQueryState: setUserQueryState, + stepsContainer: tourContainer.current ?? undefined, }) const onSubmit = useCallback( (event?: React.FormEvent): void => { @@ -104,6 +107,9 @@ export const SearchPageInput: React.FunctionComponent = (props: Props) =>
+ {/* Search onboarding tour must be rendered before the SearchBox so + the Monaco autocomplete suggestions are not blocked by the tour. */} +
Get started
- - + + ` content.querySelector('.tour-language-button')?.addEventListener('click', () => { languageButtonHandler() @@ -170,8 +171,11 @@ const generateStepContent = (title: string, description: string): HTMLElement => return element } -const useTourWithSteps = ({ setQueryState }: Pick): Tour => { - const tour = useMemo(() => new Shepherd.Tour(tourOptions), []) +const useTourWithSteps = ({ + setQueryState, + stepsContainer, +}: Pick): Tour => { + const tour = useMemo(() => new Shepherd.Tour({ ...tourOptions, stepsContainer }), [stepsContainer]) useEffect(() => { tour.addSteps([ { @@ -304,6 +308,11 @@ interface UseSearchOnboardingTourOptions { queryState: QueryState history: H.History location: H.Location + + /** + * HTML element where the steps should be attached to + */ + stepsContainer?: HTMLElement } /** @@ -330,8 +339,9 @@ export const useSearchOnboardingTour = ({ showOnboardingTour, queryState, setQueryState, + stepsContainer, }: UseSearchOnboardingTourOptions): UseSearchOnboardingTourReturnValue => { - const tour = useTourWithSteps({ setQueryState }) + const tour = useTourWithSteps({ setQueryState, stepsContainer }) // True when the user has manually cancelled the tour const [hasCancelledTour, setHasCancelledTour] = useTemporarySetting('search.onboarding.tourCancelled', false) const [daysActiveCount] = useTemporarySetting('user.daysActiveCount', 0) diff --git a/package.json b/package.json index bd2695a0b76..9599b0e0270 100644 --- a/package.json +++ b/package.json @@ -403,7 +403,7 @@ "rxjs": "^6.6.3", "sanitize-html": "^2.0.0", "semver": "^7.3.2", - "shepherd.js": "^8.0.2", + "shepherd.js": "^8.3.1", "string-score": "^1.0.1", "tabbable": "^5.1.5", "tagged-template-noop": "^2.1.1", diff --git a/yarn.lock b/yarn.lock index a144f68a879..63fa5125b8c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2862,10 +2862,10 @@ qs "^6.7.0" url-parse "^1.4.7" -"@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0": - version "2.9.2" - resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353" - integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q== +"@popperjs/core@^2.5.4", "@popperjs/core@^2.6.0", "@popperjs/core@^2.9.2": + version "2.10.2" + resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590" + integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ== "@reach/accordion@^0.10.2": version "0.10.2" @@ -21235,12 +21235,12 @@ shellwords@^0.1.1: resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shepherd.js@^8.0.2: - version "8.0.2" - resolved "https://registry.npmjs.org/shepherd.js/-/shepherd.js-8.0.2.tgz#30675a68883c474b5c7b4056b98f2423b577708f" - integrity sha512-qFt5vrnVoshg6fS5gKGQznYGyIaEclyKKSl1Siw6gO7GyKnCEJ2aBDrp8pxKusMfZo5J5dtgeKJtsRav5cimjA== +shepherd.js@^8.3.1: + version "8.3.1" + resolved "https://registry.npmjs.org/shepherd.js/-/shepherd.js-8.3.1.tgz#131eeefc5eb2bc44c9e23d0da139db46b2b55339" + integrity sha512-IhxZNhnK2m/pNTXudNfYrcwvcZNWkeYngQbQee8nC3xJ2GjeIatGqivhdZAMZ+LeogZvKMakB931d/V534uhrw== dependencies: - "@popperjs/core" "^2.4.4" + "@popperjs/core" "^2.9.2" deepmerge "^4.2.2" smoothscroll-polyfill "^0.4.4"