Merge pull request #17 from tmshv/fix/footer-refactoring
Footer refactoring
This commit is contained in:
16 files changed
+254
-184
No files matched your search
+8
-5
@@ -1,16 +1,19 @@
|
||||
import { NextPage } from 'next'
|
||||
import { Wrapper } from 'src/components/Wrapper'
|
||||
import { NotFound } from 'src/components/NotFound'
|
||||
import { Copyright } from 'src/components/Copyright'
|
||||
import { Block } from 'src/components/Block'
|
||||
import { Spacer } from 'src/components/Spacer'
|
||||
|
||||
const Page: NextPage = () => (
|
||||
<Wrapper
|
||||
header={null}
|
||||
footer={(
|
||||
<footer className="footer--centered">
|
||||
<div className="copyright">
|
||||
<span>© 2012—2019 Шлиссельбургская детская художественная школа</span>
|
||||
</div>
|
||||
</footer>
|
||||
<Block as={'footer'} direction={'horizontal'}>
|
||||
<Spacer />
|
||||
<Copyright />
|
||||
<Spacer />
|
||||
</Block>
|
||||
)}
|
||||
>
|
||||
<NotFound />
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import dynamic from 'next/dynamic'
|
||||
import cx from 'classnames'
|
||||
import { Footer } from '../Footer'
|
||||
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'
|
||||
|
||||
const Navigation = dynamic(() => import('../Navigation').then(mod => mod.Navigation), {
|
||||
ssr: false,
|
||||
})
|
||||
@@ -20,31 +23,30 @@ export const App: React.FC<IAppProps> = props => {
|
||||
const motionDisabled = useReducedMotion()
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
header={(
|
||||
<Header>
|
||||
<Navigation
|
||||
items={props.menu.items}
|
||||
<ConfigContext.Provider value={config}>
|
||||
<Wrapper
|
||||
header={(
|
||||
<Header>
|
||||
<Navigation
|
||||
items={props.menu.items}
|
||||
/>
|
||||
</Header>
|
||||
)}
|
||||
footer={(
|
||||
<Footer
|
||||
showAuthor={props.showAuthor}
|
||||
/>
|
||||
</Header>
|
||||
)}
|
||||
footer={(
|
||||
<Footer
|
||||
showAuthor={props.showAuthor}
|
||||
address=" г. Шлиссельбург ул. 18 января д. 3"
|
||||
telephone="+7 (81362) 76-312"
|
||||
email="hudozka@gmail.com"
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<section className={cx('content', `content_${props.layout}`, {
|
||||
'content--padding-top--menu': props.menuPadding,
|
||||
'reduced-motion': motionDisabled,
|
||||
})}>
|
||||
{props.children}
|
||||
</section>
|
||||
)}
|
||||
>
|
||||
<section className={cx('content', `content_${props.layout}`, {
|
||||
'content--padding-top--menu': props.menuPadding,
|
||||
'reduced-motion': motionDisabled,
|
||||
})}>
|
||||
{props.children}
|
||||
</section>
|
||||
|
||||
<Comments />
|
||||
</Wrapper>
|
||||
<Comments />
|
||||
</Wrapper>
|
||||
</ConfigContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import './styles.css'
|
||||
|
||||
import cx from 'classnames'
|
||||
import { createElement } from 'react'
|
||||
|
||||
export type BlockProps = {
|
||||
as?: keyof HTMLElementTagNameMap
|
||||
style?: React.CSSProperties
|
||||
direction: 'horizontal' | 'vertical'
|
||||
}
|
||||
|
||||
export const Block: React.FC<BlockProps> = ({ as = 'div', style, direction, ...props }) => {
|
||||
const newProps = { className: cx('block', direction), style }
|
||||
|
||||
return createElement(as, newProps, props.children)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.block {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.block.horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.block.vertical {
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { useContext } from 'react'
|
||||
import { ConfigContext } from 'src/context/ConfigContext'
|
||||
|
||||
export const Contacts: React.FC = props => {
|
||||
const { contacts } = useContext(ConfigContext)
|
||||
|
||||
return (
|
||||
<>
|
||||
<style jsx>{`
|
||||
h4 {
|
||||
margin-bottom: var(--half-margin);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: var(--single-margin);
|
||||
margin-bottom: var(--half-margin);
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<h4>Контактная информация</h4>
|
||||
|
||||
{contacts.map((x, i) => (
|
||||
<p><a href={x.value}>{x.title}</a></p>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useContext } from 'react'
|
||||
import { ConfigContext } from 'src/context/ConfigContext'
|
||||
|
||||
export const Copyright: React.FC = () => {
|
||||
const { yearStart, yearEnd } = useContext(ConfigContext)
|
||||
|
||||
return (
|
||||
<span>© {yearStart}—{yearEnd} Шлиссельбургская детская художественная школа</span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export const Author: React.FC = () => (
|
||||
<span>
|
||||
Разработка и поддержка сайта —
|
||||
<a href="http://tmshv.ru?utm_source=artshburg&utm_medium=developer&utm_campaign=tmshv_ru">
|
||||
www.tmshv.ru
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
@@ -1,49 +1,31 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const mailto = email => `mailto:${email}`
|
||||
const currentYear = () => (new Date()).getFullYear()
|
||||
import { Copyright } from '../Copyright'
|
||||
import { Author } from './Author'
|
||||
import { Block } from '../Block'
|
||||
import { Spacer } from '../Spacer'
|
||||
import { Contacts } from '../Contacts'
|
||||
|
||||
export interface IFooterProps {
|
||||
address: string
|
||||
telephone: string
|
||||
email: string
|
||||
showAuthor: boolean
|
||||
}
|
||||
|
||||
export const Footer: React.FC<IFooterProps> = props => (
|
||||
<footer>
|
||||
<div className="contacts">
|
||||
<div>
|
||||
<h4>Контактная информация</h4>
|
||||
<p>Адрес: {props.address}</p>
|
||||
<p>Телефон: {props.telephone}</p>
|
||||
<p>Почта: <a href={mailto(props.email)}>{props.email}</a></p>
|
||||
<p>Вконтакте: <a href="https://vk.com/shlisselburghudozka">shlisselburghudozka</a></p>
|
||||
<p>Инстаграм: <a href="https://www.instagram.com/hudozka/">hudozka</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<footer className={'opposite'}>
|
||||
<Block direction={'vertical'} style={{
|
||||
marginBottom: 'var(--single-margin)',
|
||||
}}>
|
||||
<Contacts />
|
||||
</Block>
|
||||
|
||||
<Block direction={'horizontal'}>
|
||||
<Copyright />
|
||||
|
||||
<div className="copyright">
|
||||
<Copyright
|
||||
yearStart={2012}
|
||||
yearEnd={currentYear()}
|
||||
/>
|
||||
{!props.showAuthor ? null : (
|
||||
<Author />
|
||||
<>
|
||||
<Spacer as={'span'} />
|
||||
<Author />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</footer>
|
||||
</Block>
|
||||
</footer >
|
||||
)
|
||||
|
||||
const Author = () => (
|
||||
<span>
|
||||
Разработка и поддержка сайта —
|
||||
<a href="http://tmshv.ru?utm_source=artshburg&utm_medium=developer&utm_campaign=tmshv_ru">
|
||||
www.tmshv.ru
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
|
||||
const Copyright = ({ yearStart, yearEnd }) => (
|
||||
<span>© {yearStart}—{yearEnd} Шлиссельбургская детская художественная школа</span>
|
||||
)
|
||||
@@ -2,7 +2,8 @@ export const NotFound: React.FC = () => (
|
||||
<section>
|
||||
<style jsx>{`
|
||||
section {
|
||||
margin: 1em 0;
|
||||
margin-top: var(--size-l);
|
||||
margin-bottom: var(--size-l);
|
||||
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
@@ -17,8 +18,8 @@ export const NotFound: React.FC = () => (
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 20px;
|
||||
width: 40%;
|
||||
margin-top: var(--size-m);
|
||||
margin-bottom: var(--size-m);
|
||||
max-width: 400px;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { createElement } from 'react'
|
||||
|
||||
export type SpacerProps = {
|
||||
as?: keyof HTMLElementTagNameMap
|
||||
}
|
||||
|
||||
export const Spacer: React.FC<SpacerProps> = ({ as = 'div' }) => createElement(as, {
|
||||
style: {
|
||||
flex: 1,
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,33 @@
|
||||
const currentYear = () => (new Date()).getFullYear()
|
||||
|
||||
export default {
|
||||
yearStart: 2012,
|
||||
yearEnd: currentYear(),
|
||||
contacts: [
|
||||
{
|
||||
type: 'link',
|
||||
value: 'https://yandex.ru/maps/-/CKUkAXIb',
|
||||
title: 'г. Шлиссельбург ул. 18 января д. 3',
|
||||
},
|
||||
{
|
||||
type: 'tel',
|
||||
value: 'tel:+78136276312',
|
||||
title: '+7 (81362) 76-312',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
value: 'mailto:hudozka@gmail.com',
|
||||
title: 'hudozka@gmail.com',
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
value: 'https://vk.com/shlisselburghudozka',
|
||||
title: 'Вконтакте'
|
||||
},
|
||||
{
|
||||
type: 'link',
|
||||
value: 'https://www.instagram.com/hudozka',
|
||||
title: 'Инстаграм'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { createContext } from 'react'
|
||||
import config from 'src/config'
|
||||
|
||||
export const ConfigContext = createContext(config)
|
||||
+59
-4
@@ -30,9 +30,6 @@
|
||||
|
||||
--embed-video-ratio: 56.25%;
|
||||
|
||||
--text-color: #303030;
|
||||
--text-color-second: #ccc;
|
||||
|
||||
/* FONTS */
|
||||
--font-size-default: 14pt;
|
||||
--font-size-second: 0.9rem;
|
||||
@@ -61,6 +58,21 @@
|
||||
|
||||
--schedule-row-color: hsl(210, 55%, 90%);
|
||||
|
||||
/* TEXT COLOR */
|
||||
--color-text: #303030;
|
||||
--color-text-second: #ccc;
|
||||
--color-text-opposite: var(--light-color);
|
||||
|
||||
--color-back-main: white;
|
||||
--color-back-opposite: var(--darker-color);
|
||||
|
||||
/* SIZE */
|
||||
--size-sx: 0.2em;
|
||||
--size-s: 0.5em;
|
||||
--size-m: 1em;
|
||||
--size-l: 2em;
|
||||
--size-xl: 5em;
|
||||
|
||||
/* MARGINS */
|
||||
--small-margin: 0.2em;
|
||||
--half-margin: 0.5em;
|
||||
@@ -85,7 +97,14 @@ body {
|
||||
body {
|
||||
min-width: 320px;
|
||||
|
||||
color: var(--text-color);
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: var(--single-margin);
|
||||
color: var(--color-text-opposite);
|
||||
background-color: var(--color-back-opposite);
|
||||
font-size: var(--smaller-font-size);
|
||||
}
|
||||
|
||||
h1 {
|
||||
@@ -110,6 +129,42 @@ h3 {
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2 {
|
||||
font-family: var(--title-font);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--dark-color);
|
||||
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid var(--link-color);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
border-bottom: 2px solid var(--dark-color);
|
||||
}
|
||||
|
||||
a:active {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #a4059c;
|
||||
}
|
||||
|
||||
a.invisible {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.opposite a {
|
||||
color: var(--color-text-opposite);
|
||||
}
|
||||
|
||||
.opposite a:hover {
|
||||
border-bottom-color: var(--color-text-opposite);
|
||||
}
|
||||
|
||||
.actor {
|
||||
border-bottom: 1px dashed black;
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
footer {
|
||||
padding: 0 var(--half-margin) var(--half-margin);
|
||||
position: relative;
|
||||
|
||||
.footer-info {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: var(--double-margin) var(--single-margin) 0;
|
||||
margin-bottom: var(--double-margin);
|
||||
}
|
||||
|
||||
.contacts {
|
||||
margin: var(--double-margin) 0 var(--half-margin);
|
||||
|
||||
& > div {
|
||||
padding: 0 var(--single-margin);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: var(--half-margin) var(--single-margin);
|
||||
}
|
||||
}
|
||||
|
||||
.copyright {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
padding: 1.5em 1em 0.25em;
|
||||
box-sizing: padding-box;
|
||||
}
|
||||
}
|
||||
|
||||
&.footer--centered {
|
||||
.copyright {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@
|
||||
@import "components/ArticleTags";
|
||||
|
||||
@import "content";
|
||||
@import "footer";
|
||||
|
||||
// THEMES
|
||||
|
||||
|
||||
@@ -1,74 +1,25 @@
|
||||
.theme-default {
|
||||
h1, h2{
|
||||
font-family: var(--title-font);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--dark-color);
|
||||
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid var(--link-color);
|
||||
|
||||
&:hover {
|
||||
border-bottom: 2px solid var(--dark-color);
|
||||
}
|
||||
|
||||
&:active {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
&.invisible {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: #a4059c;
|
||||
}
|
||||
}
|
||||
|
||||
.accessibility-control {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.schedule-table {
|
||||
a{
|
||||
color: var(--dark-color);
|
||||
.schedule-table {
|
||||
a {
|
||||
color: var(--dark-color);
|
||||
}
|
||||
|
||||
.lesson {
|
||||
font-size: 1.1em;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.current {
|
||||
border-color: var(--current-week-day-color);
|
||||
border-color: var(--current-week-day-color);
|
||||
}
|
||||
|
||||
&__head{
|
||||
.group {
|
||||
color: #666;
|
||||
}
|
||||
&__head {
|
||||
.group {
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&__body-row{
|
||||
&:nth-child(even) {
|
||||
background-color: var(--schedule-row-color);
|
||||
}
|
||||
&__body-row {
|
||||
&:nth-child(even) {
|
||||
background-color: var(--schedule-row-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
color: var(--light-color);
|
||||
background-color: var(--darker-color);
|
||||
|
||||
font-size: var(--smaller-font-size);
|
||||
|
||||
a {
|
||||
color: var(--light-color);
|
||||
border-bottom-color: var(--light-color);
|
||||
|
||||
&:hover {
|
||||
border-bottom-color: var(--light-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user