Browse Source

feat(suggested-fix): New banner design (#65206)

Malachi Willey 1 year ago
parent
commit
325a0960fc

+ 10 - 2
static/app/components/events/aiAutofix/banner.spec.tsx

@@ -23,7 +23,11 @@ describe('PII Certification Check', () => {
         setAdditionalContext={() => {}}
       />
     );
-    expect(getByText('Certify No PII')).toBeInTheDocument();
+    expect(
+      getByText(
+        'By clicking the button above, you confirm that there is no PII in this event.'
+      )
+    ).toBeInTheDocument();
   });
 
   it('does not show PII check for non sentry employee users', () => {
@@ -36,6 +40,10 @@ describe('PII Certification Check', () => {
         setAdditionalContext={() => {}}
       />
     );
-    expect(queryByText('Certify No PII')).not.toBeInTheDocument();
+    expect(
+      queryByText(
+        'By clicking the button above, you confirm that there is no PII in this event.'
+      )
+    ).not.toBeInTheDocument();
   });
 });

+ 79 - 173
static/app/components/events/aiAutofix/banner.tsx

@@ -1,4 +1,4 @@
-import {useState} from 'react';
+import {Fragment} from 'react';
 import styled from '@emotion/styled';
 
 import bannerBackground from 'sentry-images/spot/ai-suggestion-banner-background.svg';
@@ -6,20 +6,12 @@ import bannerSentaur from 'sentry-images/spot/ai-suggestion-banner-sentaur.svg';
 import bannerStars from 'sentry-images/spot/ai-suggestion-banner-stars.svg';
 
 import {Button} from 'sentry/components/button';
-import ButtonBar from 'sentry/components/buttonBar';
-import EmptyMessage from 'sentry/components/emptyMessage';
-import TextArea from 'sentry/components/forms/controls/textarea';
-import ExternalLink from 'sentry/components/links/externalLink';
+import Input from 'sentry/components/input';
 import Panel from 'sentry/components/panels/panel';
 import PanelBody from 'sentry/components/panels/panelBody';
-import QuestionTooltip from 'sentry/components/questionTooltip';
-import {IconFlag} from 'sentry/icons';
-import {t, tct} from 'sentry/locale';
+import {t} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {useIsSentryEmployee} from 'sentry/utils/useIsSentryEmployee';
-import TextBlock from 'sentry/views/settings/components/text/textBlock';
-
-import {ExperimentalFeatureBadge} from '../aiSuggestedSolution/experimentalFeatureBadge';
 
 type Props = {
   additionalContext: string;
@@ -29,78 +21,45 @@ type Props = {
 
 export function Banner({onButtonClick, additionalContext, setAdditionalContext}: Props) {
   const isSentryEmployee = useIsSentryEmployee();
-  const [piiCertified, setPiiCertified] = useState(false);
-
-  const showPiiMessage = isSentryEmployee && !piiCertified;
 
   return (
     <Wrapper>
+      <IllustrationContainer>
+        <Background src={bannerBackground} />
+        <Stars src={bannerStars} />
+        <Sentaur src={bannerSentaur} />
+      </IllustrationContainer>
       <Body>
-        <Header>
-          <TitleContent>
-            <Title>
-              {t('AI Autofix')}
-              <MoreInfoTooltip
-                isHoverable
-                size="sm"
-                title={tct(
-                  'This is an OpenAI generated solution that automatically creates a pull request for this issue. Be aware that this may not be accurate. [learnMore:Learn more]',
-                  {
-                    learnMore: (
-                      <ExternalLink href="https://docs.sentry.io/product/issues/issue-details/ai-suggested-solution/" />
-                    ),
-                  }
-                )}
-              />
-              <ExperimentalFeatureBadge />
-            </Title>
-            <Description>
-              {t('You might get lucky, but again, maybe not\u2026')}
-            </Description>
-          </TitleContent>
-          <Action>
-            <Background src={bannerBackground} />
-            <Stars src={bannerStars} />
-            <Sentaur src={bannerSentaur} />
-            <ViewSuggestionButton
-              size="xs"
-              onClick={onButtonClick}
-              disabled={showPiiMessage}
-            >
-              {t('Try your luck')}
-            </ViewSuggestionButton>
-          </Action>
-        </Header>
-        {showPiiMessage ? (
-          <PiiArea>
-            <EmptyMessage
-              icon={<IconFlag size="xl" />}
-              title={t('PII Certification Required')}
-              description={t(
-                'Before using this feature, please confirm that there is no personally identifiable information in this event.'
-              )}
-              action={
-                <ButtonBar gap={2}>
-                  <Button priority="primary" onClick={() => setPiiCertified(true)}>
-                    {t('Certify No PII')}
-                  </Button>
-                </ButtonBar>
+        <div>
+          <Title>{t('Try AI Autofix')}</Title>
+          <SubTitle>{t('You might get lucky, but then again, maybe not...')}</SubTitle>
+        </div>
+        <ContextArea>
+          <Button onClick={onButtonClick} size="sm">
+            {t('Gimme Fix')}
+          </Button>
+          <Input
+            aria-label={t('Provide additional context (optional)')}
+            value={additionalContext}
+            placeholder={t('Add context (optional)...')}
+            onChange={e => setAdditionalContext(e.target.value)}
+            onKeyDown={e => {
+              if (e.key === 'Enter') {
+                onButtonClick();
               }
-            />
-          </PiiArea>
-        ) : (
-          <AdditionalContextArea>
-            <AdditionalContextLabel>
-              {t('Additional Context (Optional)')}
-            </AdditionalContextLabel>
-            <StyledTextArea
-              value={additionalContext}
-              placeholder={t(
-                'Add additional context to help the AI find a better solution'
+            }}
+            size="sm"
+          />
+        </ContextArea>
+        {isSentryEmployee && (
+          <Fragment>
+            <Separator />
+            <PiiMessage>
+              {t(
+                'By clicking the button above, you confirm that there is no PII in this event.'
               )}
-              onChange={e => setAdditionalContext(e.target.value)}
-            />
-          </AdditionalContextArea>
+            </PiiMessage>
+          </Fragment>
         )}
       </Body>
     </Wrapper>
@@ -109,133 +68,80 @@ export function Banner({onButtonClick, additionalContext, setAdditionalContext}:
 
 const Wrapper = styled(Panel)`
   margin-bottom: 0;
+  background: linear-gradient(269.35deg, ${p => p.theme.backgroundTertiary} 0.32%, rgba(245, 243, 247, 0) 99.69%);
 `;
 
 const Body = styled(PanelBody)`
-  display: flex;
-  flex-direction: column;
-`;
-
-const Header = styled('div')`
-  display: flex;
-  align-items: center;
-  flex-wrap: wrap;
-  gap: ${space(1)};
-
-  > *:first-child {
-    flex: 1;
-  }
+  padding: ${space(2)} ${space(3)};
 
   @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
-    display: grid;
-    grid-template-columns: 42% 1fr;
-    height: 80px;
-    position: relative;
+    max-width: calc(100% - 400px);
   }
 `;
 
 const Title = styled('div')`
-  font-size: ${p => p.theme.fontSizeSmall};
-  text-transform: uppercase;
-  color: ${p => p.theme.gray300};
-  display: flex;
-  align-items: center;
-  /* to be consistent with the feature badge size */
-  height: ${space(2)};
-  line-height: ${space(2)};
-  white-space: nowrap;
-`;
-
-const TitleContent = styled('div')`
-  display: flex;
-  flex-direction: column;
-  padding-left: ${space(2)};
+  font-size: ${p => p.theme.fontSizeExtraLarge};
+  font-weight: bold;
+  margin-bottom: ${space(1)};
 `;
 
-const Description = styled(TextBlock)`
-  margin: ${space(1)} 0 0 0;
+const SubTitle = styled('p')`
+  margin: ${space(1)} 0;
 `;
 
-const Action = styled('div')`
-  display: flex;
-  justify-content: flex-end;
-  align-items: center;
+const ContextArea = styled('div')`
+  display: grid;
+  gap: ${space(1)};
+  grid-template-columns: auto 1fr;
+  margin-top: ${space(1)};
 `;
 
-const Sentaur = styled('img')`
+const IllustrationContainer = styled('div')`
   display: none;
-  @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
-    display: block;
-    height: 8.563rem;
-    position: absolute;
-    bottom: 0;
-    right: 6.608rem;
-    object-fit: cover;
-    z-index: 1;
-    pointer-events: none;
-  }
-`;
 
-const Background = styled('img')`
-  display: none;
   @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
     display: block;
     position: absolute;
-    top: 0;
+    bottom: 0;
     right: 0;
-    object-fit: cover;
-    max-width: 100%;
-    height: 100%;
-    border-top-right-radius: ${p => p.theme.panelBorderRadius};
+    top: 0;
+    width: 400px;
+    overflow: hidden;
+    border-radius: 0 ${p => p.theme.borderRadius} ${p => p.theme.borderRadius} 0;
   }
 `;
 
-const Stars = styled('img')`
-  display: none;
-  @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
-    display: block;
-    height: 8.563rem;
-    position: absolute;
-    right: -1rem;
-    bottom: -0.125rem;
-    object-fit: cover;
-    /* workaround to remove a  extra svg on the bottom right */
-    border-radius: ${p => p.theme.panelBorderRadius};
-  }
+const Sentaur = styled('img')`
+  height: 125px;
+  position: absolute;
+  bottom: 0;
+  right: 185px;
+  z-index: 1;
+  pointer-events: none;
 `;
 
-const ViewSuggestionButton = styled(Button)`
-  @media (min-width: ${p => p.theme.breakpoints.xlarge}) {
-    position: absolute;
-    right: 1rem;
-    top: 1.5rem;
-  }
+const Background = styled('img')`
+  position: absolute;
+  bottom: 0;
+  right: 0;
+  max-width: 100%;
 `;
 
-const MoreInfoTooltip = styled(QuestionTooltip)`
-  margin-left: ${space(0.5)};
+const Stars = styled('img')`
+  pointer-events: none;
+  position: absolute;
+  right: -140px;
+  bottom: 40px;
+  height: 120px;
 `;
 
-const AdditionalContextLabel = styled('label')`
-  font-size: ${p => p.theme.fontSizeSmall};
-  color: ${p => p.theme.gray300};
+const Separator = styled('hr')`
+  margin-top: ${space(2)};
   margin-bottom: ${space(1)};
+  border-color: ${p => p.theme.translucentBorder};
 `;
 
-const PiiArea = styled('div')`
-  background-color: ${p => p.theme.backgroundSecondary};
-  border-radius: ${p => p.theme.panelBorderRadius};
-`;
-
-const AdditionalContextArea = styled('div')`
-  display: flex;
-  flex-direction: column;
-  padding: ${space(2)};
-  background-color: ${p => p.theme.backgroundSecondary};
-  border-radius: ${p => p.theme.panelBorderRadius};
-`;
-
-const StyledTextArea = styled(TextArea)`
-  resize: vertical;
-  min-height: 80px;
+const PiiMessage = styled('p')`
+  font-size: ${p => p.theme.fontSizeSmall};
+  color: ${p => p.theme.subText};
 `;

+ 1 - 1
static/app/components/events/aiAutofix/index.spec.tsx

@@ -18,7 +18,7 @@ describe('AiAutofix', () => {
   it('renders the Banner component when autofixData is null', () => {
     render(<AiAutofix group={group} />);
 
-    expect(screen.getByText('AI Autofix')).toBeInTheDocument();
+    expect(screen.getByText('Try AI Autofix')).toBeInTheDocument();
   });
 
   it('renders the FixResult component when autofixData is present', () => {