Expand textbox for account status & add 140 char limit

The current character count is displayed on the left.

To support multiple lines the iron-input was converted to a
iron-autogrow-textarea, and the hovercard needed to respect newlines in
whitespace.

https://imgur.com/a/yYQFLiH

Release-Notes: skip
Google-Bug-Id: b/222687832
Change-Id: I187a4719d3baeba91833c07c54363bc4abb728cd
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
index f63f34e..1549da5 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
@@ -3,6 +3,7 @@
  * Copyright 2016 Google LLC
  * SPDX-License-Identifier: Apache-2.0
  */
+import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
 import '@polymer/iron-input/iron-input';
 import '../../shared/gr-avatar/gr-avatar';
 import '../../shared/gr-date-formatter/gr-date-formatter';
@@ -87,6 +88,13 @@
         border-radius: var(--border-radius);
         box-shadow: var(--elevation-level-5);
       }
+      iron-autogrow-textarea {
+        background-color: var(--view-background-color);
+        color: var(--primary-text-color);
+      }
+      .lengthCounter {
+        font-weight: var(--font-weight-normal);
+      }
     `,
   ];
 
@@ -200,25 +208,26 @@
         </span>
       </section>
       <section>
-        <label class="title" for="statusInput">About me (e.g. employer)</label>
+        <span class="title">
+          <label for="statusInput">About me (e.g. employer)</label>
+          <div class="lengthCounter">
+            ${this.account.status?.length ?? 0}/140
+          </div>
+        </span>
         <span class="value">
-          <iron-input
-            id="statusIronInput"
-            @keydown=${this.handleKeydown}
-            .bindValue=${this.account?.status}
+          <iron-autogrow-textarea
+            id="statusInput"
+            .name=${'statusInput'}
+            ?disabled=${this.saving}
+            maxlength="140"
+            .value=${this.account?.status}
             @bind-value-changed=${(e: BindValueChangeEvent) => {
               const oldAccount = this.account;
               if (!oldAccount || oldAccount.status === e.detail.value) return;
               this.account = {...oldAccount, status: e.detail.value};
               this.hasStatusChange = true;
             }}
-          >
-            <input
-              id="statusInput"
-              ?disabled=${this.saving}
-              @keydown=${this.handleKeydown}
-            />
-          </iron-input>
+          ></iron-autogrow-textarea>
         </span>
       </section>
       <section>
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
index f7e5dee..e968b12 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
@@ -5,7 +5,12 @@
  */
 import '../../../test/common-test-setup';
 import './gr-account-info';
-import {query, queryAll, stubRestApi} from '../../../test/test-utils';
+import {
+  query,
+  queryAll,
+  queryAndAssert,
+  stubRestApi,
+} from '../../../test/test-utils';
 import {GrAccountInfo} from './gr-account-info';
 import {AccountDetailInfo, ServerInfo} from '../../../types/common';
 import {
@@ -20,6 +25,7 @@
 import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
 import {EditableAccountField} from '../../../api/rest-api';
 import {fixture, html, assert} from '@open-wc/testing';
+import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea';
 
 suite('gr-account-info tests', () => {
   let element!: GrAccountInfo;
@@ -100,13 +106,16 @@
             </span>
           </section>
           <section>
-            <label class="title" for="statusInput">
-              About me (e.g. employer)
-            </label>
+            <span class="title">
+              <label for="statusInput">About me (e.g. employer)</label>
+              <div class="lengthCounter">0/140</div>
+            </span>
             <span class="value">
-              <iron-input id="statusIronInput">
-                <input id="statusInput" />
-              </iron-input>
+              <iron-autogrow-textarea
+                aria-disabled="false"
+                id="statusInput"
+                maxlength="140"
+              />
             </span>
           </section>
           <section>
@@ -276,8 +285,11 @@
     test('status', async () => {
       assert.isFalse(element.hasUnsavedChanges);
 
-      const statusInputEl = queryIronInput('#statusIronInput');
-      statusInputEl.bindValue = 'new status';
+      const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+        element,
+        '#statusInput'
+      );
+      statusTextarea.value = 'new status';
       await element.updateComplete;
       assert.isFalse(element.hasNameChange);
       assert.isTrue(element.hasStatusChange);
@@ -320,8 +332,11 @@
       await element.updateComplete;
       assert.isTrue(element.hasNameChange);
 
-      const statusInputEl = queryIronInput('#statusIronInput');
-      statusInputEl.bindValue = 'new status';
+      const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+        element,
+        '#statusInput'
+      );
+      statusTextarea.value = 'new status';
       await element.updateComplete;
       assert.isTrue(element.hasStatusChange);
 
@@ -366,8 +381,11 @@
       assert.equal(displaySpan.textContent, account.name);
       assert.isUndefined(inputSpan);
 
-      const inputEl = queryIronInput('#statusIronInput');
-      inputEl.bindValue = 'new status';
+      const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+        element,
+        '#statusInput'
+      );
+      statusTextarea.value = 'new status';
       await element.updateComplete;
       assert.isTrue(element.hasStatusChange);
 
diff --git a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
index dc08648..abc7f3c 100644
--- a/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
+++ b/polygerrit-ui/app/elements/shared/gr-hovercard-account/gr-hovercard-account-contents.ts
@@ -157,6 +157,9 @@
         .reason {
           padding-top: var(--spacing-s);
         }
+        .status .value {
+          white-space: pre-wrap;
+        }
       `,
     ];
   }