-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
styles(autofix): Use scraps to layout explorer seer drawer #106294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,12 +2,13 @@ import {useCallback, useMemo} from 'react'; | |
| import styled from '@emotion/styled'; | ||
| import {AnimatePresence} from 'framer-motion'; | ||
|
|
||
| import {Flex} from '@sentry/scraps/layout'; | ||
| import {Flex, Stack} from '@sentry/scraps/layout'; | ||
| import {Heading, Text} from '@sentry/scraps/text'; | ||
|
|
||
| import Feature from 'sentry/components/acl/feature'; | ||
| import {Breadcrumbs as NavigationBreadcrumbs} from 'sentry/components/breadcrumbs'; | ||
| import {Breadcrumbs} from 'sentry/components/breadcrumbs'; | ||
| import {ProjectAvatar} from 'sentry/components/core/avatar/projectAvatar'; | ||
| import {Button, ButtonBar} from 'sentry/components/core/button'; | ||
| import {Button} from 'sentry/components/core/button'; | ||
| import {LinkButton} from 'sentry/components/core/button/linkButton'; | ||
| import AutofixFeedback from 'sentry/components/events/autofix/autofixFeedback'; | ||
| import { | ||
|
|
@@ -33,7 +34,7 @@ import {ExplorerNextSteps} from 'sentry/components/events/autofix/v2/nextSteps'; | |
| import {formatArtifactsToMarkdown} from 'sentry/components/events/autofix/v2/utils'; | ||
| import {DrawerBody, DrawerHeader} from 'sentry/components/globalDrawer/components'; | ||
| import Placeholder from 'sentry/components/placeholder'; | ||
| import {IconAdd, IconCopy, IconSeer, IconSettings} from 'sentry/icons'; | ||
| import {IconCopy, IconRefresh, IconSeer, IconSettings} from 'sentry/icons'; | ||
| import {t} from 'sentry/locale'; | ||
| import type {Event} from 'sentry/types/event'; | ||
| import type {Group} from 'sentry/types/group'; | ||
|
|
@@ -42,7 +43,6 @@ import type {Project} from 'sentry/types/project'; | |
| import {getShortEventId} from 'sentry/utils/events'; | ||
| import useCopyToClipboard from 'sentry/utils/useCopyToClipboard'; | ||
| import useOrganization from 'sentry/utils/useOrganization'; | ||
| import {MIN_NAV_HEIGHT} from 'sentry/views/issueDetails/streamline/eventTitle'; | ||
| import type {useAiConfig} from 'sentry/views/issueDetails/streamline/hooks/useAiConfig'; | ||
| import {SeerNotices} from 'sentry/views/issueDetails/streamline/sidebar/seerNotices'; | ||
| import {openSeerExplorer} from 'sentry/views/seerExplorer/openSeerExplorer'; | ||
|
|
@@ -60,45 +60,59 @@ interface ExplorerSeerDrawerProps { | |
| const drawerBreadcrumbs = (group: Group, event: Event, project: Project) => [ | ||
| { | ||
| label: ( | ||
| <CrumbContainer> | ||
| <Flex gap="md" align="center"> | ||
| <ProjectAvatar project={project} /> | ||
| <ShortId>{group.shortId}</ShortId> | ||
| </CrumbContainer> | ||
| <Text variant="muted">{group.shortId}</Text> | ||
| </Flex> | ||
| ), | ||
| }, | ||
| {label: getShortEventId(event.id)}, | ||
| {label: t('Seer')}, | ||
| ]; | ||
|
|
||
| interface DrawerNavigatorProps { | ||
| iconAnimation: 'loading' | 'waiting'; | ||
| interface SeerDrawerHeaderProps { | ||
| event: Event; | ||
| group: Group; | ||
| project: Project; | ||
| } | ||
|
|
||
| function SeerDrawerHeader({event, group, project}: SeerDrawerHeaderProps) { | ||
| const breadcrumbs = useMemo( | ||
| () => drawerBreadcrumbs(group, event, project), | ||
| [group, event, project] | ||
| ); | ||
| return ( | ||
| <DrawerHeader> | ||
| <NavigationBreadcrumbs crumbs={breadcrumbs} /> | ||
| </DrawerHeader> | ||
| ); | ||
| } | ||
|
|
||
| interface SeerDrawerNavigatorProps { | ||
| organization: Organization; | ||
| project: Project; | ||
| copyButtonDisabled?: boolean; | ||
| loading?: boolean; | ||
| onCopyMarkdown?: () => void; | ||
| onReset?: () => void; | ||
| } | ||
|
|
||
| /** | ||
| * Common navigator section with header and buttons. | ||
| */ | ||
| function DrawerNavigator({ | ||
| iconAnimation, | ||
| function SeerDrawerNavigator({ | ||
| loading, | ||
| organization, | ||
| project, | ||
| copyButtonDisabled = false, | ||
| onCopyMarkdown, | ||
| onReset, | ||
| }: DrawerNavigatorProps) { | ||
| }: SeerDrawerNavigatorProps) { | ||
| return ( | ||
| <SeerDrawerNavigator> | ||
| <HeaderContainer> | ||
| <Header>{t('Seer')}</Header> | ||
| <IconSeer animation={iconAnimation} size="md" /> | ||
| </HeaderContainer> | ||
| <ButtonWrapper> | ||
| <SeerDrawerNavigatorContainer justify="between" padding="sm 2xl"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Navigator missing vertical alignment and background stylingMedium Severity The Additional Locations (1) |
||
| <Flex align="center" gap="sm"> | ||
| <Heading as="h3" size="xl"> | ||
| {t('Seer')} | ||
| </Heading> | ||
| <IconSeer animation={loading ? 'loading' : 'waiting'} size="md" /> | ||
| </Flex> | ||
| <Flex gap="md"> | ||
| <AutofixFeedback iconOnly /> | ||
|
|
||
| <Feature features={['organizations:autofix-seer-preferences']}> | ||
| <LinkButton | ||
| external | ||
|
|
@@ -115,18 +129,18 @@ function DrawerNavigator({ | |
| title={t('Copy analysis as Markdown / LLM prompt')} | ||
| aria-label={t('Copy analysis as Markdown')} | ||
| icon={<IconCopy />} | ||
| disabled={copyButtonDisabled} | ||
| disabled={!onCopyMarkdown} | ||
| /> | ||
| <Button | ||
| size="xs" | ||
| onClick={onReset} | ||
| icon={<IconAdd />} | ||
| icon={<IconRefresh />} | ||
| aria-label={t('Start a new analysis from scratch')} | ||
| title={t('Start a new analysis from scratch')} | ||
| disabled={!onReset} | ||
| /> | ||
| </ButtonWrapper> | ||
| </SeerDrawerNavigator> | ||
| </Flex> | ||
| </SeerDrawerNavigatorContainer> | ||
| ); | ||
| } | ||
|
|
||
|
|
@@ -219,11 +233,6 @@ export function ExplorerSeerDrawer({ | |
| copy(markdownText, {successMessage: t('Analysis copied to clipboard.')}); | ||
| }, [artifacts, group, event, copy]); | ||
|
|
||
| const breadcrumbs = useMemo( | ||
| () => drawerBreadcrumbs(group, event, project), | ||
| [group, event, project] | ||
| ); | ||
|
|
||
| const hasArtifacts = | ||
| !!artifacts.root_cause?.data || | ||
| !!artifacts.solution?.data || | ||
|
|
@@ -234,21 +243,18 @@ export function ExplorerSeerDrawer({ | |
| if (isLoading) { | ||
| return ( | ||
| <DrawerContainer> | ||
| <SeerDrawerHeader> | ||
| <NavigationCrumbs crumbs={breadcrumbs} /> | ||
| </SeerDrawerHeader> | ||
| <DrawerNavigator | ||
| iconAnimation="loading" | ||
| copyButtonDisabled={!hasArtifacts} | ||
| onCopyMarkdown={handleCopyMarkdown} | ||
| <SeerDrawerHeader event={event} group={group} project={project} /> | ||
| <SeerDrawerNavigator | ||
| loading | ||
| onCopyMarkdown={hasArtifacts ? handleCopyMarkdown : undefined} | ||
| onReset={undefined} | ||
| organization={organization} | ||
| project={project} | ||
| /> | ||
| <PlaceholderStack> | ||
| <Stack gap="xl" padding="xl"> | ||
| <Placeholder height="10rem" /> | ||
| <Placeholder height="15rem" /> | ||
| </PlaceholderStack> | ||
| </Stack> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loading state Stack missing top margin spacingLow Severity The |
||
| </DrawerContainer> | ||
| ); | ||
| } | ||
|
|
@@ -257,13 +263,9 @@ export function ExplorerSeerDrawer({ | |
| if (!runState && aiConfig.hasAutofix) { | ||
| return ( | ||
| <DrawerContainer> | ||
| <SeerDrawerHeader> | ||
| <NavigationCrumbs crumbs={breadcrumbs} /> | ||
| </SeerDrawerHeader> | ||
| <DrawerNavigator | ||
| iconAnimation="waiting" | ||
| copyButtonDisabled={!hasArtifacts} | ||
| onCopyMarkdown={handleCopyMarkdown} | ||
| <SeerDrawerHeader event={event} group={group} project={project} /> | ||
| <SeerDrawerNavigator | ||
| onCopyMarkdown={hasArtifacts ? handleCopyMarkdown : undefined} | ||
| onReset={undefined} | ||
| organization={organization} | ||
| project={project} | ||
|
|
@@ -284,13 +286,9 @@ export function ExplorerSeerDrawer({ | |
| if (!runState) { | ||
| return ( | ||
| <DrawerContainer> | ||
| <SeerDrawerHeader> | ||
| <NavigationCrumbs crumbs={breadcrumbs} /> | ||
| </SeerDrawerHeader> | ||
| <DrawerNavigator | ||
| iconAnimation="waiting" | ||
| copyButtonDisabled={!hasArtifacts} | ||
| onCopyMarkdown={handleCopyMarkdown} | ||
| <SeerDrawerHeader event={event} group={group} project={project} /> | ||
| <SeerDrawerNavigator | ||
| onCopyMarkdown={hasArtifacts ? handleCopyMarkdown : undefined} | ||
| onReset={undefined} | ||
| organization={organization} | ||
| project={project} | ||
|
|
@@ -309,16 +307,11 @@ export function ExplorerSeerDrawer({ | |
| // Has run - show artifacts and status | ||
| return ( | ||
| <DrawerContainer> | ||
| <SeerDrawerHeader> | ||
| <NavigationCrumbs crumbs={breadcrumbs} /> | ||
| </SeerDrawerHeader> | ||
| <DrawerNavigator | ||
| iconAnimation={ | ||
| runState.status === 'processing' && isPolling ? 'loading' : 'waiting' | ||
| } | ||
| copyButtonDisabled={!hasArtifacts} | ||
| onCopyMarkdown={handleCopyMarkdown} | ||
| onReset={() => reset()} | ||
| <SeerDrawerHeader event={event} group={group} project={project} /> | ||
| <SeerDrawerNavigator | ||
| loading={runState.status === 'processing' && isPolling} | ||
| onCopyMarkdown={hasArtifacts ? handleCopyMarkdown : undefined} | ||
| onReset={reset} | ||
| organization={organization} | ||
| project={project} | ||
| /> | ||
|
|
@@ -425,23 +418,6 @@ const DrawerContainer = styled('div')` | |
| background: ${p => p.theme.tokens.background.secondary}; | ||
| `; | ||
|
|
||
| const SeerDrawerHeader = styled(DrawerHeader)` | ||
| position: unset; | ||
| max-height: ${MIN_NAV_HEIGHT}px; | ||
| box-shadow: none; | ||
| border-bottom: 1px solid ${p => p.theme.tokens.border.primary}; | ||
| `; | ||
|
|
||
| const SeerDrawerNavigator = styled('div')` | ||
| display: flex; | ||
| align-items: center; | ||
| padding: ${p => p.theme.space.sm} ${p => p.theme.space['2xl']}; | ||
| background: ${p => p.theme.tokens.background.primary}; | ||
| z-index: 1; | ||
| min-height: ${MIN_NAV_HEIGHT}px; | ||
| box-shadow: ${p => p.theme.tokens.border.transparent.neutral.muted} 0 1px; | ||
| `; | ||
|
|
||
| const SeerDrawerBody = styled(DrawerBody)` | ||
| overflow: auto; | ||
| overscroll-behavior: contain; | ||
|
|
@@ -453,43 +429,11 @@ const SeerDrawerBody = styled(DrawerBody)` | |
| } | ||
| `; | ||
|
|
||
| const HeaderContainer = styled('div')` | ||
| display: flex; | ||
| align-items: center; | ||
| gap: ${p => p.theme.space.sm}; | ||
| `; | ||
|
|
||
| const Header = styled('h3')` | ||
| font-size: ${p => p.theme.fontSize.xl}; | ||
| font-weight: ${p => p.theme.fontWeight.bold}; | ||
| margin: 0; | ||
| `; | ||
|
|
||
| const NavigationCrumbs = styled(NavigationBreadcrumbs)` | ||
| const NavigationBreadcrumbs = styled(Breadcrumbs)` | ||
| margin: 0; | ||
| padding: 0; | ||
| `; | ||
|
|
||
| const CrumbContainer = styled('div')` | ||
| display: flex; | ||
| gap: ${p => p.theme.space.md}; | ||
| align-items: center; | ||
| `; | ||
|
|
||
| const ShortId = styled('div')` | ||
| font-family: ${p => p.theme.text.family}; | ||
| font-size: ${p => p.theme.fontSize.md}; | ||
| line-height: 1; | ||
| `; | ||
|
|
||
| const ButtonWrapper = styled(ButtonBar)` | ||
| margin-left: auto; | ||
| `; | ||
|
|
||
| const PlaceholderStack = styled('div')` | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: ${p => p.theme.space.xl}; | ||
| margin-top: ${p => p.theme.space.xl}; | ||
| padding: ${p => p.theme.space.xl}; | ||
| const SeerDrawerNavigatorContainer = styled(Flex)` | ||
| box-shadow: ${p => p.theme.tokens.border.transparent.neutral.muted} 0 1px; | ||
| `; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drawer header missing position and border style overrides
Medium Severity
The new
SeerDrawerHeaderfunction component wrapsDrawerHeaderwithout the style overrides that were present in the original styled component. The old version setposition: unset,box-shadow: none,max-height, andborder-bottom. Without these overrides, the header will now have sticky positioning (causing it to stick when scrolling), display an unwanted box-shadow, lack the intended border-bottom, and have no height constraint.