-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Expand file tree
/
Copy pathHeader.tsx
More file actions
127 lines (116 loc) · 4.45 KB
/
Header.tsx
File metadata and controls
127 lines (116 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use client';
import {ActionButton, Badge, Text} from '@react-spectrum/s2';
// @ts-ignore
import BetaApp from '@react-spectrum/s2/icons/BetaApp';
import {flushSync} from 'react-dom';
import {getLibraryFromPage, getLibraryIcon, getLibraryLabel} from './library';
import GithubLogo from './icons/GithubLogo';
import {MarkdownMenu} from './MarkdownMenu';
// @ts-ignore
import {PageProps} from '@parcel/rsc';
import React, {CSSProperties, useId, useState} from 'react';
import SearchMenuTrigger, {preloadSearchMenu} from './SearchMenuTrigger';
import {style} from '@react-spectrum/s2/style' with { type: 'macro' };
function getButtonText(currentPage) {
return getLibraryLabel(getLibraryFromPage(currentPage));
}
function getButtonIcon(currentPage) {
return getLibraryIcon(getLibraryFromPage(currentPage));
}
export default function Header(props: PageProps) {
const {pages, currentPage} = props;
const [searchOpen, setSearchOpen] = useState(false);
const searchMenuId = useId();
let openSearchMenu = async () => {
if (!document.startViewTransition) {
setSearchOpen((prev) => !prev);
return;
}
// Preload SearchMenu so it is ready to render immediately.
await preloadSearchMenu();
document.startViewTransition(() => {
flushSync(() => {
setSearchOpen((prev) => !prev);
});
});
};
let closeSearchMenu = () => {
if (!document.startViewTransition) {
setSearchOpen(false);
return;
}
document.startViewTransition(() => {
flushSync(() => {
setSearchOpen(false);
});
});
};
let handleActionButtonKeyDown = (e: React.KeyboardEvent<HTMLButtonElement>) => {
if (e.key === 'ArrowDown' && !searchOpen) {
e.preventDefault();
openSearchMenu();
}
};
const ChevronDownIcon = (props) => (
<svg xmlns="http://www.w3.org/2000/svg" width={20} height={20} {...props}>
<path
fill="var(--iconPrimary, #222)"
d="M3.755 7.243a.748.748 0 0 1 1.06-.02l5.183 4.986 5.197-4.999a.749.749 0 1 1 1.04 1.08l-5.717 5.5a.747.747 0 0 1-1.04 0L3.776 8.303a.746.746 0 0 1-.02-1.06Z" />
</svg>
);
return (
<>
<header className={style({width: 'full', display: {default: 'none', lg: 'flex'}, justifyContent: 'center'})}>
<div
className={style({
width: 'full',
display: 'grid',
// @eslint-disable-next-line
gridTemplateColumns: '1fr auto 1fr',
alignItems: 'center'
})}>
<div className={style({justifySelf: 'start'})}>
<ActionButton
aria-label="Open menu and search"
aria-expanded={searchOpen}
aria-controls={searchOpen ? searchMenuId : undefined}
size="XL"
isQuiet
onPress={openSearchMenu}
onKeyDown={handleActionButtonKeyDown}
// @ts-ignore
onHoverStart={() => preloadSearchMenu()}
UNSAFE_style={{paddingInlineStart: 10}}>
<div className={style({display: 'flex', alignItems: 'center'})}>
<div className={style({marginTop: 4})} style={{viewTransitionName: !searchOpen ? 'search-menu-icon' : 'none'} as CSSProperties}>
{getButtonIcon(currentPage)}
</div>
<span className={style({font: 'ui-2xl', marginStart: 8})} style={{viewTransitionName: !searchOpen ? 'search-menu-label' : 'none'} as CSSProperties}>
{getButtonText(currentPage)}
</span>
</div>
<ChevronDownIcon className={style({width: 18})} />
</ActionButton>
</div>
<SearchMenuTrigger
pages={pages}
currentPage={currentPage}
onOpen={openSearchMenu}
onClose={closeSearchMenu}
isSearchOpen={searchOpen}
overlayId={searchMenuId} />
<div className={style({display: 'flex', alignItems: 'center', gap: 4, justifySelf: 'end'})}>
<Badge variant="indigo" size="M" styles={style({marginEnd: 8})}>
<BetaApp />
<Text>Beta Preview</Text>
</Badge>
<MarkdownMenu url={currentPage.url} />
<ActionButton aria-label="React Spectrum GitHub repo" size="L" isQuiet onPress={() => window.open('https://github.com/adobe/react-spectrum', '_blank', 'noopener,noreferrer')}>
<GithubLogo />
</ActionButton>
</div>
</div>
</header>
</>
);
}