2024-05-31 19:49:46 +05:30
|
|
|
import React, { ReactNode } from 'react';
|
2026-06-04 10:26:08 -04:00
|
|
|
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';
|
2024-05-31 19:49:46 +05:30
|
|
|
|
|
|
|
|
type ClientLayoutProps = {
|
|
|
|
|
nav: ReactNode;
|
|
|
|
|
children: ReactNode;
|
|
|
|
|
};
|
|
|
|
|
export function ClientLayout({ nav, children }: ClientLayoutProps) {
|
2026-06-04 10:26:08 -04:00
|
|
|
const [bookmarksOpen, setBookmarksOpen] = useAtom(bookmarksPanelAtom);
|
|
|
|
|
const screenSize = useScreenSizeContext();
|
|
|
|
|
|
2024-05-31 19:49:46 +05:30
|
|
|
return (
|
2026-05-20 21:44:41 -04:00
|
|
|
<>
|
|
|
|
|
<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',
|
|
|
|
|
}}
|
2026-05-21 20:49:33 -04:00
|
|
|
onFocus={(e) => {
|
|
|
|
|
(e.currentTarget as HTMLElement).style.top = '0';
|
|
|
|
|
}}
|
|
|
|
|
onBlur={(e) => {
|
|
|
|
|
(e.currentTarget as HTMLElement).style.top = '-40px';
|
|
|
|
|
}}
|
2026-09-24 12:15:02 -04:00
|
|
|
// #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();
|
|
|
|
|
}}
|
2026-05-20 21:44:41 -04:00
|
|
|
>
|
|
|
|
|
Skip to main content
|
|
|
|
|
</a>
|
|
|
|
|
<Box grow="Yes">
|
2026-05-21 20:49:33 -04:00
|
|
|
<Box shrink="No" as="nav" aria-label="Room navigation">
|
|
|
|
|
{nav}
|
|
|
|
|
</Box>
|
2026-09-24 12:15:02 -04:00
|
|
|
<Box grow="Yes" as="main" id="main-content" tabIndex={-1} style={{ outline: 'none' }}>
|
2026-05-21 20:49:33 -04:00
|
|
|
{children}
|
|
|
|
|
</Box>
|
2026-06-17 20:26:43 -04:00
|
|
|
{bookmarksOpen && (
|
2026-06-04 10:26:08 -04:00
|
|
|
<>
|
2026-06-17 20:26:43 -04:00
|
|
|
{screenSize === ScreenSize.Desktop && (
|
|
|
|
|
<Line variant="Background" direction="Vertical" size="300" />
|
|
|
|
|
)}
|
2026-06-19 11:21:29 -04:00
|
|
|
<BookmarksPanel onClose={() => setBookmarksOpen(false)} />
|
2026-06-04 10:26:08 -04:00
|
|
|
</>
|
|
|
|
|
)}
|
2026-05-20 21:44:41 -04:00
|
|
|
</Box>
|
|
|
|
|
</>
|
2024-05-31 19:49:46 +05:30
|
|
|
);
|
|
|
|
|
}
|