First step in making things focusable

This commit is contained in:
Lim Chee Aun 2022-12-30 20:37:57 +08:00
parent 30c529fe02
commit 9201f7a118
8 changed files with 62 additions and 9 deletions

View file

@ -298,6 +298,26 @@ export function App() {
}, []);
const [currentDeck, setCurrentDeck] = useState('home');
const focusDeck = () => {
let timer = setTimeout(() => {
const page = document.getElementById(`${currentDeck}-page`);
console.log('focus', currentDeck, page);
if (page) {
page.focus();
}
}, 100);
return () => clearTimeout(timer);
};
useEffect(focusDeck, [currentDeck]);
useEffect(() => {
if (
!snapStates.showCompose &&
!snapStates.showSettings &&
!snapStates.showAccount
) {
focusDeck();
}
}, [snapStates.showCompose, snapStates.showSettings, snapStates.showAccount]);
useEffect(() => {
// HACK: prevent this from running again due to HMR
@ -324,7 +344,7 @@ export function App() {
return (
<>
{isLoggedIn && currentDeck && (
{isLoggedIn && (
<>
<button
type="button"
@ -345,7 +365,7 @@ export function App() {
</button>
<div class="decks">
{/* Home will never be unmounted */}
<Home hidden={currentDeck !== 'home'} />
<Home />
{/* Notifications can be unmounted */}
{currentDeck === 'notifications' && <Notifications />}
</div>
@ -355,6 +375,7 @@ export function App() {
<Router
history={createHashHistory()}
onChange={(e) => {
console.log('router onChange', e);
// Special handling for Home and Notifications
const { url } = e;
if (/notifications/i.test(url)) {
@ -362,7 +383,7 @@ export function App() {
} else if (url === '/') {
setCurrentDeck('home');
document.title = `Home / ${CLIENT_NAME}`;
} else if (url === '/login' || url === '/welcome') {
} else {
setCurrentDeck(null);
}
states.history.push(url);

View file

@ -102,7 +102,6 @@ function Account({ account }) {
return (
<div
id="account-container"
tabIndex="-1"
class={`sheet ${uiState === 'loading' ? 'skeleton' : ''}`}
>
{!info || uiState === 'loading' ? (
@ -129,7 +128,7 @@ function Account({ account }) {
<Avatar url={avatar} size="xxxl" />
<NameText account={info} showAcct external />
</header>
<main>
<main tabIndex="-1">
{bot && (
<>
<span class="tag">

View file

@ -1,14 +1,26 @@
import './modal.css';
import { createPortal } from 'preact/compat';
import { useEffect, useRef } from 'preact/hooks';
const $modalContainer = document.getElementById('modal-container');
function Modal({ children, onClick, class: className }) {
if (!children) return null;
const modalRef = useRef();
useEffect(() => {
let timer = setTimeout(() => {
const focusElement = modalRef.current?.querySelector('[tabindex="-1"]');
if (focusElement) {
focusElement.focus();
}
}, 100);
return () => clearTimeout(timer);
}, []);
const Modal = (
<div className={className} onClick={onClick}>
<div ref={modalRef} className={className} onClick={onClick}>
{children}
</div>
);

View file

@ -186,8 +186,12 @@ function Status({
});
const readMoreText = 'Read more →';
const statusRef = useRef(null);
return (
<article
ref={statusRef}
tabindex="-1"
class={`status ${
!withinContext && inReplyToAccount ? 'status-reply-to' : ''
} visibility-${visibility} ${
@ -653,6 +657,7 @@ function Status({
index={showMediaModal}
onClose={() => {
setShowMediaModal(false);
statusRef.current?.focus();
}}
/>
</Modal>
@ -662,6 +667,7 @@ function Status({
onClick={(e) => {
if (e.target === e.currentTarget) {
setShowEdited(false);
statusRef.current?.focus();
}
}}
>
@ -669,6 +675,7 @@ function Status({
statusID={showEdited}
onClose={() => {
setShowEdited(false);
statusRef.current?.focus();
}}
/>
</Modal>
@ -1153,7 +1160,7 @@ function EditedAtModal({ statusID, onClose = () => {} }) {
const currentYear = new Date().getFullYear();
return (
<div id="edit-history" class="sheet" tabIndex="-1">
<div id="edit-history" class="sheet">
<header>
{/* <button type="button" class="close-button plain large" onClick={onClose}>
<Icon icon="x" alt="Close" />
@ -1166,7 +1173,7 @@ function EditedAtModal({ statusID, onClose = () => {} }) {
</p>
)}
</header>
<main>
<main tabIndex="-1">
{editHistory.length > 0 && (
<ol>
{editHistory.map((status) => {

View file

@ -242,6 +242,10 @@ code {
}
}
[tabindex='-1'] {
outline: 0;
}
/* UTILS */
.ib {

View file

@ -73,6 +73,7 @@ function Home({ hidden }) {
return (
<div
id="home-page"
class="deck-container"
hidden={hidden}
ref={scrollableRef}

View file

@ -290,7 +290,12 @@ function Notifications() {
);
// console.log(groupedNotifications);
return (
<div class="deck-container" ref={scrollableRef} tabIndex="-1">
<div
id="notifications-page"
class="deck-container"
ref={scrollableRef}
tabIndex="-1"
>
<div class={`timeline-deck deck ${onlyMentions ? 'only-mentions' : ''}`}>
<header
onClick={() => {

View file

@ -33,6 +33,9 @@ function StatusPage({ id }) {
const heroStatusRef = useRef();
const scrollableRef = useRef();
useEffect(() => {
scrollableRef.current?.focus();
}, []);
useEffect(() => {
const onScroll = debounce(() => {
// console.log('onScroll');
@ -279,6 +282,7 @@ function StatusPage({ id }) {
<div class="deck-backdrop">
<Link href={closeLink}></Link>
<div
tabIndex="-1"
ref={scrollableRef}
class={`status-deck deck contained ${
statuses.length > 1 ? 'padded-bottom' : ''