返回 marp
Header.tsx
根目录 / website / components / Header.tsx
1 import classNames from 'classnames'
2 import Link from 'next/link'
3 import MarpLogo from 'public/assets/marp-logo.svg'
4
5 const handleMouseUp = (e: React.MouseEvent<HTMLElement>) =>
6 e.currentTarget.blur()
7
8 export type ItemSlug = 'docs' | 'blog'
9
10 export const Header = ({ activeItem }: { activeItem?: ItemSlug }) => (
11 <>
12 <header className="header">
13 <Link href="/" legacyBehavior>
14 <a
15 className="custom-anchor header-item"
16 role="link"
17 tabIndex={0}
18 onMouseUp={handleMouseUp}
19 >
20 <MarpLogo className="block h-16 w-16 p-2 md:h-20 md:w-20 md:p-3" />
21 <span className="sr-only">Marp</span>
22 </a>
23 </Link>
24 <nav className="ml-2">
25 <ul className="flex h-16 items-stretch md:h-20">
26 {process.env.NEXT_PUBLIC_DOCS && (
27 <li className="relative flex items-center justify-center">
28 <Link href="/docs" legacyBehavior>
29 <a
30 className={classNames('custom-anchor header-item nav-item', {
31 active: activeItem === 'docs',
32 })}
33 role="link"
34 tabIndex={0}
35 onMouseUp={handleMouseUp}
36 >
37 <span>Docs</span>
38 </a>
39 </Link>
40 </li>
41 )}
42 <li className="relative flex items-center justify-center">
43 <Link href="/blog" legacyBehavior>
44 <a
45 className={classNames('custom-anchor header-item nav-item', {
46 active: activeItem === 'blog',
47 })}
48 role="link"
49 tabIndex={0}
50 onMouseUp={handleMouseUp}
51 >
52 <span>Blog</span>
53 </a>
54 </Link>
55 </li>
56 <li className="relative flex items-center justify-center">
57 <a
58 href="https://github.com/marp-team/marp"
59 target="_blank"
60 rel="noopener noreferrer"
61 className="custom-anchor header-item nav-item"
62 onMouseUp={handleMouseUp}
63 >
64 <span>GitHub</span>
65 </a>
66 </li>
67 </ul>
68 </nav>
69 <style jsx>{`
70 :global(:root) {
71 @apply [--header-height:theme(spacing.16)] md:[--header-height:theme(spacing.20)];
72 }
73
74 .header {
75 @apply fixed top-0 left-0 z-50 flex h-[var(--header-height)] w-full justify-center bg-white shadow-sm;
76 }
77
78 .header-item {
79 @apply text-current no-underline outline-none;
80 }
81
82 .header-item > :global(svg) {
83 @apply transition-transform duration-200;
84 }
85
86 .header-item:hover:active > :global(svg) {
87 @apply duration-0 scale-125 transform shadow-none;
88 }
89
90 @media not all and (hover: none) {
91 .header-item:hover:active > :global(svg) {
92 @apply scale-110;
93 }
94 }
95
96 .nav-item {
97 @apply font-rounded mx-2 text-lg font-medium uppercase leading-none outline-none;
98 }
99
100 .nav-item::before {
101 @apply absolute inset-0;
102
103 content: '';
104 }
105
106 .header-item:focus-visible,
107 .nav-item:focus-visible::before {
108 @apply bg-gray-200;
109 }
110
111 .header-item:not(.nav-item) {
112 -webkit-tap-highlight-color: transparent;
113 }
114
115 @screen md {
116 .nav-item {
117 @apply mx-3 tracking-wider;
118 }
119 }
120
121 .nav-item > span {
122 @apply relative z-10;
123 }
124
125 .nav-item > span::after {
126 @apply absolute inset-x-0 mt-1 block h-1 transition-all duration-300;
127
128 content: '';
129 top: 100%;
130 }
131
132 .nav-item:hover > span::after,
133 .nav-item:focus-within > span::after {
134 box-shadow: inset 0 -0.25rem theme('colors.gray.400');
135 }
136
137 .nav-item.active > span::after {
138 @apply duration-0;
139 box-shadow: inset 0 -0.25rem theme('colors.marp.brand');
140 }
141
142 .nav-item:hover:active > span::after {
143 @apply duration-0;
144 box-shadow: inset 0 -0.25rem theme('colors.marp.dark');
145 }
146 `}</style>
147 </header>
148 </>
149 )
150
150 lines Plain Text