Repository: grommet/grommet (JavaScript)

Issue:
TextInput placeholder duplicated
<!--- Provide a general summary of the issue in the Title above -->

### Expected Behavior
Placeholder text should not be duplicated.

### Actual Behavior
Placeholder text shows up twice

### URL, screen shot, or Codepen exhibiting the issue
<img width="456" alt="Screen Shot 2021-02-03 at 1 31 16 PM" src="https://user-images.githubusercontent.com/54560994/106805572-19a48400-6624-11eb-9cb1-8dd74952f60f.png">

https://storybook.grommet.io/?path=/story/input-textinput--icon

### Steps to Reproduce

1. Go to link above (Or any TextInput with a placeholder)
2. Type something into the TextInput
3. Delete what you typed
4. Placeholder text will be duplicated

### Your Environment
- Grommet version: stable branch
- Browser Name and version: chrome
- Operating System and version (desktop or mobile): desktop



Discussion:

Patch:
diff --git a/src/js/components/TextInput/TextInput.js b/src/js/components/TextInput/TextInput.js
index b67687d8a88..72d382e64e2 100644
--- a/src/js/components/TextInput/TextInput.js
+++ b/src/js/components/TextInput/TextInput.js
@@ -466,7 +466,11 @@ const TextInput = forwardRef(
                     // will come from this onChange and remove the placeholder
                     // so we need to update state to ensure the styled
                     // placeholder only appears when there is no value
-                    setShowStyledPlaceholder(!event.target.value);
+                    setShowStyledPlaceholder(
+                      placeholder &&
+                        typeof placeholder !== 'string' &&
+                        !event.target.value,
+                    );
                     setValue(event.target.value);
                     setActiveSuggestionIndex(-1);
                     if (onChange) onChange(event);


Test patch:
diff --git a/src/js/components/TextInput/__tests__/TextInput-test.js b/src/js/components/TextInput/__tests__/TextInput-test.js
index 7d3db5c0bfa..b6553dfd21b 100644
--- a/src/js/components/TextInput/__tests__/TextInput-test.js
+++ b/src/js/components/TextInput/__tests__/TextInput-test.js
@@ -575,6 +575,33 @@ describe('TextInput', () => {
     expect(container.firstChild).toMatchSnapshot();
   });
 
+  test(`should only should default placeholder when placeholder is a 
+  string`, () => {
+    const { container, getByTestId } = render(
+      <Grommet>
+        <TextInput
+          data-testid="placeholder"
+          id="placeholder"
+          name="placeholder"
+          placeholder="placeholder text"
+        />
+      </Grommet>,
+    );
+
+    const placeholder = screen.queryByText('placeholder text');
+    fireEvent.change(getByTestId('placeholder'), {
+      target: { value: 'something' },
+    });
+    expect(placeholder).toBeNull();
+    expect(container.firstChild).toMatchSnapshot();
+
+    // after value is removed, only one placeholder should be present
+    // nothing from styled placeholder should appear since placeholder
+    // is a string
+    fireEvent.change(getByTestId('placeholder'), { target: { value: '' } });
+    expect(container.firstChild).toMatchSnapshot();
+  });
+
   test('textAlign end', () => {
     const { container } = render(
       <Grommet>
diff --git a/src/js/components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap b/src/js/components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap
index c10c1e8751a..fded189cfc5 100644
--- a/src/js/components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap
+++ b/src/js/components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap
@@ -2836,6 +2836,105 @@ exports[`TextInput should not have padding when plain="full" 1`] = `
 </div>
 `;
 
+exports[`TextInput should only should default placeholder when placeholder is a 
+  string 1`] = `
+.c0 {
+  font-size: 18px;
+  line-height: 24px;
+  box-sizing: border-box;
+  -webkit-text-size-adjust: 100%;
+  -ms-text-size-adjust: 100%;
+  -moz-osx-font-smoothing: grayscale;
+  -webkit-font-smoothing: antialiased;
+}
+
+.c2 {
+  box-sizing: border-box;
+  font-size: inherit;
+  font-family: inherit;
+  border: none;
+  -webkit-appearance: none;
+  background: transparent;
+  color: inherit;
+  width: 100%;
+  padding: 11px;
+  font-weight: 600;
+  margin: 0;
+  border: 1px solid rgba(0,0,0,0.33);
+  border-radius: 4px;
+}
+
+.c2::-webkit-input-placeholder {
+  color: #AAAAAA;
+}
+
+.c2::-moz-placeholder {
+  color: #AAAAAA;
+}
+
+.c2:-ms-input-placeholder {
+  color: #AAAAAA;
+}
+
+.c2::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+.c2::-moz-focus-inner {
+  border: none;
+  outline: none;
+}
+
+.c2:-moz-placeholder,
+.c2::-moz-placeholder {
+  opacity: 1;
+}
+
+.c1 {
+  position: relative;
+  width: 100%;
+}
+
+<div
+  class="c0"
+>
+  <div
+    class="c1"
+  >
+    <input
+      autocomplete="off"
+      class="c2"
+      data-testid="placeholder"
+      id="placeholder"
+      name="placeholder"
+      placeholder="placeholder text"
+      value=""
+    />
+  </div>
+</div>
+`;
+
+exports[`TextInput should only should default placeholder when placeholder is a 
+  string 2`] = `
+<div
+  class="StyledGrommet-sc-19lkkz7-0 djOnwZ"
+>
+  <div
+    class="StyledTextInput__StyledTextInputContainer-sc-1x30a0s-1 dpaJQp"
+  >
+    <input
+      autocomplete="off"
+      class="StyledTextInput-sc-1x30a0s-0 jKshUE"
+      data-testid="placeholder"
+      id="placeholder"
+      name="placeholder"
+      placeholder="placeholder text"
+      value=""
+    />
+  </div>
+</div>
+`;
+
 exports[`TextInput should show non-string placeholder 1`] = `
 .c0 {
   font-size: 18px;