Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
brillout committed Oct 30, 2024
1 parent 8735857 commit ac4dba5
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 63 deletions.
2 changes: 2 additions & 0 deletions src/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export { Layout }
export { containerQueryMobile }
export { navWidthMin }
export { navWidthMax }

import React from 'react'
import { NavigationContent } from './navigation/Navigation'
Expand Down
6 changes: 1 addition & 5 deletions src/config/resolveHeadingsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,12 @@ function resolveHeadingsData(pageContext: PageContextOriginal) {
// TODO/refactor: remove navItems
let navItems: NavItem[]
let navItemsAll: NavItemAll[]
let columnLayouts: number[][]
{
const navItemsPageSections = pageSectionsResolved
.filter((pageSection) => pageSection.pageSectionLevel === 2)
.map(pageSectionToNavItem)
navItemsAll = headingsResolved.map(headingToNavItem)
const res = determineColumnLayoutEntries(navItemsAll)
columnLayouts = res.columnLayouts
determineColumnLayoutEntries(navItemsAll)
if (isDetachedPage) {
navItems = [headingToNavItem(activeHeading), ...navItemsPageSections]
} else {
Expand All @@ -85,8 +83,6 @@ function resolveHeadingsData(pageContext: PageContextOriginal) {
pageTitle,
documentTitle,
// TODO: don't pass to client-side
columnLayouts,
// TODO: don't pass to client-side
activeCategory,
}
return pageContextAddendum
Expand Down
116 changes: 72 additions & 44 deletions src/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { usePageContext } from '../renderer/usePageContext'
import '@docsearch/css'
import '../global.d.ts'
import { getViewportWidth } from '../utils/getViewportWidth'
import { navWidthMax, navWidthMin } from '../Layout'

type NavItem = {
level: number
Expand All @@ -22,7 +23,8 @@ type NavItem = {
menuModalFullWidth?: true
}
type NavItemAll = NavItem & {
isColumnLayoutElement?: true
// TODO/refactor: rename to isColumnLayoutEntry
isColumnLayoutElement?: ColumnMap
}
function NavigationContent(props: {
navItems: NavItem[]
Expand Down Expand Up @@ -50,49 +52,51 @@ function NavigationContent(props: {
}

function NavigationColumnLayout(props: { navItemsWithComputed: NavItemComputed[] }) {
const navItemsColumnLayout = groupByColumnLayout(props.navItemsWithComputed)
const paddingBottom = 40
let [viewportWidth, setViewportWidth] = useState<number | undefined>()
const updateviewportwidth = () => setViewportWidth(getViewportWidth())
useEffect(() => {
updateviewportwidth()
window.addEventListener('resize', updateviewportwidth, { passive: true })
})

const navItemsByColumnLayouts = getNavItemsByColumnLayouts(props.navItemsWithComputed, viewportWidth)

return (
<>
{navItemsColumnLayout.map(({ navItemsColumnEntries, isFullWidth }, i) => (
{navItemsByColumnLayouts.map(({ columns, isFullWidth }, i) => (
<div
key={i}
style={{
display: 'flex',
justifyContent: 'center',
width: columns.length * (navWidthMax + 20),
justifyContent: 'space-between',
maxWidth: '100%',
margin: 'auto',
marginBottom: 40,
}}
>
<div
className={`column-layout-${i}`}
style={{
flexGrow: 1,
columnGap: 20,
paddingBottom: isFullWidth ? paddingBottom : undefined,
}}
>
{navItemsColumnEntries.map((navItemColumnEntry, j) => (
<div
key={j}
className="column-layout-entry"
style={{
breakInside: 'avoid',
paddingBottom: !isFullWidth ? paddingBottom : undefined,
paddingTop: isFullWidth ? undefined : 0,
width: '100%',
}}
>
<div>
<NavItemComponent navItem={navItemColumnEntry} />
{navItemColumnEntry.navItemChilds.map((navItem, k) => (
<NavItemComponent navItem={navItem} key={k} />
{columns.map((columnEntry, j) => (
<div
key={j}
style={{
flexGrow: 1,
maxWidth: navWidthMax,
display: 'flex',
flexDirection: 'column',
paddingTop: isFullWidth && j !== 0 ? 36 : undefined,
}}
>
{columnEntry.map((navItems, k) => (
<div key={k}>
{navItems.map((navItem, l) => (
<NavItemComponent navItem={navItem} key={l} />
))}
<CategoryBorder navItemLevel1={isFullWidth ? undefined : navItemColumnEntry!} />
<CategoryBorder navItemLevel1={isFullWidth ? undefined : navItems[0]!} />
</div>
</div>
))}
<CategoryBorder navItemLevel1={!isFullWidth ? undefined : navItemsColumnEntries[0]!} />
</div>
))}
</div>
))}
<CategoryBorder navItemLevel1={!isFullWidth ? undefined : columns[0][0][0]!} />
</div>
))}
</>
Expand Down Expand Up @@ -164,33 +168,57 @@ function NavItemComponent({
}
}

type NavItemsColumnEntry = NavItemComputed & { navItemChilds: NavItemComputed[] }
function groupByColumnLayout(navItems: NavItemComputed[]) {
const navItemsColumnLayout: { navItemsColumnEntries: NavItemsColumnEntry[]; isFullWidth: boolean }[] = []
let navItemsColumnEntries: NavItemsColumnEntry[] = []
type NavItemsByColumnLayout = { columns: NavItemComputed[][][]; isFullWidth: boolean }
function getNavItemsByColumnLayouts(navItems: NavItemComputed[], viewportWidth: number = 0): NavItemsByColumnLayout[] {
const navItemsByColumnEntries = getNavItemsByColumnEntries(navItems)
const numberOfColumnsMax = Math.floor(viewportWidth / navWidthMin) || 1
const navItemsByColumnLayouts: NavItemsByColumnLayout[] = navItemsByColumnEntries.map(
({ columnEntries, isFullWidth }) => {
const numberOfColumns = Math.min(numberOfColumnsMax, columnEntries.length)
const columns: NavItemComputed[][][] = []
columnEntries.forEach((columnEntry) => {
const idx = numberOfColumns === 1 ? 0 : columnEntry.columnMap[numberOfColumns]!
assert(idx >= 0)
columns[idx] ??= []
columns[idx].push(columnEntry.navItems)
})
const navItemsByColumnLayout: NavItemsByColumnLayout = { columns, isFullWidth }
return navItemsByColumnLayout
},
)
return navItemsByColumnLayouts
}

type NavItemsByColumnEntries = { columnEntries: ColumnEntry[]; isFullWidth: boolean }[]
type ColumnEntry = { navItems: NavItemComputed[]; columnMap: ColumnMap }
type ColumnMap = Record<number, number>
function getNavItemsByColumnEntries(navItems: NavItemComputed[]): NavItemsByColumnEntries {
const navItemsByColumnEntries: NavItemsByColumnEntries = []
let columnEntries: ColumnEntry[] = []
let columnEntry: ColumnEntry
let isFullWidth: boolean | undefined
navItems.forEach((navItem) => {
if (navItem.level === 1) {
const isFullWidthPrevious = isFullWidth
isFullWidth = !!navItem.menuModalFullWidth
if (isFullWidthPrevious !== undefined && isFullWidthPrevious !== isFullWidth) {
navItemsColumnLayout.push({ navItemsColumnEntries, isFullWidth: isFullWidthPrevious })
navItemsColumnEntries = []
navItemsByColumnEntries.push({ columnEntries, isFullWidth: isFullWidthPrevious })
columnEntries = []
}
}
assert(isFullWidth !== undefined)
if (navItem.isColumnLayoutElement) {
assert(navItem.level === 1 || navItem.level === 4)
const navItemColumnEntry = { ...navItem, navItemChilds: [] }
navItemsColumnEntries.push(navItemColumnEntry)
columnEntry = { navItems: [navItem], columnMap: navItem.isColumnLayoutElement }
columnEntries.push(columnEntry)
} else {
assert(navItem.level !== 1)
navItemsColumnEntries[navItemsColumnEntries.length - 1].navItemChilds.push(navItem)
columnEntry.navItems.push(navItem)
}
})
assert(isFullWidth !== undefined)
navItemsColumnLayout.push({ navItemsColumnEntries, isFullWidth })
return navItemsColumnLayout
navItemsByColumnEntries.push({ columnEntries, isFullWidth })
return navItemsByColumnEntries
}

type NavItemComputed = ReturnType<typeof getNavItemsWithComputed>[number]
Expand Down
33 changes: 23 additions & 10 deletions src/renderer/getStyleColumnLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const columnWidthMin = 300
const columnWidthMax = 350

type NavItemWithLength = NavItemAll & { numberOfHeadings: number | null }
function determineColumnLayoutEntries(navItems: NavItemAll[]): { columnLayouts: number[][] } {
function determineColumnLayoutEntries(navItems: NavItemAll[]): undefined {
const navItemsWithLength: NavItemWithLength[] = navItems.map((navItem) => ({
...navItem,
numberOfHeadings: navItem.level === 1 || navItem.level === 4 ? 0 : null,
Expand Down Expand Up @@ -61,8 +61,9 @@ function determineColumnLayoutEntries(navItems: NavItemAll[]): { columnLayouts:
}
})

const columnLayouts: number[][] = []
let columns: number[] = []
type ColumnEntry = { navItemLeader: NavItemAll; numberOfEntries: number }
const columnLayouts: ColumnEntry[][] = []
let columnEntries: ColumnEntry[] = []
let isFullWidth: boolean | undefined
navItemsWithLength.forEach((navItem, i) => {
let isFullWidthBegin = false
Expand All @@ -71,8 +72,8 @@ function determineColumnLayoutEntries(navItems: NavItemAll[]): { columnLayouts:
isFullWidth = !!navItem.menuModalFullWidth
if (isFullWidth) isFullWidthBegin = true
if (isFullWidthPrevious !== undefined && isFullWidthPrevious !== isFullWidth) {
columnLayouts.push(columns)
columns = []
columnLayouts.push(columnEntries)
columnEntries = []
}
}
const navItemPrevious = navItemsWithLength[i - 1]
Expand All @@ -97,15 +98,28 @@ function determineColumnLayoutEntries(navItems: NavItemAll[]): { columnLayouts:
assert(navItemNext.numberOfHeadings)
numberOfHeadings = navItemNext.numberOfHeadings
}
columns.push(numberOfHeadings)
navItems[i].isColumnLayoutElement = true
columnEntries.push({ navItemLeader: navItems[i], numberOfEntries: numberOfHeadings })
}
})
columnLayouts.push(columns)
assert(columnEntries!)
columnLayouts.push(columnEntries)

return { columnLayouts }
columnLayouts.forEach((columnEntries) => {
for (let numberOfColumns = columnEntries.length; numberOfColumns >= 1; numberOfColumns--) {
const columnsIdMap = determineColumns(
columnEntries.map((columnEntry) => columnEntry.numberOfEntries),
numberOfColumns,
)
// console.log(numberOfColumns, columnsIdMap) // TODO/refactor: remove
columnEntries.forEach((columnEntry, i) => {
columnEntry.navItemLeader.isColumnLayoutElement ??= {}
columnEntry.navItemLeader.isColumnLayoutElement[numberOfColumns] = columnsIdMap[i]
})
}
})
}

// TODO/refactor: remove
function getStyleColumnLayout(columnLayouts: number[][]): string {
let style =
'\n' +
Expand All @@ -121,7 +135,6 @@ function getStyleColumnLayout(columnLayouts: number[][]): string {
styleGivenNumberOfColumns.push(
css`
.column-layout-${i} {
column-count: ${numberOfColumns};
max-width: min(100%, ${columnWidthMax * numberOfColumns}px);
}
`,
Expand Down
4 changes: 0 additions & 4 deletions src/renderer/onRenderHtml.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { assert } from '../utils/server'
import type { PageContextResolved } from '../config/resolvePageContext'
import { getPageElement } from './getPageElement'
import type { OnRenderHtmlAsync } from 'vike/types'
import { getStyleColumnLayout } from './getStyleColumnLayout'

const onRenderHtml: OnRenderHtmlAsync = async (
pageContext,
Expand All @@ -16,8 +15,6 @@ Promise<Awaited<ReturnType<OnRenderHtmlAsync>>> => {

const page = getPageElement(pageContext, pageContextResolved)

const styleMenuModalLayout = getStyleColumnLayout(pageContextResolved.columnLayouts)

const descriptionTag = pageContextResolved.isLandingPage
? dangerouslySkipEscape(`<meta name="description" content="${pageContextResolved.meta.tagline}" />`)
: ''
Expand All @@ -33,7 +30,6 @@ Promise<Awaited<ReturnType<OnRenderHtmlAsync>>> => {
${descriptionTag}
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />
${getOpenGraphTags(pageContext.urlPathname, pageContextResolved.documentTitle, pageContextResolved.meta)}
<style>${dangerouslySkipEscape(styleMenuModalLayout)}</style>
<meta name="docsearch:category" content="${pageContextResolved.activeCategory}" />
</head>
<body>
Expand Down

0 comments on commit ac4dba5

Please sign in to comment.