Browse Source

ref(storybook): Use `CodeSnippet` to render code (#44190)

Use the new `<CodeSnippet />` component to render code blocks in
Storybook, instead of the current custom implementation that basically
does the same thing as `<CodeSnippet />`.

**Before ——**
<img width="570" alt="Screenshot 2023-02-06 at 2 39 59 PM"
src="https://user-images.githubusercontent.com/44172267/217104112-e3e617c4-d146-4ef4-afb4-01e4080822b3.png">

**After ——**
<img width="570" alt="Screenshot 2023-02-06 at 2 43 57 PM"
src="https://user-images.githubusercontent.com/44172267/217104333-b9cf81d2-b749-4f06-8dd8-2fdbc209cbde.png">
Vu Luong 2 years ago
parent
commit
9fdcc265b9
2 changed files with 22 additions and 110 deletions
  1. 21 110
      docs-ui/components/code.tsx
  2. 1 0
      docs-ui/storybook/globalStyles.tsx

+ 21 - 110
docs-ui/components/code.tsx

@@ -1,18 +1,6 @@
-// eslint-disable-next-line simple-import-sort/imports
-import 'prismjs/themes/prism.css';
-
-import {useEffect, useRef, useState} from 'react';
-import {useTheme, Theme} from '@emotion/react';
 import styled from '@emotion/styled';
-import copy from 'copy-text-to-clipboard';
-import Prism from 'prismjs';
-/**
- * JSX syntax for Prism. This file uses Prism
- * internally, so it must be imported after Prism.
- */
-import 'prismjs/components/prism-jsx.min';
 
-import {IconCode} from 'sentry/icons';
+import {CodeSnippet} from 'sentry/components/codeSnippet';
 import space from 'sentry/styles/space';
 
 type Props = {
@@ -36,81 +24,29 @@ type Props = {
    * the label prop is set to 'hello'
    */
   label?: string;
-  theme?: Theme;
 };
 
 const Code = ({children, className, label}: Props) => {
-  const theme = useTheme();
-  const codeRef = useRef<HTMLElement | null>(null);
-  const copyTimeoutRef = useRef<number | undefined>(undefined);
-
-  const [copied, setCopied] = useState(false);
-
-  function handleCopyCode() {
-    // Remove comments from code
-    const copiableContent = children.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
-
-    copy(copiableContent);
-    setCopied(true);
-
-    copyTimeoutRef.current = window.setTimeout(() => {
-      setCopied(false);
-    }, 500);
-  }
-
-  // Cleanup timeout on component unmount
-  useEffect(() => {
-    return () => {
-      if (copyTimeoutRef.current !== null) {
-        window.clearTimeout(copyTimeoutRef.current);
-      }
-    };
-  }, []);
-
-  useEffect(() => {
-    Prism.highlightElement(codeRef.current, false);
-  }, [children]);
-
   return (
-    <Wrap className={className}>
-      <LabelWrap>
-        <IconCode theme={theme} color="subText" />
-        {label && <Label>{label.replaceAll('_', ' ')}</Label>}
-      </LabelWrap>
-      <HighlightedCode className={className} ref={codeRef}>
+    <CodeWrap className={className}>
+      <LabelWrap>{label && <Label>{label.replaceAll('_', ' ')}</Label>}</LabelWrap>
+      <CodeSnippet language={className?.split('language-')[1] ?? ''}>
         {children}
-      </HighlightedCode>
-      <CopyButton onClick={handleCopyCode} disabled={copied}>
-        {copied ? 'Copied' : 'Copy'}
-      </CopyButton>
-    </Wrap>
+      </CodeSnippet>
+    </CodeWrap>
   );
 };
 
 export default Code;
 
-const Wrap = styled('pre')`
-  /* Increase specificity to override default styles */
-  && {
-    position: relative;
-    padding: ${space(2)};
-    padding-top: ${space(4)};
-    margin-top: ${space(4)};
-    margin-bottom: ${space(2)};
-    background: ${p => p.theme.bodyBackground};
-    border: solid 1px ${p => p.theme.border};
-    overflow: visible;
-    text-shadow: none;
-  }
-  & code {
-    text-shadow: none;
-  }
+const CodeWrap = styled('div')`
+  position: relative;
+  padding: ${space(2)} 0;
 
-  /* Overwrite default Prism behavior to allow for code wrapping */
-  pre[class*='language-'],
-  code[class*='language-'] {
-    white-space: normal;
-    word-break: break-word;
+  pre {
+    font-size: ${p => p.theme.fontSizeMedium};
+    border: solid 1px ${p => p.theme.border};
+    padding-top: ${space(2)};
   }
 `;
 
@@ -118,47 +54,22 @@ const LabelWrap = styled('div')`
   display: flex;
   align-items: center;
   position: absolute;
-  top: 0;
+  top: ${space(2)};
   left: calc(${space(2)} - ${space(1)});
   transform: translateY(-50%);
-  padding: ${space(0.25)} ${space(1)};
+  z-index: 1;
+
+  padding: 0 ${space(0.75)};
   background: ${p => p.theme.docsBackground};
-  border: solid 1px ${p => p.theme.border};
+  border: solid 1px ${p => p.theme.innerBorder};
   border-radius: ${p => p.theme.borderRadius};
 `;
 
 const Label = styled('p')`
-  font-size: 0.875rem;
-  font-weight: 600;
   color: ${p => p.theme.subText};
-  text-transform: uppercase;
-  margin-bottom: 0;
-  margin-left: ${space(1)};
-`;
-
-const HighlightedCode = styled('code')`
-  /** Increase specificity to override default styles */
-  ${Wrap} > & {
-    font-family: ${p => p.theme.text.familyMono};
-    font-size: 0.875rem;
-    line-height: 1.6;
-  }
-`;
-
-const CopyButton = styled('button')`
-  position: absolute;
-  top: ${space(0.5)};
-  right: ${space(0.5)};
-  background: transparent;
-  border: none;
-  border-radius: ${p => p.theme.borderRadius};
-  padding: ${space(0.5)} ${space(1)};
-
-  font-size: 0.875rem;
+  font-size: ${p => p.theme.fontSizeMedium};
   font-weight: 600;
-  color: ${p => p.theme.subText};
 
-  &:hover:not(:disabled) {
-    color: ${p => p.theme.textColor};
-  }
+  text-transform: uppercase;
+  margin-bottom: 0;
 `;

+ 1 - 0
docs-ui/storybook/globalStyles.tsx

@@ -101,6 +101,7 @@ const docsStyles = (theme: Theme) => css`
   /** Code */
   .sbdocs.sbdocs-pre {
     overflow: visible;
+    font-family: ${theme.text.familyMono};
   }
   .sbdocs.sbdocs-wrapper *:not(pre) > code {
     font-family: ${theme.text.familyMono};