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 @@ -4,3 +4,7 @@
## 2026-04-26 - [Form Input Accessibility without Visible Labels]
**Learning:** This app's form design relies heavily on placeholder attributes instead of visible `<label>` tags. Since placeholders disappear upon input and may not be reliably announced by all screen readers, this creates an accessibility issue for users relying on screen readers.
**Action:** When a visible `<label>` is not present (or omitted for visual layout reasons), always add an `aria-label` attribute to the input/select element to ensure it is accessible.

## 2026-07-23 - [Dynamic ARIA labels for Stateful Icon Buttons]
**Learning:** When using stateful icon-only buttons (like a password visibility toggle), relying solely on visual icon changes (e.g., eye to eye-slash) leaves screen reader users unaware of the state change. The `aria-label` must be dynamically updated via JavaScript to reflect the current action (e.g., "Show password" to "Hide password").
**Action:** Always bind `aria-label` updates to state changes in JavaScript for icon-only toggle buttons to ensure the accessibility tree remains accurate.
7 changes: 6 additions & 1 deletion frontend/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,12 @@ <h2 class="text-center mb-4 font-weight-bold" style="color: var(--text-main);">A
</div>
<div class="mb-4">
<label for="password" class="form-label fw-bold" style="color: var(--text-muted);">Password</label>
<input type="password" id="password" class="form-control" style="border-radius: var(--radius-md); padding: 0.75rem 1rem;" required>
<div class="position-relative">
<input type="password" id="password" class="form-control" style="border-radius: var(--radius-md); padding: 0.75rem 1rem; padding-right: 2.5rem;" required>
<button type="button" id="toggle-password" class="btn border-0 position-absolute end-0 top-50 translate-middle-y" aria-label="Show password" style="background: transparent; color: var(--text-muted); z-index: 10;">
<i class="fas fa-eye" id="toggle-password-icon"></i>
</button>
</div>
</div>
<button type="submit" class="btn btn-primary w-100 py-2" style="border-radius: var(--radius-md); font-weight: 600;">Sign In</button>
</form>
Expand Down
15 changes: 15 additions & 0 deletions frontend/login.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
document.addEventListener("DOMContentLoaded", () => {
const togglePasswordBtn = document.getElementById("toggle-password");
const passwordInput = document.getElementById("password");
const togglePasswordIcon = document.getElementById("toggle-password-icon");

if (togglePasswordBtn && passwordInput && togglePasswordIcon) {
togglePasswordBtn.addEventListener("click", () => {
const isPassword = passwordInput.getAttribute("type") === "password";
passwordInput.setAttribute("type", isPassword ? "text" : "password");
togglePasswordIcon.className = isPassword ? "fas fa-eye-slash" : "fas fa-eye";
togglePasswordBtn.setAttribute("aria-label", isPassword ? "Hide password" : "Show password");
});
}
});

document.getElementById("login-form").addEventListener("submit", (e) => {
e.preventDefault();

Expand Down