wip(shared): Changes to layouts
This will break the org build, but we need to rip out sanity anyway so I don't think it's worth obsessing over it now. I've essentially changes the default layout and added a new navigation component.
This commit is contained in:
parent
8b79de2bd6
commit
5a9f2f8d40
26 changed files with 318 additions and 172 deletions
|
@ -16,6 +16,7 @@ import {
|
||||||
MeasieIcon,
|
MeasieIcon,
|
||||||
PageIcon,
|
PageIcon,
|
||||||
PlusIcon,
|
PlusIcon,
|
||||||
|
RssIcon,
|
||||||
} from 'shared/components/icons.mjs'
|
} from 'shared/components/icons.mjs'
|
||||||
import { HeaderWrapper } from 'shared/components/wrappers/header.mjs'
|
import { HeaderWrapper } from 'shared/components/wrappers/header.mjs'
|
||||||
import { ModalThemePicker, ns as themeNs } from 'shared/components/modal/theme-picker.mjs'
|
import { ModalThemePicker, ns as themeNs } from 'shared/components/modal/theme-picker.mjs'
|
||||||
|
@ -40,20 +41,20 @@ const NavIcons = ({ setModal, setSearch }) => {
|
||||||
<DesignIcon className={iconSize} />
|
<DesignIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton
|
<NavButton
|
||||||
href="/patterns"
|
href="/docs"
|
||||||
label={t('header:patterns')}
|
label={t('header:docs')}
|
||||||
color={colors[2]}
|
color={colors[2]}
|
||||||
extraClasses="hidden lg:flex"
|
extraClasses="hidden lg:flex"
|
||||||
>
|
>
|
||||||
<PageIcon className={iconSize} />
|
<DocsIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton
|
<NavButton
|
||||||
href="/sets"
|
href="/blog"
|
||||||
label={t('header:sets')}
|
label={t('header:blog')}
|
||||||
color={colors[3]}
|
color={colors[3]}
|
||||||
extraClasses="hidden lg:flex"
|
extraClasses="hidden lg:flex"
|
||||||
>
|
>
|
||||||
<MeasieIcon className={iconSize} />
|
<RssIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton
|
<NavButton
|
||||||
href="/showcase"
|
href="/showcase"
|
||||||
|
@ -63,39 +64,44 @@ const NavIcons = ({ setModal, setSearch }) => {
|
||||||
>
|
>
|
||||||
<ShowcaseIcon className={iconSize} />
|
<ShowcaseIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
|
<NavSpacer />
|
||||||
<NavButton
|
<NavButton
|
||||||
href="/docs"
|
href="/patterns"
|
||||||
label={t('header:docs')}
|
label={t('header:patterns')}
|
||||||
color={colors[5]}
|
color={colors[5]}
|
||||||
extraClasses="hidden lg:flex"
|
extraClasses="hidden lg:flex"
|
||||||
>
|
>
|
||||||
<DocsIcon className={iconSize} />
|
<PageIcon className={iconSize} />
|
||||||
|
</NavButton>
|
||||||
|
<NavButton
|
||||||
|
href="/sets"
|
||||||
|
label={t('header:sets')}
|
||||||
|
color={colors[6]}
|
||||||
|
extraClasses="hidden lg:flex"
|
||||||
|
>
|
||||||
|
<MeasieIcon className={iconSize} />
|
||||||
|
</NavButton>
|
||||||
|
<NavButton href="/account" label={t('header:account')} color={colors[7]}>
|
||||||
|
<UserIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavSpacer />
|
<NavSpacer />
|
||||||
<NavButton
|
<NavButton
|
||||||
onClick={() => setModal(<ModalThemePicker />)}
|
onClick={() => setModal(<ModalThemePicker />)}
|
||||||
label={t('header:theme')}
|
label={t('header:theme')}
|
||||||
color={colors[6]}
|
color={colors[8]}
|
||||||
>
|
>
|
||||||
<ThemeIcon className={iconSize} />
|
<ThemeIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton
|
<NavButton
|
||||||
onClick={() => setModal(<ModalLocalePicker />)}
|
onClick={() => setModal(<ModalLocalePicker />)}
|
||||||
label={t('header:language')}
|
label={t('header:language')}
|
||||||
color={colors[7]}
|
color={colors[9]}
|
||||||
>
|
>
|
||||||
<I18nIcon className={iconSize} />
|
<I18nIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavButton onClick={() => setSearch(true)} label={t('header:search')} color={colors[8]}>
|
<NavButton onClick={() => setSearch(true)} label={t('header:search')} color={colors[10]}>
|
||||||
<SearchIcon className={iconSize} />
|
<SearchIcon className={iconSize} />
|
||||||
</NavButton>
|
</NavButton>
|
||||||
<NavSpacer />
|
|
||||||
<NavButton href="/account" label={t('header:account')} color={colors[9]}>
|
|
||||||
<UserIcon className={iconSize} />
|
|
||||||
</NavButton>
|
|
||||||
<NavButton href="/new" label={t('header:new')} color={colors[10]}>
|
|
||||||
<PlusIcon className={iconSize} />
|
|
||||||
</NavButton>
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
|
|
||||||
|
|
||||||
export const ns = []
|
export const ns = []
|
||||||
|
|
||||||
export const BareLayout = (props) => (
|
export const BareLayout = (props) => props.children
|
||||||
<>
|
|
||||||
<AsideNavigation mobileOnly />
|
|
||||||
{props.children}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,26 +1,43 @@
|
||||||
|
// Hooks
|
||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
// Components
|
import { useNavigation } from 'site/hooks/use-navigation.mjs'
|
||||||
import { AsideNavigation, ns as navNs } from 'shared/components/navigation/aside.mjs'
|
// Context
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
|
||||||
import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
||||||
|
// Components
|
||||||
|
//import { AsideNavigation, ns as navNs } from 'shared/components/navigation/aside.mjs'
|
||||||
|
//import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
||||||
|
//import { NavigationContext } from 'shared/context/navigation-context.mjs'
|
||||||
|
|
||||||
export const ns = navNs
|
import { BaseLayout, BaseLayoutLeft, BaseLayoutWide } from 'shared/components/base-layout.mjs'
|
||||||
|
import { NavLinks, Breadcrumbs, MainSections } from 'shared/components/navigation/sitenav.mjs'
|
||||||
|
|
||||||
export const DefaultLayout = ({ children = [], pageTitle = false }) => {
|
export const ns = [] //navNs
|
||||||
const { crumbs } = useContext(NavigationContext)
|
|
||||||
|
export const DefaultLayout = ({ children = [], slug, pageTitle = false }) => {
|
||||||
|
const { siteNav } = useNavigation({ ignoreControl: true })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-4 mx-auto justify-center place-items-stretch">
|
<BaseLayout>
|
||||||
<AsideNavigation />
|
<BaseLayoutLeft>
|
||||||
<section className="col-span-4 lg:col-span-3 py-8 lg:py-24 px-4 lg:pl-8 bg-base-50">
|
{slug ? (
|
||||||
|
<>
|
||||||
|
<MainSections {...{ siteNav, slug }} />
|
||||||
|
<NavLinks {...{ siteNav, slug }} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<p>Slug not passed to layout</p>
|
||||||
|
)}
|
||||||
|
</BaseLayoutLeft>
|
||||||
|
|
||||||
|
<BaseLayoutWide>
|
||||||
{pageTitle && (
|
{pageTitle && (
|
||||||
<div className="xl:pl-4">
|
<div className="xl:pl-4">
|
||||||
<Breadcrumbs crumbs={crumbs} title={pageTitle} />
|
{slug && <Breadcrumbs {...{ siteNav, slug }} />}
|
||||||
<h1 className="break-words">{pageTitle}</h1>
|
<h1 className="break-words">{pageTitle}</h1>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="xl:pl-4">{children}</div>
|
<div className="xl:pl-4">{children}</div>
|
||||||
</section>
|
</BaseLayoutWide>
|
||||||
</div>
|
</BaseLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
69
sites/org/components/layouts/docs.mjs
Normal file
69
sites/org/components/layouts/docs.mjs
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// Hooks
|
||||||
|
import { useNavigation } from 'site/hooks/use-navigation.mjs'
|
||||||
|
// Components
|
||||||
|
import Head from 'next/head'
|
||||||
|
import {
|
||||||
|
BaseLayout,
|
||||||
|
BaseLayoutLeft,
|
||||||
|
BaseLayoutProse,
|
||||||
|
BaseLayoutRight,
|
||||||
|
} from 'shared/components/base-layout.mjs'
|
||||||
|
import { NavLinks, Breadcrumbs, MainSections } from 'shared/components/navigation/sitenav.mjs'
|
||||||
|
import { Toc } from 'shared/components/mdx/toc.mjs'
|
||||||
|
import { MdxMetaData } from 'shared/components/mdx/meta.mjs'
|
||||||
|
import { PrevNext } from 'shared/components/prev-next.mjs'
|
||||||
|
|
||||||
|
export const ns = [] //navNs
|
||||||
|
|
||||||
|
export const DocsLayout = ({ children = [], slug, frontmatter }) => {
|
||||||
|
const { siteNav } = useNavigation({ ignoreControl: true })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<meta property="og:title" content={frontmatter.title} key="title" />
|
||||||
|
<meta property="og:type" content="article" key="type" />
|
||||||
|
<meta property="og:description" content={``} key="type" />
|
||||||
|
<meta property="og:article:author" content="Joost De Cock" key="author" />
|
||||||
|
<meta
|
||||||
|
property="og:image"
|
||||||
|
content={`https://canary.backend.freesewing.org/og-img/en/org/${slug}}`}
|
||||||
|
key="image"
|
||||||
|
/>
|
||||||
|
<meta property="og:image:type" content="image/png" />
|
||||||
|
<meta property="og:image:width" content="1200" />
|
||||||
|
<meta property="og:image:height" content="630" />
|
||||||
|
<meta property="og:url" content={`https://freesewing.org/${slug}`} key="url" />
|
||||||
|
<meta property="og:locale" content="en" key="locale" />
|
||||||
|
<meta property="og:site_name" content="freesewing.org" key="site" />
|
||||||
|
<title>{frontmatter.title} - FreeSewing.org</title>
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<BaseLayout>
|
||||||
|
<BaseLayoutLeft>
|
||||||
|
<MainSections {...{ siteNav, slug }} />
|
||||||
|
<NavLinks {...{ siteNav, slug }} />
|
||||||
|
</BaseLayoutLeft>
|
||||||
|
|
||||||
|
<BaseLayoutProse>
|
||||||
|
<div className="w-full">
|
||||||
|
<Breadcrumbs {...{ siteNav, slug }} />
|
||||||
|
<h1 className="break-words searchme">{frontmatter.title}</h1>
|
||||||
|
<div className="block xl:hidden">
|
||||||
|
<Toc toc={frontmatter.toc} wrap />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{children}
|
||||||
|
<PrevNext slug={slug} noPrev={slug === 'docs'} />
|
||||||
|
</BaseLayoutProse>
|
||||||
|
|
||||||
|
<BaseLayoutRight>
|
||||||
|
<MdxMetaData frontmatter={frontmatter} slug={slug} locale="en" />
|
||||||
|
<div className="hidden xl:block">
|
||||||
|
<Toc toc={frontmatter.toc} wrap />
|
||||||
|
</div>
|
||||||
|
</BaseLayoutRight>
|
||||||
|
</BaseLayout>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,4 +0,0 @@
|
||||||
export const ns = []
|
|
||||||
|
|
||||||
// This layout adds nothing
|
|
||||||
export const NoLayout = ({ children = [] }) => children
|
|
|
@ -17,10 +17,12 @@ export const SanityPageWrapper = ({
|
||||||
author = {},
|
author = {},
|
||||||
page = {},
|
page = {},
|
||||||
namespaces = ['common'],
|
namespaces = ['common'],
|
||||||
|
slug,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation(namespaces)
|
const { t } = useTranslation(namespaces)
|
||||||
|
console.log({ slug })
|
||||||
return (
|
return (
|
||||||
<PageWrapper title={post.title} {...page}>
|
<PageWrapper title={post.title} {...page} slug={slug}>
|
||||||
<Head>
|
<Head>
|
||||||
<meta property="og:type" content="article" key="type" />
|
<meta property="og:type" content="article" key="type" />
|
||||||
<meta property="og:description" content={post.intro || post.title} key="description" />
|
<meta property="og:description" content={post.intro || post.title} key="description" />
|
||||||
|
|
|
@ -14,8 +14,17 @@ import { useRouter } from 'next/router'
|
||||||
* - home page => no navvigation shown
|
* - home page => no navvigation shown
|
||||||
* - /contact => Added below
|
* - /contact => Added below
|
||||||
*
|
*
|
||||||
* Note: Set 'h' to truthy to not show a top-level entry as a section
|
* Remember Mc_Shifton:
|
||||||
* Note: Set 'c' to set the control level to hide things from users
|
* Note: Set 'm' to truthy to show this as a main section in the side-navigation (optional)
|
||||||
|
* Note: Set 'c' to set the control level to hide things from users (optional)
|
||||||
|
* Note: Set 's' to the slug (optional insofar as it's not a real page (a spacer for the header))
|
||||||
|
* Note: Set '_' to never show the page in the site navigation (like the tags pages)
|
||||||
|
* Note: Set 'h' to indicate this is a top-level page that should be hidden from the side-nav (like search)
|
||||||
|
* Note: Set 'i' when something should be included as top-level in the collapse side-navigation (optional)
|
||||||
|
* Note: Set 'f' to add the page to the footer
|
||||||
|
* Note: Set 't' to the title
|
||||||
|
* Note: Set 'o' to set the order (optional)
|
||||||
|
* Note: Set 'n' to mark this as a noisy entry that should always be closed unless active (like blog)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const ns = ['account', 'sections', 'design', 'tags', 'designs']
|
export const ns = ['account', 'sections', 'design', 'tags', 'designs']
|
||||||
|
@ -26,55 +35,59 @@ const sitePages = (t = false, control = 99) => {
|
||||||
const pages = {
|
const pages = {
|
||||||
// Top-level pages that are the sections menu
|
// Top-level pages that are the sections menu
|
||||||
designs: {
|
designs: {
|
||||||
t: t('sections:designs'),
|
m: 1,
|
||||||
s: 'designs',
|
s: 'designs',
|
||||||
o: 10,
|
t: t('sections:designs'),
|
||||||
|
n: 1,
|
||||||
tags: {
|
tags: {
|
||||||
t: t('design:tags'),
|
_: 1,
|
||||||
s: 'designs/tags',
|
s: 'designs/tags',
|
||||||
h: 1,
|
t: t('design:tags'),
|
||||||
o: 'aaa',
|
o: 'aaa',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
patterns: {
|
patterns: {
|
||||||
t: t('sections:patterns'),
|
m: 1,
|
||||||
s: 'patterns',
|
s: 'patterns',
|
||||||
o: 14,
|
t: t('sections:patterns'),
|
||||||
},
|
},
|
||||||
sets: {
|
sets: {
|
||||||
t: t('sections:sets'),
|
m: 1,
|
||||||
s: 'sets',
|
s: 'sets',
|
||||||
o: 16,
|
t: t('sections:sets'),
|
||||||
},
|
},
|
||||||
community: {
|
community: {
|
||||||
t: t('sections:community'),
|
m: 1,
|
||||||
s: 'community',
|
s: 'community',
|
||||||
o: 40,
|
t: t('sections:community'),
|
||||||
},
|
},
|
||||||
account: {
|
account: {
|
||||||
t: t('sections:account'),
|
m: 1,
|
||||||
s: 'account',
|
s: 'account',
|
||||||
o: 99,
|
t: t('sections:account'),
|
||||||
|
n: 1,
|
||||||
},
|
},
|
||||||
// Top-level pages that are not in the sections menu
|
// Top-level pages that are not in the sections menu
|
||||||
apikeys: {
|
apikeys: {
|
||||||
t: t('apikeys'),
|
_: 1,
|
||||||
s: 'apikeys',
|
s: 'apikeys',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('apikeys'),
|
||||||
},
|
},
|
||||||
curate: {
|
curate: {
|
||||||
t: t('curate'),
|
|
||||||
s: 'curate',
|
s: 'curate',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('curate'),
|
||||||
sets: {
|
sets: {
|
||||||
t: t('curateSets'),
|
t: t('curateSets'),
|
||||||
s: 'curate/sets',
|
s: 'curate/sets',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
new: {
|
new: {
|
||||||
t: t('new'),
|
m: 1,
|
||||||
s: 'new',
|
s: 'new',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('new'),
|
||||||
pattern: {
|
pattern: {
|
||||||
t: t('patternNew'),
|
t: t('patternNew'),
|
||||||
s: 'new/pattern',
|
s: 'new/pattern',
|
||||||
|
@ -87,56 +100,54 @@ const sitePages = (t = false, control = 99) => {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
profile: {
|
profile: {
|
||||||
t: t('yourProfile'),
|
|
||||||
s: 'profile',
|
s: 'profile',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('yourProfile'),
|
||||||
},
|
},
|
||||||
translation: {
|
translation: {
|
||||||
t: t('translation'),
|
|
||||||
s: 'translation',
|
s: 'translation',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('translation'),
|
||||||
join: {
|
join: {
|
||||||
t: t('translation:joinATranslationTeam'),
|
t: t('translation:joinATranslationTeam'),
|
||||||
s: 'translation',
|
s: 'translation',
|
||||||
h: 1,
|
|
||||||
},
|
},
|
||||||
'suggest-language': {
|
'suggest-language': {
|
||||||
t: t('translation:suggestLanguage'),
|
t: t('translation:suggestLanguage'),
|
||||||
s: 'translation',
|
s: 'translation',
|
||||||
h: 1,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
sitemap: {
|
sitemap: {
|
||||||
t: t('sitemap'),
|
|
||||||
s: 'sitemap',
|
s: 'sitemap',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: t('sitemap'),
|
||||||
},
|
},
|
||||||
|
|
||||||
// Not translated, this is a developer page
|
// Not translated, this is a developer page
|
||||||
typography: {
|
typography: {
|
||||||
t: 'Typography',
|
|
||||||
s: 'typography',
|
s: 'typography',
|
||||||
h: 1,
|
h: 1,
|
||||||
|
t: 'Typography',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for (const section in conf.account.fields) {
|
for (const section in conf.account.fields) {
|
||||||
for (const [field, controlScore] of Object.entries(conf.account.fields[section])) {
|
for (const [field, controlScore] of Object.entries(conf.account.fields[section])) {
|
||||||
if (Number(control) >= controlScore)
|
if (Number(control) >= controlScore)
|
||||||
pages.account[field] = {
|
pages.account[field] = {
|
||||||
t: t(`account:${field}`),
|
|
||||||
s: `account/${field}`,
|
s: `account/${field}`,
|
||||||
|
t: t(`account:${field}`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Number(control) >= conf.account.fields.developer.apikeys)
|
if (Number(control) >= conf.account.fields.developer.apikeys)
|
||||||
pages.new.apikey = {
|
pages.new.apikey = {
|
||||||
t: t('newApikey'),
|
|
||||||
s: 'new/apikey',
|
s: 'new/apikey',
|
||||||
|
t: t('newApikey'),
|
||||||
o: 30,
|
o: 30,
|
||||||
}
|
}
|
||||||
pages.account.reload = {
|
pages.account.reload = {
|
||||||
t: t(`account:reload`),
|
|
||||||
s: `account/reload`,
|
s: `account/reload`,
|
||||||
|
t: t(`account:reload`),
|
||||||
}
|
}
|
||||||
for (const design in designs) {
|
for (const design in designs) {
|
||||||
// pages.designs[design] = {
|
// pages.designs[design] = {
|
||||||
|
@ -144,21 +155,22 @@ const sitePages = (t = false, control = 99) => {
|
||||||
// s: `designs/${design}`,
|
// s: `designs/${design}`,
|
||||||
// }
|
// }
|
||||||
pages.new.pattern[design] = {
|
pages.new.pattern[design] = {
|
||||||
t: t(`account:generateANewThing`, { thing: t(`designs:${design}.t`) }),
|
|
||||||
s: `new/${design}`,
|
s: `new/${design}`,
|
||||||
|
t: t(`account:generateANewThing`, { thing: t(`designs:${design}.t`) }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
pages.designs.tags[tag] = {
|
pages.designs.tags[tag] = {
|
||||||
t: t(`tags:${tag}`),
|
|
||||||
s: `designs/tags/${tag}`,
|
s: `designs/tags/${tag}`,
|
||||||
|
t: t(`tags:${tag}`),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pages
|
return pages
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useNavigation = ({ ignoreControl = false }, extra = []) => {
|
export const useNavigation = (param = {}, extra = []) => {
|
||||||
|
const { ignoreControl = false } = param
|
||||||
// Passing in the locale is not very DRY so let's just grab it from the router
|
// Passing in the locale is not very DRY so let's just grab it from the router
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
// We need translation
|
// We need translation
|
||||||
|
@ -174,8 +186,23 @@ export const useNavigation = ({ ignoreControl = false }, extra = []) => {
|
||||||
objUpdate(siteNav, _path, _data)
|
objUpdate(siteNav, _path, _data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set order on docs key (from from prebuild siteNav)
|
// Apply some tweaks
|
||||||
siteNav.docs.o = 30
|
siteNav.blog.m = 1
|
||||||
|
siteNav.blog.n = 1
|
||||||
|
siteNav.showcase.m = 1
|
||||||
|
siteNav.showcase.n = 1
|
||||||
|
siteNav.docs.m = 1
|
||||||
|
|
||||||
|
// Set order on main sections
|
||||||
|
siteNav.designs.o = 10
|
||||||
|
siteNav.docs.o = 20
|
||||||
|
siteNav.blog.o = 30
|
||||||
|
siteNav.showcase.o = 40
|
||||||
|
siteNav.community.o = 50
|
||||||
|
siteNav.patterns.o = 60
|
||||||
|
siteNav.sets.o = 70
|
||||||
|
siteNav.account.o = 80
|
||||||
|
siteNav.new.o = 90
|
||||||
|
|
||||||
return {
|
return {
|
||||||
siteNav, // Site navigation
|
siteNav, // Site navigation
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { Spinner } from 'shared/components/spinner.mjs'
|
||||||
import { components } from 'shared/components/mdx/index.mjs'
|
import { components } from 'shared/components/mdx/index.mjs'
|
||||||
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
|
import { MdxWrapper } from 'shared/components/wrappers/mdx.mjs'
|
||||||
import { Toc } from 'shared/components/mdx/toc.mjs'
|
import { Toc } from 'shared/components/mdx/toc.mjs'
|
||||||
|
import { DocsLayout } from 'site/components/layouts/docs.mjs'
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PLEASE READ THIS BEFORE YOU TRY TO REFACTOR THIS PAGE
|
* PLEASE READ THIS BEFORE YOU TRY TO REFACTOR THIS PAGE
|
||||||
|
@ -61,7 +62,11 @@ const HeadInfo = ({ frontmatter, locale, slug }) => (
|
||||||
)
|
)
|
||||||
|
|
||||||
export const Page = ({ page, frontmatter, slug, locale, MDX }) => (
|
export const Page = ({ page, frontmatter, slug, locale, MDX }) => (
|
||||||
<PageWrapper {...page} title={frontmatter.title}>
|
<PageWrapper
|
||||||
|
{...page}
|
||||||
|
title={frontmatter.title}
|
||||||
|
layout={(props) => <DocsLayout {...props} {...{ slug, frontmatter }} />}
|
||||||
|
>
|
||||||
<HeadInfo {...{ frontmatter, locale, slug }} />
|
<HeadInfo {...{ frontmatter, locale, slug }} />
|
||||||
<div className="flex flex-row-reverse flex-wrap xl:flex-nowrap justify-end">
|
<div className="flex flex-row-reverse flex-wrap xl:flex-nowrap justify-end">
|
||||||
{frontmatter.toc && frontmatter.toc.length > 0 && (
|
{frontmatter.toc && frontmatter.toc.length > 0 && (
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
// Components
|
// Components
|
||||||
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
||||||
import { BareLayout as Layout } from 'site/components/layouts/bare.mjs'
|
|
||||||
import { TranslationStatus } from 'site/components/crowdin/status.mjs'
|
import { TranslationStatus } from 'site/components/crowdin/status.mjs'
|
||||||
import { Translators } from 'site/components/crowdin/translators.mjs'
|
import { Translators } from 'site/components/crowdin/translators.mjs'
|
||||||
import { Popout } from 'shared/components/popout.mjs'
|
import { Popout } from 'shared/components/popout.mjs'
|
||||||
|
@ -20,26 +19,29 @@ const TranslationPage = ({ page }) => {
|
||||||
const title = t('translation:translation')
|
const title = t('translation:translation')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} layout={Layout}>
|
<PageWrapper {...page} title={title}>
|
||||||
<div className="max-w-4xl mx-auto p-4 mt-4">
|
<div className="max-w-2xl">
|
||||||
<Breadcrumbs crumbs={[{ s: 'translation', t: title }]} title={title} />
|
|
||||||
|
|
||||||
<h1>{title}</h1>
|
|
||||||
<p>{t('translation:proudlyMultilingual')}</p>
|
<p>{t('translation:proudlyMultilingual')}</p>
|
||||||
|
|
||||||
|
<div className="max-w-2xl">
|
||||||
<Popout tip>
|
<Popout tip>
|
||||||
<h5>{t('translation:getInvolved')}</h5>
|
<h5>{t('translation:getInvolved')}</h5>
|
||||||
<p>{t('translation:teamEffort')}</p>
|
<p>{t('translation:teamEffort')}</p>
|
||||||
|
<p>
|
||||||
<Link href="/translation/join" className="btn btn-accent mr-2">
|
<Link href="/translation/join" className="btn btn-accent mr-2">
|
||||||
{t('translation:joinTheTeam')}
|
{t('translation:joinTheTeam')}
|
||||||
</Link>
|
</Link>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
<a
|
<a
|
||||||
href="https://freesewing.dev/guides/translation"
|
href="https://freesewing.dev/guides/translation"
|
||||||
className="btn btn-accent btn-outline"
|
className="btn btn-accent btn-outline"
|
||||||
>
|
>
|
||||||
{t('translation:seeTranslationGuide')}
|
{t('translation:seeTranslationGuide')}
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</Popout>
|
</Popout>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2 id="status">Translation Status</h2>
|
<h2 id="status">Translation Status</h2>
|
||||||
<TranslationStatus />
|
<TranslationStatus />
|
||||||
|
@ -91,6 +93,7 @@ const TranslationPage = ({ page }) => {
|
||||||
<b>{t('locales:uk')}</b>
|
<b>{t('locales:uk')}</b>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div className="max-w-3xl">
|
||||||
<Popout tip>
|
<Popout tip>
|
||||||
<h5>{t('translation:addLanguage1')}</h5>
|
<h5>{t('translation:addLanguage1')}</h5>
|
||||||
<p>
|
<p>
|
||||||
|
@ -98,17 +101,22 @@ const TranslationPage = ({ page }) => {
|
||||||
<br />
|
<br />
|
||||||
{t('translation:addLanguage3')}
|
{t('translation:addLanguage3')}
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
<Link href="/translation/suggest-language" className="btn btn-accent mr-2">
|
<Link href="/translation/suggest-language" className="btn btn-accent mr-2">
|
||||||
{t('translation:suggestLanguage')}
|
{t('translation:suggestLanguage')}
|
||||||
</Link>
|
</Link>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
<a
|
<a
|
||||||
href="https://freesewing.dev/guides/translation"
|
href="https://freesewing.dev/guides/translation"
|
||||||
className="btn btn-accent btn-outline"
|
className="btn btn-accent btn-outline"
|
||||||
>
|
>
|
||||||
{t('translation:seeTranslationGuide')}
|
{t('translation:seeTranslationGuide')}
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
</Popout>
|
</Popout>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
// Components
|
// Components
|
||||||
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
||||||
import { BareLayout as Layout } from 'site/components/layouts/bare.mjs'
|
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
|
||||||
|
|
||||||
// Translation namespaces used on this page
|
// Translation namespaces used on this page
|
||||||
const namespaces = [...new Set(pageNs), 'translation', 'locales']
|
const namespaces = [...new Set(pageNs), 'translation', 'locales']
|
||||||
|
@ -31,17 +29,7 @@ const TranslationJoinPage = ({ page }) => {
|
||||||
const title = t('translation:joinATranslationTeam')
|
const title = t('translation:joinATranslationTeam')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} layout={Layout}>
|
<PageWrapper {...page} title={title}>
|
||||||
<div className="max-w-4xl mx-auto p-4 mt-4">
|
|
||||||
<Breadcrumbs
|
|
||||||
crumbs={[
|
|
||||||
{ s: 'translation', t: t('translation:translation') },
|
|
||||||
{ s: 'translation/join', t: title },
|
|
||||||
]}
|
|
||||||
title={title}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h1>{title}</h1>
|
|
||||||
<p>
|
<p>
|
||||||
{t('translation:joinIntro')}
|
{t('translation:joinIntro')}
|
||||||
<br />
|
<br />
|
||||||
|
@ -50,7 +38,6 @@ const TranslationJoinPage = ({ page }) => {
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<DynamicForm />
|
<DynamicForm />
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
</div>
|
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
// Components
|
// Components
|
||||||
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
import { PageWrapper, ns as pageNs } from 'shared/components/wrappers/page.mjs'
|
||||||
import { BareLayout as Layout } from 'site/components/layouts/bare.mjs'
|
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
|
||||||
|
|
||||||
// Translation namespaces used on this page
|
// Translation namespaces used on this page
|
||||||
const namespaces = [...new Set(pageNs), 'translation', 'locales']
|
const namespaces = [...new Set(pageNs), 'translation', 'locales']
|
||||||
|
@ -32,17 +30,8 @@ const SuggestLanguagePage = ({ page }) => {
|
||||||
const title = t('translation:suggestLanguage')
|
const title = t('translation:suggestLanguage')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} layout={Layout}>
|
<PageWrapper {...page} title={title}>
|
||||||
<div className="max-w-4xl mx-auto p-4 mt-4">
|
<div className="max-w-2xl">
|
||||||
<Breadcrumbs
|
|
||||||
crumbs={[
|
|
||||||
{ s: 'translation', t: t('translation:translation') },
|
|
||||||
{ s: 'translation/join', t: title },
|
|
||||||
]}
|
|
||||||
title={title}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<h1>{title}</h1>
|
|
||||||
<p>
|
<p>
|
||||||
{t('translation:suggestIntro')}
|
{t('translation:suggestIntro')}
|
||||||
<br />
|
<br />
|
||||||
|
|
|
@ -32,7 +32,7 @@ const DynamicBio = dynamic(
|
||||||
const WelcomeBioPage = ({ page }) => (
|
const WelcomeBioPage = ({ page }) => (
|
||||||
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicBio title welcome />
|
<DynamicBio title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -32,7 +32,7 @@ const DynamicCompare = dynamic(
|
||||||
const WelcomeComparePage = ({ page }) => (
|
const WelcomeComparePage = ({ page }) => (
|
||||||
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicCompare title welcome />
|
<DynamicCompare title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -37,7 +37,7 @@ const WelcomeImgPage = ({ page }) => {
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} title={t('imgTitle')} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} title={t('imgTitle')} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicImg title welcome />
|
<DynamicImg title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -32,7 +32,7 @@ const DynamicControl = dynamic(
|
||||||
const WelcomePage = ({ page }) => (
|
const WelcomePage = ({ page }) => (
|
||||||
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicControl title welcome />
|
<DynamicControl title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -38,7 +38,7 @@ const WelcomeNewsletterPage = ({ page }) => {
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} title={t('title')} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} title={t('title')} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicNewsletter title welcome />
|
<DynamicNewsletter title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -32,7 +32,7 @@ const DynamicImperial = dynamic(
|
||||||
const WelcomeUnitsPage = ({ page }) => (
|
const WelcomeUnitsPage = ({ page }) => (
|
||||||
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicImperial title welcome />
|
<DynamicImperial title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
|
@ -37,7 +37,7 @@ const WelcomeUsernamePage = ({ page }) => {
|
||||||
return (
|
return (
|
||||||
<PageWrapper {...page} title={t('title')} layout={BareLayout} footer={false}>
|
<PageWrapper {...page} title={t('title')} layout={BareLayout} footer={false}>
|
||||||
<DynamicAuthWrapper>
|
<DynamicAuthWrapper>
|
||||||
<div className="m-auto max-w-lg text-center lg:mt-24 p-8">
|
<div className="m-auto max-w-lg text-center lg:mt-4 p-8">
|
||||||
<DynamicUsername title welcome />
|
<DynamicUsername title welcome />
|
||||||
</div>
|
</div>
|
||||||
</DynamicAuthWrapper>
|
</DynamicAuthWrapper>
|
||||||
|
|
36
sites/shared/components/base-layout.mjs
Normal file
36
sites/shared/components/base-layout.mjs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* The default full-page FreeSewing layout
|
||||||
|
*/
|
||||||
|
export const BaseLayout = ({ children = [] }) => (
|
||||||
|
<div className="flex flex-row items-start mt-8 w-full justify-between 2xl:px-36 xl:px-12 px-4">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The left column of the default layout
|
||||||
|
*/
|
||||||
|
export const BaseLayoutLeft = ({ children = [] }) => (
|
||||||
|
<div className="max-w-96 w-1/4 mt-8 hidden lg:block shrink-0">{children}</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The right column of the default layout
|
||||||
|
*/
|
||||||
|
export const BaseLayoutRight = ({ children = [] }) => (
|
||||||
|
<div className="max-w-96 w-1/4 mt-8 hidden xl:block">{children}</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main column for prose (text like docs and so on)
|
||||||
|
*/
|
||||||
|
export const BaseLayoutProse = ({ children = [] }) => (
|
||||||
|
<div className="grow w-full m-auto max-w-prose mt-0 mb-8">{children}</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The central column for wide content (no max-width)
|
||||||
|
*/
|
||||||
|
export const BaseLayoutWide = ({ children = [] }) => (
|
||||||
|
<div className="grow w-full m-auto mt-0 mb-8 grow">{children}</div>
|
||||||
|
)
|
|
@ -9,11 +9,13 @@ import { Pattern, PatternXray } from '@freesewing/react-components'
|
||||||
|
|
||||||
// Get code from children
|
// Get code from children
|
||||||
export const asText = (reactEl) => {
|
export const asText = (reactEl) => {
|
||||||
|
if (reactEl) {
|
||||||
if (typeof reactEl.props.children === 'string') return reactEl.props.children
|
if (typeof reactEl.props.children === 'string') return reactEl.props.children
|
||||||
if (Array.isArray(reactEl.props.children)) {
|
if (Array.isArray(reactEl.props.children)) {
|
||||||
return reactEl.props.children.map((el) => (typeof el === 'string' ? el : asText(el))).join('')
|
return reactEl.props.children.map((el) => (typeof el === 'string' ? el : asText(el))).join('')
|
||||||
}
|
}
|
||||||
if (typeof reactEl.props.children === 'object') return asText(reactEl.props.children)
|
if (typeof reactEl.props.children === 'object') return asText(reactEl.props.children)
|
||||||
|
}
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
FreeSewingIcon,
|
FreeSewingIcon,
|
||||||
HeartIcon,
|
HeartIcon,
|
||||||
BulletIcon,
|
BulletIcon,
|
||||||
|
PlusIcon,
|
||||||
GitHubIcon,
|
GitHubIcon,
|
||||||
} from 'shared/components/icons.mjs'
|
} from 'shared/components/icons.mjs'
|
||||||
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
import { Breadcrumbs } from 'shared/components/breadcrumbs.mjs'
|
||||||
|
@ -43,6 +44,7 @@ export const icons = {
|
||||||
community: (className = '') => <CommunityIcon className={className} />,
|
community: (className = '') => <CommunityIcon className={className} />,
|
||||||
sets: (className = '') => <MeasieIcon className={className} />,
|
sets: (className = '') => <MeasieIcon className={className} />,
|
||||||
patterns: (className = '') => <PageIcon className={className} />,
|
patterns: (className = '') => <PageIcon className={className} />,
|
||||||
|
new: (className = '') => <PlusIcon className={className} />,
|
||||||
|
|
||||||
// Lab
|
// Lab
|
||||||
code: (className = '') => <GitHubIcon className={className} />,
|
code: (className = '') => <GitHubIcon className={className} />,
|
||||||
|
|
|
@ -4,7 +4,7 @@ showcase: Showcase
|
||||||
showcaseAbout: Examples and inspiration from the FreeSewing community using our designs
|
showcaseAbout: Examples and inspiration from the FreeSewing community using our designs
|
||||||
docs: Documentation
|
docs: Documentation
|
||||||
docsAbout: In-depth documenation for all our designs, our website, and much more
|
docsAbout: In-depth documenation for all our designs, our website, and much more
|
||||||
account: Account
|
account: Your Account
|
||||||
accountAbout: Manage your account settings and preferences, and your presonal data
|
accountAbout: Manage your account settings and preferences, and your presonal data
|
||||||
designs: Designs
|
designs: Designs
|
||||||
designsAbout: Our library of designs that you can turn into made-to-measure patterns with a few clicks
|
designsAbout: Our library of designs that you can turn into made-to-measure patterns with a few clicks
|
||||||
|
@ -24,12 +24,12 @@ referenceAbout: Reference holds technical descriptions of the underlying technol
|
||||||
trainingAbout: Training materials are the most in-depth and strive to teach you a new skill.
|
trainingAbout: Training materials are the most in-depth and strive to teach you a new skill.
|
||||||
mainSections: Main sections
|
mainSections: Main sections
|
||||||
currentSection: Current section
|
currentSection: Current section
|
||||||
sets: Measurements Sets
|
sets: Your Measurements Sets
|
||||||
patterns: Patterns
|
patterns: Your Patterns
|
||||||
curate: Curate
|
curate: Curate
|
||||||
curateSets: Curate Sets
|
curateSets: Curate Sets
|
||||||
code: Code
|
code: Code
|
||||||
patternsAbout: Lists the patterns that you have stored in your FreeSewing account
|
patternsAbout: Lists the patterns that you have stored in your FreeSewing account
|
||||||
setsAbout: Lists the measurements sets that you have stored in your FreeSewing account
|
setsAbout: Lists the measurements sets that you have stored in your FreeSewing account
|
||||||
codeAbout: Here you can find (links to) the Freesewing source code
|
codeAbout: Here you can find (links to) the Freesewing source code
|
||||||
|
new: New...
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { icons } from 'shared/components/navigation/primary.mjs'
|
||||||
*/
|
*/
|
||||||
const onlyValidChildren = (tree, hIsOk = false) =>
|
const onlyValidChildren = (tree, hIsOk = false) =>
|
||||||
orderBy(tree, ['o', 't'], ['asc', 'asc']).filter(
|
orderBy(tree, ['o', 't'], ['asc', 'asc']).filter(
|
||||||
(entry) => typeof entry === 'object' && entry.t !== 'spacer' && !entry.h && !entry.m
|
(entry) => typeof entry === 'object' && entry.t !== 'spacer' && !entry.h
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -39,7 +39,7 @@ const onlyMainSections = (tree) =>
|
||||||
orderBy(tree, ['o', 't'], ['asc', 'asc']).filter((entry) => entry.m)
|
orderBy(tree, ['o', 't'], ['asc', 'asc']).filter((entry) => entry.m)
|
||||||
|
|
||||||
const SectionLink = ({ skey, tree, slug }) =>
|
const SectionLink = ({ skey, tree, slug }) =>
|
||||||
tree[skey].s === slug ? (
|
tree[skey]._ ? null : tree[skey].s === slug ? ( // Underscore means always hide
|
||||||
<>
|
<>
|
||||||
<span className="pl-2 border-l-2 py-2 block w-full border-secondary bg-opacity-10">
|
<span className="pl-2 border-l-2 py-2 block w-full border-secondary bg-opacity-10">
|
||||||
{tree[skey].t}
|
{tree[skey].t}
|
||||||
|
@ -189,7 +189,7 @@ export const NavLinks = ({ slug, siteNav, ignoreControl = false }) => (
|
||||||
{onlyValidChildren(siteNav).map((page, i) => (
|
{onlyValidChildren(siteNav).map((page, i) => (
|
||||||
<li key={i} className="w-full">
|
<li key={i} className="w-full">
|
||||||
<MainLink s={page.s} t={page.t} slug={slug} />
|
<MainLink s={page.s} t={page.t} slug={slug} />
|
||||||
{pageHasChildren(page) && <Section {...{ tree: page, slug }} />}
|
{pageHasChildren(page) && !page.n && <Section {...{ tree: page, slug }} />}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -31,7 +31,7 @@ const NextPage = ({ t, s }) =>
|
||||||
<span></span>
|
<span></span>
|
||||||
)
|
)
|
||||||
|
|
||||||
export const PrevNext = ({ slug }) => {
|
export const PrevNext = ({ slug, noPrev = false }) => {
|
||||||
// Grab site navigation and slug lookup table from the useNavigatin hook
|
// Grab site navigation and slug lookup table from the useNavigatin hook
|
||||||
const { siteNav, slugLut } = useNavigation()
|
const { siteNav, slugLut } = useNavigation()
|
||||||
|
|
||||||
|
@ -42,13 +42,13 @@ export const PrevNext = ({ slug }) => {
|
||||||
const iNext = index === slugLut.length - 1 ? 0 : index + 1
|
const iNext = index === slugLut.length - 1 ? 0 : index + 1
|
||||||
|
|
||||||
// Subtract 1 for the previous page, unless it's the first page
|
// Subtract 1 for the previous page, unless it's the first page
|
||||||
const iPrev = index === 0 ? slugLut.length - 1 : index - 1
|
const iPrev = noPrev ? false : index === 0 ? slugLut.length - 1 : index - 1
|
||||||
|
|
||||||
// Get the next page from the siteNav object
|
// Get the next page from the siteNav object
|
||||||
const next = get(siteNav, slugLut[iNext].split('/'))
|
const next = get(siteNav, slugLut[iNext].split('/'))
|
||||||
|
|
||||||
// Get the previous page from the siteNav object
|
// Get the previous page from the siteNav object
|
||||||
const prev = get(siteNav, slugLut[iPrev].split('/'))
|
const prev = noPrev ? false : get(siteNav, slugLut[iPrev].split('/'))
|
||||||
|
|
||||||
// Return content
|
// Return content
|
||||||
return (
|
return (
|
||||||
|
@ -58,7 +58,7 @@ export const PrevNext = ({ slug }) => {
|
||||||
'items-start pt-6 mt-6 border-t-2 border-solid border-r-0 border-l-0 border-b-0'
|
'items-start pt-6 mt-6 border-t-2 border-solid border-r-0 border-l-0 border-b-0'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<PrevPage t={prev.t} s={prev.s} />
|
{noPrev ? <span /> : <PrevPage t={prev.t} s={prev.s} />}
|
||||||
<NextPage t={next.t} s={next.s} />
|
<NextPage t={next.t} s={next.s} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,6 +12,7 @@ export const LayoutWrapper = ({
|
||||||
setSearch,
|
setSearch,
|
||||||
noSearch = false,
|
noSearch = false,
|
||||||
header = false,
|
header = false,
|
||||||
|
footer = true,
|
||||||
}) => {
|
}) => {
|
||||||
const ChosenHeader = header ? header : Header
|
const ChosenHeader = header ? header : Header
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ export const LayoutWrapper = ({
|
||||||
<div className="fixed top-0 left-0 w-full min-h-screen bg-neutral z-20 bg-opacity-70"></div>
|
<div className="fixed top-0 left-0 w-full min-h-screen bg-neutral z-20 bg-opacity-70"></div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Footer />
|
{footer && <Footer />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,17 @@ export const PageWrapper = (props) => {
|
||||||
// Title is typically set in props.t but check props.title too
|
// Title is typically set in props.t but check props.title too
|
||||||
const pageTitle = props.t ? props.t : props.title ? props.title : null
|
const pageTitle = props.t ? props.t : props.title ? props.title : null
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slug should come from page props.path not from context
|
||||||
|
* which won't be available in SSR
|
||||||
|
*/
|
||||||
|
const slug = path.join('/')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Contexts
|
* Contexts
|
||||||
*/
|
*/
|
||||||
const { modalContent } = useContext(ModalContext)
|
const { modalContent } = useContext(ModalContext)
|
||||||
const { setNavigation, slug } = useContext(NavigationContext)
|
const { setNavigation } = useContext(NavigationContext)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This forces a re-render upon initial bootstrap of the app
|
* This forces a re-render upon initial bootstrap of the app
|
||||||
|
@ -73,7 +79,7 @@ export const PageWrapper = (props) => {
|
||||||
//const [search, setSearch] = useState(false)
|
//const [search, setSearch] = useState(false)
|
||||||
|
|
||||||
// Helper object to pass props down (keeps things DRY)
|
// Helper object to pass props down (keeps things DRY)
|
||||||
const childProps = { footer, header, pageTitle }
|
const childProps = { footer, header, pageTitle, slug }
|
||||||
|
|
||||||
// Make layout prop into a (uppercase) component
|
// Make layout prop into a (uppercase) component
|
||||||
const Layout = layout
|
const Layout = layout
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue