Files
cinny/src/app/pages/client/ClientLayout.tsx
T

66 lines
2.0 KiB
TypeScript
Raw Normal View History

import React, { ReactNode } from 'react';
import { Box, Line } from 'folds';
import { useAtom } from 'jotai';
import { bookmarksPanelAtom } from '../../state/bookmarksPanel';
import { BookmarksPanel } from '../../features/bookmarks/BookmarksPanel';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
type ClientLayoutProps = {
nav: ReactNode;
children: ReactNode;
};
export function ClientLayout({ nav, children }: ClientLayoutProps) {
const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
const screenSize = useScreenSizeContext();
return (
<>
<a
href="#main-content"
style={{
position: 'absolute',
top: '-40px',
left: 0,
padding: '8px 16px',
background: '#000',
color: '#fff',
zIndex: 9999,
borderRadius: '0 0 4px 0',
transition: 'top 0.1s',
}}
onFocus={(e) => {
(e.currentTarget as HTMLElement).style.top = '0';
}}
onBlur={(e) => {
(e.currentTarget as HTMLElement).style.top = '-40px';
}}
// #185 P1: following the fragment left focus on <body> (the <main> target
// wasn't focusable), so screen readers announced nothing and the URL got
// a stray #main-content. Move focus to <main> explicitly instead.
onClick={(e) => {
e.preventDefault();
document.getElementById('main-content')?.focus();
}}
>
Skip to main content
</a>
<Box grow="Yes">
<Box shrink="No" as="nav" aria-label="Room navigation">
{nav}
</Box>
<Box grow="Yes" as="main" id="main-content" tabIndex={-1} style={{ outline: 'none' }}>
{children}
</Box>
{bookmarksOpen && (
<>
{screenSize === ScreenSize.Desktop && (
<Line variant="Background" direction="Vertical" size="300" />
)}
<BookmarksPanel onClose={() => setBookmarksOpen(false)} />
</>
)}
</Box>
</>
);
}