diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..68c839b --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,3 @@ +## 2026-01-10 - Search Keyboard Shortcut & Accessibility +**Learning:** Users often rely on standard keyboard shortcuts like `/` or `Ctrl+K` for search, but visual cues are essential for discoverability. Adding a `.sr-only` label significantly improves accessibility for screen readers without altering the visual design. +**Action:** When implementing search features, always include a proper label (even if visually hidden) and consider adding standard keyboard shortcuts with visual hints for desktop users. \ No newline at end of file diff --git a/index.html b/index.html index 3966a00..8d05b1e 100644 --- a/index.html +++ b/index.html @@ -1,175 +1,177 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - Connect Dump Analyser V2.0 - - - - - - - - - -
- - - - -
- -
- -
-
-
- - search - -
-
-
- - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - -
Course CodeSEC Faculty Faculty InfoSchedule Lab ScheduleAvailable Booked Capacity Exam DateRoom
-
- - -
- - - - arrow_upward - - - - - - -
- - -
- - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + Connect Dump Analyser V2.0 + + + + + + + + + +
+ + + + +
+ +
+ +
+
+
+ + + search + + +
+
+
+ + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + +
Course CodeSEC Faculty Faculty InfoSchedule Lab ScheduleAvailable Booked Capacity Exam DateRoom
+
+ + +
+ + + + arrow_upward + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/js/uiController.js b/js/uiController.js index 560c631..14e382e 100644 --- a/js/uiController.js +++ b/js/uiController.js @@ -278,6 +278,31 @@ const UIController = { } }); } + + // Keyboard Shortcuts + document.addEventListener('keydown', (e) => { + // Guard clause if search input doesn't exist + if (!this.elements.searchInput) return; + + // Focus search on '/' or Ctrl+K (Cmd+K) + if ((e.key === '/' || (e.key === 'k' && (e.metaKey || e.ctrlKey))) && + document.activeElement !== this.elements.searchInput) { + + // Don't trigger if user is typing in another input (if any existed) + if (document.activeElement.tagName === 'INPUT' || + document.activeElement.tagName === 'TEXTAREA') { + return; + } + + e.preventDefault(); + this.elements.searchInput.focus(); + } + + // Remove focus from search on Escape + if (e.key === 'Escape' && document.activeElement === this.elements.searchInput) { + this.elements.searchInput.blur(); + } + }); }, /** diff --git a/styles.css b/styles.css index d8b4838..2565c01 100644 --- a/styles.css +++ b/styles.css @@ -145,6 +145,19 @@ body { transition: background 0.2s, color 0.2s; } +/* ---------- ACCESSIBILITY UTILITIES ---------- */ +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + /* ---------- CONTAINER ---------- */ .container { width: 100%; @@ -451,6 +464,33 @@ h1 { color: var(--accent-danger); } +.shortcut-hint { + position: absolute; + right: 65px; + top: 50%; + transform: translateY(-50%); + font-size: 0.75rem; + color: var(--text-muted); + border: 1px solid var(--border-color); + border-radius: 4px; + padding: 2px 6px; + background: var(--bg-tertiary); + pointer-events: none; + transition: opacity 0.2s; + display: none; +} + +@media (min-width: 769px) { + .shortcut-hint { + display: block; + } +} + +#searchInput:focus ~ .shortcut-hint, +#searchInput:not(:placeholder-shown) ~ .shortcut-hint { + display: none; +} + /* ---------- TABLE WRAPPER ---------- */ .table-responsive { width: 100%;