From 9ab23c47cca547a0c70bf62f7ff6aa658fbc0310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Gla=CC=88ser?= Date: Thu, 4 Jun 2026 18:12:57 +0200 Subject: [PATCH] Add large table search filter --- components/data-display.html | 48 ++++++++++++++++++++++----- styles/42-components-data-display.css | 43 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/components/data-display.html b/components/data-display.html index 7f80f15..d04bcbb 100644 --- a/components/data-display.html +++ b/components/data-display.html @@ -78,8 +78,19 @@

Component: Large Table

-
+
Large Table
+
@@ -209,9 +220,11 @@ const headerButtons = headerCells.map((cell) => cell.querySelector('.sg-large-table__sort-button')); const rows = Array.from(table.querySelectorAll('[data-component-part="large-table-row"]')); const headerRow = table.querySelector('[data-component-part="large-table-header-row"]'); + const searchInput = table.querySelector('[data-large-table-search]'); const state = { columnIndex: 0, direction: 'ascending', + query: '', }; function setHeaderState(activeIndex, direction) { @@ -251,21 +264,33 @@ return direction === 'ascending' ? comparison : -comparison; } - function sortRows(columnIndex, direction) { + function rowMatchesQuery(row, query) { + if (!query) { + return true; + } + + return Array.from(row.querySelectorAll('[role="cell"]')).some((cell) => { + const value = cell.textContent || ''; + return value.toLowerCase().includes(query); + }); + } + + function renderRows() { const sortedRows = rows.slice().sort((leftRow, rightRow) => { - const leftCell = leftRow.querySelectorAll('[role="cell"]')[columnIndex]; - const rightCell = rightRow.querySelectorAll('[role="cell"]')[columnIndex]; + const leftCell = leftRow.querySelectorAll('[role="cell"]')[state.columnIndex]; + const rightCell = rightRow.querySelectorAll('[role="cell"]')[state.columnIndex]; const leftValue = leftCell ? leftCell.textContent : ''; const rightValue = rightCell ? rightCell.textContent : ''; - return compareValues(leftValue, rightValue, direction); + return compareValues(leftValue, rightValue, state.direction); }); sortedRows.forEach((row) => { table.appendChild(row); + row.hidden = !rowMatchesQuery(row, state.query); }); - setHeaderState(columnIndex, direction); + setHeaderState(state.columnIndex, state.direction); } headerButtons.forEach((button, index) => { @@ -280,14 +305,21 @@ state.columnIndex = index; state.direction = direction; - sortRows(index, direction); + renderRows(); }); }); + if (searchInput) { + searchInput.addEventListener('input', () => { + state.query = searchInput.value.trim().toLowerCase(); + renderRows(); + }); + } + if (headerRow) { setHeaderState(state.columnIndex, state.direction); } - sortRows(state.columnIndex, state.direction); + renderRows(); })(); diff --git a/styles/42-components-data-display.css b/styles/42-components-data-display.css index fc9349d..8b0b8e0 100644 --- a/styles/42-components-data-display.css +++ b/styles/42-components-data-display.css @@ -71,6 +71,49 @@ width: 100%; } +.sg-large-table__title-segment { + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: var(--spacing-large); +} + +.sg-large-table__search { + display: flex; + align-items: center; + justify-content: flex-end; + gap: var(--spacing-small); + margin-left: auto; +} + +.sg-large-table__search-label { + color: var(--text-card-header); + font-family: var(--font-family-base); + font-size: var(--font-size-small); + font-weight: var(--font-weight-semibold); + line-height: var(--line-height-base); + white-space: nowrap; +} + +.sg-large-table__search-input { + width: 14rem; + max-width: 100%; + box-sizing: border-box; + padding: 0.35rem var(--spacing-small); + border: var(--border-none); + border-radius: var(--radius-card); + background: var(--color-white); + color: var(--text-control-default); + font-family: var(--font-family-base); + font-size: var(--font-size-small); + line-height: var(--line-height-base); +} + +.sg-large-table__search-input:focus-visible { + outline: 2px solid var(--color-white); + outline-offset: 2px; +} + .sg-large-table__row { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));