@brillout/docpress 0.15.13 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EditLink.tsx +28 -16
- package/ExternalLinks.tsx +31 -8
- package/Layout.css +4 -0
- package/Layout.tsx +243 -194
- package/MenuModal/NavigationWithColumnLayout.tsx +34 -17
- package/MenuModal/toggleMenuModal.ts +36 -9
- package/MenuModal.tsx +34 -11
- package/NavItemComponent.css +20 -15
- package/NavItemComponent.tsx +18 -4
- package/code-blocks/components/Pre.tsx +1 -1
- package/css/colorize-on-hover.css +10 -3
- package/css/heading.css +7 -1
- package/css/tooltip.css +8 -2
- package/determineNavItemsColumnLayout.spec.ts +518 -0
- package/determineNavItemsColumnLayout.ts +11 -10
- package/dist/NavItemComponent.d.ts +24 -2
- package/dist/NavItemComponent.js +3 -3
- package/dist/determineNavItemsColumnLayout.js +10 -9
- package/docsearch/SearchLink.tsx +5 -1
- package/icons/coin.svg +38 -0
- package/icons/index.ts +3 -0
- package/icons/loudspeaker.svg +1 -0
- package/icons/megaphone.svg +1 -0
- package/installSectionUrlHashs.ts +3 -1
- package/package.json +1 -1
- package/utils/getViewportWidth.ts +2 -2
package/Layout.tsx
CHANGED
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
export { Layout }
|
|
2
2
|
export { MenuToggle }
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
3
|
+
export { viewDesktop }
|
|
4
|
+
export { viewTablet }
|
|
5
5
|
export { navLeftWidthMin }
|
|
6
6
|
export { navLeftWidthMax }
|
|
7
|
+
export { bodyMaxWidth }
|
|
7
8
|
export { unexpandNav }
|
|
8
9
|
export { blockMargin }
|
|
9
10
|
|
|
11
|
+
// - @media VS @container
|
|
12
|
+
// - Using `@container container-viewport` instead of @media would be interesting because @media doesn't consider the scrollbar width.
|
|
13
|
+
// - But we still use @media because using @container is complicated(/buggy?) to use inside <MenuModal> because of `position: fixed`.
|
|
14
|
+
// - We use --padding-side because we cannot set a fixed max-width on the <NavHead> container .nav-head-content — DocPress doesn't know how many extra <NavHead> elements the user adds using the +docpress.topNavigation setting.
|
|
15
|
+
|
|
10
16
|
import React from 'react'
|
|
11
17
|
import { getNavItemsWithComputed, NavItem, NavItemComponent } from './NavItemComponent'
|
|
12
18
|
import { parseMarkdownMini } from './parseMarkdownMini'
|
|
13
19
|
import { usePageContext } from './renderer/usePageContext'
|
|
14
20
|
import { ExternalLinks } from './ExternalLinks'
|
|
15
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
closeMenuModalOnMouseLeaveToggle,
|
|
23
|
+
ignoreHoverOnTouchStart,
|
|
24
|
+
openMenuModalOnMouseEnter,
|
|
25
|
+
toggleMenuModal,
|
|
26
|
+
} from './MenuModal/toggleMenuModal'
|
|
16
27
|
import { MenuModal } from './MenuModal'
|
|
17
28
|
import { autoScrollNav_SSR } from './autoScrollNav'
|
|
18
29
|
import { initializeJsToggle_SSR } from './code-blocks/hooks/useSelectCodeLang'
|
|
@@ -23,17 +34,19 @@ import { Style } from './utils/Style'
|
|
|
23
34
|
import { cls } from './utils/cls'
|
|
24
35
|
import { iconBooks } from './icons'
|
|
25
36
|
import { EditLink } from './EditLink'
|
|
37
|
+
import './Layout.css'
|
|
26
38
|
|
|
27
|
-
const blockMargin =
|
|
39
|
+
const blockMargin = 4
|
|
28
40
|
const mainViewPadding = 20
|
|
29
|
-
const
|
|
30
|
-
const
|
|
41
|
+
const mainViewWidthMaxInner = 800
|
|
42
|
+
const mainViewWidthMax = (mainViewWidthMaxInner + mainViewPadding * 2) as 840 // 840 = 800 + 20 * 2
|
|
31
43
|
const navLeftWidthMin = 300
|
|
32
44
|
const navLeftWidthMax = 370
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
const
|
|
45
|
+
const viewMobile = 450
|
|
46
|
+
const viewTablet = 1016
|
|
47
|
+
const viewDesktop = (mainViewWidthMax + navLeftWidthMin + blockMargin) as 1144 // 1140 = 840 + 300 + 4
|
|
48
|
+
const viewDesktopLarge = (mainViewWidthMax + navLeftWidthMax + blockMargin) as 1214 // 1214 = 840 + 370 + 4
|
|
49
|
+
const bodyMaxWidth = 1300
|
|
37
50
|
|
|
38
51
|
// Avoid whitespace at the bottom of pages with almost no content
|
|
39
52
|
const whitespaceBuster1: React.CSSProperties = {
|
|
@@ -56,98 +69,77 @@ function Layout({ children }: { children: React.ReactNode }) {
|
|
|
56
69
|
content = <LayoutDocsPage>{children}</LayoutDocsPage>
|
|
57
70
|
}
|
|
58
71
|
|
|
72
|
+
const isNavLeftAlwaysHidden_ = isNavLeftAlwaysHidden()
|
|
59
73
|
return (
|
|
60
74
|
<div
|
|
61
75
|
style={{
|
|
62
|
-
['--bg-
|
|
76
|
+
['--color-bg-gray']: '#f5f5f5',
|
|
63
77
|
['--block-margin']: `${blockMargin}px`,
|
|
64
|
-
['--icon-text-padding']: '8px',
|
|
65
78
|
// ['--nav-head-height']: `${isLandingPage ? 70 : 63}px`,
|
|
66
79
|
['--nav-head-height']: `63px`,
|
|
80
|
+
['--main-view-padding']: `${mainViewPadding}px`,
|
|
81
|
+
// We don't add `container` to `body` nor `html` beacuse in Firefox it breaks the `position: fixed` of <MenuModal>
|
|
82
|
+
// https://stackoverflow.com/questions/74601420/css-container-inline-size-and-fixed-child
|
|
83
|
+
container: 'container-viewport / inline-size',
|
|
84
|
+
maxWidth: isNavLeftAlwaysHidden_ ? undefined : bodyMaxWidth,
|
|
85
|
+
margin: 'auto',
|
|
67
86
|
}}
|
|
68
87
|
>
|
|
69
|
-
<MenuModal isTopNav={isLandingPage} />
|
|
70
|
-
<div
|
|
71
|
-
className={isLandingPage ? '' : 'doc-page'}
|
|
72
|
-
style={{
|
|
73
|
-
// We don't add `container` to `body` nor `html` beacuse in Firefox it breaks the `position: fixed` of <MenuModal>
|
|
74
|
-
// https://stackoverflow.com/questions/74601420/css-container-inline-size-and-fixed-child
|
|
75
|
-
container: 'container-viewport / inline-size',
|
|
76
|
-
...whitespaceBuster1,
|
|
77
|
-
}}
|
|
78
|
-
>
|
|
88
|
+
<MenuModal isTopNav={isLandingPage} isNavLeftAlwaysHidden_={isNavLeftAlwaysHidden_} />
|
|
89
|
+
<div className={isLandingPage ? '' : 'doc-page'} style={whitespaceBuster1}>
|
|
79
90
|
<NavHead />
|
|
80
91
|
{content}
|
|
81
92
|
</div>
|
|
82
93
|
{/* Early toggling, to avoid layout jumps */}
|
|
83
94
|
<script dangerouslySetInnerHTML={{ __html: initializeJsToggle_SSR }}></script>
|
|
95
|
+
<Style>{getStyleLayout()}</Style>
|
|
84
96
|
</div>
|
|
85
97
|
)
|
|
86
98
|
}
|
|
87
99
|
|
|
88
100
|
function LayoutDocsPage({ children }: { children: React.ReactNode }) {
|
|
89
|
-
const pageContext = usePageContext()
|
|
90
|
-
const hideNavLeftAlways =
|
|
91
|
-
pageContext.resolved.pageDesign?.hideMenuLeft ||
|
|
92
|
-
(pageContext.resolved.navItemsDetached && pageContext.resolved.navItemsDetached.length <= 1)
|
|
93
101
|
return (
|
|
94
102
|
<>
|
|
95
|
-
<Style>{getStyle()}</Style>
|
|
96
103
|
<div style={{ display: 'flex', ...whitespaceBuster2 }}>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
{!isNavLeftAlwaysHidden() && (
|
|
105
|
+
<>
|
|
106
|
+
<NavLeft />
|
|
107
|
+
<div
|
|
108
|
+
id="nav-left-margin"
|
|
109
|
+
className="low-prio-grow"
|
|
110
|
+
style={{ width: 0, maxWidth: 50, background: 'var(--color-bg-gray)' }}
|
|
111
|
+
/>
|
|
112
|
+
</>
|
|
113
|
+
)}
|
|
103
114
|
<PageContent>{children}</PageContent>
|
|
104
115
|
</div>
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
<Style>{css`
|
|
117
|
+
@container container-viewport (max-width: ${viewDesktopLarge - 1}px) {
|
|
118
|
+
#nav-left {
|
|
119
|
+
flex-grow: 1;
|
|
120
|
+
min-width: ${navLeftWidthMin + blockMargin}px;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
@container container-viewport (min-width: ${viewDesktopLarge}px) {
|
|
110
124
|
.low-prio-grow {
|
|
111
125
|
flex-grow: 1;
|
|
112
126
|
}
|
|
113
|
-
#
|
|
114
|
-
width: ${navLeftWidthMax}px
|
|
127
|
+
#nav-left {
|
|
128
|
+
min-width: ${navLeftWidthMax + blockMargin}px;
|
|
115
129
|
}
|
|
116
|
-
}`
|
|
117
|
-
let navLeftHidden = css`
|
|
118
|
-
#nav-left, #nav-left-margin {
|
|
119
|
-
display: none;
|
|
120
|
-
}
|
|
121
|
-
.page-wrapper {
|
|
122
|
-
--main-view-padding: 10px !important;
|
|
123
|
-
flex-grow: 1;
|
|
124
|
-
align-items: center;
|
|
125
130
|
}
|
|
126
131
|
.page-content {
|
|
127
|
-
|
|
132
|
+
--hash-offset: 24px;
|
|
128
133
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
`
|
|
133
|
-
if (!hideNavLeftAlways) {
|
|
134
|
-
navLeftHidden = css`
|
|
135
|
-
@container container-viewport (max-width: ${containerQueryMobileLayout - 1}px) {
|
|
136
|
-
${navLeftHidden}
|
|
137
|
-
}
|
|
138
|
-
@container container-viewport (min-width: ${containerQueryMobileLayout}px) {
|
|
139
|
-
.nav-head-full-width {
|
|
140
|
-
display: none !important;
|
|
134
|
+
@container container-viewport (max-width: ${viewDesktopLarge - 1}px) and (min-width: ${viewDesktop}px) {
|
|
135
|
+
.page-content {
|
|
136
|
+
--hash-offset: 27px;
|
|
141
137
|
}
|
|
142
138
|
}
|
|
143
|
-
`
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return style
|
|
148
|
-
}
|
|
139
|
+
`}</Style>
|
|
140
|
+
</>
|
|
141
|
+
)
|
|
149
142
|
}
|
|
150
|
-
|
|
151
143
|
function LayoutLandingPage({ children }: { children: React.ReactNode }) {
|
|
152
144
|
return (
|
|
153
145
|
<>
|
|
@@ -164,15 +156,16 @@ function PageContent({ children }: { children: React.ReactNode }) {
|
|
|
164
156
|
const { globalNote } = pageContext.globalContext.config.docpress
|
|
165
157
|
*/
|
|
166
158
|
const ifDocPage = (style: React.CSSProperties) => (isLandingPage ? {} : style)
|
|
167
|
-
const contentMaxWidth = pageContext.resolved.pageDesign?.contentMaxWidth ??
|
|
159
|
+
const contentMaxWidth = pageContext.resolved.pageDesign?.contentMaxWidth ?? mainViewWidthMaxInner
|
|
168
160
|
return (
|
|
169
161
|
<div
|
|
170
162
|
className="page-wrapper low-prio-grow"
|
|
171
163
|
style={{
|
|
172
|
-
//
|
|
164
|
+
// We must set min-width to avoid layout overflow on mobile/desktop view.
|
|
165
|
+
// https://stackoverflow.com/questions/36230944/prevent-flex-items-from-overflowing-a-container/66689926#66689926
|
|
173
166
|
minWidth: 0,
|
|
174
167
|
...ifDocPage({
|
|
175
|
-
backgroundColor: 'var(--bg-
|
|
168
|
+
backgroundColor: 'var(--color-bg-gray)',
|
|
176
169
|
paddingBottom: 50,
|
|
177
170
|
}),
|
|
178
171
|
}}
|
|
@@ -180,8 +173,6 @@ function PageContent({ children }: { children: React.ReactNode }) {
|
|
|
180
173
|
<div
|
|
181
174
|
className="page-content"
|
|
182
175
|
style={{
|
|
183
|
-
// Also define --main-view-padding for landing page because it's used by <Contributors> and <Sponsors>
|
|
184
|
-
['--main-view-padding']: `${mainViewPadding}px`,
|
|
185
176
|
...ifDocPage({
|
|
186
177
|
width: `calc(${contentMaxWidth}px + 2 * var(--main-view-padding))`,
|
|
187
178
|
maxWidth: '100%',
|
|
@@ -192,7 +183,7 @@ function PageContent({ children }: { children: React.ReactNode }) {
|
|
|
192
183
|
{/* globalNote */}
|
|
193
184
|
{pageTitleParsed && !pageContext.resolved.pageDesign?.hideTitle && (
|
|
194
185
|
<div>
|
|
195
|
-
<EditLink className="show-only-on-desktop" style={{ float: 'right', marginTop:
|
|
186
|
+
<EditLink className="show-only-on-desktop" style={{ float: 'right', marginTop: 15 }} />
|
|
196
187
|
<h1 id={`${pageContext.urlPathname.replace('/', '')}`}>{pageTitleParsed}</h1>
|
|
197
188
|
</div>
|
|
198
189
|
)}
|
|
@@ -211,9 +202,10 @@ function NavLeft() {
|
|
|
211
202
|
id="nav-left"
|
|
212
203
|
className="link-hover-animation"
|
|
213
204
|
style={{
|
|
214
|
-
|
|
215
|
-
borderRight: 'var(--block-margin) solid white',
|
|
205
|
+
borderRight: 'var(--block-margin) solid var(--color-bg-white)',
|
|
216
206
|
zIndex: 1,
|
|
207
|
+
// We must set min-width to avoid layout overflow when the text of a navigation item exceeds the available width.
|
|
208
|
+
// https://stackoverflow.com/questions/36230944/prevent-flex-items-from-overflowing-a-container/66689926#66689926
|
|
217
209
|
}}
|
|
218
210
|
>
|
|
219
211
|
<div
|
|
@@ -225,9 +217,7 @@ function NavLeft() {
|
|
|
225
217
|
<NavHead isNavLeft={true} />
|
|
226
218
|
<div
|
|
227
219
|
style={{
|
|
228
|
-
backgroundColor: 'var(--bg-
|
|
229
|
-
display: 'flex',
|
|
230
|
-
justifyContent: 'flex-end',
|
|
220
|
+
backgroundColor: 'var(--color-bg-gray)',
|
|
231
221
|
}}
|
|
232
222
|
>
|
|
233
223
|
<div
|
|
@@ -239,7 +229,6 @@ function NavLeft() {
|
|
|
239
229
|
overscrollBehavior: 'contain',
|
|
240
230
|
paddingBottom: 40,
|
|
241
231
|
minWidth: navLeftWidthMin,
|
|
242
|
-
maxWidth: navLeftWidthMax,
|
|
243
232
|
width: '100%',
|
|
244
233
|
}}
|
|
245
234
|
>
|
|
@@ -254,9 +243,18 @@ function NavLeft() {
|
|
|
254
243
|
</div>
|
|
255
244
|
{/* Early scrolling, to avoid flashing */}
|
|
256
245
|
<script dangerouslySetInnerHTML={{ __html: autoScrollNav_SSR }}></script>
|
|
246
|
+
<Style>{getStyleNavLeft()}</Style>
|
|
257
247
|
</>
|
|
258
248
|
)
|
|
259
249
|
}
|
|
250
|
+
function getStyleNavLeft() {
|
|
251
|
+
return css`
|
|
252
|
+
.nav-item {
|
|
253
|
+
box-sizing: content-box;
|
|
254
|
+
max-width: ${navLeftWidthMax}px;
|
|
255
|
+
}`
|
|
256
|
+
}
|
|
257
|
+
|
|
260
258
|
function NavigationContent(props: {
|
|
261
259
|
navItems: NavItem[]
|
|
262
260
|
showOnlyRelevant?: true
|
|
@@ -275,43 +273,51 @@ function NavigationContent(props: {
|
|
|
275
273
|
)
|
|
276
274
|
}
|
|
277
275
|
|
|
276
|
+
function isNavLeftAlwaysHidden() {
|
|
277
|
+
const pageContext = usePageContext()
|
|
278
|
+
const { isLandingPage, navItemsDetached, pageDesign } = pageContext.resolved
|
|
279
|
+
return isLandingPage || !!pageDesign?.hideMenuLeft || !!(navItemsDetached && navItemsDetached.length <= 1)
|
|
280
|
+
}
|
|
281
|
+
|
|
278
282
|
const menuLinkStyle: React.CSSProperties = {
|
|
279
283
|
height: '100%',
|
|
280
284
|
padding: '0 var(--padding-side)',
|
|
281
285
|
justifyContent: 'center',
|
|
282
286
|
}
|
|
283
287
|
|
|
288
|
+
// Two <NavHead> instances are rendered:
|
|
289
|
+
// - The left-side <NavHead> shown on documentation pages on desktop
|
|
290
|
+
// - The top <NavHead> shown otherwise
|
|
284
291
|
function NavHead({ isNavLeft }: { isNavLeft?: true }) {
|
|
285
292
|
const pageContext = usePageContext()
|
|
286
|
-
const { isLandingPage } = pageContext.resolved
|
|
287
293
|
const { navMaxWidth, name, algolia } = pageContext.globalContext.config.docpress
|
|
294
|
+
const hideNavHeadLogo = pageContext.resolved.isLandingPage && !navMaxWidth
|
|
288
295
|
|
|
289
|
-
const
|
|
296
|
+
const navHeadSecondary = (
|
|
290
297
|
<div
|
|
291
|
-
className={isNavLeft
|
|
298
|
+
className={cls(['nav-head-secondary', isNavLeft && 'show-on-nav-hover add-transition'])}
|
|
292
299
|
style={{
|
|
293
300
|
padding: 0,
|
|
294
301
|
display: 'flex',
|
|
295
302
|
height: '100%',
|
|
296
|
-
...(
|
|
297
|
-
? {
|
|
298
|
-
: {
|
|
303
|
+
...(isNavLeft
|
|
304
|
+
? {
|
|
299
305
|
position: 'absolute',
|
|
300
306
|
left: '100%',
|
|
301
307
|
top: 0,
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
308
|
+
width: mainViewWidthMax, // guaranteed real estate
|
|
309
|
+
}
|
|
310
|
+
: {}),
|
|
305
311
|
}}
|
|
306
312
|
>
|
|
307
313
|
{pageContext.globalContext.config.docpress.topNavigation}
|
|
308
|
-
|
|
314
|
+
<div className="desktop-grow" style={{ display: 'none' }} />
|
|
309
315
|
<ExternalLinks
|
|
310
316
|
style={{
|
|
311
317
|
display: 'inline-flex',
|
|
312
318
|
fontSize: '1.06em',
|
|
313
|
-
|
|
314
|
-
|
|
319
|
+
paddingRight: 'var(--main-view-padding)',
|
|
320
|
+
paddingLeft: 'var(--padding-side)',
|
|
315
321
|
}}
|
|
316
322
|
/>
|
|
317
323
|
</div>
|
|
@@ -319,22 +325,19 @@ function NavHead({ isNavLeft }: { isNavLeft?: true }) {
|
|
|
319
325
|
|
|
320
326
|
return (
|
|
321
327
|
<div
|
|
322
|
-
className={cls(['nav-head-
|
|
328
|
+
className={cls(['nav-head link-hover-animation', isNavLeft && 'is-nav-left', !!navMaxWidth && 'has-max-width'])}
|
|
323
329
|
style={{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
backgroundColor: 'var(--bg-color)',
|
|
327
|
-
borderBottom: 'var(--block-margin) solid white',
|
|
330
|
+
backgroundColor: 'var(--color-bg-gray)',
|
|
331
|
+
borderBottom: 'var(--block-margin) solid var(--color-bg-white)',
|
|
328
332
|
position: 'relative',
|
|
329
333
|
}}
|
|
330
334
|
>
|
|
331
|
-
{isNavLeft && <
|
|
335
|
+
{isNavLeft && <NavHeadLeftFullWidthBackground />}
|
|
332
336
|
<div
|
|
333
337
|
style={{
|
|
338
|
+
// DON'T REMOVE this container: it's needed for the `cqw` values
|
|
334
339
|
container: 'container-nav-head / inline-size',
|
|
335
340
|
width: '100%',
|
|
336
|
-
minWidth: isNavLeft && navLeftWidthMin,
|
|
337
|
-
maxWidth: isNavLeft && navLeftWidthMax,
|
|
338
341
|
}}
|
|
339
342
|
>
|
|
340
343
|
<div
|
|
@@ -344,107 +347,154 @@ function NavHead({ isNavLeft }: { isNavLeft?: true }) {
|
|
|
344
347
|
maxWidth: navMaxWidth,
|
|
345
348
|
margin: 'auto',
|
|
346
349
|
height: 'var(--nav-head-height)',
|
|
347
|
-
fontSize: `min(
|
|
350
|
+
fontSize: `min(14.2px, ${isProjectNameShort(name) ? '4.8cqw' : '4.5cqw'})`,
|
|
348
351
|
color: '#666',
|
|
349
|
-
['--icon-text-padding']: 'min(8px, 1.8cqw)',
|
|
350
352
|
display: 'flex',
|
|
351
353
|
justifyContent: 'center',
|
|
352
354
|
}}
|
|
353
355
|
>
|
|
354
|
-
<
|
|
355
|
-
|
|
356
|
-
{algolia && <SearchLink className="
|
|
357
|
-
<MenuToggleMain className="
|
|
358
|
-
{
|
|
356
|
+
{!hideNavHeadLogo && <NavHeadLogo isNavLeft={isNavLeft} />}
|
|
357
|
+
<div className="desktop-grow" style={{ display: 'none' }} />
|
|
358
|
+
{algolia && <SearchLink className="always-shown" style={menuLinkStyle} />}
|
|
359
|
+
<MenuToggleMain className="always-shown nav-head-menu-toggle" style={menuLinkStyle} />
|
|
360
|
+
{navHeadSecondary}
|
|
359
361
|
</div>
|
|
360
362
|
</div>
|
|
361
|
-
<Style>{getStyle()}</Style>
|
|
362
363
|
</div>
|
|
363
364
|
)
|
|
365
|
+
}
|
|
366
|
+
function getStyleLayout() {
|
|
367
|
+
let style = ''
|
|
364
368
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
@
|
|
368
|
-
.
|
|
369
|
-
|
|
369
|
+
// Mobile
|
|
370
|
+
style += css`
|
|
371
|
+
@media(max-width: ${viewMobile}px) {
|
|
372
|
+
.nav-head:not(.is-nav-left) {
|
|
373
|
+
.nav-head-menu-toggle {
|
|
374
|
+
justify-content: flex-end !important;
|
|
375
|
+
padding-right: var(--main-view-padding) !important;
|
|
376
|
+
}
|
|
377
|
+
.nav-head-content {
|
|
378
|
+
--icon-text-padding: min(8px, 1.3cqw);
|
|
379
|
+
& > * {
|
|
380
|
+
flex-grow: 1;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
370
383
|
}
|
|
371
|
-
|
|
372
|
-
|
|
384
|
+
}`
|
|
385
|
+
|
|
386
|
+
// Mobile + tablet
|
|
387
|
+
style += css`
|
|
388
|
+
@media(max-width: ${viewTablet}px) {
|
|
389
|
+
.nav-head:not(.is-nav-left) {
|
|
390
|
+
.nav-head-secondary {
|
|
391
|
+
display: none !important;
|
|
392
|
+
}
|
|
373
393
|
}
|
|
374
|
-
|
|
375
|
-
|
|
394
|
+
}`
|
|
395
|
+
|
|
396
|
+
// Tablet
|
|
397
|
+
style += css`
|
|
398
|
+
@media(max-width: ${viewTablet}px) and (min-width: ${viewMobile + 1}px) {
|
|
399
|
+
.nav-head:not(.is-nav-left) {
|
|
400
|
+
.nav-head-content {
|
|
401
|
+
--icon-text-padding: 8px;
|
|
402
|
+
--padding-side: 20px;
|
|
403
|
+
}
|
|
376
404
|
}
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
405
|
+
}`
|
|
406
|
+
|
|
407
|
+
// Desktop small + desktop
|
|
408
|
+
style += css`
|
|
409
|
+
@media(min-width: ${viewTablet + 1}px) {
|
|
410
|
+
.nav-head:not(.is-nav-left) {
|
|
411
|
+
.nav-head-content {
|
|
412
|
+
--icon-text-padding: min(8px, 0.5cqw);
|
|
413
|
+
--padding-side: min(20px, 1.2cqw);
|
|
414
|
+
}
|
|
415
|
+
&.has-max-width {
|
|
416
|
+
.desktop-grow {
|
|
417
|
+
display: block !important;
|
|
418
|
+
}
|
|
419
|
+
.desktop-grow,
|
|
420
|
+
.nav-head-secondary {
|
|
421
|
+
flex-grow: 1;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
.page-wrapper {
|
|
426
|
+
min-width: ${mainViewWidthMax}px !important;
|
|
381
427
|
}
|
|
382
428
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
429
|
+
`
|
|
430
|
+
|
|
431
|
+
// Desktop
|
|
432
|
+
if (!isNavLeftAlwaysHidden()) {
|
|
433
|
+
style += css`
|
|
434
|
+
@container container-viewport (min-width: ${viewDesktop}px) {
|
|
435
|
+
.nav-head:not(.is-nav-left) {
|
|
436
|
+
display: none !important;
|
|
386
437
|
}
|
|
387
|
-
.nav-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
438
|
+
.nav-head.is-nav-left {
|
|
439
|
+
.nav-head-content {
|
|
440
|
+
--icon-text-padding: min(8px, 7 * (1cqw - 2.5px));
|
|
441
|
+
& > :not(.always-shown) {
|
|
442
|
+
--padding-side: min(24px, 27 * (1cqw - 2.5px));
|
|
443
|
+
}
|
|
444
|
+
& > * {
|
|
445
|
+
flex-grow: 0.5;
|
|
446
|
+
}
|
|
447
|
+
& > .nav-head-menu-toggle {
|
|
448
|
+
flex-grow: 1;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
391
451
|
}
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
452
|
+
.show-on-nav-hover {
|
|
453
|
+
opacity: 0;
|
|
454
|
+
transition-property: opacity;
|
|
455
|
+
pointer-events: none;
|
|
396
456
|
}
|
|
397
|
-
.nav
|
|
398
|
-
|
|
457
|
+
html:not(.unexpand-nav) {
|
|
458
|
+
& .nav-head.is-nav-left:hover .show-on-nav-hover,
|
|
459
|
+
&:has(.nav-head:hover) #menu-modal-wrapper.show-on-nav-hover,
|
|
460
|
+
&.menu-modal-show .nav-head.is-nav-left .show-on-nav-hover,
|
|
461
|
+
&.menu-modal-show #menu-modal-wrapper.show-on-nav-hover {
|
|
462
|
+
opacity: 1;
|
|
463
|
+
pointer-events: all;
|
|
464
|
+
}
|
|
399
465
|
}
|
|
400
466
|
}
|
|
401
|
-
@container container-
|
|
402
|
-
|
|
403
|
-
|
|
467
|
+
@container container-viewport (max-width: ${viewDesktop - 1}px) {
|
|
468
|
+
#nav-left, #nav-left-margin {
|
|
469
|
+
display: none;
|
|
404
470
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
.hide-on-shrink {
|
|
408
|
-
display: none !important;
|
|
471
|
+
body {
|
|
472
|
+
--main-view-padding: 10px !important;
|
|
409
473
|
}
|
|
474
|
+
${getStyleNavLeftHidden()}
|
|
410
475
|
}
|
|
411
476
|
`
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
@media(min-width: ${containerQueryMobileNav + 1}px) {
|
|
415
|
-
.desktop-grow {
|
|
416
|
-
flex-grow: 1;
|
|
477
|
+
} else {
|
|
478
|
+
style += getStyleNavLeftHidden()
|
|
417
479
|
}
|
|
480
|
+
|
|
481
|
+
return style
|
|
418
482
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
.nav-logo {
|
|
425
|
-
display: none !important;
|
|
426
|
-
}
|
|
483
|
+
function getStyleNavLeftHidden() {
|
|
484
|
+
return css`
|
|
485
|
+
.page-wrapper {
|
|
486
|
+
flex-grow: 1;
|
|
487
|
+
align-items: center;
|
|
427
488
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
style += css`
|
|
431
|
-
|
|
432
|
-
.show-on-nav-hover {
|
|
433
|
-
opacity: 0;
|
|
434
|
-
transition-property: opacity;
|
|
435
|
-
pointer-events: none;
|
|
489
|
+
.page-content {
|
|
490
|
+
margin: auto;
|
|
436
491
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
html:not(.unexpand-nav).menu-modal-show .show-on-nav-hover {
|
|
440
|
-
opacity: 1;
|
|
441
|
-
pointer-events: all;
|
|
492
|
+
#menu-modal-wrapper {
|
|
493
|
+
position: absolute !important;
|
|
442
494
|
}
|
|
443
495
|
`
|
|
444
|
-
}
|
|
445
|
-
return style
|
|
446
|
-
}
|
|
447
496
|
}
|
|
497
|
+
|
|
448
498
|
function unexpandNav() {
|
|
449
499
|
document.documentElement.classList.add('unexpand-nav')
|
|
450
500
|
// Using setTimeout() because requestAnimationFrame() doesn't delay enough
|
|
@@ -453,27 +503,27 @@ function unexpandNav() {
|
|
|
453
503
|
}, 1000)
|
|
454
504
|
}
|
|
455
505
|
|
|
456
|
-
function
|
|
506
|
+
function NavHeadLeftFullWidthBackground() {
|
|
457
507
|
return (
|
|
458
508
|
<>
|
|
459
509
|
<div
|
|
460
|
-
className="nav-bg show-on-nav-hover add-transition"
|
|
510
|
+
className="nav-head-bg show-on-nav-hover add-transition"
|
|
461
511
|
style={{
|
|
462
512
|
height: '100%',
|
|
463
513
|
zIndex: -1,
|
|
464
|
-
background: 'var(--bg-
|
|
514
|
+
background: 'var(--color-bg-gray)',
|
|
465
515
|
position: 'absolute',
|
|
466
516
|
left: 0,
|
|
467
517
|
top: 0,
|
|
468
518
|
boxSizing: 'content-box',
|
|
469
|
-
borderBottom: 'var(--block-margin) solid white',
|
|
519
|
+
borderBottom: 'var(--block-margin) solid var(--color-bg-white)',
|
|
470
520
|
}}
|
|
471
521
|
/>
|
|
472
522
|
<Style>{
|
|
473
523
|
// (min-width: 0px) => trick to always apply => @container seems to always require a condition
|
|
474
524
|
css`
|
|
475
525
|
@container container-viewport (min-width: 0px) {
|
|
476
|
-
.nav-bg {
|
|
526
|
+
.nav-head-bg {
|
|
477
527
|
width: 100cqw;
|
|
478
528
|
}
|
|
479
529
|
}
|
|
@@ -483,7 +533,7 @@ function NavHeaderLeftFullWidthBackground() {
|
|
|
483
533
|
)
|
|
484
534
|
}
|
|
485
535
|
|
|
486
|
-
function
|
|
536
|
+
function NavHeadLogo({ isNavLeft }: { isNavLeft?: true }) {
|
|
487
537
|
const pageContext = usePageContext()
|
|
488
538
|
|
|
489
539
|
const { navLogo } = pageContext.globalContext.config.docpress
|
|
@@ -517,12 +567,18 @@ function NavLogo({ className }: { className: string }) {
|
|
|
517
567
|
|
|
518
568
|
return (
|
|
519
569
|
<a
|
|
520
|
-
className=
|
|
570
|
+
className="nav-head-logo"
|
|
521
571
|
style={{
|
|
522
572
|
display: 'flex',
|
|
523
573
|
alignItems: 'center',
|
|
524
574
|
height: '100%',
|
|
525
575
|
color: 'inherit',
|
|
576
|
+
...(!isNavLeft
|
|
577
|
+
? {
|
|
578
|
+
paddingLeft: 'var(--main-view-padding)',
|
|
579
|
+
paddingRight: 'var(--padding-side)',
|
|
580
|
+
}
|
|
581
|
+
: {}),
|
|
526
582
|
}}
|
|
527
583
|
href="/"
|
|
528
584
|
onContextMenu={!navLogo ? undefined : onContextMenu}
|
|
@@ -542,7 +598,6 @@ function isProjectNameShort(name: string) {
|
|
|
542
598
|
return name.length <= 4
|
|
543
599
|
}
|
|
544
600
|
|
|
545
|
-
let onMouseIgnore: ReturnType<typeof setTimeout> | undefined
|
|
546
601
|
type PropsDiv = React.HTMLProps<HTMLDivElement>
|
|
547
602
|
function MenuToggleMain(props: PropsDiv) {
|
|
548
603
|
return (
|
|
@@ -554,12 +609,12 @@ function MenuToggleMain(props: PropsDiv) {
|
|
|
554
609
|
<MenuIcon /> Menu
|
|
555
610
|
</span>
|
|
556
611
|
<Style>{css`
|
|
557
|
-
@media(max-width: ${
|
|
612
|
+
@media(max-width: ${viewTablet}px) {
|
|
558
613
|
.text-docs, .caret-icon {
|
|
559
614
|
display: none !important;
|
|
560
615
|
}
|
|
561
616
|
}
|
|
562
|
-
@media(min-width: ${
|
|
617
|
+
@media(min-width: ${viewTablet + 1}px) {
|
|
563
618
|
.text-menu {
|
|
564
619
|
display: none;
|
|
565
620
|
}
|
|
@@ -587,29 +642,23 @@ function MenuToggle({ menuId, ...props }: PropsDiv & { menuId: number }) {
|
|
|
587
642
|
toggleMenuModal(menuId)
|
|
588
643
|
}}
|
|
589
644
|
onMouseEnter={() => {
|
|
590
|
-
|
|
591
|
-
openMenuModal(menuId)
|
|
645
|
+
openMenuModalOnMouseEnter(menuId)
|
|
592
646
|
}}
|
|
593
647
|
onMouseLeave={() => {
|
|
594
|
-
|
|
595
|
-
coseMenuModalOnMouseLeave(menuId)
|
|
596
|
-
}}
|
|
597
|
-
onTouchStart={() => {
|
|
598
|
-
onMouseIgnore = setTimeout(() => {
|
|
599
|
-
onMouseIgnore = undefined
|
|
600
|
-
}, 1000)
|
|
648
|
+
closeMenuModalOnMouseLeaveToggle(menuId)
|
|
601
649
|
}}
|
|
650
|
+
onTouchStart={ignoreHoverOnTouchStart}
|
|
602
651
|
>
|
|
603
652
|
<Style>{getAnimation()}</Style>
|
|
604
653
|
{props.children}
|
|
605
654
|
<CaretIcon
|
|
606
655
|
style={{
|
|
607
656
|
width: 11,
|
|
608
|
-
marginLeft:
|
|
657
|
+
marginLeft: 'calc(var(--icon-text-padding) - 1px)',
|
|
609
658
|
flexShrink: 0,
|
|
610
659
|
color: '#888',
|
|
611
660
|
position: 'relative',
|
|
612
|
-
top:
|
|
661
|
+
top: 1,
|
|
613
662
|
}}
|
|
614
663
|
/>
|
|
615
664
|
</div>
|
|
@@ -635,7 +684,7 @@ function MenuToggle({ menuId, ...props }: PropsDiv & { menuId: number }) {
|
|
|
635
684
|
height: 100%;
|
|
636
685
|
width: 100%;
|
|
637
686
|
top: var(--nav-head-height);
|
|
638
|
-
background-color: var(--active
|
|
687
|
+
background-color: var(--color-active);
|
|
639
688
|
transition-property: top !important;
|
|
640
689
|
transition: top 0.4s ease !important;
|
|
641
690
|
z-index: -1;
|
|
@@ -687,7 +736,7 @@ function DocsIcon() {
|
|
|
687
736
|
<img
|
|
688
737
|
src={iconBooks}
|
|
689
738
|
width={18}
|
|
690
|
-
style={{ marginRight: 'calc(var(--icon-text-padding) + 2px)' }}
|
|
739
|
+
style={{ marginRight: 'calc(var(--icon-text-padding) + 2px)', position: 'relative', top: 2 }}
|
|
691
740
|
className="decolorize-5"
|
|
692
741
|
/>
|
|
693
742
|
)
|