Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
## 2026-02-15 - [Semantic Form Labels]
**Learning:** Even with clear visual labels, missing `for` attributes on `<label>` elements prevents proper association with inputs for assistive technologies.
**Action:** Explicitly link labels and inputs using `for` and `id` attributes in all form components.

## 2026-02-23 - [Micro-UX: Maintainable Diffs in Legacy Templates]
**Learning:** When working with legacy templates that use CRLF line endings, performing full-file conversions (like `dos2unix`) results in massive, unreviewable diffs. For micro-UX improvements, it is critical to preserve original line endings to keep the PR focused on semantic changes.
**Action:** Use `dos2unix` only temporarily for patching, or use targeted tools like `sed` to modify specific lines while respecting original formatting. Always verify diff size before submission.
2 changes: 1 addition & 1 deletion app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@
<!-- Scanner Animation -->
<div class="absolute w-full h-0.5 bg-primary/50 -top-1 left-0 animate-scanner after:content-[''] after:absolute after:top-0 after:left-0 after:w-full after:h-full after:bg-primary/30"></div>
</div>
</button>
</div>

<!-- Trennlinie -->
<div class="sidebar-divider"></div>
Expand Down
34 changes: 26 additions & 8 deletions app/templates/shared/list_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
<!-- Suchleiste und Aktionen -->
<div class="flex flex-col md:flex-row gap-4 items-center">
<div class="form-control flex-1">
<label for="searchInput" class="sr-only">Suchen</label>
<div class="input-group">
<label for="searchInput" class="sr-only">Suchen</label>
<div class="join">
<input type="text"
placeholder="Suchen..."
class="input input-bordered w-full"
id="searchInput"
aria-label="Suchen">
<button type="button" class="btn btn-square" aria-label="Suche ausführen">
class="input input-bordered w-full join-item"
id="searchInput"
aria-label="Suchen">
<button type="button" class="btn btn-square join-item" aria-label="Suche ausführen">
<i class="fas fa-search"></i>
</button>
</div>
Expand Down Expand Up @@ -95,7 +95,12 @@ <h3 class="card-title text-lg">
document.querySelectorAll('th').forEach(th => {
if (!th.classList.contains('no-sort')) {
const wrapper = document.createElement('div');
wrapper.className = 'flex items-center gap-2 cursor-pointer select-none';
wrapper.className = 'flex items-center gap-2 cursor-pointer select-none focus:outline-none focus:ring-2 focus:ring-primary/50 rounded px-1';
wrapper.setAttribute('role', 'button');
wrapper.setAttribute('tabindex', '0');
const label = th.textContent.trim();
wrapper.setAttribute('aria-label', `Sortieren nach ${label}`);

wrapper.innerHTML = `
${th.innerHTML}
<span class="sort-icons opacity-50">
Expand All @@ -105,9 +110,17 @@ <h3 class="card-title text-lg">
th.innerHTML = '';
th.appendChild(wrapper);

wrapper.addEventListener('click', () => {
const sortHandler = () => {
const column = Array.from(th.parentElement.children).indexOf(th);
sortTable(column, th);
};

wrapper.addEventListener('click', sortHandler);
wrapper.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
sortHandler();
}
});
}
});
Expand All @@ -117,6 +130,9 @@ <h3 class="card-title text-lg">
const tbody = table.querySelector('tbody');
const rows = Array.from(tbody.querySelectorAll('tr'));

// Reset all aria-sort
table.querySelectorAll('th').forEach(header => header.removeAttribute('aria-sort'));

// Update Sort-Direction
if (currentSort.column === column) {
currentSort.direction = currentSort.direction === 'asc' ? 'desc' : 'asc';
Expand All @@ -125,6 +141,8 @@ <h3 class="card-title text-lg">
currentSort.direction = 'asc';
}

th.setAttribute('aria-sort', currentSort.direction === 'asc' ? 'ascending' : 'descending');

// Update Sort-Icons
table.querySelectorAll('.sort-icons').forEach(icon => {
icon.innerHTML = '<i class="fas fa-sort"></i>';
Expand Down