From d1601517f065ee0a62e68971b15e24c48f7882eb Mon Sep 17 00:00:00 2001 From: Michelle Zhang <56095982+michellewzhang@users.noreply.github.com> Date: Fri, 20 Sep 2024 10:18:44 -0700 Subject: [PATCH] ref(flags): search button leads to focus in drawer (#77839) Add a search icon button to the feature flag section, which opens the fly-out drawer with the search focused. This is the same behavior as the breadcrumbs section. https://github.com/user-attachments/assets/553cfd39-f4b3-480b-aa0d-ce961e2d6361 --- .../events/breadcrumbs/breadcrumbsDrawer.tsx | 20 +---- .../events/{eventReplay => }/eventDrawer.tsx | 0 .../featureFlags/eventFeatureFlagList.tsx | 73 +++++++++++-------- .../events/featureFlags/featureFlagDrawer.tsx | 7 +- .../app/components/events/useFocusControl.tsx | 21 ++++++ .../groupEventAttachmentsDrawer.tsx | 2 +- 6 files changed, 74 insertions(+), 49 deletions(-) rename static/app/components/events/{eventReplay => }/eventDrawer.tsx (100%) create mode 100644 static/app/components/events/useFocusControl.tsx diff --git a/static/app/components/events/breadcrumbs/breadcrumbsDrawer.tsx b/static/app/components/events/breadcrumbs/breadcrumbsDrawer.tsx index f2b16699be1759..5d3d9520be0f4c 100644 --- a/static/app/components/events/breadcrumbs/breadcrumbsDrawer.tsx +++ b/static/app/components/events/breadcrumbs/breadcrumbsDrawer.tsx @@ -1,4 +1,4 @@ -import {useCallback, useMemo, useState} from 'react'; +import {useMemo, useState} from 'react'; import {useTheme} from '@emotion/react'; import styled from '@emotion/styled'; @@ -24,13 +24,14 @@ import { NavigationCrumbs, SearchInput, ShortId, -} from 'sentry/components/events/eventReplay/eventDrawer'; +} from 'sentry/components/events/eventDrawer'; import { applyBreadcrumbSearch, BREADCRUMB_SORT_LOCALSTORAGE_KEY, BREADCRUMB_SORT_OPTIONS, BreadcrumbSort, } from 'sentry/components/events/interfaces/breadcrumbs'; +import useFocusControl from 'sentry/components/events/useFocusControl'; import {InputGroup} from 'sentry/components/inputGroup'; import {IconClock, IconFilter, IconSearch, IconSort, IconTimer} from 'sentry/icons'; import {t} from 'sentry/locale'; @@ -49,21 +50,6 @@ export const enum BreadcrumbControlOptions { SORT = 'sort', } -function useFocusControl(initialFocusControl?: BreadcrumbControlOptions) { - const [focusControl, setFocusControl] = useState(initialFocusControl); - // If the focused control element is blurred, unset the state to remove styles - // This will allow us to simulate :focus-visible on the button elements. - const getFocusProps = useCallback( - (option: BreadcrumbControlOptions) => { - return option === focusControl - ? {autoFocus: true, onBlur: () => setFocusControl(undefined)} - : {}; - }, - [focusControl] - ); - return {getFocusProps}; -} - interface BreadcrumbsDrawerProps { breadcrumbs: EnhancedCrumb[]; event: Event; diff --git a/static/app/components/events/eventReplay/eventDrawer.tsx b/static/app/components/events/eventDrawer.tsx similarity index 100% rename from static/app/components/events/eventReplay/eventDrawer.tsx rename to static/app/components/events/eventDrawer.tsx diff --git a/static/app/components/events/featureFlags/eventFeatureFlagList.tsx b/static/app/components/events/featureFlags/eventFeatureFlagList.tsx index a8bd9dda3da71c..9ce421ed1eba7f 100644 --- a/static/app/components/events/featureFlags/eventFeatureFlagList.tsx +++ b/static/app/components/events/featureFlags/eventFeatureFlagList.tsx @@ -9,6 +9,7 @@ import { CardContainer, FeatureFlagDrawer, FLAG_SORT_OPTIONS, + FlagControlOptions, FlagSort, getLabel, } from 'sentry/components/events/featureFlags/featureFlagDrawer'; @@ -16,7 +17,7 @@ import useDrawer from 'sentry/components/globalDrawer'; import KeyValueData, { type KeyValueDataContentProps, } from 'sentry/components/keyValueData'; -import {IconMegaphone, IconSort} from 'sentry/icons'; +import {IconMegaphone, IconSearch, IconSort} from 'sentry/icons'; import {t} from 'sentry/locale'; import type {Event, FeatureFlag} from 'sentry/types/event'; import type {Group} from 'sentry/types/group'; @@ -91,35 +92,39 @@ export function EventFeatureFlagList({ ? [...hydratedFlags].reverse() : hydratedFlags; - const onViewAllFlags = useCallback(() => { - trackAnalytics('flags.view-all-clicked', { - organization, - }); - openDrawer( - () => ( - - ), - { - ariaLabel: t('Feature flags drawer'), - // We prevent a click on the 'View All' button from closing the drawer so that - // we don't reopen it immediately, and instead let the button handle this itself. - shouldCloseOnInteractOutside: element => { - const viewAllButton = viewAllButtonRef.current; - if (viewAllButton?.contains(element)) { - return false; - } - return true; - }, - transitionProps: {stiffness: 1000}, - } - ); - }, [openDrawer, event, group, project, sortMethod, hydratedFlags, organization]); + const onViewAllFlags = useCallback( + (focusControl?: FlagControlOptions) => { + trackAnalytics('flags.view-all-clicked', { + organization, + }); + openDrawer( + () => ( + + ), + { + ariaLabel: t('Feature flags drawer'), + // We prevent a click on the 'View All' button from closing the drawer so that + // we don't reopen it immediately, and instead let the button handle this itself. + shouldCloseOnInteractOutside: element => { + const viewAllButton = viewAllButtonRef.current; + if (viewAllButton?.contains(element)) { + return false; + } + return true; + }, + transitionProps: {stiffness: 1000}, + } + ); + }, + [openDrawer, event, group, project, sortMethod, hydratedFlags, organization] + ); if (!hydratedFlags.length) { return null; @@ -128,10 +133,18 @@ export function EventFeatureFlagList({ const actions = ( {feedbackButton} +