mirror of
https://github.com/tuono-labs/tuono
synced 2026-07-25 21:02:45 -07:00
docs: add footer to doc (#512)
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
import type { JSX } from 'react'
|
||||
import { Link } from 'tuono'
|
||||
import {
|
||||
Container,
|
||||
Box,
|
||||
AppShell,
|
||||
Title,
|
||||
Divider,
|
||||
Flex,
|
||||
Text,
|
||||
Anchor,
|
||||
} from '@mantine/core'
|
||||
import type { MantineSize } from '@mantine/core'
|
||||
|
||||
interface LinkData {
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
|
||||
interface FooterLinkListProps {
|
||||
title: string
|
||||
links: Array<LinkData>
|
||||
hiddenFrom?: MantineSize
|
||||
}
|
||||
|
||||
const aboutLinks: Array<LinkData> = [
|
||||
{ title: 'Contribute', url: '/documentation/contributing' },
|
||||
{
|
||||
title: 'GitHub releases',
|
||||
url: 'https://github.com/tuono-labs/tuono/releases',
|
||||
},
|
||||
]
|
||||
|
||||
const communityLinks: Array<LinkData> = [
|
||||
{ title: 'Chat on Discord', url: 'https://discord.com/invite/khQzPa654B' },
|
||||
{ title: 'Follow on X', url: 'https://twitter.com/valerioageno' },
|
||||
{ title: 'Follow on GitHub', url: 'https://github.com/tuono-labs' },
|
||||
]
|
||||
|
||||
const legalLinks: Array<LinkData> = [
|
||||
{ title: 'Privacy Policy', url: '/policies/privacy' },
|
||||
]
|
||||
|
||||
function FooterLink({ link }: { link: LinkData }): JSX.Element {
|
||||
const component = link.url.startsWith('http') ? undefined : Link
|
||||
const target = link.url.startsWith('http') ? '_blank' : undefined
|
||||
return (
|
||||
<Box>
|
||||
<Anchor
|
||||
component={component}
|
||||
href={link.url}
|
||||
key={link.url}
|
||||
fz={14}
|
||||
target={target}
|
||||
>
|
||||
{link.title}
|
||||
</Anchor>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function FooterLinkList({
|
||||
title,
|
||||
links,
|
||||
hiddenFrom,
|
||||
}: FooterLinkListProps): JSX.Element {
|
||||
return (
|
||||
<Box hiddenFrom={hiddenFrom}>
|
||||
<Title order={5} mb={8}>
|
||||
{title}
|
||||
</Title>
|
||||
{links.map((link) => (
|
||||
<FooterLink link={link} key={link.url} />
|
||||
))}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function FooterTitle(): JSX.Element {
|
||||
const size = 44
|
||||
return (
|
||||
<Box mb={24}>
|
||||
<Flex gap={12} align="center" h={size} mb={8}>
|
||||
<img src="/logo.svg" alt="Tuono" width={size} height={size} />
|
||||
<Title order={2} fz={size}>
|
||||
Tuono
|
||||
</Title>
|
||||
</Flex>
|
||||
<Text fz={12}>Simply the fastest full-stack web framework ⚡</Text>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
function TocPlaceholder(): JSX.Element {
|
||||
return (
|
||||
<Box
|
||||
w={220}
|
||||
miw={220}
|
||||
data-id="table-of-content-placeholder"
|
||||
visibleFrom="lg"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function FooterOutro(): JSX.Element {
|
||||
const fontSize = 14
|
||||
return (
|
||||
<Container
|
||||
size={1000}
|
||||
w="100%"
|
||||
display="flex"
|
||||
style={{ gap: 12, justifyContent: 'space-between' }}
|
||||
>
|
||||
<Box w="100%">
|
||||
<Text fz={fontSize}>
|
||||
Built by{' '}
|
||||
<Anchor fz={fontSize} href="https://github.com/Valerioageno">
|
||||
Valerio Ageno
|
||||
</Anchor>{' '}
|
||||
and{' '}
|
||||
<Anchor
|
||||
fz={fontSize}
|
||||
href="https://github.com/tuono-labs/tuono/graphs/contributors"
|
||||
>
|
||||
these awesome people
|
||||
</Anchor>
|
||||
</Text>
|
||||
</Box>
|
||||
<Anchor
|
||||
fz={fontSize}
|
||||
w={150}
|
||||
component={Link}
|
||||
href="/policies/privacy"
|
||||
ta="right"
|
||||
visibleFrom="xs"
|
||||
>
|
||||
Privacy Policy
|
||||
</Anchor>
|
||||
<TocPlaceholder />
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Footer(): JSX.Element {
|
||||
return (
|
||||
<AppShell.Footer id="app-footer" withBorder={false} zIndex={0} p={0}>
|
||||
<Box m={0} pt={52} pb={8} w="100%" bg="var(--mantine-color-footer-bg)">
|
||||
<Container
|
||||
size={1000}
|
||||
w="100%"
|
||||
display="flex"
|
||||
style={{ gap: 12, justifyContent: 'space-between' }}
|
||||
mb={24}
|
||||
>
|
||||
<Flex
|
||||
justify="space-between"
|
||||
w="100%"
|
||||
direction={{ base: 'column', xs: 'row' }}
|
||||
>
|
||||
<FooterTitle />
|
||||
<Flex
|
||||
gap={{ base: 12, md: 32 }}
|
||||
justify="space-between"
|
||||
direction={{ base: 'column', xs: 'row' }}
|
||||
>
|
||||
<FooterLinkList title="About" links={aboutLinks} />
|
||||
<FooterLinkList title="Community" links={communityLinks} />
|
||||
<FooterLinkList
|
||||
title="Legal"
|
||||
links={legalLinks}
|
||||
hiddenFrom="xs"
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<TocPlaceholder />
|
||||
</Container>
|
||||
<Divider mb={8} mt={28} />
|
||||
<FooterOutro />
|
||||
</Box>
|
||||
</AppShell.Footer>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import Footer from './Footer'
|
||||
|
||||
export default Footer
|
||||
@@ -4,6 +4,5 @@ import { Code } from '@mantine/core'
|
||||
export default function MdxCode(
|
||||
props: HTMLAttributes<HTMLPreElement>,
|
||||
): JSX.Element {
|
||||
console.log(props)
|
||||
return <Code {...props} style={{ fontSize: 'inherit' }} />
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { JSX, ReactNode } from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Box, Container } from '@mantine/core'
|
||||
import { useViewportSize } from '@mantine/hooks'
|
||||
|
||||
import TableOfContents from '@/components/TableOfContents'
|
||||
|
||||
@@ -10,24 +12,51 @@ interface PageWithTOCProps {
|
||||
}
|
||||
|
||||
export function PageWithTOC({ children }: PageWithTOCProps): JSX.Element {
|
||||
return (
|
||||
<Container
|
||||
size={1000}
|
||||
w="100%"
|
||||
display="flex"
|
||||
style={{ gap: 12, justifyContent: 'space-between' }}
|
||||
>
|
||||
<Box
|
||||
id="mdx-root"
|
||||
component="article"
|
||||
mt="xl"
|
||||
py={36}
|
||||
className={classes.wrapper}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
const { width } = useViewportSize()
|
||||
const [footerHeight, setFooterHeight] = useState<number>(0)
|
||||
const mainRef = useRef<HTMLDivElement>(null)
|
||||
const height = `calc(100% - ${footerHeight}px)`
|
||||
|
||||
<TableOfContents />
|
||||
</Container>
|
||||
useEffect(() => {
|
||||
const footer = document.getElementById('app-footer')
|
||||
|
||||
if (footer) {
|
||||
setFooterHeight(footer.clientHeight)
|
||||
}
|
||||
}, [
|
||||
setFooterHeight,
|
||||
// Reload on window width resize
|
||||
width,
|
||||
])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
style={{ zIndex: 10, height }}
|
||||
pos="relative"
|
||||
ref={mainRef}
|
||||
mb={footerHeight}
|
||||
bg="var(--mantine-color-body)"
|
||||
>
|
||||
<Container
|
||||
size={1000}
|
||||
w="100%"
|
||||
display="flex"
|
||||
style={{ gap: 12, justifyContent: 'space-between' }}
|
||||
>
|
||||
<Box
|
||||
id="mdx-root"
|
||||
component="article"
|
||||
mt="xl"
|
||||
py={36}
|
||||
className={classes.wrapper}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
|
||||
<TableOfContents />
|
||||
</Container>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import MdxProvider from '@/components/MdxProvider'
|
||||
|
||||
import '@mantine/core/styles.css'
|
||||
import '@mantine/code-highlight/styles.css'
|
||||
import Footer from '@/components/Footer'
|
||||
|
||||
interface RootRouteProps {
|
||||
children: ReactNode
|
||||
@@ -81,11 +82,13 @@ const resolver: CSSVariablesResolver = (th) => {
|
||||
return {
|
||||
variables: {},
|
||||
light: {
|
||||
'--mantine-color-footer-bg': th.colors.gray[1],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayLight,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverLight,
|
||||
'--mantine-color-quote-border': th.colors.violet[1],
|
||||
},
|
||||
dark: {
|
||||
'--mantine-color-footer-bg': th.colors.dark[6],
|
||||
'--mantine-color-sidebar-gray': sidebarGrayDark,
|
||||
'--mantine-color-sidebar-text-hover': sidebarTextHoverDark,
|
||||
'--mantine-color-quote-border': th.colors.violet[9],
|
||||
@@ -139,6 +142,7 @@ export default function RootRoute({ children }: RootRouteProps): JSX.Element {
|
||||
<PageWithTOC>{children}</PageWithTOC>
|
||||
</MdxProvider>
|
||||
</AppShell.Main>
|
||||
<Footer />
|
||||
</AppShell>
|
||||
</MantineProvider>
|
||||
<TuonoScripts />
|
||||
|
||||
Reference in New Issue
Block a user