diff --git a/static_src/elements/framework/mr-issue-list/mr-issue-list.js b/static_src/elements/framework/mr-issue-list/mr-issue-list.js
new file mode 100644
index 0000000..3e0a279
--- /dev/null
+++ b/static_src/elements/framework/mr-issue-list/mr-issue-list.js
@@ -0,0 +1,1575 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LitElement, html, css} from 'lit-element';
+
+import page from 'page';
+import {connectStore, store} from 'reducers/base.js';
+import * as issueV0 from 'reducers/issueV0.js';
+import * as sitewide from 'reducers/sitewide.js';
+import 'elements/framework/links/mr-issue-link/mr-issue-link.js';
+import 'elements/framework/links/mr-crbug-link/mr-crbug-link.js';
+import 'elements/framework/mr-dropdown/mr-dropdown.js';
+import 'elements/framework/mr-star/mr-issue-star.js';
+import {constructHref, prepareDataForDownload} from './list-to-csv-helpers.js';
+import {
+  issueRefToUrl,
+  issueRefToString,
+  issueStringToRef,
+  issueToIssueRef,
+  issueToIssueRefString,
+  labelRefsToOneWordLabels,
+} from 'shared/convertersV0.js';
+import {isTextInput, findDeepEventTarget} from 'shared/dom-helpers.js';
+import {
+  urlWithNewParams,
+  pluralize,
+  setHasAny,
+  objectValuesForKeys,
+} from 'shared/helpers.js';
+import {SHARED_STYLES} from 'shared/shared-styles.js';
+import {parseColSpec, EMPTY_FIELD_VALUE} from 'shared/issue-fields.js';
+import './mr-show-columns-dropdown.js';
+
+/**
+ * Column to display name mapping dictionary
+ * @type {Object<string, string>}
+ */
+const COLUMN_DISPLAY_NAMES = Object.freeze({
+  'summary': 'Summary + Labels',
+});
+
+/** @const {number} Button property value of DOM click event */
+const PRIMARY_BUTTON = 0;
+/** @const {number} Button property value of DOM auxclick event */
+const MIDDLE_BUTTON = 1;
+
+/** @const {string} A short transition to ease movement of list items. */
+const EASE_OUT_TRANSITION = 'transform 0.05s cubic-bezier(0, 0, 0.2, 1)';
+
+/**
+ * Really high cardinality attributes like ID and Summary are unlikely to be
+ * useful if grouped, so it's better to just hide the option.
+ * @const {Set<string>}
+ */
+const UNGROUPABLE_COLUMNS = new Set(['id', 'summary']);
+
+/**
+ * Columns that should render as issue links.
+ * @const {Set<string>}
+ */
+const ISSUE_COLUMNS = new Set(['id', 'mergedinto', 'blockedon', 'blocking']);
+
+/**
+ * `<mr-issue-list>`
+ *
+ * A list of issues intended to be used in multiple contexts.
+ * @extends {LitElement}
+ */
+export class MrIssueList extends connectStore(LitElement) {
+  /** @override */
+  static get styles() {
+    return [
+      SHARED_STYLES,
+      css`
+        :host {
+          width: 100%;
+          font-size: var(--chops-main-font-size);
+        }
+        table {
+          width: 100%;
+        }
+        .edit-widget-container {
+          display: flex;
+          flex-wrap: no-wrap;
+          align-items: center;
+        }
+        mr-issue-star {
+          --mr-star-size: 18px;
+          margin-bottom: 1px;
+          margin-left: 4px;
+        }
+        input[type="checkbox"] {
+          cursor: pointer;
+          margin: 0 4px;
+          width: 16px;
+          height: 16px;
+          border-radius: 2px;
+          box-sizing: border-box;
+          appearance: none;
+          -webkit-appearance: none;
+          border: 2px solid var(--chops-gray-400);
+          position: relative;
+          background: var(--chops-white);
+        }
+        th input[type="checkbox"] {
+          border-color: var(--chops-gray-500);
+        }
+        input[type="checkbox"]:checked {
+          background: var(--chops-primary-accent-color);
+          border-color: var(--chops-primary-accent-color);
+        }
+        input[type="checkbox"]:checked::after {
+          left: 1px;
+          top: 2px;
+          position: absolute;
+          content: "";
+          width: 8px;
+          height: 4px;
+          border: 2px solid white;
+          border-right: none;
+          border-top: none;
+          transform: rotate(-45deg);
+        }
+        td, th.group-header {
+          padding: 4px 8px;
+          text-overflow: ellipsis;
+          border-bottom: var(--chops-normal-border);
+          cursor: pointer;
+          font-weight: normal;
+        }
+        .group-header-content {
+          height: 100%;
+          width: 100%;
+          align-items: center;
+          display: flex;
+        }
+        th.group-header i.material-icons {
+          font-size: var(--chops-icon-font-size);
+          color: var(--chops-primary-icon-color);
+          margin-right: 4px;
+        }
+        td.ignore-navigation {
+          cursor: default;
+        }
+        th {
+          background: var(--chops-table-header-bg);
+          white-space: nowrap;
+          text-align: left;
+          border-bottom: var(--chops-normal-border);
+        }
+        th.selection-header {
+          padding: 3px 8px;
+        }
+        th > mr-dropdown, th > mr-show-columns-dropdown {
+          font-weight: normal;
+          color: var(--chops-link-color);
+          --mr-dropdown-icon-color: var(--chops-link-color);
+          --mr-dropdown-anchor-padding: 3px 8px;
+          --mr-dropdown-anchor-font-weight: bold;
+          --mr-dropdown-menu-min-width: 150px;
+        }
+        tr {
+          padding: 0 8px;
+        }
+        tr[selected] {
+          background: var(--chops-selected-bg);
+        }
+        td:first-child, th:first-child {
+          border-left: 4px solid transparent;
+        }
+        tr[cursored] > td:first-child {
+          border-left: 4px solid var(--chops-blue-700);
+        }
+        mr-crbug-link {
+          /* We need the shortlink to be hidden but still accessible.
+          * The opacity attribute visually hides a link while still
+          * keeping it in the DOM.opacity. */
+          --mr-crbug-link-opacity: 0;
+          --mr-crbug-link-opacity-focused: 1;
+        }
+        td:hover > mr-crbug-link {
+          --mr-crbug-link-opacity: 1;
+        }
+        .col-summary, .header-summary {
+          /* Setting a table cell to 100% width makes it take up
+          * all remaining space in the table, not the full width of
+          * the table. */
+          width: 100%;
+        }
+        .summary-label {
+          display: inline-block;
+          margin: 0 2px;
+          color: var(--chops-green-800);
+          text-decoration: none;
+          font-size: 90%;
+        }
+        .summary-label:hover {
+          text-decoration: underline;
+        }
+        td.draggable i {
+          opacity: 0;
+        }
+        td.draggable {
+          color: var(--chops-primary-icon-color);
+          cursor: grab;
+          padding-left: 0;
+          padding-right: 0;
+        }
+        tr.dragged {
+          opacity: 0.74;
+        }
+        tr:hover td.draggable i {
+          opacity: 1;
+        }
+        .csv-download-container {
+          border-bottom: none;
+          text-align: end;
+          cursor: default;
+        }
+        #hidden-data-link {
+          display: none;
+        }
+        @media (min-width: 1024px) {
+          .first-row th {
+            position: sticky;
+            top: var(--monorail-header-height);
+            z-index: 10;
+          }
+        }
+      `,
+    ];
+  }
+
+  /** @override */
+  render() {
+    const selectAllChecked = this._selectedIssues.size > 0;
+    const checkboxLabel = `Select ${selectAllChecked ? 'None' : 'All'}`;
+
+    return html`
+      <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+      <table cellspacing="0">
+        <thead>
+          <tr class="first-row">
+            ${this.rerank ? html`<th></th>` : ''}
+            <th class="selection-header">
+              <div class="edit-widget-container">
+                ${this.selectionEnabled ? html`
+                  <input
+                    class="select-all"
+                    .checked=${selectAllChecked}
+                    type="checkbox"
+                    aria-label=${checkboxLabel}
+                    title=${checkboxLabel}
+                    @change=${this._selectAll}
+                  />
+                ` : ''}
+              </div>
+            </th>
+            ${this.columns.map((column, i) => this._renderHeader(column, i))}
+            <th style="z-index: ${this.highestZIndex};">
+              <mr-show-columns-dropdown
+                title="Show columns"
+                menuAlignment="right"
+                .columns=${this.columns}
+                .issues=${this.issues}
+                .defaultFields=${this.defaultFields}
+              ></mr-show-columns-dropdown>
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          ${this._renderIssues()}
+        </tbody>
+        ${this.userDisplayName && html`
+          <tfoot><tr><td colspan=999 class="csv-download-container">
+            <a id="download-link" aria-label="Download page as CSV"
+                @click=${this._downloadCsv} href>CSV</a>
+            <a id="hidden-data-link" download="${this.projectName}-issues.csv"
+              href=${this._csvDataHref}></a>
+          </td></tr></tfoot>
+        `}
+      </table>
+    `;
+  }
+
+  /**
+   * @param {string} column
+   * @param {number} i The index of the column in the table.
+   * @return {TemplateResult} html for header for the i-th column.
+   * @private
+   */
+  _renderHeader(column, i) {
+    // zIndex is used to render the z-index property in descending order
+    const zIndex = this.highestZIndex - i;
+    const colKey = column.toLowerCase();
+    const name = colKey in COLUMN_DISPLAY_NAMES ? COLUMN_DISPLAY_NAMES[colKey] :
+      column;
+    return html`
+      <th style="z-index: ${zIndex};" class="header-${colKey}">
+        <mr-dropdown
+          class="dropdown-${colKey}"
+          .text=${name}
+          .items=${this._headerActions(column, i)}
+          menuAlignment="left"
+        ></mr-dropdown>
+      </th>`;
+  }
+
+  /**
+   * @param {string} column
+   * @param {number} i The index of the column in the table.
+   * @return {Array<Object>} Available actions for the column.
+   * @private
+   */
+  _headerActions(column, i) {
+    const columnKey = column.toLowerCase();
+
+    const isGroupable = this.sortingAndGroupingEnabled &&
+        !UNGROUPABLE_COLUMNS.has(columnKey);
+
+    let showOnly = [];
+    if (isGroupable) {
+      const values = [...this._uniqueValuesByColumn.get(columnKey)];
+      if (values.length) {
+        showOnly = [{
+          text: 'Show only',
+          items: values.map((v) => ({
+            text: v,
+            handler: () => this.showOnly(column, v),
+          })),
+        }];
+      }
+    }
+    const sortingActions = this.sortingAndGroupingEnabled ? [
+      {
+        text: 'Sort up',
+        handler: () => this.updateSortSpec(column),
+      },
+      {
+        text: 'Sort down',
+        handler: () => this.updateSortSpec(column, true),
+      },
+    ] : [];
+    const actions = [
+      ...sortingActions,
+      ...showOnly,
+      {
+        text: 'Hide column',
+        handler: () => this.removeColumn(i),
+      },
+    ];
+    if (isGroupable) {
+      actions.push({
+        text: 'Group rows',
+        handler: () => this.addGroupBy(i),
+      });
+    }
+    return actions;
+  }
+
+  /**
+   * @return {TemplateResult}
+   */
+  _renderIssues() {
+    // Keep track of all the groups that we've seen so far to create
+    // group headers as needed.
+    const {issues, groupedIssues} = this;
+
+    if (groupedIssues) {
+      // Make sure issues in groups are rendered with unique indices across
+      // groups to make sure hot keys and the like still work.
+      let indexOffset = 0;
+      return html`${groupedIssues.map(({groupName, issues}) => {
+        const template = html`
+          ${this._renderGroup(groupName, issues, indexOffset)}
+        `;
+        indexOffset += issues.length;
+        return template;
+      })}`;
+    }
+
+    return html`
+      ${issues.map((issue, i) => this._renderRow(issue, i))}
+    `;
+  }
+
+  /**
+   * @param {string} groupName
+   * @param {Array<Issue>} issues
+   * @param {number} iOffset
+   * @return {TemplateResult}
+   * @private
+   */
+  _renderGroup(groupName, issues, iOffset) {
+    if (!this.groups.length) return html``;
+
+    const count = issues.length;
+    const groupKey = groupName.toLowerCase();
+    const isHidden = this._hiddenGroups.has(groupKey);
+
+    return html`
+      <tr>
+        <th
+          class="group-header"
+          colspan="${this.numColumns}"
+          @click=${() => this._toggleGroup(groupKey)}
+          aria-expanded=${(!isHidden).toString()}
+        >
+          <div class="group-header-content">
+            <i
+              class="material-icons"
+              title=${isHidden ? 'Show' : 'Hide'}
+            >${isHidden ? 'add' : 'remove'}</i>
+            ${count} ${pluralize(count, 'issue')}: ${groupName}
+          </div>
+        </th>
+      </tr>
+      ${issues.map((issue, i) => this._renderRow(issue, iOffset + i, isHidden))}
+    `;
+  }
+
+  /**
+   * @param {string} groupKey Lowercase group key.
+   * @private
+   */
+  _toggleGroup(groupKey) {
+    if (this._hiddenGroups.has(groupKey)) {
+      this._hiddenGroups.delete(groupKey);
+    } else {
+      this._hiddenGroups.add(groupKey);
+    }
+
+    // Lit-element's default hasChanged check does not notice when Sets mutate.
+    this.requestUpdate('_hiddenGroups');
+  }
+
+  /**
+   * @param {Issue} issue
+   * @param {number} i Index within the list of issues
+   * @param {boolean=} isHidden
+   * @return {TemplateResult}
+   */
+  _renderRow(issue, i, isHidden = false) {
+    const rowSelected = this._selectedIssues.has(issueRefToString(issue));
+    const id = issueRefToString(issue);
+    const cursorId = issueRefToString(this.cursor);
+    const hasCursor = cursorId === id;
+    const dragged = this._dragging && rowSelected;
+
+    return html`
+      <tr
+        class="row-${i} list-row ${dragged ? 'dragged' : ''}"
+        ?selected=${rowSelected}
+        ?cursored=${hasCursor}
+        ?hidden=${isHidden}
+        data-issue-ref=${id}
+        data-index=${i}
+        data-name=${issue.name}
+        @focus=${this._setRowAsCursorOnFocus}
+        @click=${this._clickIssueRow}
+        @auxclick=${this._clickIssueRow}
+        @keydown=${this._keydownIssueRow}
+        tabindex="0"
+      >
+        ${this.rerank ? html`
+          <td class="draggable ignore-navigation"
+              @mousedown=${this._onMouseDown}>
+            <i class="material-icons" title="Drag issue">drag_indicator</i>
+          </td>
+        ` : ''}
+        <td class="ignore-navigation">
+          <div class="edit-widget-container">
+            ${this.selectionEnabled ? html`
+              <input
+                class="issue-checkbox"
+                .value=${id}
+                .checked=${rowSelected}
+                type="checkbox"
+                data-index=${i}
+                aria-label="Select Issue ${issue.localId}"
+                @change=${this._selectIssue}
+                @click=${this._selectIssueRange}
+              />
+            ` : ''}
+            ${this.starringEnabled ? html`
+              <mr-issue-star
+                .issueRef=${issueToIssueRef(issue)}
+              ></mr-issue-star>
+            ` : ''}
+          </div>
+        </td>
+
+        ${this.columns.map((column) => html`
+          <td class="col-${column.toLowerCase()}">
+            ${this._renderCell(column, issue)}
+          </td>
+        `)}
+
+        <td>
+          <mr-crbug-link .issue=${issue}></mr-crbug-link>
+        </td>
+      </tr>
+    `;
+  }
+
+  /**
+   * @param {string} column
+   * @param {Issue} issue
+   * @return {TemplateResult} Html for the given column for the given issue.
+   * @private
+   */
+  _renderCell(column, issue) {
+    const columnName = column.toLowerCase();
+    if (columnName === 'summary') {
+      return html`
+        ${issue.summary}
+        ${labelRefsToOneWordLabels(issue.labelRefs).map(({label}) => html`
+          <a
+            class="summary-label"
+            href="/p/${issue.projectName}/issues/list?q=label%3A${label}"
+          >${label}</a>
+        `)}
+      `;
+    }
+    const values = this.extractFieldValues(issue, column);
+
+    if (!values.length) return EMPTY_FIELD_VALUE;
+
+    // TODO(zhangtiff): Make this based on the "ISSUE" field type rather than a
+    // hardcoded list of issue fields.
+    if (ISSUE_COLUMNS.has(columnName)) {
+      return values.map((issueRefString, i) => {
+        const issue = this._issueForRefString(issueRefString, this.projectName);
+        return html`
+          <mr-issue-link
+            .projectName=${this.projectName}
+            .issue=${issue}
+            .queryParams=${this._queryParams}
+            short
+          ></mr-issue-link>${values.length - 1 > i ? ', ' : ''}
+        `;
+      });
+    }
+    return values.join(', ');
+  }
+
+  /** @override */
+  static get properties() {
+    return {
+      /**
+       * Array of columns to display.
+       */
+      columns: {type: Array},
+      /**
+       * Array of built in fields that are available outside of project
+       * configuration.
+       */
+      defaultFields: {type: Array},
+      /**
+       * A function that takes in an issue and a field name and returns the
+       * value for that field in the issue. This function accepts custom fields,
+       * built in fields, and ad hoc fields computed from label prefixes.
+       */
+      extractFieldValues: {type: Object},
+      /**
+       * Array of columns that are used as groups for issues.
+       */
+      groups: {type: Array},
+      /**
+       * List of issues to display.
+       */
+      issues: {type: Array},
+      /**
+       * A Redux action creator that calls the API to rerank the issues
+       * in the list. If set, reranking is enabled for this issue list.
+       */
+      rerank: {type: Object},
+      /**
+       * Whether issues should be selectable or not.
+       */
+      selectionEnabled: {type: Boolean},
+      /**
+       * Whether issues should be sortable and groupable or not. This will
+       * change how column headers will be displayed. The ability to sort and
+       * group are currently coupled.
+       */
+      sortingAndGroupingEnabled: {type: Boolean},
+      /**
+       * Whether to show issue starring or not.
+       */
+      starringEnabled: {type: Boolean},
+      /**
+       * A query representing the current set of matching issues in the issue
+       * list. Does not necessarily match queryParams.q since queryParams.q can
+       * be empty while currentQuery is set to a default project query.
+       */
+      currentQuery: {type: String},
+      /**
+       * Object containing URL parameters to be preserved when issue links are
+       * clicked. This Object is only used for the purpose of preserving query
+       * parameters across links, not for the purpose of evaluating the query
+       * parameters themselves to get values like columns, sort, or q. This
+       * separation is important because we don't want to tightly couple this
+       * list component with a specific URL system.
+       * @private
+       */
+      _queryParams: {type: Object},
+      /**
+       * The initial cursor that a list view uses. This attribute allows users
+       * of the list component to specify and control the cursor. When the
+       * initialCursor attribute updates, the list focuses the element specified
+       * by the cursor.
+       */
+      initialCursor: {type: String},
+      /**
+       * Logged in user's display name
+       */
+      userDisplayName: {type: String},
+      /**
+       * IssueRef Object specifying which issue the user is currently focusing.
+       */
+      _localCursor: {type: Object},
+      /**
+       * Set of group keys that are currently hidden.
+       */
+      _hiddenGroups: {type: Object},
+      /**
+       * Set of all selected issues where each entry is an issue ref string.
+       */
+      _selectedIssues: {type: Object},
+      /**
+       * List of unique phase names for all phases in issues.
+       */
+      _phaseNames: {type: Array},
+      /**
+       * True iff the user is dragging issues.
+       */
+      _dragging: {type: Boolean},
+      /**
+       * CSV data in data HREF format, used to download csv
+       */
+      _csvDataHref: {type: String},
+      /**
+       * Function to get a full Issue object for a given ref string.
+       */
+      _issueForRefString: {type: Object},
+    };
+  };
+
+  /** @override */
+  constructor() {
+    super();
+    /** @type {Array<Issue>} */
+    this.issues = [];
+    // TODO(jojwang): monorail:6336#c8, when ezt listissues page is fully
+    // deprecated, remove phaseNames from mr-issue-list.
+    this._phaseNames = [];
+    /** @type {IssueRef} */
+    this._localCursor;
+    /** @type {IssueRefString} */
+    this.initialCursor;
+    /** @type {Set<IssueRefString>} */
+    this._selectedIssues = new Set();
+    /** @type {string} */
+    this.projectName;
+    /** @type {Object} */
+    this._queryParams = {};
+    /** @type {string} */
+    this.currentQuery = '';
+    /**
+     * @param {Array<String>} items
+     * @param {number} index
+     * @return {Promise<void>}
+     */
+    this.rerank = null;
+    /** @type {boolean} */
+    this.selectionEnabled = false;
+    /** @type {boolean} */
+    this.sortingAndGroupingEnabled = false;
+    /** @type {boolean} */
+    this.starringEnabled = false;
+    /** @type {Array} */
+    this.columns = ['ID', 'Summary'];
+    /** @type {Array<string>} */
+    this.defaultFields = [];
+    /** @type {Array} */
+    this.groups = [];
+    this.userDisplayName = '';
+
+    /** @type {function(KeyboardEvent): void} */
+    this._boundRunListHotKeys = this._runListHotKeys.bind(this);
+    /** @type {function(MouseEvent): void} */
+    this._boundOnMouseMove = this._onMouseMove.bind(this);
+    /** @type {function(MouseEvent): void} */
+    this._boundOnMouseUp = this._onMouseUp.bind(this);
+
+    /**
+     * @param {Issue} _issue
+     * @param {string} _fieldName
+     * @return {Array<string>}
+     */
+    this.extractFieldValues = (_issue, _fieldName) => [];
+
+    /**
+     * @param {IssueRefString} _issueRefString
+     * @param {string} projectName The currently viewed project.
+     * @return {Issue}
+     */
+    this._issueForRefString = (_issueRefString, projectName) =>
+      issueStringToRef(_issueRefString, projectName);
+
+    this._hiddenGroups = new Set();
+
+    this._starredIssues = new Set();
+    this._fetchingStarredIssues = false;
+    this._starringIssues = new Map();
+
+    this._uniqueValuesByColumn = new Map();
+
+    this._dragging = false;
+    this._mouseX = null;
+    this._mouseY = null;
+
+    /** @type {number} */
+    this._lastSelectedCheckbox = -1;
+
+    // Expose page.js for stubbing.
+    this._page = page;
+    /** @type {string} page data in csv format as data href */
+    this._csvDataHref = '';
+  };
+
+  /** @override */
+  stateChanged(state) {
+    this._starredIssues = issueV0.starredIssues(state);
+    this._fetchingStarredIssues =
+        issueV0.requests(state).fetchStarredIssues.requesting;
+    this._starringIssues = issueV0.starringIssues(state);
+
+    this._phaseNames = (issueV0.issueListPhaseNames(state) || []);
+    this._queryParams = sitewide.queryParams(state);
+
+    this._issueForRefString = issueV0.issueForRefString(state);
+  }
+
+  /** @override */
+  firstUpdated() {
+    // Only attach an event listener once the DOM has rendered.
+    window.addEventListener('keydown', this._boundRunListHotKeys);
+    this._dataLink = this.shadowRoot.querySelector('#hidden-data-link');
+  }
+
+  /** @override */
+  disconnectedCallback() {
+    super.disconnectedCallback();
+
+    window.removeEventListener('keydown', this._boundRunListHotKeys);
+  }
+
+  /**
+   * @override
+   * @fires CustomEvent#selectionChange
+   */
+  update(changedProperties) {
+    if (changedProperties.has('issues')) {
+      // Clear selected issues to avoid an ever-growing Set size. In the future,
+      // we may want to consider saving selections across issue reloads, though,
+      // such as in the case or list refreshing.
+      this._selectedIssues = new Set();
+      this.dispatchEvent(new CustomEvent('selectionChange'));
+
+      // Clear group toggle state when the list of issues changes to prevent an
+      // ever-growing Set size.
+      this._hiddenGroups = new Set();
+
+      this._lastSelectedCheckbox = -1;
+    }
+
+    const valuesByColumnArgs = ['issues', 'columns', 'extractFieldValues'];
+    if (setHasAny(changedProperties, valuesByColumnArgs)) {
+      this._uniqueValuesByColumn = this._computeUniqueValuesByColumn(
+          ...objectValuesForKeys(this, valuesByColumnArgs));
+    }
+
+    super.update(changedProperties);
+  }
+
+  /** @override */
+  updated(changedProperties) {
+    if (changedProperties.has('initialCursor')) {
+      const ref = issueStringToRef(this.initialCursor, this.projectName);
+      const row = this._getRowFromIssueRef(ref);
+      if (row) {
+        row.focus();
+      }
+    }
+  }
+
+  /**
+   * Iterates through all issues in a list to sort unique values
+   * across columns, for use in the "Show only" feature.
+   * @param {Array} issues
+   * @param {Array} columns
+   * @param {function(Issue, string): Array<string>} fieldExtractor
+   * @return {Map} Map where each entry has a String key for the
+   *   lowercase column name and a Set value, continuing all values for
+   *   that column.
+   */
+  _computeUniqueValuesByColumn(issues, columns, fieldExtractor) {
+    const valueMap = new Map(
+        columns.map((col) => [col.toLowerCase(), new Set()]));
+
+    issues.forEach((issue) => {
+      columns.forEach((col) => {
+        const key = col.toLowerCase();
+        const valueSet = valueMap.get(key);
+
+        const values = fieldExtractor(issue, col);
+        // Note: This allows multiple casings of the same values to be added
+        // to the Set.
+        values.forEach((v) => valueSet.add(v));
+      });
+    });
+    return valueMap;
+  }
+
+  /**
+   * Used for dynamically computing z-index to ensure column dropdowns overlap
+   * properly.
+   */
+  get highestZIndex() {
+    return this.columns.length + 10;
+  }
+
+  /**
+   * The number of columns displayed in the table. This is the count of
+   * customized columns + number of built in columns.
+   */
+  get numColumns() {
+    return this.columns.length + 2;
+  }
+
+  /**
+   * Sort issues into groups if groups are defined. The grouping feature is used
+   * when the "groupby" URL parameter is set in the list view.
+   */
+  get groupedIssues() {
+    if (!this.groups || !this.groups.length) return;
+
+    const issuesByGroup = new Map();
+
+    this.issues.forEach((issue) => {
+      const groupName = this._groupNameForIssue(issue);
+      const groupKey = groupName.toLowerCase();
+
+      if (!issuesByGroup.has(groupKey)) {
+        issuesByGroup.set(groupKey, {groupName, issues: [issue]});
+      } else {
+        const entry = issuesByGroup.get(groupKey);
+        entry.issues.push(issue);
+      }
+    });
+    return [...issuesByGroup.values()];
+  }
+
+  /**
+   * The currently selected issue, with _localCursor overriding initialCursor.
+   *
+   * @return {IssueRef} The currently selected issue.
+   */
+  get cursor() {
+    if (this._localCursor) {
+      return this._localCursor;
+    }
+    if (this.initialCursor) {
+      return issueStringToRef(this.initialCursor, this.projectName);
+    }
+    return {};
+  }
+
+  /**
+   * Computes the name of the group that an issue belongs to. Issues are grouped
+   * by fields that the user specifies and group names are generated using a
+   * combination of an issue's field values for all specified groups.
+   *
+   * @param {Issue} issue
+   * @return {string}
+   */
+  _groupNameForIssue(issue) {
+    const groups = this.groups;
+    const keyPieces = [];
+
+    groups.forEach((group) => {
+      const values = this.extractFieldValues(issue, group);
+      if (!values.length) {
+        keyPieces.push(`-has:${group}`);
+      } else {
+        values.forEach((v) => {
+          keyPieces.push(`${group}=${v}`);
+        });
+      }
+    });
+
+    return keyPieces.join(' ');
+  }
+
+  /**
+   * @return {Array<Issue>} Selected issues in the order they appear.
+   */
+  get selectedIssues() {
+    return this.issues.filter((issue) =>
+      this._selectedIssues.has(issueToIssueRefString(issue)));
+  }
+
+  /**
+   * Update the search query to filter values matching a specific one.
+   *
+   * @param {string} column name of the column being filtered.
+   * @param {string} value value of the field to filter by.
+   */
+  showOnly(column, value) {
+    column = column.toLowerCase();
+
+    // TODO(zhangtiff): Handle edge cases where column names are not
+    // mapped directly to field names. For example, "AllLabels", should
+    // query for "Labels".
+    const querySegment = `${column}=${value}`;
+
+    let query = this.currentQuery.trim();
+
+    if (!query.includes(querySegment)) {
+      query += ' ' + querySegment;
+
+      this._updateQueryParams({q: query.trim()}, ['start']);
+    }
+  }
+
+  /**
+   * Update sort parameter in the URL based on user input.
+   *
+   * @param {string} column name of the column to be sorted.
+   * @param {boolean} descending descending or ascending order.
+   */
+  updateSortSpec(column, descending = false) {
+    column = column.toLowerCase();
+    const oldSpec = this._queryParams.sort || '';
+    const columns = parseColSpec(oldSpec.toLowerCase());
+
+    // Remove any old instances of the same sort spec.
+    const newSpec = columns.filter(
+        (c) => c && c !== column && c !== `-${column}`);
+
+    newSpec.unshift(`${descending ? '-' : ''}${column}`);
+
+    this._updateQueryParams({sort: newSpec.join(' ')}, ['start']);
+  }
+
+  /**
+   * Updates the groupby URL parameter to include a new column to group.
+   *
+   * @param {number} i index of the column to be grouped.
+   */
+  addGroupBy(i) {
+    const groups = [...this.groups];
+    const columns = [...this.columns];
+    const groupedColumn = columns[i];
+    columns.splice(i, 1);
+
+    groups.unshift(groupedColumn);
+
+    this._updateQueryParams({
+      groupby: groups.join(' '),
+      colspec: columns.join('+'),
+    }, ['start']);
+  }
+
+  /**
+   * Removes the column at a particular index.
+   *
+   * @param {number} i the issue column to be removed.
+   */
+  removeColumn(i) {
+    const columns = [...this.columns];
+    columns.splice(i, 1);
+    this.reloadColspec(columns);
+  }
+
+  /**
+   * Adds a new column to a particular index.
+   *
+   * @param {string} name of the new column added.
+   */
+  addColumn(name) {
+    this.reloadColspec([...this.columns, name]);
+  }
+
+  /**
+   * Reflects changes to the columns of an issue list to the URL, through
+   * frontend routing.
+   *
+   * @param {Array} newColumns the new colspec to set in the URL.
+   */
+  reloadColspec(newColumns) {
+    this._updateQueryParams({colspec: newColumns.join('+')});
+  }
+
+  /**
+   * Navigates to the same URL as the current page, but with query
+   * params updated.
+   *
+   * @param {Object} newParams keys and values of the queryParams
+   * Object to be updated.
+   * @param {Array} deletedParams keys to be cleared from queryParams.
+   */
+  _updateQueryParams(newParams = {}, deletedParams = []) {
+    const url = urlWithNewParams(this._baseUrl(), this._queryParams, newParams,
+        deletedParams);
+    this._page(url);
+  }
+
+  /**
+   * Get the current URL of the page, without query params. Useful for
+   * test stubbing.
+   *
+   * @return {string} the URL of the list page, without params.
+   */
+  _baseUrl() {
+    return window.location.pathname;
+  }
+
+  /**
+   * Run issue list hot keys. This event handler needs to be bound globally
+   * because a list cursor can be defined even when no element in the list is
+   * focused.
+   * @param {KeyboardEvent} e
+   */
+  _runListHotKeys(e) {
+    if (!this.issues || !this.issues.length) return;
+    const target = findDeepEventTarget(e);
+    if (!target || isTextInput(target)) return;
+
+    const key = e.key;
+
+    const activeRow = this._getCursorElement();
+
+    let i = -1;
+    if (activeRow) {
+      i = Number.parseInt(activeRow.dataset.index);
+
+      const issue = this.issues[i];
+
+      switch (key) {
+        case 's': // Star focused issue.
+          this._starIssue(issueToIssueRef(issue));
+          return;
+        case 'x': // Toggle selection of focused issue.
+          const issueRefString = issueToIssueRefString(issue);
+          this._updateSelectedIssues([issueRefString],
+              !this._selectedIssues.has(issueRefString));
+          return;
+        case 'o': // Open current issue.
+        case 'O': // Open current issue in new tab.
+          this._navigateToIssue(issue, e.shiftKey);
+          return;
+      }
+    }
+
+    // Move up and down the issue list.
+    // 'j' moves 'down'.
+    // 'k' moves 'up'.
+    if (key === 'j' || key === 'k') {
+      if (key === 'j') { // Navigate down the list.
+        i += 1;
+        if (i >= this.issues.length) {
+          i = 0;
+        }
+      } else if (key === 'k') { // Navigate up the list.
+        i -= 1;
+        if (i < 0) {
+          i = this.issues.length - 1;
+        }
+      }
+
+      const nextRow = this.shadowRoot.querySelector(`.row-${i}`);
+      this._setRowAsCursor(nextRow);
+    }
+  }
+
+  /**
+   * @return {HTMLTableRowElement}
+   */
+  _getCursorElement() {
+    const cursor = this.cursor;
+    if (cursor) {
+      // If there's a cursor set, use that instead of focus.
+      return this._getRowFromIssueRef(cursor);
+    }
+    return;
+  }
+
+  /**
+   * @param {FocusEvent} e
+   */
+  _setRowAsCursorOnFocus(e) {
+    this._setRowAsCursor(/** @type {HTMLTableRowElement} */ (e.target));
+  }
+
+  /**
+   *
+   * @param {HTMLTableRowElement} row
+   */
+  _setRowAsCursor(row) {
+    this._localCursor = issueStringToRef(row.dataset.issueRef,
+        this.projectName);
+    row.focus();
+  }
+
+  /**
+   * @param {IssueRef} ref The issueRef to query for.
+   * @return {HTMLTableRowElement}
+   */
+  _getRowFromIssueRef(ref) {
+    return this.shadowRoot.querySelector(
+        `.list-row[data-issue-ref="${issueRefToString(ref)}"]`);
+  }
+
+  /**
+   * Returns an Array containing every <tr> in the list, excluding the header.
+   * @return {Array<HTMLTableRowElement>}
+   */
+  _getRows() {
+    return Array.from(this.shadowRoot.querySelectorAll('.list-row'));
+  }
+
+  /**
+   * Returns an Array containing every selected <tr> in the list.
+   * @return {Array<HTMLTableRowElement>}
+   */
+  _getSelectedRows() {
+    return this._getRows().filter((row) => {
+      return this._selectedIssues.has(row.dataset.issueRef);
+    });
+  }
+
+  /**
+   * @param {IssueRef} issueRef Issue to star
+   */
+  _starIssue(issueRef) {
+    if (!this.starringEnabled) return;
+    const issueKey = issueRefToString(issueRef);
+
+    // TODO(zhangtiff): Find way to share star disabling logic more.
+    const isStarring = this._starringIssues.has(issueKey) &&
+      this._starringIssues.get(issueKey).requesting;
+    const starEnabled = !this._fetchingStarredIssues && !isStarring;
+    if (starEnabled) {
+      const newIsStarred = !this._starredIssues.has(issueKey);
+      this._starIssueInternal(issueRef, newIsStarred);
+    }
+  }
+
+  /**
+   * Wrap store.dispatch and issue.star, for testing.
+   *
+   * @param {IssueRef} issueRef the issue being starred.
+   * @param {boolean} newIsStarred whether to star or unstar the issue.
+   * @private
+   */
+  _starIssueInternal(issueRef, newIsStarred) {
+    store.dispatch(issueV0.star(issueRef, newIsStarred));
+  }
+  /**
+   * @param {Event} e
+   * @fires CustomEvent#open-dialog
+   * @private
+   */
+  _selectAll(e) {
+    const checkbox = /** @type {HTMLInputElement} */ (e.target);
+
+    if (checkbox.checked) {
+      this._selectedIssues = new Set(this.issues.map(issueRefToString));
+    } else {
+      this._selectedIssues = new Set();
+    }
+    this.dispatchEvent(new CustomEvent('selectionChange'));
+  }
+
+  // TODO(zhangtiff): Implement Shift+Click to select a range of checkboxes
+  // for the 'x' hot key.
+  /**
+   * @param {MouseEvent} e
+   * @private
+   */
+  _selectIssueRange(e) {
+    if (!this.selectionEnabled) return;
+
+    const checkbox = /** @type {HTMLInputElement} */ (e.target);
+
+    const index = Number.parseInt(checkbox.dataset.index);
+    if (Number.isNaN(index)) {
+      console.error('Issue checkbox has invalid data-index attribute.');
+      return;
+    }
+
+    const lastIndex = this._lastSelectedCheckbox;
+    if (e.shiftKey && lastIndex >= 0) {
+      const newCheckedState = checkbox.checked;
+
+      const start = Math.min(lastIndex, index);
+      const end = Math.max(lastIndex, index) + 1;
+
+      const updatedIssueKeys = this.issues.slice(start, end).map(
+          issueToIssueRefString);
+      this._updateSelectedIssues(updatedIssueKeys, newCheckedState);
+    }
+
+    this._lastSelectedCheckbox = index;
+  }
+
+  /**
+   * @param {Event} e
+   * @private
+   */
+  _selectIssue(e) {
+    if (!this.selectionEnabled) return;
+
+    const checkbox = /** @type {HTMLInputElement} */ (e.target);
+    const issueKey = checkbox.value;
+
+    this._updateSelectedIssues([issueKey], checkbox.checked);
+  }
+
+  /**
+   * @param {Array<IssueRefString>} issueKeys Stringified issue refs.
+   * @param {boolean} selected
+   * @fires CustomEvent#selectionChange
+   * @private
+   */
+  _updateSelectedIssues(issueKeys, selected) {
+    let hasChanges = false;
+
+    issueKeys.forEach((issueKey) => {
+      const oldSelection = this._selectedIssues.has(issueKey);
+
+      if (selected) {
+        this._selectedIssues.add(issueKey);
+      } else if (this._selectedIssues.has(issueKey)) {
+        this._selectedIssues.delete(issueKey);
+      }
+
+      const newSelection = this._selectedIssues.has(issueKey);
+
+      hasChanges = hasChanges || newSelection !== oldSelection;
+    });
+
+
+    if (hasChanges) {
+      this.requestUpdate('_selectedIssues');
+      this.dispatchEvent(new CustomEvent('selectionChange'));
+    }
+  }
+
+  /**
+   * Handles 'Enter' being pressed when a row is focused.
+   * Note we install the 'Enter' listener on the row rather than the window so
+   * 'Enter' behaves as expected when the focus is on other elements.
+   *
+   * @param {KeyboardEvent} e
+   * @private
+   */
+  _keydownIssueRow(e) {
+    if (e.key === 'Enter') {
+      this._maybeOpenIssueRow(e);
+    }
+  }
+
+  /**
+   * Handles mouseDown to start drag events.
+   * @param {MouseEvent} event
+   * @private
+   */
+  _onMouseDown(event) {
+    event.cancelable && event.preventDefault();
+
+    this._mouseX = event.clientX;
+    this._mouseY = event.clientY;
+
+    this._setRowAsCursor(event.currentTarget.parentNode);
+    this._startDrag();
+
+    // We add the event listeners to window because the mouse can go out of the
+    // bounds of the target element. window.mouseUp still triggers even if the
+    // mouse is outside the browser window.
+    window.addEventListener('mousemove', this._boundOnMouseMove);
+    window.addEventListener('mouseup', this._boundOnMouseUp);
+  }
+
+  /**
+   * Handles mouseMove to continue drag events.
+   * @param {MouseEvent} event
+   * @private
+   */
+  _onMouseMove(event) {
+    event.cancelable && event.preventDefault();
+
+    const x = event.clientX - this._mouseX;
+    const y = event.clientY - this._mouseY;
+    this._continueDrag(x, y);
+  }
+
+  /**
+   * Handles mouseUp to end drag events.
+   * @param {MouseEvent} event
+   * @private
+   */
+  _onMouseUp(event) {
+    event.cancelable && event.preventDefault();
+
+    window.removeEventListener('mousemove', this._boundOnMouseMove);
+    window.removeEventListener('mouseup', this._boundOnMouseUp);
+
+    this._endDrag(event.clientY - this._mouseY);
+  }
+
+  /**
+   * Gives a visual indicator that we've started dragging an issue row.
+   * @private
+   */
+  _startDrag() {
+    this._dragging = true;
+
+    // If the dragged row is not selected, select it.
+    // TODO(dtu): Allow dragging an existing selection for multi-drag.
+    const issueRefString = issueRefToString(this.cursor);
+    this._selectedIssues = new Set();
+    this._updateSelectedIssues([issueRefString], true);
+  }
+
+  /**
+   * @param {number} x The x-distance the cursor has moved since mouseDown.
+   * @param {number} y The y-distance the cursor has moved since mouseDown.
+   * @private
+   */
+  _continueDrag(x, y) {
+    // Unselected rows: Transition them to their new positions.
+    const [rows, initialIndex, finalIndex] = this._computeRerank(y);
+    this._translateRows(rows, initialIndex, finalIndex);
+
+    // Selected rows: Stick them to the cursor. No transition.
+    for (const row of this._getSelectedRows()) {
+      row.style.transform = `translate(${x}px, ${y}px`;
+    };
+  }
+
+  /**
+   * @param {number} y The y-distance the cursor has moved since mouseDown.
+   * @private
+   */
+  async _endDrag(y) {
+    this._dragging = false;
+
+    // Unselected rows: Transition them to their new positions.
+    const [rows, initialIndex, finalIndex] = this._computeRerank(y);
+    const targetTranslation =
+        this._translateRows(rows, initialIndex, finalIndex);
+
+    // Selected rows: Transition them to their final positions
+    // and reset their opacity.
+    const selectedRows = this._getSelectedRows();
+    for (const row of selectedRows) {
+      row.style.transition = EASE_OUT_TRANSITION;
+      row.style.transform = `translate(0px, ${targetTranslation}px)`;
+    };
+
+    // Submit the change.
+    const items = selectedRows.map((row) => row.dataset.name);
+    await this.rerank(items, finalIndex);
+
+    // Reset the transforms.
+    for (const row of this._getRows()) {
+      row.style.transition = '';
+      row.style.transform = '';
+    };
+
+    // Set the cursor to the new row.
+    // In order to focus the correct element, we need the DOM to be in sync
+    // with the issue list. We modified this.issues, so wait for a re-render.
+    await this.updateComplete;
+    const selector = `.list-row[data-index="${finalIndex}"]`;
+    this.shadowRoot.querySelector(selector).focus();
+  }
+
+  /**
+   * Computes the starting and ending indices of the cursor row,
+   * given how far the mouse has been dragged in the y-direction.
+   * The indices assume the cursor row has been removed from the list.
+   * @param {number} y The y-distance the cursor has moved since mouseDown.
+   * @return {[Array<HTMLTableRowElement>, number, number]} A tuple containing:
+   *     An Array of table rows with the cursor row removed.
+   *     The initial index of the cursor row.
+   *     The final index of the cursor row.
+   * @private
+   */
+  _computeRerank(y) {
+    const row = this._getCursorElement();
+    const rows = this._getRows();
+    const listTop = row.parentNode.offsetTop;
+
+    // Find the initial index of the cursor row.
+    // TODO(dtu): If we support multi-drag, this should be the adjusted index of
+    // the first selected row after collapsing spaces in the selected group.
+    const initialIndex = rows.indexOf(row);
+    rows.splice(initialIndex, 1);
+
+    // Compute the initial and final y-positions of the top
+    // of the cursor row relative to the top of the list.
+    const initialY = row.offsetTop - listTop;
+    const finalY = initialY + y;
+
+    // Compute the final index of the cursor row.
+    // The break points are the halfway marks of each row.
+    let finalIndex = 0;
+    for (finalIndex = 0; finalIndex < rows.length; ++finalIndex) {
+      const rowTop = rows[finalIndex].offsetTop - listTop -
+          (finalIndex >= initialIndex ? row.scrollHeight : 0);
+      const breakpoint = rowTop + rows[finalIndex].scrollHeight / 2;
+      if (breakpoint > finalY) {
+        break;
+      }
+    }
+
+    return [rows, initialIndex, finalIndex];
+  }
+
+  /**
+   * @param {Array<HTMLTableRowElement>} rows Array of table rows with the
+   *    cursor row removed.
+   * @param {number} initialIndex The initial index of the cursor row.
+   * @param {number} finalIndex The final index of the cursor row.
+   * @return {number} The number of pixels the cursor row moved.
+   * @private
+   */
+  _translateRows(rows, initialIndex, finalIndex) {
+    const firstIndex = Math.min(initialIndex, finalIndex);
+    const lastIndex = Math.max(initialIndex, finalIndex);
+
+    const rowHeight = this._getCursorElement().scrollHeight;
+    const translation = initialIndex < finalIndex ? -rowHeight : rowHeight;
+
+    let targetTranslation = 0;
+    for (let i = 0; i < rows.length; ++i) {
+      rows[i].style.transition = EASE_OUT_TRANSITION;
+      if (i >= firstIndex && i < lastIndex) {
+        rows[i].style.transform = `translate(0px, ${translation}px)`;
+        targetTranslation += rows[i].scrollHeight;
+      } else {
+        rows[i].style.transform = '';
+      }
+    }
+
+    return initialIndex < finalIndex ? targetTranslation : -targetTranslation;
+  }
+
+  /**
+   * Handle click and auxclick on issue row.
+   * @param {MouseEvent} event
+   * @private
+   */
+  _clickIssueRow(event) {
+    if (event.button === PRIMARY_BUTTON || event.button === MIDDLE_BUTTON) {
+      this._maybeOpenIssueRow(
+          event, /* openNewTab= */ event.button === MIDDLE_BUTTON);
+    }
+  }
+
+  /**
+   * Checks that the given event should not be ignored, then navigates to the
+   * issue associated with the row.
+   *
+   * @param {MouseEvent|KeyboardEvent} rowEvent A click or 'enter' on a row.
+   * @param {boolean=} openNewTab Forces opening in a new tab
+   * @private
+   */
+  _maybeOpenIssueRow(rowEvent, openNewTab = false) {
+    const path = rowEvent.composedPath();
+    const containsIgnoredElement = path.find(
+        (node) => (node.tagName || '').toUpperCase() === 'A' ||
+        (node.classList && node.classList.contains('ignore-navigation')));
+    if (containsIgnoredElement) return;
+
+    const row = /** @type {HTMLTableRowElement} */ (rowEvent.currentTarget);
+
+    const i = Number.parseInt(row.dataset.index);
+
+    if (i >= 0 && i < this.issues.length) {
+      this._navigateToIssue(this.issues[i], openNewTab || rowEvent.metaKey ||
+          rowEvent.ctrlKey);
+    }
+  }
+
+  /**
+   * @param {Issue} issue
+   * @param {boolean} newTab
+   * @private
+   */
+  _navigateToIssue(issue, newTab) {
+    const link = issueRefToUrl(issueToIssueRef(issue),
+        this._queryParams);
+
+    if (newTab) {
+      // Whether the link opens in a new tab or window is based on the
+      // user's browser preferences.
+      window.open(link, '_blank', 'noopener');
+    } else {
+      this._page(link);
+    }
+  }
+
+  /**
+   * Convert an issue's data into an array of strings, where the columns
+   * match this.columns. Extracting data like _renderCell.
+   * @param {Issue} issue
+   * @return {Array<string>}
+   * @private
+   */
+  _convertIssueToPlaintextArray(issue) {
+    return this.columns.map((column) => {
+      return this.extractFieldValues(issue, column).join(', ');
+    });
+  }
+
+  /**
+   * Convert each Issue into array of strings, where the columns
+   * match this.columns.
+   * @return {Array<Array<string>>}
+   * @private
+   */
+  _convertIssuesToPlaintextArrays() {
+    return this.issues.map(this._convertIssueToPlaintextArray.bind(this));
+  }
+
+  /**
+   * Download content as csv. Conversion to CSV only on button click
+   * instead of on data change because CSV download is not often used.
+   * @param {MouseEvent} event
+   * @private
+   */
+  async _downloadCsv(event) {
+    event.preventDefault();
+
+    if (this.userDisplayName) {
+      // convert issues to array of arrays of strings
+      const issueData = this._convertIssuesToPlaintextArrays();
+
+      // convert the data into csv formatted string.
+      const csvDataString = prepareDataForDownload(issueData, this.columns);
+
+      // construct data href
+      const href = constructHref(csvDataString);
+
+      // modify a tag's href
+      this._csvDataHref = href;
+      await this.requestUpdate('_csvDataHref');
+
+      // click to trigger download
+      this._dataLink.click();
+
+      // reset dataHref
+      this._csvDataHref = '';
+    }
+  }
+};
+
+customElements.define('mr-issue-list', MrIssueList);
