Add large table search filter

This commit is contained in:
2026-06-04 18:12:57 +02:00
parent fc86eb0697
commit 9ab23c47cc
2 changed files with 83 additions and 8 deletions
+40 -8
View File
@@ -78,8 +78,19 @@
<p class="sg-preview-label">Component: Large Table</p> <p class="sg-preview-label">Component: Large Table</p>
<article class="sg-card sg-large-table" data-component="large-table" role="table" aria-label="Beispiel Large Table"> <article class="sg-card sg-large-table" data-component="large-table" role="table" aria-label="Beispiel Large Table">
<div class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue" data-component-part="large-table-header"> <div class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-large-table__title-segment" data-component-part="large-table-header">
<div class="sg-strong">Large Table</div> <div class="sg-strong">Large Table</div>
<div class="sg-large-table__search" data-component="search-field">
<label class="sg-large-table__search-label" for="large-table-search">Suchfeld</label>
<input
class="sg-large-table__search-input"
id="large-table-search"
type="search"
placeholder="Tabelle durchsuchen"
aria-label="Tabelle durchsuchen"
data-large-table-search
>
</div>
</div> </div>
<div class="sg-card-segment sg-card-segment--body sg-card-segment--white sg-large-table__row sg-large-table__row--header" role="row" data-component-part="large-table-header-row"> <div class="sg-card-segment sg-card-segment--body sg-card-segment--white sg-large-table__row sg-large-table__row--header" role="row" data-component-part="large-table-header-row">
@@ -209,9 +220,11 @@
const headerButtons = headerCells.map((cell) => cell.querySelector('.sg-large-table__sort-button')); 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 rows = Array.from(table.querySelectorAll('[data-component-part="large-table-row"]'));
const headerRow = table.querySelector('[data-component-part="large-table-header-row"]'); const headerRow = table.querySelector('[data-component-part="large-table-header-row"]');
const searchInput = table.querySelector('[data-large-table-search]');
const state = { const state = {
columnIndex: 0, columnIndex: 0,
direction: 'ascending', direction: 'ascending',
query: '',
}; };
function setHeaderState(activeIndex, direction) { function setHeaderState(activeIndex, direction) {
@@ -251,21 +264,33 @@
return direction === 'ascending' ? comparison : -comparison; 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 sortedRows = rows.slice().sort((leftRow, rightRow) => {
const leftCell = leftRow.querySelectorAll('[role="cell"]')[columnIndex]; const leftCell = leftRow.querySelectorAll('[role="cell"]')[state.columnIndex];
const rightCell = rightRow.querySelectorAll('[role="cell"]')[columnIndex]; const rightCell = rightRow.querySelectorAll('[role="cell"]')[state.columnIndex];
const leftValue = leftCell ? leftCell.textContent : ''; const leftValue = leftCell ? leftCell.textContent : '';
const rightValue = rightCell ? rightCell.textContent : ''; const rightValue = rightCell ? rightCell.textContent : '';
return compareValues(leftValue, rightValue, direction); return compareValues(leftValue, rightValue, state.direction);
}); });
sortedRows.forEach((row) => { sortedRows.forEach((row) => {
table.appendChild(row); table.appendChild(row);
row.hidden = !rowMatchesQuery(row, state.query);
}); });
setHeaderState(columnIndex, direction); setHeaderState(state.columnIndex, state.direction);
} }
headerButtons.forEach((button, index) => { headerButtons.forEach((button, index) => {
@@ -280,14 +305,21 @@
state.columnIndex = index; state.columnIndex = index;
state.direction = direction; state.direction = direction;
sortRows(index, direction); renderRows();
}); });
}); });
if (searchInput) {
searchInput.addEventListener('input', () => {
state.query = searchInput.value.trim().toLowerCase();
renderRows();
});
}
if (headerRow) { if (headerRow) {
setHeaderState(state.columnIndex, state.direction); setHeaderState(state.columnIndex, state.direction);
} }
sortRows(state.columnIndex, state.direction); renderRows();
})(); })();
</script> </script>
+43
View File
@@ -71,6 +71,49 @@
width: 100%; 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 { .sg-large-table__row {
display: grid; display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr)); grid-template-columns: repeat(5, minmax(0, 1fr));