Table Filter Row

<sl-table-filter-row> | SlTableFilterRow
Since 2.4.0 stable

Used to support filtering table content.

<sl-table-filter-row placeholder="table filter row"></sl-table-filter-row>

Examples

Size

Visual difference between default and compact size is the height and padding.

Compact size is used when screen real estate is limited due to other important content on the page.

Placeholder block
Placeholder block

Placeholder block
Placeholder block

Placeholder block
Placeholder block

Placeholder block
Placeholder block
<sl-table-filter-row placeholder="table filter row">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row> 
<br>
<sl-table-filter-row placeholder="table filter row" size="compact">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>
<br>
<sl-table-filter-row placeholder="table filter row" has-full-border>
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>
<br>
<sl-table-filter-row placeholder="table filter row" has-full-border size="compact">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>
<style>
  .placeholder-block {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    background: var(--hds-color-bg-secondary);
    color: white;
  }
</style>

Position

Table filter row should fill the amount of space available of where it’s placed.

inline is the default position and has a slot for filters are right aligned on the same row. It has a minimum width of 800px and will be responsive when the viewport is less than that.

stacked has a slot for filters that wraps to the next row below the search input. This variant is recommended for mobile and tablet displays when horizontal space is limited. It has a maximum width of 800px.

Placeholder block
Placeholder block

Placeholder block
Placeholder block

Placeholder block
Placeholder block

Placeholder block
Placeholder block

Placeholder block
Placeholder block
<sl-table-filter-row placeholder="table filter row" position="inline">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row> 
<br>
<sl-table-filter-row class="demo-row" placeholder="table filter row" position="stacked">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row> 
<br>
<sl-table-filter-row class="demo-row" placeholder="table filter row" size="compact" position="stacked">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>
<br>
<sl-table-filter-row class="demo-row" placeholder="table filter row table filter row table filter row table filter row" position="stacked" has-full-border>
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>
<br>
<sl-table-filter-row class="demo-row" placeholder="table filter row" size="compact" position="stacked" has-full-border>
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row>

<style>
  .demo-row {
    width: 682px;
  }

  .placeholder-block {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    background: var(--hds-color-bg-secondary);
    color: white;
  }
</style>

Input values

While the component itself does not provide explicit filter rules, you can access the input values and create filter rules on application level.

Placeholder block
Placeholder block
<sl-table-filter-row placeholder="table filter row" position="inline">
  <div slot="filter-slots">
    <div class="placeholder-block">Placeholder block</div>
    <div class="placeholder-block">Placeholder block</div>
  </div>
</sl-table-filter-row> 


Appearance

Default

Default table filter row is attached to a table as the leading row unless specified otherwise by designer.

Created date

Dropdown Dropdown Item 1 Dropdown Item 2
Account Reporting group Nickname Override perf inception date Source Balance
Row 1, Cell 1 Row 1, Cell 2 Row 1, Cell 3 Row 1, Cell 4 Row 1, Cell 5 Row 1, Cell 6
Row 2, Cell 1 Row 2, Cell 2 Row 2, Cell 3 Row 2, Cell 4 Row 2, Cell 5 Row 2, Cell 6
Row 3, Cell 1 Row 3, Cell 2 Row 3, Cell 3 Row 3, Cell 4 Row 3, Cell 5 Row 3, Cell 6
<div class="default-table-container">
  <sl-table-filter-row placeholder="Filter by account or display name">
    <div slot="filter-slots">
      <div class="date-range-container">
      <p>Created date</p>
      <sl-date-range-input always-editing hide-range-type show-shortcuts></sl-date-range-input>
        <sl-dropdown variant="secondary">
          <sl-button slot="trigger" caret>Dropdown</sl-button>
          <sl-menu>
            <sl-menu-item>Dropdown Item 1</sl-menu-item>
            <sl-menu-item>Dropdown Item 2</sl-menu-item>
          </sl-menu>
        </sl-dropdown>
      </div>
    </div>
  </sl-table-filter-row>
  <table style="border-collapse: collapse;">
    <thead>
      <tr>
        <th is-heading><sl-checkbox></sl-checkbox></th>
        <th is-heading>Account</th>
        <th is-heading>Reporting group</th>
        <th is-heading>Nickname</th>
        <th is-heading>Override perf inception date</th>
        <th is-heading>Source</th>
        <th is-heading>Balance</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 6</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 6</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 6</sl-table-cell></td>
      </tr>
    </tbody>
  </table>
</div>

<style>
  .default-table-container {
    border-radius: var(--hds-border-radius-lg);
    border: 1px solid var(--hds-color-border);
    align-items: flex-start;
  }

  table {
    width: -webkit-fill-available;
  }

  .date-range-container {
    display: flex;
    gap: var(--hds-space-gap-md);
    align-items: baseline;
  }

  .date-range-container > p {
    color: var(--hds-color-fg);
    font-size: var(--hds-font-application-label-fontSize);
  }
</style>

Full border

Table filter row alternatively can be encased with full border and detached from tables.

This style allows for elements or other relevant content to sit right above table headers.

Created date

Dropdown Dropdown Item 1 Dropdown Item 2
Applied(1):
Open Clear all
Account Reporting group Nickname Override perf inception date Source Balance
Row 1, Cell 1 Row 1, Cell 2 Row 1, Cell 3 Row 1, Cell 4 Row 1, Cell 5 Row 1, Cell 6
Row 2, Cell 1 Row 2, Cell 2 Row 2, Cell 3 Row 2, Cell 4 Row 2, Cell 5 Row 2, Cell 6
Row 3, Cell 1 Row 3, Cell 2 Row 3, Cell 3 Row 3, Cell 4 Row 3, Cell 5 Row 3, Cell 6
<sl-table-filter-row placeholder="Search by fund or trustee name" has-full-border>
  <div slot="filter-slots">
    <div class="date-range-container">
    <p>Created date</p>
    <sl-date-range-input always-editing hide-range-type show-shortcuts></sl-date-range-input>
    <sl-dropdown variant="secondary">
      <sl-button slot="trigger" caret>Dropdown</sl-button>
      <sl-menu>
        <sl-menu-item>Dropdown Item 1</sl-menu-item>
        <sl-menu-item>Dropdown Item 2</sl-menu-item>
      </sl-menu>
    </div>
  </div>
</sl-table-filter-row>

<div class="datapair-group">
  <div>Applied(1):</div>
  <sl-tag removable>Open</sl-tag>
  <sl-button variant="naked" size="small">Clear all</sl-button>
</div>

<div class="full-border-table-container">
  <table style="border-collapse: collapse;">
    <thead>
      <tr>
        <th is-heading><sl-checkbox></sl-checkbox></th>
        <th is-heading>Account</th>
        <th is-heading>Reporting group</th>
        <th is-heading>Nickname</th>
        <th is-heading>Override perf inception date</th>
        <th is-heading>Source</th>
        <th is-heading>Balance</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 1, Cell 6</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 2, Cell 6</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell><sl-checkbox></sl-checkbox></sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 1</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 2</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 3</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 4</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 5</sl-table-cell></td>
        <td><sl-table-cell>Row 3, Cell 6</sl-table-cell></td>
      </tr>
    </tbody>
  </table>
</div>

<style>
  .full-border-table-container {
    border-radius: var(--hds-border-radius-lg);
    border: 1px solid var(--hds-color-border);
    align-items: flex-start;
  }

  table {
    width: -webkit-fill-available;
  }

  .datapair-group {
    display: flex;
    padding: var(--hds-space-atom-xs) var(--hds-space-atom-md);
    align-items: center;
    gap: var(--hds-space-atom-sm);
    align-self: stretch;
  }
</style>

Filtering usage example

Here is an example on how to filter table content by using input field and/or dropdown menu.

Status All Active Inactive
Trustee name Trustee email Trustee status Balance ($)
Charlie Smith charliesmith@email.com Active 12,000
Jane Jacobs janejacobs@email.com Active 56,000
Mary James maryjames@email.com Inactive 24,000
<div class="example-table-container">
  <sl-table-filter-row placeholder="Filter by trutee name or email address" id="filter-row">
    <div slot="filter-slots">
      <sl-dropdown variant="secondary">
        <sl-button slot="trigger" caret>Status</sl-button>
        <sl-menu id="status-menu">
          <sl-menu-item value="">All</sl-menu-item>
          <sl-menu-item value="active">Active</sl-menu-item>
          <sl-menu-item value="inactive">Inactive</sl-menu-item>
        </sl-menu>
      </sl-dropdown>
    </div>
  </sl-table-filter-row>
  <table style="border-collapse: collapse;" id="trustee-table">
    <thead>
      <tr>
        <th is-heading>Trustee name</th>
        <th is-heading>Trustee email</th>
        <th is-heading>Trustee status</th>
        <th is-heading>Balance ($)</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><sl-table-cell>Charlie Smith</sl-table-cell></td>
        <td><sl-table-cell>charliesmith@email.com</sl-table-cell></td>
        <td><sl-table-cell value="active">Active</sl-table-cell></td>
        <td><sl-table-cell>12,000</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell>Jane Jacobs</sl-table-cell></td>
        <td><sl-table-cell>janejacobs@email.com</sl-table-cell></td>
        <td><sl-table-cell value="active">Active</sl-table-cell></td>
        <td><sl-table-cell>56,000</sl-table-cell></td>
      </tr>
      <tr>
        <td><sl-table-cell>Mary James</sl-table-cell></td>
        <td><sl-table-cell>maryjames@email.com</sl-table-cell></td>
        <td><sl-table-cell value="inactive">Inactive</sl-table-cell></td>
        <td><sl-table-cell>24,000</sl-table-cell></td>
      </tr>
    </tbody>
  </table>
</div>

<script type="module">
  const filterRow = document.getElementById('filter-row');
  const statusMenu = document.getElementById('status-menu');
  const rows = [...document.querySelectorAll('#trustee-table tbody tr')];
  let query = '';
  let status = '';

  function applyFilters() {
    const q = query.toLowerCase().trim();
    rows.forEach(row => {
      const name = row.cells[1].textContent.toLowerCase();
      const email = row.cells[2].textContent.toLowerCase();
      const statusCell = row.cells[3].querySelector('sl-table-cell');
      const rowStatus = statusCell?.getAttribute('value') ?? '';
      const matchesQuery = !q || name.includes(q) || email.includes(q);
      const matchesStatus = !status || rowStatus === status;
      
      row.hidden = !(matchesQuery && matchesStatus);
    });
  }

  // Typing "charlie" → only Charlie Smith stays visible
  filterRow.addEventListener('sl-input', () => {
    query = filterRow.inputValue;
    applyFilters();
  });

  // Choosing Active or Inactive status
  statusMenu.addEventListener('sl-select', event => {
    status = event.detail.item.value;
    applyFilters();
  });
</script>

<style>
  .example-table-container {
    border-radius: var(--hds-border-radius-lg);
    border: 1px solid var(--hds-color-border);
    align-items: flex-start;
  }

  table {
    width: -webkit-fill-available;
  }

  .date-range-container {
    display: flex;
    gap: var(--hds-space-gap-md);
    align-items: baseline;
  }

  .date-range-container > p {
    color: var(--hds-color-fg);
    font-size: var(--hds-font-application-label-fontSize);
  }
</style>

[component-metadata:sl-table-filter-row]

Slots

Name Description
filter-slots Reserved for filter controls such as dropdowns, date range inputs, toggle button etc. The recommendation is maximum 4 filter controls.

Learn more about using slots.

Properties

Name Description Reflects Type Default
placeholder The placeholder text of the input element. string ''
size The table filter row’s size. 'default' | 'compact' 'default'
position The table filter row’s position 'inline' | 'stacked' 'inline'
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Events

Name React Event Description Event Detail
sl-change Emitted when an item is selected. -
sl-input Emitted when the input value changes. -

Learn more about events.

Parts

Name Description
base The component’s base wrapper.
filter-slots The component’s filter slots wrapper.

Learn more about customizing CSS parts.

Dependencies

This component automatically imports the following dependencies.

  • <sl-icon>
  • <sl-input>