I do love my keyboard
This commit is contained in:
@@ -4072,6 +4072,7 @@ div.posts>a:not(.notif-item)::before {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.posts>a:not(.notif-item):hover,
|
div.posts>a:not(.notif-item):hover,
|
||||||
|
div.posts>a:not(.notif-item):focus-visible,
|
||||||
div.posts>a:not(.notif-item).touch-active {
|
div.posts>a:not(.notif-item).touch-active {
|
||||||
box-shadow: 0 0 0 1px var(--white);
|
box-shadow: 0 0 0 1px var(--white);
|
||||||
}
|
}
|
||||||
@@ -4094,6 +4095,7 @@ div.posts>a:not(.notif-item)::after {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.posts>a:not(.notif-item):hover::after,
|
div.posts>a:not(.notif-item):hover::after,
|
||||||
|
div.posts>a:not(.notif-item):focus-visible::after,
|
||||||
div.posts>a:not(.notif-item).touch-active::after {
|
div.posts>a:not(.notif-item).touch-active::after {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
@@ -10974,7 +10976,8 @@ div.posts>a.thumb.has-notif {
|
|||||||
border: 1px solid var(--accent);
|
border: 1px solid var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
div.posts>a.thumb.has-notif:hover {
|
div.posts>a.thumb.has-notif:hover,
|
||||||
|
div.posts>a.thumb.has-notif:focus-visible {
|
||||||
box-shadow: inset 0 0 0 1000px rgba(255, 0, 0, 0.4), 0 0 0 2px var(--accent) !important;
|
box-shadow: inset 0 0 0 1000px rgba(255, 0, 0, 0.4), 0 0 0 2px var(--accent) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -10988,7 +10991,8 @@ div.posts>a.thumb.has-notif::after {
|
|||||||
z-index: 10 !important;
|
z-index: 10 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.posts>a.thumb.has-notif:hover::after {
|
div.posts>a.thumb.has-notif:hover::after,
|
||||||
|
div.posts>a.thumb.has-notif:focus-visible::after {
|
||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9388,22 +9388,24 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
};
|
};
|
||||||
window.startHoverPreview = startPreview;
|
window.startHoverPreview = startPreview;
|
||||||
|
|
||||||
document.addEventListener('mouseover', (e) => {
|
const handleEnter = (e) => {
|
||||||
const thumb = e.target.closest('.thumb');
|
const thumb = e.target.closest('.thumb');
|
||||||
|
|
||||||
// If we are hovering a thumb, and it's NOT the active one
|
|
||||||
if (thumb && thumb !== activeThumb) {
|
if (thumb && thumb !== activeThumb) {
|
||||||
startPreview(thumb, 150);
|
startPreview(thumb, 150);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
document.addEventListener('mouseover', handleEnter);
|
||||||
|
document.addEventListener('focusin', handleEnter);
|
||||||
|
|
||||||
document.addEventListener('mouseout', (e) => {
|
const handleLeave = (e) => {
|
||||||
const thumb = e.target.closest('.thumb');
|
const thumb = e.target.closest('.thumb');
|
||||||
if (thumb) {
|
if (thumb) {
|
||||||
if (e.relatedTarget && thumb.contains(e.relatedTarget)) return;
|
if (e.type === 'mouseout' && e.relatedTarget && thumb.contains(e.relatedTarget)) return;
|
||||||
clearPreview();
|
clearPreview();
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
document.addEventListener('mouseout', handleLeave);
|
||||||
|
document.addEventListener('focusout', handleLeave);
|
||||||
|
|
||||||
// Touch handling to support "tap to activate" behavior
|
// Touch handling to support "tap to activate" behavior
|
||||||
// 1. First tap: Activate (visuals + preview) AND prevent navigation
|
// 1. First tap: Activate (visuals + preview) AND prevent navigation
|
||||||
@@ -11281,3 +11283,61 @@ document.addEventListener('click', (e) => {
|
|||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
// --- Grid Keyboard Accessibility ---
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
const isTab = e.key === 'Tab';
|
||||||
|
const isArrow = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key);
|
||||||
|
if (!isTab && !isArrow) return;
|
||||||
|
|
||||||
|
const thumbs = Array.from(document.querySelectorAll('.posts .thumb'));
|
||||||
|
if (thumbs.length === 0) return;
|
||||||
|
|
||||||
|
if (isTab && document.activeElement === document.body) {
|
||||||
|
e.preventDefault();
|
||||||
|
thumbs[0].focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const active = document.activeElement;
|
||||||
|
if (isArrow && active && active.classList.contains('thumb')) {
|
||||||
|
const currentIndex = thumbs.indexOf(active);
|
||||||
|
if (currentIndex === -1) return;
|
||||||
|
|
||||||
|
let nextIndex = currentIndex;
|
||||||
|
|
||||||
|
if (e.key === 'ArrowRight') {
|
||||||
|
nextIndex = currentIndex + 1;
|
||||||
|
} else if (e.key === 'ArrowLeft') {
|
||||||
|
nextIndex = currentIndex - 1;
|
||||||
|
} else if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||||
|
const currentRow = thumbs.filter(t => t.offsetTop === active.offsetTop);
|
||||||
|
const columns = currentRow.length;
|
||||||
|
|
||||||
|
let maxCols = columns;
|
||||||
|
const firstRowTop = thumbs[0].offsetTop;
|
||||||
|
const firstRow = thumbs.filter(t => t.offsetTop === firstRowTop);
|
||||||
|
if (firstRow.length > columns) maxCols = firstRow.length;
|
||||||
|
|
||||||
|
if (e.key === 'ArrowDown') {
|
||||||
|
nextIndex = currentIndex + maxCols;
|
||||||
|
if (nextIndex >= thumbs.length) {
|
||||||
|
const lastRowTop = thumbs[thumbs.length - 1].offsetTop;
|
||||||
|
if (active.offsetTop < lastRowTop) {
|
||||||
|
nextIndex = thumbs.length - 1;
|
||||||
|
} else {
|
||||||
|
nextIndex = currentIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nextIndex = currentIndex - maxCols;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextIndex >= 0 && nextIndex < thumbs.length && nextIndex !== currentIndex) {
|
||||||
|
e.preventDefault();
|
||||||
|
thumbs[nextIndex].focus();
|
||||||
|
thumbs[nextIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user