wip(shared): Nav prebuild changes
This commit is contained in:
parent
847598f059
commit
995bb23551
17 changed files with 103 additions and 349 deletions
|
@ -2,13 +2,13 @@
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
// Components
|
// Components
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
|
import { AsideNavigation, ns as navNs } from 'shared/components/navigation/aside.mjs'
|
||||||
import { ThemePicker } from 'shared/components/theme-picker/index.mjs'
|
import { ThemePicker } from 'shared/components/theme-picker/index.mjs'
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
||||||
import { HomeIcon } from 'shared/components/icons.mjs'
|
import { HomeIcon } from 'shared/components/icons.mjs'
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
export const ns = []
|
export const ns = navNs
|
||||||
|
|
||||||
export const DocsLayout = ({ app, children = [], title }) => (
|
export const DocsLayout = ({ app, children = [], title }) => (
|
||||||
<div className="grid grid-cols-4 m-auto justify-center place-items-stretch">
|
<div className="grid grid-cols-4 m-auto justify-center place-items-stretch">
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { PrimaryNavigation } from './primary.mjs'
|
|
||||||
|
|
||||||
export const AsideNavigation = ({ app, slug, mobileOnly = false, before = [], after = [] }) => (
|
|
||||||
<aside
|
|
||||||
className={`
|
|
||||||
fixed top-0 right-0 h-screen w-screen
|
|
||||||
overflow-y-auto z-20
|
|
||||||
text-base-content
|
|
||||||
transition-all
|
|
||||||
bg-base-100 px-4 py-4
|
|
||||||
md:bg-transparent md:px-0 md:py-0
|
|
||||||
${app.primaryMenu ? '' : 'translate-x-[-120%]'} transition-transform
|
|
||||||
md:flex md:flex-col md:sticky md:top-16
|
|
||||||
md:relative md:transform-none
|
|
||||||
md:max-w-xl
|
|
||||||
shrink-0
|
|
||||||
md:w-full
|
|
||||||
${mobileOnly ? 'block md:hidden' : ''}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{before}
|
|
||||||
<PrimaryNavigation app={app} active={slug} />
|
|
||||||
{after}
|
|
||||||
</aside>
|
|
||||||
)
|
|
|
@ -1,280 +0,0 @@
|
||||||
import { useState, useEffect } from 'react'
|
|
||||||
import Link from 'next/link'
|
|
||||||
import orderBy from 'lodash.orderby'
|
|
||||||
import { FreeSewingIcon } from 'shared/components/icons.mjs'
|
|
||||||
import { TopLevelNavigation as TopLevel } from './top-level.mjs'
|
|
||||||
|
|
||||||
/* helper method to order nav entries */
|
|
||||||
const order = (obj) => orderBy(obj, ['__order', '__title'], ['asc', 'asc'])
|
|
||||||
|
|
||||||
// Component for the collapse toggle
|
|
||||||
// Exported for re-use
|
|
||||||
export const Chevron = ({ w = 8, m = 2 }) => (
|
|
||||||
<svg
|
|
||||||
className={`
|
|
||||||
fill-current opacity-75 w-${w} h-${w} mr-${m}
|
|
||||||
details-toggle hover:text-secondary sm:hover:text-secondary
|
|
||||||
`}
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
>
|
|
||||||
<path d="M12.95 10.707l.707-.707L8 4.343 6.586 5.757 10.828 10l-4.242 4.243L8 15.657l4.95-4.95z" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
|
|
||||||
// Helper method to filter out the real children
|
|
||||||
const currentChildren = (current) =>
|
|
||||||
Object.values(order(current)).filter((entry) => typeof entry === 'object')
|
|
||||||
|
|
||||||
// Shared classes for links
|
|
||||||
// Exported for re-use
|
|
||||||
export const linkClasses = `
|
|
||||||
py-1
|
|
||||||
text-base-content sm:text-base-content
|
|
||||||
hover:text-secondary
|
|
||||||
sm:hover:text-secondary
|
|
||||||
`
|
|
||||||
|
|
||||||
// Figure out whether a page is on the path to the active page
|
|
||||||
const isActive = (slug, active) => {
|
|
||||||
if (slug === active) return true
|
|
||||||
let result = true
|
|
||||||
const slugParts = slug.split('/')
|
|
||||||
const activeParts = active.split('/')
|
|
||||||
for (const i in slugParts) {
|
|
||||||
if (slugParts[i] !== activeParts[i]) result = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// Component that renders a sublevel of navigation
|
|
||||||
const SubLevel = ({ nodes = {}, active }) => (
|
|
||||||
<ul className="pl-5 list-inside">
|
|
||||||
{currentChildren(nodes).map((child) =>
|
|
||||||
Object.keys(child).length > 4 ? (
|
|
||||||
<li key={child.__slug} className="flex flex-row">
|
|
||||||
<details className="grow" open={isActive(child.__slug, active)}>
|
|
||||||
<summary
|
|
||||||
className={`
|
|
||||||
flex flex-row
|
|
||||||
px-2
|
|
||||||
text-base-content
|
|
||||||
sm:text-base-content
|
|
||||||
hover:cursor-row-resize
|
|
||||||
items-center
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
href={`/${child.__slug}`}
|
|
||||||
title={child.__title}
|
|
||||||
className={`
|
|
||||||
grow pl-2 border-l-2
|
|
||||||
hover:cursor-pointer
|
|
||||||
hover:border-secondary
|
|
||||||
sm:hover:border-secondary
|
|
||||||
${
|
|
||||||
child.__slug === active
|
|
||||||
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
|
||||||
: 'text-base-content sm:text-base-content'
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<span className={linkClasses}>
|
|
||||||
<span
|
|
||||||
className={`
|
|
||||||
text-3xl mr-2 inline-block p-0 leading-3
|
|
||||||
${
|
|
||||||
child.__slug === active
|
|
||||||
? 'text-secondary sm:text-secondary translate-y-1'
|
|
||||||
: 'translate-y-3'
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{child.__slug === active ? <>•</> : <>°</>}
|
|
||||||
</span>
|
|
||||||
<span className={child.__slug === active ? 'font-medium' : ''}>
|
|
||||||
{child.__linktitle || child.__title}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
<Chevron w={6} m={3} />
|
|
||||||
</summary>
|
|
||||||
<SubLevel nodes={child} active={active} />
|
|
||||||
</details>
|
|
||||||
</li>
|
|
||||||
) : (
|
|
||||||
<li className="pl-2 flex flex-row items-center" key={child.__slug}>
|
|
||||||
<Link
|
|
||||||
href={`/${child.__slug}`}
|
|
||||||
title={child.__title}
|
|
||||||
className={`
|
|
||||||
pl-2 border-l-2
|
|
||||||
grow
|
|
||||||
hover:cursor-pointer
|
|
||||||
hover:border-secondary
|
|
||||||
sm:hover:border-secondary
|
|
||||||
${
|
|
||||||
child.__slug === active
|
|
||||||
? 'text-secondary border-secondary sm:text-secondary sm:border-secondary'
|
|
||||||
: 'text-base-content sm:text-base-content'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<span className={linkClasses}>
|
|
||||||
<span
|
|
||||||
className={`
|
|
||||||
text-3xl mr-2 inline-block p-0 leading-3
|
|
||||||
${
|
|
||||||
child.__slug === active
|
|
||||||
? 'text-secondary sm:text-secondary translate-y-1'
|
|
||||||
: 'translate-y-3'
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{child.__slug === active ? <>•</> : <>°</>}
|
|
||||||
</span>
|
|
||||||
<span className={child.__slug === active ? 'font-medium' : ''}>
|
|
||||||
{child.__linktitle || child.__title}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
)
|
|
||||||
|
|
||||||
const LevelHomeButton = ({ setShowLevel, level }) => (
|
|
||||||
<>
|
|
||||||
<button
|
|
||||||
className="h-8 mb-1 flex flex-row p-0 items-center -ml-7"
|
|
||||||
title="FreeSewing.org"
|
|
||||||
onClick={() => setShowLevel(level)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={`bg-neutral h-8 pl-2 pr-1 pt-1.5 font-medium text-secondary-content rounded-l-full`}
|
|
||||||
>
|
|
||||||
<FreeSewingIcon className="w-5 h-5 text-neutral-content" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`border-neutral h-12`}
|
|
||||||
style={{
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
borderWidth: '1rem',
|
|
||||||
borderRightColor: 'transparent',
|
|
||||||
borderTopColor: 'transparent',
|
|
||||||
borderBottomColor: 'transparent',
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</button>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
const colors = ['primary', 'secondary', 'accent']
|
|
||||||
|
|
||||||
const LevelButton = ({ title, level, showLevel, setShowLevel, href = false }) => {
|
|
||||||
const props = {
|
|
||||||
className: `h-8 mb-1 flex flex-row p-0 items-center -ml-7 max-w-1/3 ${
|
|
||||||
showLevel < level ? 'opacity-50' : ''
|
|
||||||
}`,
|
|
||||||
}
|
|
||||||
const content = (
|
|
||||||
<>
|
|
||||||
<div
|
|
||||||
className={`border-${colors[level]}`}
|
|
||||||
style={{
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
borderWidth: '1rem',
|
|
||||||
borderLeftColor: 'transparent',
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
<div
|
|
||||||
className={`
|
|
||||||
bg-${colors[level]} h-8 pr-1 pt-0.5 -ml-2 font-medium
|
|
||||||
text-secondary-content overflow-hidden`}
|
|
||||||
>
|
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`border-${colors[level]} h-12`}
|
|
||||||
style={{
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
borderWidth: '1rem',
|
|
||||||
borderRightColor: 'transparent',
|
|
||||||
borderTopColor: 'transparent',
|
|
||||||
borderBottomColor: 'transparent',
|
|
||||||
}}
|
|
||||||
></div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
return href ? (
|
|
||||||
<Link {...props} href={href}>
|
|
||||||
{content}
|
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<button {...props} onClick={() => setShowLevel(level)}>
|
|
||||||
{content}
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Navigation = ({ app, active, className = '' }) => {
|
|
||||||
// Levels
|
|
||||||
const levels = active.split('/')
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setShowLevel(Math.max(levels.length, 2))
|
|
||||||
}, [active])
|
|
||||||
const [showLevel, setShowLevel] = useState(Math.max(levels.length, 2))
|
|
||||||
if (!app.navigation) return null
|
|
||||||
if (levels.length < 1) return null
|
|
||||||
|
|
||||||
let navigation = app.navigation
|
|
||||||
|
|
||||||
const shared = { showLevel, setShowLevel }
|
|
||||||
const levelButtons = []
|
|
||||||
if (levels[0]) {
|
|
||||||
const title = app.navigation[levels[0].__title] || levels[0]
|
|
||||||
navigation = app.navigation[levels[0]]
|
|
||||||
levelButtons.push(<LevelHomeButton key="home" {...shared} level={-1} />)
|
|
||||||
levelButtons.push(<LevelButton title={title} key={0} level={0} {...shared} />)
|
|
||||||
}
|
|
||||||
if (levels[1]) {
|
|
||||||
const title = app.navigation[levels[0]][levels[1]]?.__title || levels[1]
|
|
||||||
if (showLevel > 0) navigation = navigation[levels[1]]
|
|
||||||
levelButtons.push(<LevelButton title={title} key={1} level={1} {...shared} />)
|
|
||||||
}
|
|
||||||
if (levels[2] && levels.length > 3) {
|
|
||||||
if (showLevel > 1) navigation = navigation[levels[2]]
|
|
||||||
levelButtons.push(
|
|
||||||
<LevelButton
|
|
||||||
title={app.navigation[levels[0]][levels[1]][levels[2]].__title}
|
|
||||||
key={2}
|
|
||||||
level={2}
|
|
||||||
{...shared}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const output = [
|
|
||||||
<div key="levelButtons" className="pl-8 flex flex-row flex-wrap mb-4">
|
|
||||||
{levelButtons}
|
|
||||||
</div>,
|
|
||||||
]
|
|
||||||
if (showLevel < 0) output.push(<TopLevel />)
|
|
||||||
else output.push(<SubLevel nodes={order(navigation)} active={active} />)
|
|
||||||
|
|
||||||
return <div className={`pb-20 ${className}`}>{output}</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PrimaryNavigation = ({ app, active, before = [], after = [] }) => (
|
|
||||||
<nav className="mb-12">
|
|
||||||
{before}
|
|
||||||
<Navigation app={app} active={active} />
|
|
||||||
{after}
|
|
||||||
</nav>
|
|
||||||
)
|
|
|
@ -1,3 +0,0 @@
|
||||||
export const TopLevelNavigation = () => {
|
|
||||||
return <p>Top-level menu here</p>
|
|
||||||
}
|
|
|
@ -15,12 +15,16 @@ import { freeSewingConfig as conf } from 'site/freesewing.config.mjs'
|
||||||
* Note: Set 'c' to set the control level to hide things from users
|
* Note: Set 'c' to set the control level to hide things from users
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const ns = ['account']
|
const ns = ['account', 'sections']
|
||||||
|
|
||||||
const sitePages = (locale, t = false) => {
|
const sitePages = (locale, t = false) => {
|
||||||
// Handle t not being present
|
// Handle t not being present
|
||||||
if (!t) t = (string) => string
|
if (!t) t = (string) => string
|
||||||
const pages = {
|
const pages = {
|
||||||
|
account: {
|
||||||
|
t: t('sections:account'),
|
||||||
|
s: 'account',
|
||||||
|
},
|
||||||
profile: {
|
profile: {
|
||||||
t: t('yourProfile'),
|
t: t('yourProfile'),
|
||||||
s: 'profile',
|
s: 'profile',
|
||||||
|
@ -31,10 +35,6 @@ const sitePages = (locale, t = false) => {
|
||||||
s: 'typography',
|
s: 'typography',
|
||||||
h: 1,
|
h: 1,
|
||||||
},
|
},
|
||||||
account: {
|
|
||||||
t: t('account'),
|
|
||||||
s: 'account',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for (const section in conf.account.fields) {
|
for (const section in conf.account.fields) {
|
||||||
for (const field in conf.account.fields[section]) {
|
for (const field in conf.account.fields[section]) {
|
||||||
|
|
1
sites/org/pages/docs/docs.en.yaml
Normal file
1
sites/org/pages/docs/docs.en.yaml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
docs: Documentation
|
|
@ -1,17 +1,19 @@
|
||||||
// Hooks
|
// Hooks
|
||||||
import { useApp } from 'shared/hooks/use-app.mjs'
|
import { useApp } from 'shared/hooks/use-app.mjs'
|
||||||
// Dependencies
|
// Dependencies
|
||||||
import Head from 'next/head'
|
|
||||||
import { mdxLoader } from 'shared/mdx/loader.mjs'
|
import { mdxLoader } from 'shared/mdx/loader.mjs'
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
// Components
|
// Components
|
||||||
import { PageWrapper } from 'shared/components/wrappers/page.mjs'
|
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
||||||
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
|
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
|
||||||
import { ReadMore } from 'shared/components/mdx/read-more.mjs'
|
import { ReadMore } from 'shared/components/mdx/read-more.mjs'
|
||||||
import { jargon } from 'site/jargon.mjs'
|
import { jargon } from 'site/jargon.mjs'
|
||||||
|
|
||||||
const DocsPage = ({ title, mdx, bugsnag }) => {
|
// Translation namespaces used on this page
|
||||||
const app = useApp({ bugsnag })
|
const namespaces = [...new Set(['docs', ...pageNs])]
|
||||||
const fullTitle = title + ' - FreeSewing.org'
|
|
||||||
|
const DocsPage = (props) => {
|
||||||
|
const app = useApp(props)
|
||||||
|
|
||||||
// We don't need all MDX components here, just ReadMore
|
// We don't need all MDX components here, just ReadMore
|
||||||
const components = {
|
const components = {
|
||||||
|
@ -19,15 +21,11 @@ const DocsPage = ({ title, mdx, bugsnag }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper app={app} title={title}>
|
<PageWrapper app={app}>
|
||||||
<Head>
|
|
||||||
<title>{fullTitle}</title>
|
|
||||||
</Head>
|
|
||||||
<div className="w-full"></div>
|
<div className="w-full"></div>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
//<MdxWrapper mdx={mdx} app={app} components={components} />
|
|
||||||
|
|
||||||
export default DocsPage
|
export default DocsPage
|
||||||
|
|
||||||
|
@ -43,13 +41,15 @@ export default DocsPage
|
||||||
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
* To learn more, see: https://nextjs.org/docs/basic-features/data-fetching
|
||||||
*/
|
*/
|
||||||
export async function getStaticProps({ locale }) {
|
export async function getStaticProps({ locale }) {
|
||||||
const { mdx, frontmatter } = await mdxLoader(locale, 'org', ['docs'], jargon[locale])
|
const { mdx } = await mdxLoader(locale, 'org', ['docs'], jargon[locale])
|
||||||
const { title = 'FIXME: Please give this page a title' } = frontmatter
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, namespaces)),
|
||||||
mdx,
|
mdx,
|
||||||
title,
|
page: {
|
||||||
|
path: ['docs'],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,31 @@ const HomePage = (props) => {
|
||||||
<Popout fixme>
|
<Popout fixme>
|
||||||
Create homepage. Meanwhile check <PageLink href="/signup" txt="the signup flow" />
|
Create homepage. Meanwhile check <PageLink href="/signup" txt="the signup flow" />
|
||||||
</Popout>
|
</Popout>
|
||||||
|
<h2>What is FreeSewing?</h2>
|
||||||
|
<small>(by ChatGPT)</small>
|
||||||
|
<p>
|
||||||
|
Freesewing is an open-source pattern making software that allows users to generate
|
||||||
|
custom sewing patterns based on their own measurements. It is designed to be flexible
|
||||||
|
and customizable, and can be used to create a wide range of garments, from simple
|
||||||
|
t-shirts and skirts to more complex dresses and jackets.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Freesewing is available for free, and users can access a wide range of pre-made patterns
|
||||||
|
or create their own from scratch. The software is designed to be easy to use, with an
|
||||||
|
intuitive interface that guides users through the process of creating a pattern
|
||||||
|
step-by-step.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In addition to the pattern making software, freesewing also has an active online
|
||||||
|
community of sewists and pattern makers who share tips, techniques, and advice on all
|
||||||
|
aspects of sewing. The community also collaborates on creating new patterns and
|
||||||
|
improving existing ones, and users can contribute their own patterns to the project as
|
||||||
|
well.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Overall, freesewing is a powerful tool for anyone interested in sewing and pattern
|
||||||
|
making, whether they are seasoned professionals or beginners just starting out.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
|
|
|
@ -25,15 +25,15 @@ const TypographyPage = (props) => {
|
||||||
<p>This typography page shows an overview of different elements and how they are styled.</p>
|
<p>This typography page shows an overview of different elements and how they are styled.</p>
|
||||||
<p>It's a good starting point for theme development.</p>
|
<p>It's a good starting point for theme development.</p>
|
||||||
<h2>Headings (this is h2)</h2>
|
<h2>Headings (this is h2)</h2>
|
||||||
{p}
|
{p} {p}
|
||||||
<h3>This is h3</h3>
|
<h3>This is h3</h3>
|
||||||
{p}
|
{p} {p}
|
||||||
<h4>This is h4</h4>
|
<h4>This is h4</h4>
|
||||||
{p}
|
{p} {p}
|
||||||
<h5>This is h5</h5>
|
<h5>This is h5</h5>
|
||||||
{p}
|
{p} {p}
|
||||||
<h6>This is h6</h6>
|
<h6>This is h6</h6>
|
||||||
{p}
|
{p} {p}
|
||||||
<h2>Links and buttons</h2>
|
<h2>Links and buttons</h2>
|
||||||
<p>
|
<p>
|
||||||
A regular link <a href="#">looks like this</a>, whereas buttons look like this:
|
A regular link <a href="#">looks like this</a>, whereas buttons look like this:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import { MainSections, ActiveSection } from './primary.mjs'
|
import { MainSections, ActiveSection, ns as navNs } from './primary.mjs'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
|
export const ns = navNs
|
||||||
|
|
||||||
export const AsideNavigation = ({ app, mobileOnly = false, before = [], after = [] }) => (
|
export const AsideNavigation = ({ app, mobileOnly = false, before = [], after = [] }) => (
|
||||||
<aside
|
<aside
|
||||||
className={`
|
className={`
|
||||||
|
|
|
@ -11,6 +11,8 @@ import {
|
||||||
} from 'shared/components/icons.mjs'
|
} from 'shared/components/icons.mjs'
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
||||||
|
|
||||||
|
export const ns = ['sections']
|
||||||
|
|
||||||
// List of icons matched to top-level slug
|
// List of icons matched to top-level slug
|
||||||
const icons = {
|
const icons = {
|
||||||
// FreeSewing.dev
|
// FreeSewing.dev
|
||||||
|
@ -191,8 +193,10 @@ export const Icons = ({
|
||||||
|
|
||||||
export const MainSections = ({ app }) => {
|
export const MainSections = ({ app }) => {
|
||||||
if (!app.state.sections) return null
|
if (!app.state.sections) return null
|
||||||
|
// Ensure each page as an `o` key so we can put them in order
|
||||||
|
const sortableSections = app.state.sections.map((s) => ({ ...s, o: s.o ? s.o : s.t }))
|
||||||
const output = []
|
const output = []
|
||||||
for (const page of app.state.sections) {
|
for (const page of orderBy(sortableSections, ['o', 't'])) {
|
||||||
const act = isActive(page.s, app.state.slug)
|
const act = isActive(page.s, app.state.slug)
|
||||||
const txt = (
|
const txt = (
|
||||||
<>
|
<>
|
||||||
|
|
4
sites/shared/components/navigation/sections.en.yaml
Normal file
4
sites/shared/components/navigation/sections.en.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
blog: Blog
|
||||||
|
showcase: Showcase
|
||||||
|
docs: Documentation
|
||||||
|
account: Account
|
|
@ -6,10 +6,10 @@ import { useHotkeys } from 'react-hotkeys-hook'
|
||||||
import { useTheme } from 'shared/hooks/use-theme.mjs'
|
import { useTheme } from 'shared/hooks/use-theme.mjs'
|
||||||
// Components
|
// Components
|
||||||
import { LayoutWrapper, ns as layoutNs } from 'site/components/wrappers/layout.mjs'
|
import { LayoutWrapper, ns as layoutNs } from 'site/components/wrappers/layout.mjs'
|
||||||
import { DocsLayout } from 'site/components/layouts/docs.mjs'
|
import { DocsLayout, ns as docsNs } from 'site/components/layouts/docs.mjs'
|
||||||
import { Feeds } from 'site/components/feeds.mjs'
|
import { Feeds } from 'site/components/feeds.mjs'
|
||||||
|
|
||||||
export const ns = [...layoutNs]
|
export const ns = [...new Set([...layoutNs, ...docsNs])]
|
||||||
|
|
||||||
/* This component should wrap all page content */
|
/* This component should wrap all page content */
|
||||||
export const PageWrapper = ({
|
export const PageWrapper = ({
|
||||||
|
|
|
@ -16,7 +16,7 @@ const locales = ['en', 'es', 'de', 'fr', 'nl']
|
||||||
* code-adjacent translation source files
|
* code-adjacent translation source files
|
||||||
*/
|
*/
|
||||||
const sitesFolder = path.join(fileURLToPath(import.meta.url), '..', '..', '..')
|
const sitesFolder = path.join(fileURLToPath(import.meta.url), '..', '..', '..')
|
||||||
const folders = {
|
export const folders = {
|
||||||
org: [path.join(sitesFolder, 'org', 'pages'), path.join(sitesFolder, 'org', 'components')],
|
org: [path.join(sitesFolder, 'org', 'pages'), path.join(sitesFolder, 'org', 'components')],
|
||||||
dev: [path.join(sitesFolder, 'dev', 'pages'), path.join(sitesFolder, 'dev', 'components')],
|
dev: [path.join(sitesFolder, 'dev', 'pages'), path.join(sitesFolder, 'dev', 'components')],
|
||||||
shared: [path.join(sitesFolder, 'shared', 'components')],
|
shared: [path.join(sitesFolder, 'shared', 'components')],
|
||||||
|
@ -79,12 +79,12 @@ const languageAndNamespaceFromFilename = (file) => {
|
||||||
/*
|
/*
|
||||||
* Helper method to load a YAML file from disk
|
* Helper method to load a YAML file from disk
|
||||||
*/
|
*/
|
||||||
const loadYaml = (file) => {
|
export const loadYaml = (file, complain = true) => {
|
||||||
let data
|
let data
|
||||||
try {
|
try {
|
||||||
data = yaml.load(fs.readFileSync(file, 'utf-8'))
|
data = yaml.load(fs.readFileSync(file, 'utf-8'))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
if (complain) console.log(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { prebuildLab } from './lab.mjs'
|
||||||
import { generateOgImage } from './og/index.mjs'
|
import { generateOgImage } from './og/index.mjs'
|
||||||
|
|
||||||
const run = async () => {
|
const run = async () => {
|
||||||
console.log('in run')
|
|
||||||
const SITE = process.env.SITE || 'lab'
|
const SITE = process.env.SITE || 'lab'
|
||||||
if (SITE === 'org') {
|
if (SITE === 'org') {
|
||||||
const mdxPages = await prebuildMdx(SITE)
|
const mdxPages = await prebuildMdx(SITE)
|
||||||
|
|
|
@ -1,10 +1,25 @@
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import set from 'lodash.set'
|
import set from 'lodash.set'
|
||||||
|
import { loadYaml, folders } from './i18n.mjs'
|
||||||
|
|
||||||
// Some arbitrary future time
|
// Some arbitrary future time
|
||||||
const future = new Date('10-12-2026').getTime()
|
const future = new Date('10-12-2026').getTime()
|
||||||
|
|
||||||
|
// We need to load the translation for blog + showcase
|
||||||
|
const loadTranslation = (locale) => {
|
||||||
|
const file = `${folders.shared}/navigation/sections.${locale}.yaml`
|
||||||
|
let data
|
||||||
|
try {
|
||||||
|
data = loadYaml(`${folders.shared}/navigation/sections.${locale}.yaml`, false)
|
||||||
|
} catch (err) {
|
||||||
|
data = {}
|
||||||
|
}
|
||||||
|
if (!data) data = {}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main method that does what needs doing
|
* Main method that does what needs doing
|
||||||
*/
|
*/
|
||||||
|
@ -20,6 +35,7 @@ export const prebuildNavigation = (mdxPages, strapiPosts, site) => {
|
||||||
*/
|
*/
|
||||||
const nav = {}
|
const nav = {}
|
||||||
for (const lang in mdxPages) {
|
for (const lang in mdxPages) {
|
||||||
|
const translations = loadTranslation(lang)
|
||||||
nav[lang] = {}
|
nav[lang] = {}
|
||||||
|
|
||||||
// Handle MDX content
|
// Handle MDX content
|
||||||
|
@ -37,10 +53,10 @@ export const prebuildNavigation = (mdxPages, strapiPosts, site) => {
|
||||||
// Handle strapi content
|
// Handle strapi content
|
||||||
for (const type in strapiPosts) {
|
for (const type in strapiPosts) {
|
||||||
set(nav, [lang, type], {
|
set(nav, [lang, type], {
|
||||||
t: type,
|
t: translations[type] ? translations[type] : type,
|
||||||
l: type,
|
l: type,
|
||||||
s: type,
|
s: type,
|
||||||
o: type,
|
o: translations[type] ? translations[type] : type,
|
||||||
})
|
})
|
||||||
for (const [slug, page] of Object.entries(strapiPosts[type][lang])) {
|
for (const [slug, page] of Object.entries(strapiPosts[type][lang])) {
|
||||||
const chunks = slug.split('/')
|
const chunks = slug.split('/')
|
||||||
|
|
|
@ -7,22 +7,22 @@
|
||||||
@layer components {
|
@layer components {
|
||||||
/* Applied styles for common HTML tags */
|
/* Applied styles for common HTML tags */
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-base-content text-4xl py-5 font-bold lg:text-6xl font-light;
|
@apply text-base-content text-4xl py-5 font-bold lg:text-6xl font-black;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
@apply text-base-content text-3xl py-4 pb-2 mb-1 font-light lg:text-4xl border-b-2 border-base-200;
|
@apply text-base-content text-3xl pt-4 pb-3 m-0 font-black lg:text-4xl border-b-2 border-base-200;
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
@apply text-base-content text-2xl py-3 font-light lg:text-3xl;
|
@apply text-base-content text-2xl pt-3 pb-2 m-0 font-black lg:text-3xl;
|
||||||
}
|
}
|
||||||
h4 {
|
h4 {
|
||||||
@apply text-base-content text-xl py-2 font-medium lg:text-2xl;
|
@apply text-base-content text-xl pt-2 pb-1 m-0 font-black lg:text-2xl;
|
||||||
}
|
}
|
||||||
h5 {
|
h5 {
|
||||||
@apply text-base-content text-lg py-1 font-medium lg:text-xl;
|
@apply text-base-content text-lg py-1 m-0 font-black lg:text-xl;
|
||||||
}
|
}
|
||||||
h6 {
|
h6 {
|
||||||
@apply text-base-content text-base font-medium lg:text-lg;
|
@apply text-base-content text-base py-0 m-0 font-black lg:text-lg;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
@apply text-base-content my-1 py-2 text-base leading-6;
|
@apply text-base-content my-1 py-2 text-base leading-6;
|
||||||
|
@ -36,6 +36,17 @@
|
||||||
max-height: 80vh;
|
max-height: 80vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Keep spacing after headings between p and non-p consistent */
|
||||||
|
h1 + p,
|
||||||
|
h2 + p,
|
||||||
|
h3 + p,
|
||||||
|
h4 + p,
|
||||||
|
h5 + p,
|
||||||
|
h6 + p {
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* mdx styles */
|
/* mdx styles */
|
||||||
.mdx a {
|
.mdx a {
|
||||||
@apply text-secondary underline decoration-1;
|
@apply text-secondary underline decoration-1;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue