mirror of
https://github.com/cheeaun/phanpy.git
synced 2025-03-14 01:48:50 +01:00
First step in making things focusable
This commit is contained in:
parent
30c529fe02
commit
9201f7a118
8 changed files with 62 additions and 9 deletions
27
src/app.jsx
27
src/app.jsx
|
@ -298,6 +298,26 @@ export function App() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const [currentDeck, setCurrentDeck] = useState('home');
|
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(() => {
|
useEffect(() => {
|
||||||
// HACK: prevent this from running again due to HMR
|
// HACK: prevent this from running again due to HMR
|
||||||
|
@ -324,7 +344,7 @@ export function App() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isLoggedIn && currentDeck && (
|
{isLoggedIn && (
|
||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -345,7 +365,7 @@ export function App() {
|
||||||
</button>
|
</button>
|
||||||
<div class="decks">
|
<div class="decks">
|
||||||
{/* Home will never be unmounted */}
|
{/* Home will never be unmounted */}
|
||||||
<Home hidden={currentDeck !== 'home'} />
|
<Home />
|
||||||
{/* Notifications can be unmounted */}
|
{/* Notifications can be unmounted */}
|
||||||
{currentDeck === 'notifications' && <Notifications />}
|
{currentDeck === 'notifications' && <Notifications />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -355,6 +375,7 @@ export function App() {
|
||||||
<Router
|
<Router
|
||||||
history={createHashHistory()}
|
history={createHashHistory()}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
console.log('router onChange', e);
|
||||||
// Special handling for Home and Notifications
|
// Special handling for Home and Notifications
|
||||||
const { url } = e;
|
const { url } = e;
|
||||||
if (/notifications/i.test(url)) {
|
if (/notifications/i.test(url)) {
|
||||||
|
@ -362,7 +383,7 @@ export function App() {
|
||||||
} else if (url === '/') {
|
} else if (url === '/') {
|
||||||
setCurrentDeck('home');
|
setCurrentDeck('home');
|
||||||
document.title = `Home / ${CLIENT_NAME}`;
|
document.title = `Home / ${CLIENT_NAME}`;
|
||||||
} else if (url === '/login' || url === '/welcome') {
|
} else {
|
||||||
setCurrentDeck(null);
|
setCurrentDeck(null);
|
||||||
}
|
}
|
||||||
states.history.push(url);
|
states.history.push(url);
|
||||||
|
|
|
@ -102,7 +102,6 @@ function Account({ account }) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id="account-container"
|
id="account-container"
|
||||||
tabIndex="-1"
|
|
||||||
class={`sheet ${uiState === 'loading' ? 'skeleton' : ''}`}
|
class={`sheet ${uiState === 'loading' ? 'skeleton' : ''}`}
|
||||||
>
|
>
|
||||||
{!info || uiState === 'loading' ? (
|
{!info || uiState === 'loading' ? (
|
||||||
|
@ -129,7 +128,7 @@ function Account({ account }) {
|
||||||
<Avatar url={avatar} size="xxxl" />
|
<Avatar url={avatar} size="xxxl" />
|
||||||
<NameText account={info} showAcct external />
|
<NameText account={info} showAcct external />
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main tabIndex="-1">
|
||||||
{bot && (
|
{bot && (
|
||||||
<>
|
<>
|
||||||
<span class="tag">
|
<span class="tag">
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
import './modal.css';
|
import './modal.css';
|
||||||
|
|
||||||
import { createPortal } from 'preact/compat';
|
import { createPortal } from 'preact/compat';
|
||||||
|
import { useEffect, useRef } from 'preact/hooks';
|
||||||
|
|
||||||
const $modalContainer = document.getElementById('modal-container');
|
const $modalContainer = document.getElementById('modal-container');
|
||||||
|
|
||||||
function Modal({ children, onClick, class: className }) {
|
function Modal({ children, onClick, class: className }) {
|
||||||
if (!children) return null;
|
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 = (
|
const Modal = (
|
||||||
<div className={className} onClick={onClick}>
|
<div ref={modalRef} className={className} onClick={onClick}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -186,8 +186,12 @@ function Status({
|
||||||
});
|
});
|
||||||
const readMoreText = 'Read more →';
|
const readMoreText = 'Read more →';
|
||||||
|
|
||||||
|
const statusRef = useRef(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article
|
<article
|
||||||
|
ref={statusRef}
|
||||||
|
tabindex="-1"
|
||||||
class={`status ${
|
class={`status ${
|
||||||
!withinContext && inReplyToAccount ? 'status-reply-to' : ''
|
!withinContext && inReplyToAccount ? 'status-reply-to' : ''
|
||||||
} visibility-${visibility} ${
|
} visibility-${visibility} ${
|
||||||
|
@ -653,6 +657,7 @@ function Status({
|
||||||
index={showMediaModal}
|
index={showMediaModal}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setShowMediaModal(false);
|
setShowMediaModal(false);
|
||||||
|
statusRef.current?.focus();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -662,6 +667,7 @@ function Status({
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (e.target === e.currentTarget) {
|
if (e.target === e.currentTarget) {
|
||||||
setShowEdited(false);
|
setShowEdited(false);
|
||||||
|
statusRef.current?.focus();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -669,6 +675,7 @@ function Status({
|
||||||
statusID={showEdited}
|
statusID={showEdited}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setShowEdited(false);
|
setShowEdited(false);
|
||||||
|
statusRef.current?.focus();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
@ -1153,7 +1160,7 @@ function EditedAtModal({ statusID, onClose = () => {} }) {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="edit-history" class="sheet" tabIndex="-1">
|
<div id="edit-history" class="sheet">
|
||||||
<header>
|
<header>
|
||||||
{/* <button type="button" class="close-button plain large" onClick={onClose}>
|
{/* <button type="button" class="close-button plain large" onClick={onClose}>
|
||||||
<Icon icon="x" alt="Close" />
|
<Icon icon="x" alt="Close" />
|
||||||
|
@ -1166,7 +1173,7 @@ function EditedAtModal({ statusID, onClose = () => {} }) {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main tabIndex="-1">
|
||||||
{editHistory.length > 0 && (
|
{editHistory.length > 0 && (
|
||||||
<ol>
|
<ol>
|
||||||
{editHistory.map((status) => {
|
{editHistory.map((status) => {
|
||||||
|
|
|
@ -242,6 +242,10 @@ code {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[tabindex='-1'] {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* UTILS */
|
/* UTILS */
|
||||||
|
|
||||||
.ib {
|
.ib {
|
||||||
|
|
|
@ -73,6 +73,7 @@ function Home({ hidden }) {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
id="home-page"
|
||||||
class="deck-container"
|
class="deck-container"
|
||||||
hidden={hidden}
|
hidden={hidden}
|
||||||
ref={scrollableRef}
|
ref={scrollableRef}
|
||||||
|
|
|
@ -290,7 +290,12 @@ function Notifications() {
|
||||||
);
|
);
|
||||||
// console.log(groupedNotifications);
|
// console.log(groupedNotifications);
|
||||||
return (
|
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' : ''}`}>
|
<div class={`timeline-deck deck ${onlyMentions ? 'only-mentions' : ''}`}>
|
||||||
<header
|
<header
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -33,6 +33,9 @@ function StatusPage({ id }) {
|
||||||
const heroStatusRef = useRef();
|
const heroStatusRef = useRef();
|
||||||
|
|
||||||
const scrollableRef = useRef();
|
const scrollableRef = useRef();
|
||||||
|
useEffect(() => {
|
||||||
|
scrollableRef.current?.focus();
|
||||||
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onScroll = debounce(() => {
|
const onScroll = debounce(() => {
|
||||||
// console.log('onScroll');
|
// console.log('onScroll');
|
||||||
|
@ -279,6 +282,7 @@ function StatusPage({ id }) {
|
||||||
<div class="deck-backdrop">
|
<div class="deck-backdrop">
|
||||||
<Link href={closeLink}></Link>
|
<Link href={closeLink}></Link>
|
||||||
<div
|
<div
|
||||||
|
tabIndex="-1"
|
||||||
ref={scrollableRef}
|
ref={scrollableRef}
|
||||||
class={`status-deck deck contained ${
|
class={`status-deck deck contained ${
|
||||||
statuses.length > 1 ? 'padded-bottom' : ''
|
statuses.length > 1 ? 'padded-bottom' : ''
|
||||||
|
|
Loading…
Reference in a new issue