Repository: zeit-ui/react (ts)

Issue:
Feature request for custom Snippet prompt
<!-- Please do NOT DELETE the template. -->
<!-- No template issues will be closed. -->

# Feature request 🚀

  - [ ] I will create Pull Request
  - [x] It's just a suggestion

### Expected

  - Snippet with custom prompt
  - Snippet without prompt

### Examples

```jsx
<Snippet {...props} prompt=">" />
```
<img src="https://user-images.githubusercontent.com/157338/87219096-1b0e1680-c38b-11ea-8cb0-a1c54da370fd.png" width="430" />

```jsx
<Snippet {...props} prompt="#" />
```
<img src="https://user-images.githubusercontent.com/157338/87219286-683eb800-c38c-11ea-96d0-5d90e24022df.png" width="324" />

```jsx
<Snippet {...props} prompt={false} />
```
<img src="https://user-images.githubusercontent.com/157338/87219231-0da55c00-c38c-11ea-8775-dce7c87c814c.png" width="324" />

### Programme (Optional)

### Others (Optional)


Pull request description:
fix(snippet): remove space when the symbol is empty
## Checklist

- [x] Fix linting errors
- [x] Tests have been added / updated (or snapshots)

## Change information

fixed #324 


Patch:
diff --git a/components/button/button.tsx b/components/button/button.tsx
index b2e3cd0..651f9f5 100644
--- a/components/button/button.tsx
+++ b/components/button/button.tsx
@@ -64,6 +64,7 @@ const Button = React.forwardRef<HTMLButtonElement, React.PropsWithChildren<Butto
     const [dripY, setDripY] = useState<number>(0)
     const groupConfig = useButtonGroupContext()
     const filteredProps = filterPropsWithGroup(btnProps, groupConfig)
+    /* eslint-disable @typescript-eslint/no-unused-vars */
     const {
       children,
       disabled,
@@ -81,6 +82,7 @@ const Button = React.forwardRef<HTMLButtonElement, React.PropsWithChildren<Butto
       className,
       ...props
     } = filteredProps
+    /* eslint-enable @typescript-eslint/no-unused-vars */
 
     const { bg, border, color } = useMemo(() => getButtonColors(theme.palette, filteredProps), [
       theme.palette,
diff --git a/components/snippet/snippet.tsx b/components/snippet/snippet.tsx
index 73599e2..232ad95 100644
--- a/components/snippet/snippet.tsx
+++ b/components/snippet/snippet.tsx
@@ -67,6 +67,10 @@ const Snippet: React.FC<React.PropsWithChildren<SnippetProps>> = ({
     if (!ref.current) return ''
     return ref.current.textContent
   }, [ref.current, children, text])
+  const symbolBefore = useMemo(() => {
+    const str = symbol.trim()
+    return str ? `${str} ` : ''
+  }, [symbol])
 
   const clickHandler = () => {
     if (!childText || !showCopyIcon) return
@@ -110,7 +114,7 @@ const Snippet: React.FC<React.PropsWithChildren<SnippetProps>> = ({
         }
 
         pre::before {
-          content: '${symbol} ';
+          content: '${symbolBefore}';
           user-select: none;
         }
 


Test patch:
diff --git a/components/image/__tests__/browser.test.tsx b/components/image/__tests__/browser.test.tsx
index db6c828..b863a16 100644
--- a/components/image/__tests__/browser.test.tsx
+++ b/components/image/__tests__/browser.test.tsx
@@ -68,6 +68,6 @@ describe('Image Browser', () => {
       </Image.Browser>,
     )
     const rel = wrapper.find('a').getDOMNode().getAttribute('rel')
-    expect(anchorRel).toEqual(anchorRel)
+    expect(rel).toEqual(anchorRel)
   })
 })
diff --git a/components/snippet/__tests__/__snapshots__/index.test.tsx.snap b/components/snippet/__tests__/__snapshots__/index.test.tsx.snap
index fdd674a..5212bc3 100644
--- a/components/snippet/__tests__/__snapshots__/index.test.tsx.snap
+++ b/components/snippet/__tests__/__snapshots__/index.test.tsx.snap
@@ -116,6 +116,64 @@ exports[`Snippet should work with custom symbol 1`] = `
       </style></div>"
 `;
 
+exports[`Snippet should work with custom symbol 2`] = `
+"<div class=\\"snippet \\"><pre>yarn add @zeit-ui/react</pre><div class=\\"copy\\"><svg viewBox=\\"0 0 24 24\\" width=\\"22\\" height=\\"22\\" stroke=\\"currentColor\\" stroke-width=\\"1.5\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\" style=\\"color: currentcolor;\\"><path d=\\"M8 17.929H6c-1.105 0-2-.912-2-2.036V5.036C4 3.91 4.895 3 6 3h8c1.105 0 2 .911 2 2.036v1.866m-6 .17h8c1.105 0 2 .91 2 2.035v10.857C20 21.09 19.105 22 18 22h-8c-1.105 0-2-.911-2-2.036V9.107c0-1.124.895-2.036 2-2.036z\\"></path></svg></div><style>
+        .snippet {
+          position: relative;
+          width: initial;
+          max-width: 100%;
+          padding: 8pt;
+          padding-right: calc(2 * 16pt);
+          color: #000;
+          background-color: #fff;
+          border: 1px solid #eaeaea;
+          border-radius: 5px;
+        }
+
+        pre {
+          margin: 0;
+          padding: 0;
+          border: none;
+          background-color: transparent;
+          color: #000;
+          font-size: 0.8125rem;
+        }
+
+        pre::before {
+          content: '';
+          user-select: none;
+        }
+
+        pre :global(*) {
+          margin: 0;
+          padding: 0;
+          font-size: inherit;
+          color: inherit;
+        }
+
+        .copy {
+          position: absolute;
+          right: 0;
+          top: -2px;
+          transform: translateY(50%);
+          background-color: #fff;
+          display: inline-flex;
+          justify-content: center;
+          align-items: center;
+          width: calc(2 * 16pt);
+          color: inherit;
+          transition: opacity 0.2s ease 0s;
+          border-radius: 5px;
+          cursor: pointer;
+          user-select: none;
+        }
+
+        .copy:hover {
+          opacity: 0.7;
+        }
+      </style></div>"
+`;
+
 exports[`Snippet should work with different styles 1`] = `
 "<div><div class=\\"snippet \\"><pre>yarn add @zeit-ui/react</pre><div class=\\"copy\\"><svg viewBox=\\"0 0 24 24\\" width=\\"22\\" height=\\"22\\" stroke=\\"currentColor\\" stroke-width=\\"1.5\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\" style=\\"color: currentcolor;\\"><path d=\\"M8 17.929H6c-1.105 0-2-.912-2-2.036V5.036C4 3.91 4.895 3 6 3h8c1.105 0 2 .911 2 2.036v1.866m-6 .17h8c1.105 0 2 .91 2 2.035v10.857C20 21.09 19.105 22 18 22h-8c-1.105 0-2-.911-2-2.036V9.107c0-1.124.895-2.036 2-2.036z\\"></path></svg></div><style>
         .snippet {
diff --git a/components/snippet/__tests__/index.test.tsx b/components/snippet/__tests__/index.test.tsx
index d3e3066..3265981 100644
--- a/components/snippet/__tests__/index.test.tsx
+++ b/components/snippet/__tests__/index.test.tsx
@@ -74,6 +74,15 @@ describe('Snippet', () => {
     const wrapper = mount(<Snippet text={command} symbol={'>'} />)
     expect(wrapper.html()).toMatchSnapshot()
     expect(() => wrapper.unmount()).not.toThrow()
+
+    const emptySymbolWrapper = mount(<Snippet text={command} symbol=" " />)
+    expect(emptySymbolWrapper.html()).toMatchSnapshot()
+
+    const emptySymbolWrapper2 = mount(<Snippet text={command} symbol="" />)
+    expect(emptySymbolWrapper2.html()).toEqual(emptySymbolWrapper.html())
+
+    expect(() => emptySymbolWrapper.unmount()).not.toThrow()
+    expect(() => emptySymbolWrapper2.unmount()).not.toThrow()
   })
 
   it('should work with custom toast', () => {