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
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-14 - Dynamic ARIA labels for icon-only toggles
**Learning:** For accessibility in icon-only buttons where the action changes dynamically (like showing/hiding a password or an API key), a static `aria-label` or `title` is insufficient and can be confusing. Screen readers will misinterpret the current state if it's just "Toggle visibility".
**Action:** Always dynamically bind the `:aria-label` attribute using a ternary operator based on the toggle state (e.g., `:aria-label="showPassword ? 'Hide password' : 'Show password'"`) to ensure screen readers announce the correct current action.
2 changes: 1 addition & 1 deletion src/components/settings/tabs/AISettingsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ async function onClearMemories() {
spellcheck="false"
autocomplete="off"
/>
<button class="key-toggle-btn" @click="showGroqKey = !showGroqKey" :title="showGroqKey ? 'Hide' : 'Show'">
<button class="key-toggle-btn" :aria-label="showGroqKey ? 'Hide API key' : 'Show API key'" @click="showGroqKey = !showGroqKey" :title="showGroqKey ? 'Hide' : 'Show'">
<EyeOff v-if="showGroqKey" :size="14" />
<Eye v-else :size="14" />
</button>
Expand Down
4 changes: 2 additions & 2 deletions src/components/settings/tabs/AccountSettingsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ const handleChangePassword = async () => {
class="form-input"
placeholder="Enter new password"
>
<button class="toggle-visibility" @click="showPassword = !showPassword">
<button class="toggle-visibility" :aria-label="showPassword ? 'Hide password' : 'Show password'" @click="showPassword = !showPassword">
<Eye v-if="!showPassword" :size="16" />
<EyeOff v-else :size="16" />
</button>
Expand Down Expand Up @@ -504,7 +504,7 @@ const handleChangePassword = async () => {
class="form-input"
@focus="(e) => (e.target as HTMLInputElement).select()"
>
<button class="toggle-visibility" :title="localApiCopied ? 'Copied!' : 'Copy'" @click="copyLocalApiToken">
<button class="toggle-visibility" :aria-label="localApiCopied ? 'Copied local API token' : 'Copy local API token'" :title="localApiCopied ? 'Copied!' : 'Copy'" @click="copyLocalApiToken">
<Check v-if="localApiCopied" :size="16" />
<Copy v-else :size="16" />
</button>
Expand Down
Loading