added optional breadcrumbs; page layout refactoring; other chages
This commit is contained in:
1 parent
1dbbe04d59
commit
db485056e0
12 files changed
+140
-63
No files matched your search
+11
-1
@@ -5,6 +5,8 @@ import { Page } from 'src/components/Page'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, wrapInitialProps, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IBreadcumbsPart, IMeta } from 'src/types'
|
||||
|
||||
function array<T>(value: T | T[]) {
|
||||
return Array.isArray(value)
|
||||
@@ -12,12 +14,20 @@ function array<T>(value: T | T[]) {
|
||||
: [value]
|
||||
}
|
||||
|
||||
const Index = props => (
|
||||
type Props = {
|
||||
title: string
|
||||
content: string
|
||||
breadcrumbs: IBreadcumbsPart[]
|
||||
meta: IMeta
|
||||
}
|
||||
|
||||
const Index: NextPage<Props> = props => (
|
||||
<App
|
||||
showAuthor={true}
|
||||
contentStyle={{
|
||||
marginTop: 'var(--size-l)'
|
||||
}}
|
||||
breadcrumbs={props.breadcrumbs}
|
||||
>
|
||||
<Head>
|
||||
<title>{props.title}</title>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
export const Header: React.FC = props => (
|
||||
<header>
|
||||
<style jsx>{`
|
||||
.navigation {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.navigation__body {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className="navigation">
|
||||
<div className="navigation__body">
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
@@ -1,12 +1,13 @@
|
||||
import dynamic from 'next/dynamic'
|
||||
import cx from 'classnames'
|
||||
import Comments from '../Comments'
|
||||
import { useReducedMotion } from 'src/hooks/useReducedMotion'
|
||||
import { Wrapper } from '../Wrapper'
|
||||
import { Header } from './Header'
|
||||
import { ConfigContext } from 'src/context/ConfigContext'
|
||||
import config from 'src/config'
|
||||
import { Footer } from '../Footer'
|
||||
import { Content } from '../Content'
|
||||
import { Block } from '../Block'
|
||||
import { Breadcrumbs } from '../Breadcrumbs'
|
||||
import { IBreadcumbsPart } from 'src/types'
|
||||
|
||||
const Navigation = dynamic(() => import('../Navigation').then(mod => mod.Navigation), {
|
||||
ssr: false,
|
||||
@@ -16,18 +17,31 @@ export interface IAppProps {
|
||||
showAuthor: boolean
|
||||
wide?: boolean
|
||||
contentStyle?: React.CSSProperties
|
||||
breadcrumbs?: IBreadcumbsPart[]
|
||||
}
|
||||
|
||||
export const App: React.FC<IAppProps> = ({ wide = false, ...props }) => {
|
||||
const motionDisabled = useReducedMotion()
|
||||
export const App: React.FC<IAppProps> = props => {
|
||||
const wide = props.wide ?? false
|
||||
const blockStyle = {
|
||||
alignItems: 'center'
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfigContext.Provider value={config}>
|
||||
<Wrapper
|
||||
header={(
|
||||
<Header>
|
||||
<header>
|
||||
<Navigation />
|
||||
</Header>
|
||||
{!props.breadcrumbs ? null : (
|
||||
<Block direction={'vertical'} style={blockStyle}>
|
||||
<Content wide={wide}>
|
||||
<Breadcrumbs
|
||||
path={props.breadcrumbs}
|
||||
/>
|
||||
</Content>
|
||||
</Block>
|
||||
)}
|
||||
</header>
|
||||
)}
|
||||
footer={(
|
||||
<Footer
|
||||
@@ -35,15 +49,11 @@ export const App: React.FC<IAppProps> = ({ wide = false, ...props }) => {
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={cx('content', {
|
||||
'reduced-motion': motionDisabled,
|
||||
'content_wide': wide,
|
||||
})}
|
||||
style={props.contentStyle}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
<Block direction={'vertical'} style={blockStyle}>
|
||||
<Content wide={wide} style={props.contentStyle}>
|
||||
{props.children}
|
||||
</Content>
|
||||
</Block>
|
||||
|
||||
{/* <Comments /> */}
|
||||
</Wrapper>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import './styles.css'
|
||||
|
||||
import { IBreadcumbsPart } from 'src/types'
|
||||
import { Button } from '../Button'
|
||||
|
||||
export type BreadcrumbsProps = {
|
||||
style?: React.CSSProperties
|
||||
path: IBreadcumbsPart[]
|
||||
}
|
||||
|
||||
export const Breadcrumbs: React.FC<BreadcrumbsProps> = props => {
|
||||
return (
|
||||
<nav className={'breadcrumbs'} style={props.style}>
|
||||
{props.path.map((x, i) => (
|
||||
<li key={x.href}>
|
||||
<Button
|
||||
href={x.href}
|
||||
theme={'ghost'}
|
||||
size={'small'}
|
||||
>
|
||||
{x.name}
|
||||
</Button>
|
||||
|
||||
{!(i < props.path.length - 1) ? null : (
|
||||
<span style={{ margin: '0 var(--size-xs)' }}>/</span>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.breadcrumbs {
|
||||
display: flex;
|
||||
list-style: none;
|
||||
|
||||
position: relative;
|
||||
right: var(--size-s);
|
||||
}
|
||||
@@ -1,16 +1,20 @@
|
||||
import './styles.css'
|
||||
|
||||
import Link from 'next/link'
|
||||
import cx from 'classnames'
|
||||
|
||||
export type ButtonProps = {
|
||||
style?: React.CSSProperties
|
||||
href?: string
|
||||
theme?: 'default' | 'ghost'
|
||||
size?: 'default' | 'small'
|
||||
}
|
||||
|
||||
export const Button: React.FC<ButtonProps> = props => {
|
||||
export const Button: React.FC<ButtonProps> = ({ size='default', theme = 'default', ...props }) => {
|
||||
if (props.href) {
|
||||
return (
|
||||
<Link href={props.href}>
|
||||
<a className={'button invisible'} style={props.style}>
|
||||
<a className={cx('button', theme, size)} style={props.style}>
|
||||
{props.children}
|
||||
</a>
|
||||
</Link>
|
||||
@@ -22,4 +26,5 @@ export const Button: React.FC<ButtonProps> = props => {
|
||||
{props.children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
.button {
|
||||
border: none;
|
||||
font-size: var(--font-size-default);
|
||||
|
||||
text-align: center;
|
||||
margin-top: var(--size-m);
|
||||
margin-bottom: var(--size-m);
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
|
||||
padding: var(--size-s) var(--size-m);
|
||||
border-radius: 100px;
|
||||
border: 1px solid var(--color-shadow);
|
||||
|
||||
background-color: var(--color-back);
|
||||
box-shadow: 0 0 0 1px var(--color-shadow);
|
||||
|
||||
transition: box-shadow 150ms;
|
||||
|
||||
@@ -21,5 +17,27 @@
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
|
||||
border: none;
|
||||
box-shadow: var(--shadow-active);
|
||||
}
|
||||
|
||||
/* THEME */
|
||||
|
||||
.button.ghost {
|
||||
border-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* SIZE */
|
||||
|
||||
.button.default {
|
||||
padding: var(--size-s) var(--size-m);
|
||||
}
|
||||
|
||||
.button.small {
|
||||
padding: var(--size-xs) var(--size-s);
|
||||
font-size: var(--font-size-second);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import cx from 'classnames'
|
||||
import { useReducedMotion } from 'src/hooks/useReducedMotion'
|
||||
|
||||
export type ContentProps = {
|
||||
style?: React.CSSProperties
|
||||
wide: boolean
|
||||
}
|
||||
|
||||
export const Content: React.FC<ContentProps> = props => {
|
||||
const motionDisabled = useReducedMotion()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cx('content', {
|
||||
'reduced-motion': motionDisabled,
|
||||
'content_wide': props.wide,
|
||||
})}
|
||||
style={props.style}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import * as React from 'react'
|
||||
import { Share } from '../Share'
|
||||
import { Html } from '../Html'
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@ import cx from 'classnames'
|
||||
export type WrapperProps = {
|
||||
header: React.ReactNode
|
||||
footer: React.ReactNode
|
||||
style?: React.CSSProperties
|
||||
mainStyle?: React.CSSProperties
|
||||
}
|
||||
|
||||
export const Wrapper: React.FC<WrapperProps> = props => (
|
||||
<div className={cx('wrapper', 'theme-default')}>
|
||||
<div className={cx('wrapper', 'theme-default')} style={props.style}>
|
||||
<style jsx>{`
|
||||
.wrapper {
|
||||
display: flex;
|
||||
@@ -17,20 +19,11 @@ export const Wrapper: React.FC<WrapperProps> = props => (
|
||||
font-family: var(--text-font);
|
||||
font-size: var(--font-size-default);
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
main {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
{props.header}
|
||||
|
||||
<main>
|
||||
<main style={props.mainStyle}>
|
||||
{props.children}
|
||||
</main>
|
||||
|
||||
|
||||
+2
-2
@@ -67,8 +67,8 @@
|
||||
--color-back-opposite: var(--darker-color);
|
||||
|
||||
/* SIZE */
|
||||
--size-xs: 0.25em;
|
||||
--size-s: 0.5em;
|
||||
--size-xs: 0.35em;
|
||||
--size-s: 0.75em;
|
||||
--size-m: 1em;
|
||||
--size-l: 2em;
|
||||
--size-xl: 3em;
|
||||
|
||||
+5
-2
@@ -1,8 +1,11 @@
|
||||
export interface IMenu {
|
||||
name: string
|
||||
href: string
|
||||
active: boolean
|
||||
items?: IMenu[]
|
||||
}
|
||||
|
||||
export interface IBreadcumbsPart {
|
||||
name: string
|
||||
href: string
|
||||
}
|
||||
|
||||
export interface IDocument {
|
||||
|
||||
Reference in new issue
Block a user