This commit is contained in:
Sergey Yarkov 2020-07-22 21:54:04 +03:00
parent 2a969a2642
commit 5b42b3c29d
18 changed files with 126 additions and 73 deletions

View File

@ -3,7 +3,7 @@ module.exports = {
keywords: keywords:
"веб разработка, javascript, seo, программирование, reactjs, graphql", "веб разработка, javascript, seo, программирование, reactjs, graphql",
siteName: "Cборник статей и руководств - devthread.ru", siteName: "Cборник статей и руководств - devthread.ru",
titleTemplate: "%s · статьи и руководства по веб-разработке", titleTemplate: "%s · devthread.ru",
description: description:
"Cборник статей и руководств по тематике веб-разработки и IT для того чтобы помочь вам", "Cборник статей и руководств по тематике веб-разработки и IT для того чтобы помочь вам",
url: "https://devthread.netlify.app", url: "https://devthread.netlify.app",

View File

@ -40,12 +40,13 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc non fermentum ligu
```js ```js
const { const {
//L1
siteMetadata: { siteMetadata: {
title, title,
menuLinks, menuLinks,
social: { twitter, telegram }, social: { twitter, telegram },
}, },
} = useSiteMetadataQuery() //L1 } = useSiteMetadataQuery()
const [isScrolled, setIsScrolled] = React.useState(false) const [isScrolled, setIsScrolled] = React.useState(false)
const [isMobileOpen, setIsMobileOpen] = React.useState(false) const [isMobileOpen, setIsMobileOpen] = React.useState(false)
const [isDark, setIsDark] = React.useState(false) const [isDark, setIsDark] = React.useState(false)

View File

@ -40,12 +40,13 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc non fermentum ligu
```js ```js
const { const {
//L1
siteMetadata: { siteMetadata: {
title, title,
menuLinks, menuLinks,
social: { twitter, telegram }, social: { twitter, telegram },
}, },
} = useSiteMetadataQuery() //L1 } = useSiteMetadataQuery()
const [isScrolled, setIsScrolled] = React.useState(false) const [isScrolled, setIsScrolled] = React.useState(false)
const [isMobileOpen, setIsMobileOpen] = React.useState(false) const [isMobileOpen, setIsMobileOpen] = React.useState(false)
const [isDark, setIsDark] = React.useState(false) const [isDark, setIsDark] = React.useState(false)

View File

@ -1,6 +1,5 @@
import React from "react" import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import SEO from "../SEO/SEO"
import Img from "gatsby-image" import Img from "gatsby-image"
import ViewCounter from "../ViewCounter/ViewCounter" import ViewCounter from "../ViewCounter/ViewCounter"
import useSiteMetadataQuery from "../../hooks/useSiteMetadataQuery" import useSiteMetadataQuery from "../../hooks/useSiteMetadataQuery"
@ -14,17 +13,7 @@ import TwitterIcon from "../../images/twitter-icon__large.svg"
import FacebookIcon from "../../images/facebook-icon__large.svg" import FacebookIcon from "../../images/facebook-icon__large.svg"
const Article = ({ const Article = ({
data: { data: { slug, title, image, description, category, tags, time, date },
slug,
keywords,
title,
image,
description,
category,
tags,
time,
date,
},
html, html,
}) => { }) => {
const { const {
@ -34,14 +23,6 @@ const Article = ({
return ( return (
<> <>
<SEO
title={title}
titleTemplate={false}
keywords={keywords.join(", ")}
description={description}
image={`${siteUrl}${image.childImageSharp.fluid.src}`}
type="article"
/>
<div className="article"> <div className="article">
<article> <article>
<div className="article-info"> <div className="article-info">

View File

@ -2,13 +2,10 @@ import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import ContactsFrom from "./ContactsForm/ContactsForm" import ContactsFrom from "./ContactsForm/ContactsForm"
import MemoIcon from "../../images/memo-icon.svg"
const Contacts = ({ email, telegram }) => { const Contacts = ({ email, telegram }) => {
return ( return (
<div className="contacts"> <div className="contacts">
<div className="contacts-heading"> <div className="contacts-heading">
<MemoIcon />
<h1>Контакты</h1> <h1>Контакты</h1>
</div> </div>
<div className="contacts-description"> <div className="contacts-description">

View File

@ -9,7 +9,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-bottom: 25px; margin-bottom: 10px;
& svg { & svg {
margin-right: 10px; margin-right: 10px;
} }

View File

@ -19,15 +19,20 @@ const Header = () => {
} = useSiteMetadataQuery() } = useSiteMetadataQuery()
const [isScrolled, setIsScrolled] = React.useState(false) const [isScrolled, setIsScrolled] = React.useState(false)
const [isMobileOpen, setIsMobileOpen] = React.useState(false) const [isMobileOpen, setIsMobileOpen] = React.useState(false)
const [ready, setReady] = React.useState(false)
const [isDark, setIsDark] = React.useState(false)
const { pathname } = useLocation() const { pathname } = useLocation()
React.useEffect(() => { React.useEffect(() => {
setIsDark(window.__isDarkTheme)
setReady(true)
isMobileOpen isMobileOpen
? (document.body.style.overflowY = "hidden") ? (document.body.style.overflowY = "hidden")
: (document.body.style.overflowY = "") : (document.body.style.overflowY = "")
document.body.onscroll = () => document.body.onscroll = () =>
window.pageYOffset >= 100 ? setIsScrolled(true) : setIsScrolled(false) window.pageYOffset >= 100 ? setIsScrolled(true) : setIsScrolled(false)
}, [isMobileOpen]) }, [isMobileOpen, setIsDark, setReady])
const mobileHandler = () => { const mobileHandler = () => {
setIsMobileOpen(!isMobileOpen) setIsMobileOpen(!isMobileOpen)
@ -71,7 +76,7 @@ const Header = () => {
<div className="header-nav__links"> <div className="header-nav__links">
<nav>{renderLinks()}</nav> <nav>{renderLinks()}</nav>
</div> </div>
<ThemeSwitcher /> <ThemeSwitcher ready={ready} isDark={isDark} setIsDark={setIsDark} />
</div> </div>
<div <div
className={ className={
@ -84,6 +89,11 @@ const Header = () => {
<> <>
<span>{title}</span> <span>{title}</span>
<nav>{renderLinks()}</nav> <nav>{renderLinks()}</nav>
<ThemeSwitcher
ready={ready}
isDark={isDark}
setIsDark={setIsDark}
/>
<div className="mobile-social"> <div className="mobile-social">
<a href="/" target="_blank"> <a href="/" target="_blank">
<TelegramIcon /> <TelegramIcon />

View File

@ -84,17 +84,10 @@ header {
color: rgba(0,0,0,.8); color: rgba(0,0,0,.8);
} }
} }
& .header-nav__theme {
cursor: pointer;
opacity: 0;
}
& .header-nav__theme.ready {
opacity: 1;
transition: all 0.2s linear 0s;
}
} }
&__nav.mobile { &__nav.mobile {
background: #0d0d0d; background-color: rgba(250,252,254, .9);
backdrop-filter: blur(8px);
position: fixed; position: fixed;
right: 0; right: 0;
left: 0; left: 0;
@ -102,11 +95,14 @@ header {
bottom: 0; bottom: 0;
height: 0%; height: 0%;
transition: padding-top .2s ease-out; transition: padding-top .2s ease-out;
overflow: scroll;
overflow-x: hidden;
z-index: 99; z-index: 99;
& .theme-switcher {
position: absolute;
right: 22px;
bottom: 45px;
}
& span { & span {
color: $white-clr; color: #0A0C10;
display: block; display: block;
margin-bottom: 20px; margin-bottom: 20px;
font-weight: 700; font-weight: 700;
@ -118,10 +114,13 @@ header {
& a { & a {
font-size: 28px; font-size: 28px;
text-decoration: none; text-decoration: none;
color: $white-clr; color: #0A0C10;
font-weight: 600; font-weight: 600;
} }
} }
& li.active {
margin-left: 20px;
}
} }
& .mobile-social { & .mobile-social {
margin-top: 30px; margin-top: 30px;
@ -135,11 +134,11 @@ header {
} }
& svg { & svg {
& .telegram-svg-social { & .telegram-svg-social {
fill: $white-clr; fill: #0A0C10;
width: 50px; width: 50px;
} }
& .twitter-svg-social { & .twitter-svg-social {
fill: $white-clr; fill: #0A0C10;
} }
} }
& a:nth-child(2) { & a:nth-child(2) {
@ -188,18 +187,18 @@ header {
&__button.mobile.active { &__button.mobile.active {
& span:nth-child(1) { & span:nth-child(1) {
transform: rotate(45deg); transform: rotate(45deg);
background: $white-clr; background: #0A0C10;
top: -3px; top: -3px;
left: 0px; left: 0px;
} }
& span:nth-child(2) { & span:nth-child(2) {
width: 0%; width: 0%;
opacity: 0; opacity: 0;
background: $white-clr; background: #0A0C10;
} }
& span:nth-child(3) { & span:nth-child(3) {
transform: rotate(-45deg); transform: rotate(-45deg);
background: $white-clr; background: #0A0C10;
top: 18px; top: 18px;
left: 0px; left: 0px;
} }
@ -261,11 +260,43 @@ header {
} }
} }
} }
&__nav.mobile {
background-color: rgba(7,11,14, .99);
& span {
color: $white-clr;
}
& nav {
& li {
& a {
color: $white-clr;
}
}
}
& svg {
& .telegram-svg-social {
fill: $white-clr;
}
& .twitter-svg-social {
fill: $white-clr;
}
}
}
&__button.mobile { &__button.mobile {
& span { & span {
background: $white-clr; background: $white-clr;
} }
} }
&__button.mobile.active {
& span:nth-child(1) {
background: $white-clr;
}
& span:nth-child(2) {
background: $white-clr;
}
& span:nth-child(3) {
background: $white-clr;
}
}
} }
} }
} }

View File

@ -1,19 +1,12 @@
import React from "react" import React from "react"
import PropTypes from "prop-types"
import MoonIcon from "../../../images/moon-icon.svg" import MoonIcon from "../../../images/moon-icon.svg"
import SunIcon from "../../../images/sun-icon.svg" import SunIcon from "../../../images/sun-icon.svg"
const ThemeSwitcher = () => { const ThemeSwitcher = ({ ready, isDark, setIsDark }) => {
const [ready, setReady] = React.useState(false)
const [isDark, setIsDark] = React.useState(false)
React.useEffect(() => {
setIsDark(window.__isDarkTheme)
setReady(true)
}, [setIsDark, setReady])
return ( return (
<div className={ready ? "header-nav__theme ready" : "header-nav__theme"}> <div className={ready ? "theme-switcher ready" : "theme-switcher"}>
{isDark ? ( {isDark ? (
<SunIcon <SunIcon
onClick={() => { onClick={() => {
@ -34,3 +27,9 @@ const ThemeSwitcher = () => {
} }
export default ThemeSwitcher export default ThemeSwitcher
ThemeSwitcher.propTypes = {
ready: PropTypes.bool,
isDark: PropTypes.bool,
setIsDark: PropTypes.func,
}

View File

@ -85,6 +85,11 @@
& .tag-item { & .tag-item {
& a { & a {
color: #5183F5; color: #5183F5;
background: rgba(0,0,0, .2);
&:hover {
background: #111;
color: #99c9f7;
}
} }
} }
} }

View File

@ -1,17 +1,9 @@
import React from "react" import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import SEO from "../SEO/SEO"
const Snippet = ({ data: { keywords, description, title, date }, html }) => { const Snippet = ({ data: { description, title, date }, html }) => {
return ( return (
<> <>
<SEO
title={title}
titleTemplate={false}
description={description}
keywords={keywords.join(", ")}
type="article"
/>
<div className="snippet"> <div className="snippet">
<article> <article>
<div className="snippet-date">{date}</div> <div className="snippet-date">{date}</div>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -7,7 +7,7 @@ import SEO from "../components/SEO/SEO"
const NotFound = () => { const NotFound = () => {
return ( return (
<> <>
<SEO /> <SEO title="Ошибка 404" />
<Main> <Main>
<Grid fluid> <Grid fluid>
<div className="error"> <div className="error">

View File

@ -23,7 +23,10 @@ const IndexPage = ({ data: { allMarkdownRemark: edges } }) => {
return ( return (
<> <>
<SEO /> <SEO
title="devthread.ru · Статьи и руководства по веб-разработке"
titleTemplate={false}
/>
<Main> <Main>
<Grid fluid> <Grid fluid>
<Row> <Row>

View File

@ -13,11 +13,11 @@ const SnippetsPage = ({
}) => { }) => {
return ( return (
<> <>
<SEO /> <SEO title="Сниппеты" />
<Main> <Main>
<Grid fluid> <Grid fluid>
<Row> <Row>
<Col lg={12}> <Col xs={12}>
<Snippets> <Snippets>
<h1>Сниппеты</h1> <h1>Сниппеты</h1>
<p> <p>

View File

@ -142,6 +142,15 @@
background: linear-gradient(135.9deg, #F5F9FF 0%, #F5F9FF 0.01%, #F6F4FB 98.96%); background: linear-gradient(135.9deg, #F5F9FF 0%, #F5F9FF 0.01%, #F6F4FB 98.96%);
} }
.theme-switcher {
cursor: pointer;
opacity: 0;
&.ready {
opacity: 1;
transition: all 0.2s linear 0s;
}
}
.dark { .dark {
background: #202020; background: #202020;
& .light-default-light { & .light-default-light {

View File

@ -1,6 +1,7 @@
import React from "react" import React from "react"
import { Main } from "../ui/ui" import { Main } from "../ui/ui"
import { Grid, Row, Col } from "react-flexbox-grid" import { Grid, Row, Col } from "react-flexbox-grid"
import SEO from "../components/SEO/SEO"
import Article from "../components/Article/Article" import Article from "../components/Article/Article"
import Offers from "../components/Offers/Offers" import Offers from "../components/Offers/Offers"
import MoreArticles from "../components/Articles/MoreArticles/MoreArticles" import MoreArticles from "../components/Articles/MoreArticles/MoreArticles"
@ -9,11 +10,22 @@ import { graphql } from "gatsby"
const articleTemplate = ({ const articleTemplate = ({
data: { data: {
markdownRemark: { frontmatter, html }, article: { frontmatter, html },
site: {
siteMetadata: { siteUrl },
},
}, },
}) => { }) => {
return ( return (
<> <>
<SEO
title={frontmatter.title}
titleTemplate={false}
keywords={frontmatter.keywords.join(", ")}
description={frontmatter.description}
image={`${siteUrl}${frontmatter.image.childImageSharp.fluid.src}`}
type="article"
/>
<Main> <Main>
<Grid fluid> <Grid fluid>
<Row> <Row>
@ -34,7 +46,7 @@ const articleTemplate = ({
export const pageQuery = graphql` export const pageQuery = graphql`
query Article($slug: String!) { query Article($slug: String!) {
markdownRemark(frontmatter: { slug: { eq: $slug } }) { article: markdownRemark(frontmatter: { slug: { eq: $slug } }) {
html html
frontmatter { frontmatter {
slug slug
@ -54,6 +66,11 @@ export const pageQuery = graphql`
category category
} }
} }
site {
siteMetadata {
siteUrl: url
}
}
} }
` `

View File

@ -1,6 +1,7 @@
import React from "react" import React from "react"
import { Main } from "../ui/ui" import { Main } from "../ui/ui"
import { Grid, Row, Col } from "react-flexbox-grid" import { Grid, Row, Col } from "react-flexbox-grid"
import SEO from "../components/SEO/SEO"
import Snippet from "../components/Snippet/Snippet" import Snippet from "../components/Snippet/Snippet"
import { graphql } from "gatsby" import { graphql } from "gatsby"
@ -11,6 +12,13 @@ const snippetTemplate = ({
}) => { }) => {
return ( return (
<> <>
<SEO
title={frontmatter.title}
titleTemplate={false}
description={frontmatter.description}
keywords={frontmatter.keywords.join(", ")}
type="article"
/>
<Main> <Main>
<Grid fluid style={{ maxWidth: 900 }}> <Grid fluid style={{ maxWidth: 900 }}>
<Row> <Row>