Repository: zeit-ui/react
Pull request #248 (2020-05-28 13:01:51)

fix: fix placeholder does not show ellipsis
## PR Checklist

- [x] Fix linting errors
- [x] Label has been added


## Change information





Patch:
diff --git a/components/auto-complete/auto-complete-item.tsx b/components/auto-complete/auto-complete-item.tsx
index 9744d1f..63b102b 100644
--- a/components/auto-complete/auto-complete-item.tsx
+++ b/components/auto-complete/auto-complete-item.tsx
@@ -2,7 +2,8 @@ import React, { useMemo } from 'react'
 import withDefaults from '../utils/with-defaults'
 import useTheme from '../styles/use-theme'
 import { useAutoCompleteContext } from './auto-complete-context'
-import { NormalSizes } from 'components/utils/prop-types'
+import { NormalSizes } from '../utils/prop-types'
+import Ellipsis from '../shared/ellipsis'
 
 interface Props {
   value: string
@@ -37,7 +38,7 @@ const AutoCompleteItem: React.FC<React.PropsWithChildren<AutoCompleteItemProps>>
 
   return (
     <div className={`item ${isActive ? 'active' : ''}`} onClick={selectHandler}>
-      <span>{children}</span>
+      <Ellipsis>{children}</Ellipsis>
       <style jsx>{`
         .item {
           display: flex;
@@ -56,13 +57,6 @@ const AutoCompleteItem: React.FC<React.PropsWithChildren<AutoCompleteItemProps>>
           transition: background 0.2s ease 0s, border-color 0.2s ease 0s;
         }
 
-        span {
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-          min-width: 0;
-        }
-
         .item:first-of-type {
           border-top-left-radius: ${theme.layout.radius};
           border-top-right-radius: ${theme.layout.radius};
diff --git a/components/select/select-option.tsx b/components/select/select-option.tsx
index 9aad57f..67d0824 100644
--- a/components/select/select-option.tsx
+++ b/components/select/select-option.tsx
@@ -3,6 +3,7 @@ import withDefaults from '../utils/with-defaults'
 import useTheme from '../styles/use-theme'
 import { useSelectContext } from './select-context'
 import useWarning from '../utils/use-warning'
+import Ellipsis from '../shared/ellipsis'
 
 interface Props {
   value?: string
@@ -80,7 +81,7 @@ const SelectOption: React.FC<React.PropsWithChildren<SelectOptionProps>> = ({
         className={`option ${divider ? 'divider' : ''} ${label ? 'label' : ''} ${className}`}
         onClick={clickHandler}
         {...props}>
-        <span>{children}</span>
+        <Ellipsis>{children}</Ellipsis>
       </div>
 
       <style jsx>{`
@@ -101,13 +102,6 @@ const SelectOption: React.FC<React.PropsWithChildren<SelectOptionProps>> = ({
           transition: background 0.2s ease 0s, border-color 0.2s ease 0s;
         }
 
-        span {
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-          min-width: 0;
-        }
-
         .option:hover {
           background-color: ${hoverBgColor};
           color: ${theme.palette.accents_7};
diff --git a/components/select/select.tsx b/components/select/select.tsx
index de10b8b..8f27829 100644
--- a/components/select/select.tsx
+++ b/components/select/select.tsx
@@ -11,6 +11,7 @@ import SelectMultipleValue from './select-multiple-value'
 import Grid from '../grid'
 import { SelectContext, SelectConfig } from './select-context'
 import { getSizes } from './styles'
+import Ellipsis from '../shared/ellipsis'
 
 interface Props {
   disabled?: boolean
@@ -136,7 +137,11 @@ const Select: React.FC<React.PropsWithChildren<SelectProps>> = ({
         ref={ref}
         onClick={clickHandler}
         {...props}>
-        {isEmpty && <span className="value placeholder">{placeholder}</span>}
+        {isEmpty && (
+          <span className="value placeholder">
+            <Ellipsis>{placeholder}</Ellipsis>
+          </span>
+        )}
         {value && !multiple && <span className="value">{selectedChild}</span>}
         {value && multiple && <Grid.Container gap={0.5}>{selectedChild}</Grid.Container>}
         <SelectDropdown
diff --git a/components/shared/ellipsis.tsx b/components/shared/ellipsis.tsx
new file mode 100644
index 0000000..6a6f218
--- /dev/null
+++ b/components/shared/ellipsis.tsx
@@ -0,0 +1,19 @@
+import React from 'react'
+
+const Ellipsis: React.FC<React.PropsWithChildren<{}>> = ({ children }) => {
+  return (
+    <span>
+      {children}
+      <style jsx>{`
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      `}</style>
+    </span>
+  )
+}
+
+export default React.memo(Ellipsis)


Test patch:
diff --git a/components/select/__tests__/__snapshots__/index.test.tsx.snap b/components/select/__tests__/__snapshots__/index.test.tsx.snap
index 0af4cc3..e3213eb 100644
--- a/components/select/__tests__/__snapshots__/index.test.tsx.snap
+++ b/components/select/__tests__/__snapshots__/index.test.tsx.snap
@@ -1,7 +1,14 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Select should render correctly 1`] = `
-"<div><div class=\\"select  \\"><span class=\\"value placeholder\\"></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
+"<div><div class=\\"select  \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
         svg {
           color: inherit;
           stroke: currentColor;
@@ -81,7 +88,14 @@ exports[`Select should render correctly 1`] = `
             align-items: center;
             color: #666;
           }
-        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
+        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
         svg {
           color: inherit;
           stroke: currentColor;
@@ -161,7 +175,14 @@ exports[`Select should render correctly 1`] = `
             align-items: center;
             color: #666;
           }
-        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
+        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
         svg {
           color: inherit;
           stroke: currentColor;
@@ -241,7 +262,14 @@ exports[`Select should render correctly 1`] = `
             align-items: center;
             color: #666;
           }
-        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
+        </style></div><div class=\\"select  \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
         svg {
           color: inherit;
           stroke: currentColor;
@@ -325,7 +353,14 @@ exports[`Select should render correctly 1`] = `
 `;
 
 exports[`Select should work correctly with labels 1`] = `
-"<div class=\\"select  \\"><span class=\\"value placeholder\\"></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
+"<div class=\\"select  \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"icon\\"><svg viewBox=\\"0 0 24 24\\" width=\\"1.25em\\" height=\\"1.25em\\" stroke-width=\\"1\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" fill=\\"none\\" shape-rendering=\\"geometricPrecision\\"><path d=\\"M6 9l6 6 6-6\\"></path><style>
         svg {
           color: inherit;
           stroke: currentColor;
@@ -419,7 +454,48 @@ initialize {
         "attribs": Object {
           "class": "value placeholder",
         },
-        "children": Array [],
+        "children": Array [
+          Object {
+            "attribs": Object {},
+            "children": Array [
+              Object {
+                "attribs": Object {},
+                "children": Array [
+                  Object {
+                    "data": "
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      ",
+                    "next": null,
+                    "parent": [Circular],
+                    "prev": null,
+                    "type": "text",
+                  },
+                ],
+                "name": "style",
+                "namespace": "http://www.w3.org/1999/xhtml",
+                "next": null,
+                "parent": [Circular],
+                "prev": null,
+                "type": "style",
+                "x-attribsNamespace": Object {},
+                "x-attribsPrefix": Object {},
+              },
+            ],
+            "name": "span",
+            "namespace": "http://www.w3.org/1999/xhtml",
+            "next": null,
+            "parent": [Circular],
+            "prev": null,
+            "type": "tag",
+            "x-attribsNamespace": Object {},
+            "x-attribsPrefix": Object {},
+          },
+        ],
         "name": "span",
         "namespace": "http://www.w3.org/1999/xhtml",
         "next": Object {
@@ -619,7 +695,48 @@ initialize {
           "attribs": Object {
             "class": "value placeholder",
           },
-          "children": Array [],
+          "children": Array [
+            Object {
+              "attribs": Object {},
+              "children": Array [
+                Object {
+                  "attribs": Object {},
+                  "children": Array [
+                    Object {
+                      "data": "
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      ",
+                      "next": null,
+                      "parent": [Circular],
+                      "prev": null,
+                      "type": "text",
+                    },
+                  ],
+                  "name": "style",
+                  "namespace": "http://www.w3.org/1999/xhtml",
+                  "next": null,
+                  "parent": [Circular],
+                  "prev": null,
+                  "type": "style",
+                  "x-attribsNamespace": Object {},
+                  "x-attribsPrefix": Object {},
+                },
+              ],
+              "name": "span",
+              "namespace": "http://www.w3.org/1999/xhtml",
+              "next": null,
+              "parent": [Circular],
+              "prev": null,
+              "type": "tag",
+              "x-attribsNamespace": Object {},
+              "x-attribsPrefix": Object {},
+            },
+          ],
           "name": "span",
           "namespace": "http://www.w3.org/1999/xhtml",
           "next": [Circular],
@@ -687,7 +804,48 @@ initialize {
         "attribs": Object {
           "class": "value placeholder",
         },
-        "children": Array [],
+        "children": Array [
+          Object {
+            "attribs": Object {},
+            "children": Array [
+              Object {
+                "attribs": Object {},
+                "children": Array [
+                  Object {
+                    "data": "
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      ",
+                    "next": null,
+                    "parent": [Circular],
+                    "prev": null,
+                    "type": "text",
+                  },
+                ],
+                "name": "style",
+                "namespace": "http://www.w3.org/1999/xhtml",
+                "next": null,
+                "parent": [Circular],
+                "prev": null,
+                "type": "style",
+                "x-attribsNamespace": Object {},
+                "x-attribsPrefix": Object {},
+              },
+            ],
+            "name": "span",
+            "namespace": "http://www.w3.org/1999/xhtml",
+            "next": null,
+            "parent": [Circular],
+            "prev": null,
+            "type": "tag",
+            "x-attribsNamespace": Object {},
+            "x-attribsPrefix": Object {},
+          },
+        ],
         "name": "span",
         "namespace": "http://www.w3.org/1999/xhtml",
         "next": Object {
@@ -959,7 +1117,48 @@ initialize {
           "attribs": Object {
             "class": "value placeholder",
           },
-          "children": Array [],
+          "children": Array [
+            Object {
+              "attribs": Object {},
+              "children": Array [
+                Object {
+                  "attribs": Object {},
+                  "children": Array [
+                    Object {
+                      "data": "
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      ",
+                      "next": null,
+                      "parent": [Circular],
+                      "prev": null,
+                      "type": "text",
+                    },
+                  ],
+                  "name": "style",
+                  "namespace": "http://www.w3.org/1999/xhtml",
+                  "next": null,
+                  "parent": [Circular],
+                  "prev": null,
+                  "type": "style",
+                  "x-attribsNamespace": Object {},
+                  "x-attribsPrefix": Object {},
+                },
+              ],
+              "name": "span",
+              "namespace": "http://www.w3.org/1999/xhtml",
+              "next": null,
+              "parent": [Circular],
+              "prev": null,
+              "type": "tag",
+              "x-attribsNamespace": Object {},
+              "x-attribsPrefix": Object {},
+            },
+          ],
           "name": "span",
           "namespace": "http://www.w3.org/1999/xhtml",
           "next": [Circular],
@@ -1104,7 +1303,48 @@ initialize {
             "attribs": Object {
               "class": "value placeholder",
             },
-            "children": Array [],
+            "children": Array [
+              Object {
+                "attribs": Object {},
+                "children": Array [
+                  Object {
+                    "attribs": Object {},
+                    "children": Array [
+                      Object {
+                        "data": "
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      ",
+                        "next": null,
+                        "parent": [Circular],
+                        "prev": null,
+                        "type": "text",
+                      },
+                    ],
+                    "name": "style",
+                    "namespace": "http://www.w3.org/1999/xhtml",
+                    "next": null,
+                    "parent": [Circular],
+                    "prev": null,
+                    "type": "style",
+                    "x-attribsNamespace": Object {},
+                    "x-attribsPrefix": Object {},
+                  },
+                ],
+                "name": "span",
+                "namespace": "http://www.w3.org/1999/xhtml",
+                "next": null,
+                "parent": [Circular],
+                "prev": null,
+                "type": "tag",
+                "x-attribsNamespace": Object {},
+                "x-attribsPrefix": Object {},
+              },
+            ],
             "name": "span",
             "namespace": "http://www.w3.org/1999/xhtml",
             "next": [Circular],
diff --git a/components/select/__tests__/__snapshots__/multiple.test.tsx.snap b/components/select/__tests__/__snapshots__/multiple.test.tsx.snap
index 94b950f..fa8a627 100644
--- a/components/select/__tests__/__snapshots__/multiple.test.tsx.snap
+++ b/components/select/__tests__/__snapshots__/multiple.test.tsx.snap
@@ -1,7 +1,14 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Select Multiple should render correctly 1`] = `
-"<div class=\\"select multiple \\"><span class=\\"value placeholder\\"></span><div class=\\"item  mock \\"><style>
+"<div class=\\"select multiple \\"><span class=\\"value placeholder\\"><span><style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></span><div class=\\"item  mock \\"><style>
         .item {
         }
 
diff --git a/components/select/__tests__/multiple.test.tsx b/components/select/__tests__/multiple.test.tsx
index cc413ee..882527a 100644
--- a/components/select/__tests__/multiple.test.tsx
+++ b/components/select/__tests__/multiple.test.tsx
@@ -24,7 +24,10 @@ describe('Select Multiple', () => {
       </Select>,
     )
     expect(wrapper.find('.option').length).toBeGreaterThan(1)
-    const text = wrapper.find('.option').map(item => item.text())
+    const text = wrapper
+      .find('.option')
+      .map(item => item.text())
+      .reduce((pre, current) => `${pre}${current}`, '')
     expect(text.includes('test-1')).toBeTruthy()
     expect(text.includes('test-2')).toBeTruthy()
     expect(text.includes('test-3')).not.toBeTruthy()
diff --git a/components/shared/__tests__/__snapshots__/ellipsis.test.tsx.snap b/components/shared/__tests__/__snapshots__/ellipsis.test.tsx.snap
new file mode 100644
index 0000000..55de572
--- /dev/null
+++ b/components/shared/__tests__/__snapshots__/ellipsis.test.tsx.snap
@@ -0,0 +1,12 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Ellipsis should render correctly 1`] = `
+"<div style=\\"width: 1px;\\"><span>text<style>
+        span {
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+          min-width: 0;
+        }
+      </style></span></div>"
+`;
diff --git a/components/shared/__tests__/ellipsis.test.tsx b/components/shared/__tests__/ellipsis.test.tsx
new file mode 100644
index 0000000..9a064d6
--- /dev/null
+++ b/components/shared/__tests__/ellipsis.test.tsx
@@ -0,0 +1,15 @@
+import React from 'react'
+import { mount } from 'enzyme'
+import Ellipsis from '../ellipsis'
+
+describe('Ellipsis', () => {
+  it('should render correctly', () => {
+    const wrapper = mount(
+      <div style={{ width: '1px' }}>
+        <Ellipsis>text</Ellipsis>
+      </div>,
+    )
+    expect(wrapper.html()).toMatchSnapshot()
+    expect(() => wrapper.unmount()).not.toThrow()
+  })
+})