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
@@ -1,3 +1,7 @@
## 2024-05-15 - ARIA and Focus Polish for Review Modals
**Learning:** Found an accessibility issue pattern where custom visual interactive elements like comment icons embedded in diff views lack both ARIA descriptions and `:focus-visible` styling, making them invisible and unexplained to keyboard/screen reader users.
**Action:** When adding interactive icons to complex nested views (like a diff viewer), always pair ARIA labels with explicit `:focus-visible` styling that matches the `:hover` interaction to ensure full keyboard support.

## 2024-05-15 - ARIA Expanded and Keyboard Support for Accordions
**Learning:** Adding keyboard support to composite components (like an accordion header with internal buttons/checkboxes) requires careful event handling to prevent inner element interactions from triggering the parent action.
**Action:** When adding `onkeydown` to make a component accessible, always check `event.target === this` if there are nested interactive elements. Also, remember to dynamically update `aria-expanded` state during the toggling lifecycle to communicate visibility to screen readers.
6 changes: 5 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ <h3>No Staged Changes</h3>
const fileDiv = document.createElement('div');
fileDiv.className = 'file-item';
fileDiv.innerHTML = `
<div class="file-header" onclick="toggleFile('${file}', '${fileId}')">
<div class="file-header" id="header-${fileId}" role="button" tabindex="0" aria-expanded="false" aria-controls="diff-${fileId}" onclick="toggleFile('${file}', '${fileId}')" onkeydown="if(event.key === 'Enter' || event.key === ' ') { if(event.target === this) { event.preventDefault(); toggleFile('${file}', '${fileId}'); } }">
<div class="file-path">
<span class="expand-icon" id="icon-${fileId}">▶️</span>
<span>${fileIcon}</span>
Expand Down Expand Up @@ -1262,18 +1262,22 @@ <h3>No Staged Changes</h3>
async function toggleFile(file, fileId) {
const diffDiv = document.getElementById(`diff-${fileId}`);
const icon = document.getElementById(`icon-${fileId}`);
const header = document.getElementById(`header-${fileId}`);

if (diffDiv.classList.contains('active')) {
diffDiv.classList.remove('active');
icon.classList.remove('rotated');
if (header) header.setAttribute('aria-expanded', 'false');
return;
}

// Close all other diffs
document.querySelectorAll('.file-diff').forEach(d => d.classList.remove('active'));
document.querySelectorAll('.expand-icon').forEach(i => i.classList.remove('rotated'));
document.querySelectorAll('.file-header').forEach(h => h.setAttribute('aria-expanded', 'false'));

icon.classList.add('rotated');
if (header) header.setAttribute('aria-expanded', 'true');

if (!allDiffs[file]) {
try {
Expand Down
Loading