From 2cbf7dbfa08ee08cedaca922928c82fec270151f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juliana=20Pe=C3=B1a?= Date: Fri, 15 Oct 2021 13:22:30 -0700 Subject: [PATCH] search: fix tour blocking monaco autocomplete (#26132) Monaco search autocomplete now shows over the onboarding tour. This required upgrading Shepherd.js to 8.1+, which adds the `stepsContainer` parameter which allows attaching the tour to someplace other than the end of the body. Attaching the tour to somewhere in the DOM tree above the search box will render the tour before the search box and allow the search box suggestions to show over the tour without any z-index fandangling. Fixes #25618 --- .../web/src/search/home/SearchPageInput.tsx | 8 +++++++- .../src/search/input/SearchOnboardingTour.ts | 20 ++++++++++++++----- package.json | 2 +- yarn.lock | 18 ++++++++--------- 4 files changed, 32 insertions(+), 16 deletions(-) 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"