Skip to content
Draft
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
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-05-22 - [Hiding visual characters from screen readers]
**Learning:** Icon-only buttons or buttons using characters like `×` or `×` as icons can be confusing for screen reader users if not properly labeled. The character itself might be announced as "multiplication sign" or similar.
**Action:** Always provide an explicit `aria-label` for such buttons and wrap the visual character in a `<span>` with `aria-hidden="true"`.
7 changes: 5 additions & 2 deletions apps/app/src/components/ConversationsSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function ConversationsSidebar({
onClick={onClose}
aria-label="Close chats panel"
>
&times;
<span aria-hidden="true">&times;</span>
</button>
</div>
)}
Expand Down Expand Up @@ -199,6 +199,7 @@ export function ConversationsSidebar({
className="px-1.5 py-0.5 text-[10px] border border-danger bg-danger text-white cursor-pointer hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed"
onClick={() => void handleConfirmDelete(conv.id)}
disabled={deletingId === conv.id}
aria-label="Confirm delete"
>
Comment on lines 201 to 203

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better accessibility, consider adding the aria-busy attribute. This will indicate to screen reader users that this button is in a loading state while the delete operation is in progress.

Suggested change
disabled={deletingId === conv.id}
aria-label="Confirm delete"
>
disabled={deletingId === conv.id}
aria-label="Confirm delete"
aria-busy={deletingId === conv.id}
>

{deletingId === conv.id ? "..." : "Yes"}
</button>
Comment on lines 199 to 205

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing User Feedback on Deletion Failure

If handleDeleteConversation fails (e.g., due to a network error), the user receives no feedback, and the UI simply resets. This can lead to confusion if the conversation is not actually deleted. Consider surfacing an error message or visual indicator when deletion fails, for example:

try {
  await handleDeleteConversation(id);
} catch (err) {
  // Show error to user, e.g., set an error state and display a message
}

This will improve the user experience and make error handling more robust.

Expand All @@ -207,6 +208,7 @@ export function ConversationsSidebar({
className="px-1.5 py-0.5 text-[10px] border border-border bg-card text-muted cursor-pointer hover:border-accent hover:text-accent disabled:opacity-50 disabled:cursor-not-allowed"
onClick={() => setConfirmDeleteId(null)}
disabled={deletingId === conv.id}
aria-label="Cancel delete"
>
No
</button>
Expand All @@ -221,8 +223,9 @@ export function ConversationsSidebar({
setConfirmDeleteId(conv.id);
}}
title="Delete conversation"
aria-label="Delete conversation"
>
×
<span aria-hidden="true">×</span>
</button>
)}
</>
Expand Down
Loading