mirror of
https://github.com/Stone-Red-Code/website.git
synced 2026-09-04 09:15:58 +02:00
ui: first pass on redesign (#228)
This commit is contained in:
Generated
+11
@@ -2704,6 +2704,12 @@
|
||||
"defer-to-connect": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"@types/classnames": {
|
||||
"version": "2.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.10.tgz",
|
||||
"integrity": "sha512-1UzDldn9GfYYEsWWnn/P4wkTlkZDH7lDb0wBMGbtIQc9zXEQq7FlKBdZUn6OBqD8sKZZ2RQO2mAjGpXiDGoRmQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/color-name": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||
@@ -5347,6 +5353,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
|
||||
},
|
||||
"clean-css": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@reach/router": "^1.3.3",
|
||||
"classnames": "^2.2.6",
|
||||
"gatsby": "^2.19.34",
|
||||
"gatsby-plugin-layout": "^1.1.23",
|
||||
"gatsby-plugin-manifest": "^2.2.45",
|
||||
@@ -62,6 +63,7 @@
|
||||
"@graphql-codegen/typescript": "1.13.0",
|
||||
"@graphql-codegen/typescript-operations": "1.13.0",
|
||||
"@graphql-codegen/typescript-react-apollo": "1.13.0",
|
||||
"@types/classnames": "^2.2.10",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/prismjs": "^1.16.0",
|
||||
"@types/ramda": "^0.26.43",
|
||||
|
||||
@@ -14,7 +14,7 @@ interface IBreadcrumbProps {
|
||||
basePath: string
|
||||
}
|
||||
|
||||
const Link: FC<ILinkProps> = ({ item }) => {
|
||||
const LinkItem: FC<ILinkProps> = ({ item }) => {
|
||||
return <SC.StyledLink to={item.path}>{humanize(item.title)}</SC.StyledLink>
|
||||
}
|
||||
|
||||
@@ -32,17 +32,17 @@ function flatten([
|
||||
export function Breadcrumb({ relativePath, basePath }: IBreadcrumbProps) {
|
||||
const paths = relativePath.split("/")
|
||||
const breadcrumbItems = flatten([traversePaths(paths, basePath)])
|
||||
let foldersDepth = 0;
|
||||
let foldersDepth = 0
|
||||
return (
|
||||
<SC.BreadcrumbWrapper>
|
||||
<SC.LinkWrapper>
|
||||
<Link
|
||||
<LinkItem
|
||||
item={{ path: "/", title: "home", type: "folder", children: [] }}
|
||||
/>
|
||||
<ChevronUp />
|
||||
</SC.LinkWrapper>
|
||||
<SC.LinkWrapper>
|
||||
<Link
|
||||
<LinkItem
|
||||
item={{
|
||||
path: basePath,
|
||||
title: basePath.replace(/\//, ""),
|
||||
@@ -55,18 +55,18 @@ export function Breadcrumb({ relativePath, basePath }: IBreadcrumbProps) {
|
||||
|
||||
{breadcrumbItems.map(item => {
|
||||
if (item.type === "folder") {
|
||||
foldersDepth++;
|
||||
foldersDepth++
|
||||
if (foldersDepth > 1) {
|
||||
return (
|
||||
<SC.LinkWrapper key={item.path}>
|
||||
{ item.title }
|
||||
<ChevronUp />
|
||||
</SC.LinkWrapper>
|
||||
<SC.LinkWrapper key={item.path}>
|
||||
{item.title}
|
||||
<ChevronUp />
|
||||
</SC.LinkWrapper>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<SC.LinkWrapper key={item.path}>
|
||||
<Link item={item} />
|
||||
<LinkItem item={item} />
|
||||
<ChevronUp />
|
||||
</SC.LinkWrapper>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Link } from "gatsby"
|
||||
import { darken, lighten } from "polished"
|
||||
import styled from "styled-components"
|
||||
|
||||
export const BreadcrumbWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
@@ -16,6 +16,7 @@ export const LinkWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
white-space: nowrap;
|
||||
|
||||
svg {
|
||||
width: 12px;
|
||||
@@ -24,20 +25,21 @@ export const LinkWrapper = styled.div`
|
||||
}
|
||||
|
||||
svg path {
|
||||
fill: ${props => props.theme.main.link};
|
||||
fill: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
}
|
||||
`
|
||||
|
||||
export const StyledLink = styled(Link)`
|
||||
color: ${props => props.theme.main.link};
|
||||
color: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
cursor: pointer;
|
||||
font-weight: 700;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: #045551;
|
||||
color: ${props =>
|
||||
props.theme.name === "dark"
|
||||
? lighten(0.15, props.theme.main.link)
|
||||
: darken(0.15, props.theme.main.link)};
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
`
|
||||
|
||||
@@ -45,4 +47,5 @@ export const CurrentPage = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 30px;
|
||||
white-space: nowrap;
|
||||
`
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
import styled from "styled-components"
|
||||
|
||||
export const ContainerWrapper = styled.div``
|
||||
export const ContainerWrapper = styled.div`
|
||||
--padding: 64px;
|
||||
width: 650px;
|
||||
max-width: calc(100% - var(--padding) * 2);
|
||||
padding: 0px var(--padding);
|
||||
margin: 0 auto;
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
--padding: 32px;
|
||||
}
|
||||
`
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import React from "react"
|
||||
import * as SC from "./styles"
|
||||
|
||||
export const ContentPage: React.FC = ({ children, ...restProps }) => {
|
||||
return (
|
||||
<SC.ContentPageWrapper {...restProps}>{children}</SC.ContentPageWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import styled from "styled-components"
|
||||
|
||||
export const ContentPageWrapper = styled.div`
|
||||
width: calc(100% - 305px);
|
||||
margin-right: 305px;
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
`
|
||||
@@ -1,19 +1,17 @@
|
||||
import React, { FC } from "react"
|
||||
import packageJson from "../../../package.json"
|
||||
import { Container } from "../Container"
|
||||
import { Link } from "../Link"
|
||||
import * as SC from "./styles"
|
||||
|
||||
export const Footer: FC = () => {
|
||||
return (
|
||||
<SC.FooterWrapper>
|
||||
<Container>
|
||||
<p>
|
||||
© {new Date().getFullYear()}, Built with
|
||||
{` `}
|
||||
<a href="https://www.gatsbyjs.org">Gatsby</a> - Source on{" "}
|
||||
<a href={packageJson.repository.url}>GitHub</a>
|
||||
</p>
|
||||
</Container>
|
||||
<p>
|
||||
© {new Date().getFullYear()}, Built with
|
||||
{` `}
|
||||
<Link to="https://www.gatsbyjs.org">Gatsby</Link> - Source on{" "}
|
||||
<Link to={packageJson.repository.url}>GitHub</Link>
|
||||
</p>
|
||||
</SC.FooterWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,20 +1,34 @@
|
||||
import styled from "styled-components"
|
||||
|
||||
export const FooterWrapper = styled.footer`
|
||||
margin-top: 128px;
|
||||
margin-top: 64px;
|
||||
|
||||
& a {
|
||||
display: inline;
|
||||
color: #0090d8;
|
||||
font-weight: 700;
|
||||
border-bottom: 2px solid;
|
||||
color: #fff;
|
||||
color: ${props => props.theme.main.foreground};
|
||||
font-weight: 700;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #5dbbea;
|
||||
transition: none;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { FC, Fragment } from "react"
|
||||
import React from "react"
|
||||
import cx from "classnames"
|
||||
|
||||
import ChevronUp from "../../icons/chevron-up.svg"
|
||||
import { HeaderBarebone } from "../HeaderBarebone"
|
||||
import { Breadcrumb } from "../Breadcrumb"
|
||||
import { StackedAvatars } from "../StackedAvatars"
|
||||
import * as SC from "./styles"
|
||||
@@ -9,54 +10,24 @@ interface IHeaderProps {
|
||||
relativePath: string
|
||||
basePath: string
|
||||
title: string
|
||||
authors?: Array<{
|
||||
authors?: {
|
||||
avatar: string
|
||||
hash: string
|
||||
name: string
|
||||
}>
|
||||
}[]
|
||||
createdAt: string
|
||||
timeToRead: number
|
||||
recommendedReading?: string[]
|
||||
externalResources?: string[]
|
||||
shifted: boolean
|
||||
}
|
||||
|
||||
function ExtraLink({
|
||||
item,
|
||||
external = false,
|
||||
}: {
|
||||
item: string
|
||||
external?: boolean
|
||||
}) {
|
||||
const Inner = () => (
|
||||
<Fragment>
|
||||
<ChevronUp /> <SC.ExtraLinkText>{item}</SC.ExtraLinkText>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
if (external) {
|
||||
return (
|
||||
<SC.ExtraLinkExternal href={item} target="_blank">
|
||||
<Inner />
|
||||
</SC.ExtraLinkExternal>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<SC.ExtraLinkInternal to={`/resources/${item}.md`}>
|
||||
<Inner />
|
||||
</SC.ExtraLinkInternal>
|
||||
)
|
||||
}
|
||||
|
||||
export const Header: FC<IHeaderProps> = ({
|
||||
export const Header: React.FC<IHeaderProps> = ({
|
||||
basePath,
|
||||
relativePath,
|
||||
title,
|
||||
authors,
|
||||
createdAt,
|
||||
timeToRead,
|
||||
recommendedReading,
|
||||
externalResources,
|
||||
shifted,
|
||||
}) => {
|
||||
const date = new Date(createdAt)
|
||||
const month = date.toLocaleString("default", { month: "long" })
|
||||
@@ -65,48 +36,31 @@ export const Header: FC<IHeaderProps> = ({
|
||||
const dateToHuman = `${month} ${day}, ${year}`
|
||||
|
||||
return (
|
||||
<SC.HeaderWrapper>
|
||||
<Breadcrumb relativePath={relativePath} basePath={basePath} />
|
||||
|
||||
<SC.Title>{title}</SC.Title>
|
||||
|
||||
<SC.Top>
|
||||
{authors && (
|
||||
<HeaderBarebone
|
||||
above={<Breadcrumb relativePath={relativePath} basePath={basePath} />}
|
||||
title={title}
|
||||
className={cx({ shifted })}
|
||||
content={
|
||||
<SC.Top>
|
||||
{authors && (
|
||||
<SC.Meta>
|
||||
<StackedAvatars authors={authors} />
|
||||
<SC.PopoverToggler>
|
||||
{authors.length} contributor{authors.length > 1 && "s"}
|
||||
<SC.Popover>
|
||||
{authors
|
||||
.map(author => `${author.name}#${author.hash}`)
|
||||
.join(", ")}
|
||||
</SC.Popover>
|
||||
</SC.PopoverToggler>
|
||||
</SC.Meta>
|
||||
)}
|
||||
{dateToHuman && <SC.Meta>{dateToHuman}</SC.Meta>}
|
||||
<SC.Meta>
|
||||
<StackedAvatars authors={authors} />
|
||||
<SC.PopoverToggler>
|
||||
{authors.length} contributor{authors.length > 1 && "s"}
|
||||
<SC.Popover>
|
||||
{authors
|
||||
.map(author => `${author.name}#${author.hash}`)
|
||||
.join(", ")}
|
||||
</SC.Popover>
|
||||
</SC.PopoverToggler>
|
||||
{timeToRead} minute{timeToRead !== 1 && "s"} read time
|
||||
</SC.Meta>
|
||||
)}
|
||||
{dateToHuman && <SC.Meta>{dateToHuman}</SC.Meta>}
|
||||
<SC.Meta>
|
||||
{timeToRead} minute{timeToRead !== 1 && "s"} read time
|
||||
</SC.Meta>
|
||||
</SC.Top>
|
||||
|
||||
{recommendedReading && (
|
||||
<SC.RecommendedReading>
|
||||
Recommended reading
|
||||
{recommendedReading.map(item => {
|
||||
return <ExtraLink key={item} item={item} />
|
||||
})}
|
||||
</SC.RecommendedReading>
|
||||
)}
|
||||
|
||||
{externalResources && (
|
||||
<SC.ExternalResources>
|
||||
External Resources
|
||||
{externalResources.map(item => {
|
||||
return <ExtraLink key={item} item={item} external />
|
||||
})}
|
||||
</SC.ExternalResources>
|
||||
)}
|
||||
</SC.HeaderWrapper>
|
||||
</SC.Top>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,42 +1,31 @@
|
||||
import { Link } from "gatsby"
|
||||
import { darken, lighten } from "polished"
|
||||
import styled, { css } from "styled-components"
|
||||
import { fontFamily, modularScale } from "../../design/typography"
|
||||
|
||||
export const HeaderWrapper = styled.div`
|
||||
border-bottom: 1px solid #dbdbdb;
|
||||
padding-bottom: 32px;
|
||||
margin-bottom: 32px;
|
||||
`
|
||||
import { transparentize } from "polished"
|
||||
import styled from "styled-components"
|
||||
|
||||
export const Top = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
@media screen and (max-width: 1200px) {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
`
|
||||
|
||||
export const Title = styled.h1`
|
||||
font-family: ${fontFamily.header};
|
||||
font-size: ${modularScale(6).fontSize}px;
|
||||
line-height: ${modularScale(6).lineHeight}px;
|
||||
letter-spacing: -1.75px;
|
||||
margin-top: 0;
|
||||
`
|
||||
|
||||
export const Meta = styled.div`
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
color: ${props =>
|
||||
props.theme.name === "dark"
|
||||
? transparentize(0.1, props.theme.main.foreground)
|
||||
: transparentize(0.1, props.theme.main.foreground)};
|
||||
|
||||
& + &::before {
|
||||
content: "•";
|
||||
margin: 0 8px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
@media screen and (max-width: 1200px) {
|
||||
& + & {
|
||||
margin-top: 8px;
|
||||
}
|
||||
@@ -47,53 +36,6 @@ export const Meta = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
const ExtraLinks = styled.div`
|
||||
margin-top: 16px;
|
||||
`
|
||||
|
||||
export const RecommendedReading = styled(ExtraLinks)``
|
||||
|
||||
export const ExternalResources = styled(ExtraLinks)``
|
||||
|
||||
const extraLink = css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: ${props => props.theme.main.link};
|
||||
margin-top: 4px;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: ${props =>
|
||||
props.theme.name === "dark"
|
||||
? lighten(0.15, props.theme.main.link)
|
||||
: darken(0.15, props.theme.main.link)};
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 14px;
|
||||
flex: 0 0 14px;
|
||||
transform: rotate(90deg);
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
svg path {
|
||||
fill: ${props => props.theme.main.link};
|
||||
}
|
||||
`
|
||||
|
||||
export const ExtraLinkInternal = styled(Link)`
|
||||
${extraLink};
|
||||
`
|
||||
|
||||
export const ExtraLinkExternal = styled.a`
|
||||
${extraLink};
|
||||
`
|
||||
|
||||
export const ExtraLinkText = styled.div`
|
||||
text-decoration: underline;
|
||||
`
|
||||
|
||||
export const Popover = styled.div`
|
||||
display: none;
|
||||
position: absolute;
|
||||
@@ -101,10 +43,11 @@ export const Popover = styled.div`
|
||||
margin-top: 8px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
backdrop-filter: blur(14px);
|
||||
background: ${props =>
|
||||
props.theme.name === "dark"
|
||||
? lighten(0.1, props.theme.main.background)
|
||||
: darken(0.1, props.theme.main.background)};
|
||||
? transparentize(0.3, props.theme.main.background)
|
||||
: transparentize(0.3, props.theme.main.background)};
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
@@ -113,13 +56,14 @@ export const Popover = styled.div`
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
backdrop-filter: blur(14px);
|
||||
border-style: solid;
|
||||
border-width: 0 3.5px 4px 3.5px;
|
||||
border-color: transparent transparent
|
||||
${props =>
|
||||
props.theme.name === "dark"
|
||||
? lighten(0.1, props.theme.main.background)
|
||||
: darken(0.1, props.theme.main.background)}
|
||||
? transparentize(0.3, props.theme.main.background)
|
||||
: transparentize(0.3, props.theme.main.background)}
|
||||
transparent;
|
||||
}
|
||||
`
|
||||
@@ -128,6 +72,11 @@ export const PopoverToggler = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-bottom: 1px dashed
|
||||
${props =>
|
||||
props.theme.name === "dark"
|
||||
? transparentize(0.1, props.theme.main.foreground)
|
||||
: transparentize(0.1, props.theme.main.foreground)};
|
||||
|
||||
&:hover ${Popover} {
|
||||
display: block;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from "react"
|
||||
|
||||
import * as SC from "./styles"
|
||||
import { Container } from "../Container"
|
||||
|
||||
interface IHeaderBareboneProps {
|
||||
above?: React.ReactNode
|
||||
title: string
|
||||
content?: React.ReactNode
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const HeaderBarebone: React.FC<IHeaderBareboneProps> = props => {
|
||||
return (
|
||||
<SC.HeaderWrapper className={props.className}>
|
||||
<SC.BackgroundWrapper>
|
||||
<SC.StyledWavesBottom />
|
||||
<SC.StyledWavesTop />
|
||||
<SC.StyledCircles />
|
||||
</SC.BackgroundWrapper>
|
||||
|
||||
<Container>
|
||||
<SC.Box>
|
||||
{props.above}
|
||||
|
||||
<SC.Title>{props.title}</SC.Title>
|
||||
|
||||
{props.content}
|
||||
</SC.Box>
|
||||
</Container>
|
||||
</SC.HeaderWrapper>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
import { transparentize, darken } from "polished"
|
||||
import styled from "styled-components"
|
||||
import { fontFamily, modularScale } from "../../design/typography"
|
||||
import { WavesTop, WavesBottom } from "../Waves"
|
||||
import Circles from "../../images/circles.svg"
|
||||
|
||||
export const HeaderWrapper = styled.div`
|
||||
width: 100%;
|
||||
height: 391px;
|
||||
padding-top: 67px;
|
||||
position: relative;
|
||||
|
||||
&.shifted {
|
||||
width: calc(100% - 305px);
|
||||
padding-right: 305px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: 100% !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
height: auto;
|
||||
min-height: 391px;
|
||||
}
|
||||
`
|
||||
|
||||
export const BackgroundWrapper = styled.div`
|
||||
height: 391px;
|
||||
padding-top: 67px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
height: calc(100% - 67px);
|
||||
background: ${props => darken(0.2, props.theme.main.background)};
|
||||
}
|
||||
`
|
||||
|
||||
export const StyledCircles = styled(Circles)`
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -200px;
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
margin-top: -145px;
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
`
|
||||
|
||||
export const StyledWavesTop = styled(WavesTop)`
|
||||
opacity: ${props => (props.theme.name === "dark" ? 0.8 : 0.2)};
|
||||
top: -10%;
|
||||
transform: scaleX(-1);
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
top: 0;
|
||||
}
|
||||
`
|
||||
|
||||
export const StyledWavesBottom = styled(WavesBottom)`
|
||||
opacity: ${props => (props.theme.name === "dark" ? 0.8 : 0.2)};
|
||||
bottom: -30%;
|
||||
transform: scaleX(-1);
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
bottom: 0;
|
||||
}
|
||||
`
|
||||
|
||||
export const Box = styled.div`
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
margin-left: -16px;
|
||||
background: ${props => transparentize(0.3, props.theme.main.background)};
|
||||
padding: 16px;
|
||||
backdrop-filter: blur(14px);
|
||||
max-width: 650px;
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
max-width: 100%;
|
||||
left: 32px;
|
||||
right: 32px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
position: static;
|
||||
bottom: auto;
|
||||
top: auto;
|
||||
margin: 32px 0;
|
||||
}
|
||||
`
|
||||
|
||||
export const Title = styled.h1`
|
||||
font-family: ${fontFamily.header};
|
||||
font-size: ${modularScale(6).fontSize}px;
|
||||
line-height: ${modularScale(6).lineHeight}px;
|
||||
letter-spacing: -1.75px;
|
||||
margin-top: 0;
|
||||
margin: 0;
|
||||
|
||||
& + * {
|
||||
margin-top: 16px;
|
||||
}
|
||||
`
|
||||
@@ -10,7 +10,7 @@ export const HomeWrapper = styled.header`
|
||||
width: 100%;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
background: #1f2a34;
|
||||
background: ${props => props.theme.main.background};
|
||||
overflow: hidden;
|
||||
`
|
||||
|
||||
|
||||
@@ -2,16 +2,31 @@ import { Link } from "gatsby"
|
||||
import styled, { css } from "styled-components"
|
||||
|
||||
const linkStyle = css`
|
||||
color: #0090d8;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
color: ${props => props.theme.main.foreground};
|
||||
font-weight: 700;
|
||||
border-bottom: 2px solid;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: #5dbbea;
|
||||
transition: none;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { darken, lighten } from "polished"
|
||||
import styled, { css } from "styled-components"
|
||||
import {
|
||||
BASE_FONT_SIZE,
|
||||
@@ -78,7 +77,7 @@ export const MarkdownWrapper = styled.div`
|
||||
}
|
||||
|
||||
code {
|
||||
background: #192129;
|
||||
background: ${props => props.theme.code.background};
|
||||
padding: 4px 8px;
|
||||
display: inline;
|
||||
border-radius: 3px;
|
||||
@@ -89,7 +88,7 @@ export const MarkdownWrapper = styled.div`
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
overflow-x: auto;
|
||||
background: #192129;
|
||||
background: ${props => props.theme.code.background};
|
||||
}
|
||||
|
||||
pre > code[class*="language-"] {
|
||||
@@ -122,16 +121,30 @@ export const MarkdownWrapper = styled.div`
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
a:not(.anchor) {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
font-weight: 700;
|
||||
color: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
text-decoration: none;
|
||||
word-break: break-word;
|
||||
color: ${props => props.theme.main.link};
|
||||
cursor: pointer;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: ${props =>
|
||||
props.theme.name === "dark"
|
||||
? lighten(0.15, props.theme.main.link)
|
||||
: darken(0.15, props.theme.main.link)};
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@@ -5,7 +5,8 @@ import Logo from "../../images/tph-logo.svg"
|
||||
|
||||
export const MobileHeaderWrapper = styled.div`
|
||||
z-index: 50;
|
||||
background: ${props => transparentize(0.2, props.theme.main.background)};
|
||||
background: ${props => transparentize(0.6, props.theme.main.background)};
|
||||
backdrop-filter: blur(14px);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import React, { FC, Fragment } from "react"
|
||||
|
||||
import { humanize } from "../../utils"
|
||||
import * as SC from "./styles"
|
||||
import { Container } from "../Container"
|
||||
|
||||
interface IPageContentProps {
|
||||
content: JSX.Element
|
||||
recommendedReading?: string[]
|
||||
externalResources?: string[]
|
||||
}
|
||||
|
||||
function ExtraLink({
|
||||
item,
|
||||
external = false,
|
||||
}: {
|
||||
item: string
|
||||
external?: boolean
|
||||
}) {
|
||||
const Inner = ({ text }: { text: string }) => (
|
||||
<Fragment>
|
||||
<SC.ExtraLinkText>{text}</SC.ExtraLinkText>
|
||||
</Fragment>
|
||||
)
|
||||
|
||||
if (external) {
|
||||
return (
|
||||
<SC.ExtraLinkExternal href={item} target="_blank">
|
||||
<Inner text={item} />
|
||||
</SC.ExtraLinkExternal>
|
||||
)
|
||||
}
|
||||
|
||||
const [internalText] = item.split("/").slice(-1)
|
||||
|
||||
return (
|
||||
<SC.ExtraLinkInternal to={`/resources/${item}.md`}>
|
||||
<Inner text={humanize(internalText)} />
|
||||
</SC.ExtraLinkInternal>
|
||||
)
|
||||
}
|
||||
|
||||
export const PageContent: FC<IPageContentProps> = ({
|
||||
content,
|
||||
recommendedReading,
|
||||
externalResources,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<SC.Content>
|
||||
<Container>{content}</Container>
|
||||
</SC.Content>
|
||||
|
||||
<SC.Sidebar>
|
||||
{recommendedReading && (
|
||||
<SC.RecommendedReading>
|
||||
<SC.SidebarHeader>Recommended reading</SC.SidebarHeader>
|
||||
{recommendedReading.map(item => {
|
||||
return <ExtraLink key={item} item={item} />
|
||||
})}
|
||||
</SC.RecommendedReading>
|
||||
)}
|
||||
|
||||
{externalResources && (
|
||||
<SC.ExternalResources>
|
||||
<SC.SidebarHeader>External Resources</SC.SidebarHeader>
|
||||
{externalResources.map(item => {
|
||||
return <ExtraLink key={item} item={item} external />
|
||||
})}
|
||||
</SC.ExternalResources>
|
||||
)}
|
||||
</SC.Sidebar>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import styled, { css } from "styled-components"
|
||||
import { Link } from "gatsby"
|
||||
import fontFamily from "../../design/typography"
|
||||
import { darken } from "polished"
|
||||
|
||||
export const Content = styled.div`
|
||||
flex: 1 1 calc(100% - 305px);
|
||||
width: calc(100% - 305px);
|
||||
padding: 64px 0;
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: 100%;
|
||||
flex-basis: auto;
|
||||
}
|
||||
`
|
||||
|
||||
export const Sidebar = styled.div`
|
||||
width: 240px;
|
||||
flex: 0 0 240px;
|
||||
border-left: 1px solid ${props => darken(0.1, props.theme.main.background)};
|
||||
color: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
margin: 64px 0;
|
||||
padding: 0 32px;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1200px) {
|
||||
width: auto;
|
||||
padding: 64px;
|
||||
flex-basis: auto;
|
||||
|
||||
& > :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
export const SidebarHeader = styled.div`
|
||||
font-family: ${fontFamily.header};
|
||||
font-weight: 700;
|
||||
font-size: 18px;
|
||||
margin-bottom: 8px;
|
||||
margin-top: 0;
|
||||
`
|
||||
|
||||
const ExtraLinks = styled.div`
|
||||
margin-top: 16px;
|
||||
`
|
||||
|
||||
export const RecommendedReading = styled(ExtraLinks)``
|
||||
|
||||
export const ExternalResources = styled(ExtraLinks)``
|
||||
|
||||
const extraLink = css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
||||
& + & {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 14px;
|
||||
flex: 0 0 14px;
|
||||
transform: rotate(90deg);
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
svg path {
|
||||
fill: ${props => (props.theme.name === "dark" ? "#f9f9f9" : "#172129")};
|
||||
}
|
||||
`
|
||||
|
||||
export const ExtraLinkInternal = styled(Link)`
|
||||
${extraLink};
|
||||
`
|
||||
|
||||
export const ExtraLinkExternal = styled.a`
|
||||
${extraLink};
|
||||
`
|
||||
|
||||
export const ExtraLinkText = styled.div`
|
||||
word-break: break-word;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: linear-gradient(92.97deg, #feaf6d 0%, #ff70a5 100%);
|
||||
}
|
||||
`
|
||||
@@ -124,6 +124,10 @@ export const ExpandLanguagesHeader = styled.div`
|
||||
cursor: pointer;
|
||||
color: ${props => transparentize(0.5, props.theme.sidebar.foreground)};
|
||||
font-weight: 700;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
`
|
||||
|
||||
export const ExpandLanguagesList = styled.div`
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Link } from "gatsby"
|
||||
import React, { FC, HTMLAttributes, PropsWithChildren } from "react"
|
||||
import Scrollbar from "react-perfect-scrollbar"
|
||||
import "react-perfect-scrollbar/dist/css/styles.css"
|
||||
import Banner from "../../images/tph-banner.svg"
|
||||
import cx from "classnames"
|
||||
import { ThemeToggler } from "../ThemeToggler"
|
||||
import * as SC from "./styles"
|
||||
|
||||
@@ -22,18 +21,21 @@ export const Sidebar: FC<PropsWithChildren<
|
||||
HTMLAttributes<HTMLDivElement>
|
||||
>> = props => {
|
||||
const { children, ...restProps } = props
|
||||
const isBorderVisible = children === undefined ? false : true
|
||||
|
||||
return (
|
||||
<SC.SidebarWrapper {...restProps}>
|
||||
<Scrollbar>
|
||||
<Link to="/">
|
||||
<Banner />
|
||||
</Link>
|
||||
<SC.Title to="/">
|
||||
The
|
||||
<br />
|
||||
Programmer's
|
||||
<br />
|
||||
Hangout
|
||||
</SC.Title>
|
||||
<SC.Inner>
|
||||
{children}
|
||||
|
||||
<SC.Menu borderVisibility={isBorderVisible}>
|
||||
<SC.Menu className={cx({ "has-border": Boolean(children) })}>
|
||||
<MenuItem to="/about">about</MenuItem>
|
||||
<MenuItem to="/rules">rules</MenuItem>
|
||||
<MenuItem to="/resources">resources</MenuItem>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Link } from "gatsby"
|
||||
import styled, { css } from "styled-components"
|
||||
import { transparentize } from "polished"
|
||||
|
||||
export const SidebarWrapper = styled.div`
|
||||
box-sizing: border-box;
|
||||
@@ -27,17 +28,34 @@ export const SidebarWrapper = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
export const Title = styled(Link)`
|
||||
display: block;
|
||||
color: ${props => props.theme.sidebar.foreground};
|
||||
font-size: 30px;
|
||||
line-height: 34px;
|
||||
font-weight: 700;
|
||||
padding: 20px 0 0 20px;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
`
|
||||
|
||||
export const Inner = styled.div`
|
||||
padding: 30px 0 30px 20px;
|
||||
padding: 20px 0 30px 20px;
|
||||
`
|
||||
|
||||
export const Menu = styled.nav`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: ${props =>
|
||||
props.borderVisibility ? "1px dashed #a5a5a5" : "none"};
|
||||
margin: 20px 0 40px;
|
||||
padding-top: 20px;
|
||||
|
||||
&.has-border {
|
||||
border-top: ${props =>
|
||||
`1px dashed ${transparentize(0.8, props.theme.sidebar.foreground)}`};
|
||||
}
|
||||
`
|
||||
|
||||
export const menuItemStyles = css`
|
||||
|
||||
@@ -22,7 +22,7 @@ export const AuthorAvatar = styled.img<{ index: number }>`
|
||||
width: ${AVATAR_SIZE}px;
|
||||
height: ${AVATAR_SIZE}px;
|
||||
flex: 0 0 ${AVATAR_SIZE}px;
|
||||
border: 2px solid #fff;
|
||||
border: 2px solid #4c6780;
|
||||
border-radius: 50%;
|
||||
z-index: ${props => props.index};
|
||||
left: -${props => AVATAR_SIZE * OVERLAP_AMOUT * props.index}px;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import React, { FC } from "react"
|
||||
import * as SC from "./styles"
|
||||
|
||||
export const WavesTop: FC = () => {
|
||||
return <SC.StyledWavesTop />
|
||||
export const WavesTop: FC = props => {
|
||||
return <SC.StyledWavesTop {...props} />
|
||||
}
|
||||
|
||||
export const WavesBottom: FC = () => {
|
||||
return <SC.StyledWavesBottom />
|
||||
export const WavesTopTwo: FC = props => {
|
||||
return <SC.StyledWavesTopTwo {...props} />
|
||||
}
|
||||
|
||||
export const WavesBottom: FC = props => {
|
||||
return <SC.StyledWavesBottom {...props} />
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import styled, { css } from "styled-components"
|
||||
import WavesBottom from "../../images/waves-bot.svg"
|
||||
import WavesTop from "../../images/waves-top.svg"
|
||||
import WavesTopTwo from "../../images/waves-top2.svg"
|
||||
|
||||
const waves = css`
|
||||
display: block;
|
||||
@@ -17,6 +18,12 @@ export const StyledWavesTop = styled(WavesTop)`
|
||||
height: 87vh;
|
||||
`
|
||||
|
||||
export const StyledWavesTopTwo = styled(WavesTopTwo)`
|
||||
${waves};
|
||||
top: 0;
|
||||
height: 87vh;
|
||||
`
|
||||
|
||||
export const StyledWavesBottom = styled(WavesBottom)`
|
||||
${waves};
|
||||
bottom: 0;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
path: /about
|
||||
---
|
||||
|
||||
# About Us
|
||||
|
||||
## What is The Programmers Hangout?
|
||||
|
||||
The Programmer's Hangout (TPH) is a discord community geared towards programming. The use of the word "geared" here is important because more accurately it's a discord for programmers of all kinds. If you're a green noob with 5 lines of code under your belt, or if you're a veteran with 15 years of industry experience, TPH has a place for you. More than that, there are over 30,000 people here. You can guarantee you won't be the only person with your experience level on the server.
|
||||
|
||||
+75
-42
@@ -12,100 +12,125 @@ path: /rules
|
||||
- [Nickname Policy](#nickname-policy)
|
||||
- [What is Modmail / How to contact staff](#what-is-modmail)
|
||||
|
||||
# General Rules
|
||||
## General Rules
|
||||
|
||||
Below you will find the rules of the server. These are the dos and don'ts of being here. Follow them if you wish to stay, ignorance is not an excuse.
|
||||
|
||||
**1. Do not advertise.**<br />
|
||||
### 1. Do not advertise.
|
||||
|
||||
This includes other servers, products or services that you stand to benefit from financially, your Youtube channel or the like.
|
||||
|
||||
**2. Do not be a dick.**<br />
|
||||
### 2. Do not be a dick.
|
||||
|
||||
If you make yourself particularly hard to deal with, if you pretend that you are better than anyone else, or if you are just in general very annoying and not a good fit for this server we will remove you. Permanently.
|
||||
|
||||
**3. Use facts, not authority.**<br />
|
||||
### 3. Use facts, not authority.
|
||||
|
||||
If you are going to provide an anecdote or your own experience, that is fine, provided you don't pass it off as axiomatic. Quote sources when you are asked to.
|
||||
|
||||
**4. Do not flame languages or other such technologies (e.g. text editors).**<br />
|
||||
### 4. Do not flame languages or other such technologies (e.g. text editors).
|
||||
|
||||
Doing so is reductive. If someone likes to use VB.Net or JavaScript or Vim, we surprisingly expect you to not jump down their throat about that. Doing so outside of regulated channels where staff have explicitly allowed the discussion for a short period of time is not allowed ( #poll-discussion is one such example of an okay place to talk about it provided the poll allows it )
|
||||
|
||||
**5. Speak English only in the chat.**<br />
|
||||
### 5. Speak English only in the chat.
|
||||
|
||||
This speaks for itself, we do not expect staff to speak extra languages and we cannot moderate what we do not understand. Sorry.
|
||||
|
||||
**6. Do not ask for free work.**<br />
|
||||
### 6. Do not ask for free work.
|
||||
|
||||
This is not an advertisement platform. If you are going to take from this community, you are going to give back to it first. We do not care about your work if you do not care about us. Thanks.
|
||||
|
||||
**7. Do not DM people who you have not built a rapport with.**<br />
|
||||
### 7. Do not DM people who you have not built a rapport with.
|
||||
|
||||
This is self-explanatory. Don't be a creep. Don't be a pest, ask questions in relevant channels. Someone's DM is not a relevant channel.
|
||||
|
||||
**8. Do not talk about your infractions publicly.**<br />
|
||||
### 8. Do not talk about your infractions publicly.
|
||||
|
||||
If you are infracted, it's not a big deal. It's simply a formal warning - you can totally recover from that. If you disagree with a warning, DM @ModMail. Complaining about infractions publicly will land you a mute or a ban. Don't pollute chat or other channels with these conversations.
|
||||
|
||||
**9. Do not participate in spoonfeeding.**<br />
|
||||
### 9. Do not participate in spoonfeeding.
|
||||
|
||||
Asking to be spoonfed is the same as asking someone else to do your work for you. We do not condone just solving the problems of others -- make them work for it. Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime.
|
||||
|
||||
**10. Do not impersonate staff members.**<br />
|
||||
### 10. Do not impersonate staff members.
|
||||
|
||||
Using the avatar of another staff member that they've had for a reasonable long time is not allowed. You will be notified if you seem like you're impersonating a staff member. We may also nickname you depending on the context. In addition, it is especially prohibited to pretend to be another staff member through messages/voice, DM or otherwise. Doing so will land you an immediate, permanent ban.
|
||||
|
||||
**11. Follow the directions of staff members to the letter.**<br />
|
||||
### 11. Follow the directions of staff members to the letter.
|
||||
|
||||
Most of us are here for our love of programming, so we like to do as much talking about programming and the like as possible. That being said, we really don't like intervening. But we especially don't like having to intervene twice. Please don't make us do that, thank you
|
||||
|
||||
**12. No backseat driving.**<br />
|
||||
### 12. No backseat driving.
|
||||
|
||||
If you see people working through a problem, you shouldn't intermittently interject advice. Let them work it out unless someone asks for help. We understand you want to help out, but this can often cause confusion and overall a negative impact on the person who originally asked the question.
|
||||
|
||||
**13. Do not bad mouth linked servers.**<br />
|
||||
### 13. Do not bad mouth linked servers.
|
||||
|
||||
TPH is joined at the hip to Controversy Central (CC), KUtils, and Late Gaming (LG). If you don't like one of our linked servers, just leave them. Each server serves its own purpose.
|
||||
|
||||
**14. TPH is not a ban appeal vector for linked servers.**<br />
|
||||
### 14. TPH is not a ban appeal vector for linked servers.
|
||||
|
||||
Bans on all linked servers are propagated. This means that if you are banned on any of our servers (CC/KUtils/Late Gaming), you will be banned on all of them. Members with certain roles will be exempt from ban propagation, but that is no excuse to run riot on other servers. If you troll them, we will also ban you here. That being said, TPH is not a place to post your ban appeal. Please take it up with those servers.
|
||||
|
||||
**15. Link to the FAQ and beginner guide channels liberally.**<br />
|
||||
### 15. Link to the FAQ and beginner guide channels liberally.
|
||||
|
||||
The FAQ and beginner guide channels represent many hours of discussion to find well-rounded answers to common questions. Please link to them regularly when beginners and the uninformed ask those questions. You may be asked to cease your participation in a conversation if you present yourself as a zealot with distracting opinions.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# Golden Rules
|
||||
## Golden Rules
|
||||
|
||||
### 1. Don't be a pedant.
|
||||
|
||||
**1. Don't be a pedant.**<br />
|
||||
Don't be the type of person who fixates on minor details or meaningless trivia.
|
||||
|
||||
**2. Don't be a gatekeeper.**<br />
|
||||
### 2. Don't be a gatekeeper.
|
||||
|
||||
_Gatekeeping_ is when someone takes it upon themselves to decide who does or does not have access to a community/identity. i.e. “You’re not a _real_ programmer if you don’t use [language x]”
|
||||
|
||||
**3. Don't be cocky.**<br />
|
||||
### 3. Don't be cocky.
|
||||
|
||||
Always be humble. No one likes a cocky fool.
|
||||
|
||||
**4. Maintain a student mentality.**<br />
|
||||
### 4. Maintain a student mentality.
|
||||
|
||||
Treat other members, regardless of their skill level, as though you have something to learn from them.
|
||||
|
||||
In general, if you have a contribution to make, _please be encouraging_. Being pedantic or gatekeeping how "hard" something is or pretending like you're some kind of God when it comes to programming is purely reductive garbage. If you are found to be guilty of violating these tenants appropriate action shall be taken against you. There are far too many people out there actively discouraging self-improvement and learning. This server refuses to stand for it.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# Content Policy
|
||||
## Content Policy
|
||||
|
||||
Below is a list of things that you cannot talk about here. If a staff member cites you the content policy, please understand that they really mean _stop_ talking about the thing you are talking about. I think you will find the list reasonable, as we construct it to be conducive to an environment that suits talking about programming and technology in the absence of distractions.
|
||||
|
||||
**1. No politics, religion, philosophy or other such topics.**<br />
|
||||
### 1. No politics, religion, philosophy or other such topics.
|
||||
|
||||
This goes without saying. You don't make friends by talking to strangers about these topics. Your political views have nothing to do with how good of a programmer you are.
|
||||
|
||||
**2. No NSFW content in any capacity.**<br />
|
||||
### 2. No NSFW content in any capacity.
|
||||
|
||||
Always ask yourself "Would my boss be okay with this fullscreen on my monitor as he walked by?". If the answer is no, don't post it. The content here is meant to be pg13. Not pg15, not pg18 - if you wouldn't show it to your kid brother in front of your mother, it has no place here. No hentai, no porn, no anything like that.
|
||||
|
||||
**3. No talk of suicide or depression.**<br />
|
||||
### 3. No talk of suicide or depression.
|
||||
|
||||
Sorry to say, but if you are depressed or considering suicide, that is terrible and we feel sorry for you, but we do **not** feel qualified to give advice, to moderate advice given, or anything of the sort. It would be absolutely unfair of me to put that weight on the shoulders of the moderators here. So please, ring your local suicide hotline which you can hopefully find here: [http://www.suicide.org/international-suicide-hotlines.html](http://www.suicide.org/international-suicide-hotlines.html "http://www.suicide.org/international-suicide-hotlines.html") (or by googling it)
|
||||
|
||||
**4. No talk of illegal topics, pirating, reverse engineering, hacking, imitating user interaction or other similar topics.**<br />
|
||||
### 4. No talk of illegal topics, pirating, reverse engineering, hacking, imitating user interaction or other similar topics.
|
||||
|
||||
This includes anything against a site's terms of service, anything protected by a captcha/robots.txt and any automated account creation/checkout/purchasing. These topics are strictly forbidden. Topics related to these may also be disallowed.
|
||||
|
||||
**5. Don't ask for relationship or life advice.**<br />
|
||||
### 5. Don't ask for relationship or life advice.
|
||||
|
||||
As annoying as it is for me to write this, do not ask about how to "get the girl" or whatever. This is not the appropriate environment. Go look for dating advice and the like elsewhere. Complicated, heavy life advice topics that are not explicitly career-related are **off-limits** here as well. We're just programmers, we're not miracle makers.
|
||||
|
||||
**6. Do not bring other server drama here.**<br />
|
||||
### 6. Do not bring other server drama here.
|
||||
|
||||
We do not care that you got banned on another server. Sorry, but not our problem. Take it up with that server's staff.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# Why don't you allow talk regarding hacking?
|
||||
## Why don't you allow talk regarding hacking?
|
||||
|
||||
There are a few reasons for not allowing it: - It is directly against the Discord Terms of Service (ToS), allowing talk of how to perform hacks is basically never going to be allowed for this reason.
|
||||
|
||||
@@ -113,37 +138,43 @@ _Hacking is a dick move. Stop trying to be a dick._
|
||||
|
||||
It generally leads to even more illegal topics
|
||||
|
||||
**So then, what is allowed?**<br />
|
||||
#### So then, what is allowed?
|
||||
|
||||
Light talk about prevention is allowed. Providing elaborate details in any capacity of how someone might get past a system is not allowed.
|
||||
|
||||
**Where should I ask?**<br />
|
||||
#### Where should I ask?
|
||||
|
||||
Try not to, honestly, if you are looking to prevent a specific kind of attack feel free to ask if your code prevents that, outside of that sharing details as to how you might get past some code isn't the best idea, try to talk about the solution more so than the gory details of the problem. Feel free to share the gory details via DM, but don't wait to take the conversation to DM. This is one of the very few topic areas we want you to take it to DM, since information spread in this area is not something we want to prevent, rather, the discussion around it.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# Roles
|
||||
## Roles
|
||||
|
||||
TPH has a relatively small amount of roles, but each of our roles has a purpose. We don't have 30 language roles and a staff rank. That being said, it's kind of tricky to keep a track of all of the roles at once - so here you can see what they're for.
|
||||
|
||||
_Community-Member, Active Contributor, Chatterbox, Super-Talky-Guy, Bepis-Drinker, Conke-Commander, and Patriotic-Procrastinator_
|
||||
### _Community-Member, Active Contributor, Chatterbox, Super-Talky-Guy, Bepis-Drinker, Conke-Commander, and Patriotic-Procrastinator_
|
||||
|
||||
These are the activity roles of the server. Different tiers will grant different perks, such as unlocking hidden channels, voice access, and nicknaming privileges. These roles are assigned automatically as you participate in the server, so don't ask for them.
|
||||
|
||||
**Wizard**<br />
|
||||
### Wizard
|
||||
|
||||
This is for helpful members who have shown exceptional aptitude or expertise in some field. This is given out at the discretion of Elliott - though other staff members may suggest for Elliot to give it to someone. Less than 0.001% of users get this role.
|
||||
|
||||
**Technology Champion**<br />
|
||||
### Technology Champion
|
||||
|
||||
These people will try to provide some answers on their own time for questions in the Technology spotlight category. Often times these people will write the introductory text for the current technology as well. Staff will be preferred for this role, but not always - This is a temporary role.
|
||||
|
||||
**Solid Contributor**<br />
|
||||
### Solid Contributor
|
||||
|
||||
This role recognizes people who contribute their time and knowledge to the server completely out of their own volition.
|
||||
|
||||
**Staff roles**<br />
|
||||
### Staff roles
|
||||
|
||||
Self-explanatory - _ChatMod/Moderator/Senior Moderator/Admin/Owner_ - These people ensure that the usage of this environment reflects the guidelines as illustrated in the rules. Staff is occasionally handpicked, and sometimes there is an application process. There is a trial period for all new staff of 2-4 weeks (Sometimes more, sometimes less) which comes with a trial role, however, they are treated as full staff members during this time. Please respect all staff equally; if you have an issue with a specific staff member, talk to an administrator.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# Nickname Policy
|
||||
## Nickname Policy
|
||||
|
||||
On TPH, we enforce a nickname policy - This means that if your nickname is deemed too NSFW (not safe for work), or hard to read/tag (it uses weird characters, it's blank or it contains numbers) we can and will forcibly nickname you to something else.
|
||||
|
||||
@@ -155,21 +186,23 @@ If you pipe up and get annoyed and flustered that you don't have your name, you'
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
# What is ModMail?
|
||||
## What is ModMail?
|
||||
|
||||
ModMail (@ModMail) is a bot that reports every direct message received to staff.
|
||||
|
||||
**How do I use it?**<br />
|
||||
### How do I use it?
|
||||
|
||||
Send it a message. This will open a two-way communication medium between you and the entire staff team. It won't notify or bother people who are offline or busy, so don't even concern yourself with that part.
|
||||
|
||||
**Use it when you...**
|
||||
### Use it when you...
|
||||
|
||||
- Notice a heated argument about how bad JavaScript is.
|
||||
- Wish to dispute an infraction you have received.
|
||||
- Would like more context about a rule.
|
||||
- Would like to screen something with the staff before posting.
|
||||
|
||||
**Don't use it when you...**<br />
|
||||
### Don't use it when you...
|
||||
|
||||
Notice something which requires immediate attention such as raids or NSFW content. In these cases, use the serious rule break tag instead to immediately alert staff.
|
||||
|
||||
[Table of Contents](#table-of-contents)
|
||||
|
||||
@@ -11,6 +11,9 @@ export interface ITheme {
|
||||
base: string
|
||||
darker: string
|
||||
}
|
||||
code: {
|
||||
background: string
|
||||
}
|
||||
}
|
||||
|
||||
const baseColors = {
|
||||
@@ -18,18 +21,21 @@ const baseColors = {
|
||||
base: "#7289DA",
|
||||
darker: "#5265AD",
|
||||
},
|
||||
code: {
|
||||
background: "#0c1115",
|
||||
},
|
||||
}
|
||||
|
||||
export const darkTheme: ITheme = {
|
||||
...baseColors,
|
||||
name: "dark",
|
||||
sidebar: {
|
||||
background: "#293845",
|
||||
background: "#22323f",
|
||||
foreground: "#FFFFFF",
|
||||
active: "#00FCFF",
|
||||
},
|
||||
main: {
|
||||
background: "#1F2A34",
|
||||
background: "#16212b",
|
||||
foreground: "#FFFFFF",
|
||||
link: "#04B0A6",
|
||||
},
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg fill="none" viewBox="0 0 1340 635">
|
||||
<path fill="#EEF2F5" fill-opacity=".5" d="M863 120.73a32.79 32.79 0 110-65.58 32.79 32.79 0 010 65.58zM1188.94 493.27a64.09 64.09 0 110-128.18 64.09 64.09 0 010 128.18zM44.71 310.02a44.72 44.72 0 110-89.43 44.72 44.72 0 010 89.43zM393.49 634.95a44.72 44.72 0 110-89.43 44.72 44.72 0 010 89.43zM1328.03 23.85a11.93 11.93 0 110-23.85 11.93 11.93 0 010 23.85zM1211.77 253.38a11.92 11.92 0 110-23.84 11.92 11.92 0 010 23.84zM292.14 132.66a11.92 11.92 0 110-23.85 11.92 11.92 0 010 23.84zM70.05 478.45a11.92 11.92 0 110-23.85 11.92 11.92 0 010 23.85zM45.46 607.02a19.38 19.38 0 1119.38-33.57 19.38 19.38 0 01-19.38 33.57zM534.34 273.14a19.38 19.38 0 1119.38-33.56 19.38 19.38 0 01-19.38 33.56zM857.03 493.35a13.41 13.41 0 110-26.83 13.41 13.41 0 010 26.83z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 804 B |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,33 @@
|
||||
<svg fill="none" viewBox="0 0 1292 653">
|
||||
<g clip-path="url(#top2_mask)" opacity=".7">
|
||||
<path fill="url(#top2_gradient1)" d="M81.27 608.1s164.68 80.48 292.77 25.22c128.1-55.26 124.75-229.97 226.97-280.8 102.23-50.81 283.17 46.84 386.02 51.39 102.84 4.54 148.41-14.37 257.29-104.05 108.87-89.68-4.22-283.29-4.22-283.29s-444.7 7.5-493.54 20.32c-48.83 12.81-495.8 149.4-495.8 149.4L0 302.53 81.27 608.1z"/>
|
||||
<path fill="url(#top2_gradient2)" d="M81.27 591.53S245.94 672 374.03 616.75c128.1-55.26 124.75-229.98 226.97-280.8 102.23-50.81 283.17 46.84 386.02 51.39 102.84 4.54 148.41-14.37 257.29-104.05C1353.19 193.61 1240.1 0 1240.1 0S795.4 7.5 746.56 20.32c-48.83 12.81-495.8 149.4-495.8 149.4L0 285.96l81.27 305.57z"/>
|
||||
<path fill="url(#top2_gradient3)" d="M81.27 599.38s164.68 80.47 292.77 25.22c128.1-55.26 124.75-229.98 226.97-280.8C703.24 293 884.18 390.65 987.03 395.2c102.84 4.54 148.41-14.37 257.29-104.05 108.87-89.68-4.22-283.29-4.22-283.29s-444.7 7.5-493.54 20.32c-48.83 12.81-495.8 149.4-495.8 149.4L0 293.8l81.27 305.57z" opacity=".68"/>
|
||||
<path fill="url(#top2_gradient4)" d="M225.64 353.63c76.4 41.07 295.11 131.56 354.85 105.79 59.75-25.77 58.19-107.26 105.87-130.97 47.67-23.7 132.07 21.85 180.04 23.97 47.97 2.12 69.22-6.7 120-48.53s-1.97-132.13-1.97-132.13-205.76-22.63-228.54-16.65-251.53 35.16-251.53 35.16l-465.61 46.3s110.48 75.98 186.89 117.06z" opacity=".39"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="top2_gradient1" x1="743.55" x2="400.27" y1="70.57" y2="757.12" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#345EFE"/>
|
||||
<stop offset=".51" stop-color="#03B8FF"/>
|
||||
<stop offset="1" stop-color="#00FCFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="top2_gradient2" x1="715.46" x2="381.83" y1="121.82" y2="738.99" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#345EFE"/>
|
||||
<stop offset=".51" stop-color="#03B8FF"/>
|
||||
<stop offset="1" stop-color="#00FCFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="top2_gradient3" x1="743.55" x2="400.27" y1="61.85" y2="748.4" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#345EFE"/>
|
||||
<stop offset=".51" stop-color="#03B8FF"/>
|
||||
<stop offset="1" stop-color="#00FCFF"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="top2_gradient4" x1="573.02" x2="428.65" y1="168.74" y2="420.27" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#345EFE"/>
|
||||
<stop offset=".51" stop-color="#03B8FF"/>
|
||||
<stop offset="1" stop-color="#00FCFF"/>
|
||||
</linearGradient>
|
||||
<clipPath id="top2_mask">
|
||||
<path fill="#fff" d="M0 0h1291.64v652.7H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -1,6 +1,5 @@
|
||||
import React, { FC, Fragment } from "react"
|
||||
|
||||
import { Footer } from "../../components/Footer"
|
||||
import { MobileHeader } from "../../components/MobileHeader"
|
||||
import { GlobalStyles } from "../../globalStyles"
|
||||
import { useLockBodyScroll } from "../../hooks/useLockBodyScroll"
|
||||
@@ -39,12 +38,7 @@ const InnerColumnLayout: FC<IColumnLayoutProps> = ({
|
||||
<SC.Main>
|
||||
<MobileHeader openMenu={openMenu}>{title}</MobileHeader>
|
||||
{sidebar({ className: openOnMobile ? "is-open" : "" })}
|
||||
<SC.MainContent>
|
||||
<SC.Container>
|
||||
{content}
|
||||
<Footer />
|
||||
</SC.Container>
|
||||
</SC.MainContent>
|
||||
<SC.MainContent>{content}</SC.MainContent>
|
||||
</SC.Main>
|
||||
<SC.Overlay
|
||||
className={openOnMobile ? "is-open" : ""}
|
||||
|
||||
@@ -31,8 +31,11 @@ export const Overlay = styled.div`
|
||||
|
||||
export const MainContent = styled.main`
|
||||
flex: 1 1 auto;
|
||||
margin: 128px 0 128px 320px;
|
||||
margin: 0 0 0 320px;
|
||||
width: calc(100% - 320px);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: flex-start;
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
margin-left: 0;
|
||||
|
||||
+5
-1
@@ -4,6 +4,8 @@ import { MarkdownRemark } from "../../generated/graphql"
|
||||
import { ComponentQuery } from "../../typings"
|
||||
import { Markdown } from "../components/Markdown"
|
||||
import { SEO } from "../components/SEO"
|
||||
import { PageContent } from "../components/PageContent"
|
||||
import { HeaderBarebone } from "../components/HeaderBarebone"
|
||||
|
||||
function AboutPage({ data }: ComponentQuery<{ md: MarkdownRemark }>) {
|
||||
const { md } = data
|
||||
@@ -11,7 +13,9 @@ function AboutPage({ data }: ComponentQuery<{ md: MarkdownRemark }>) {
|
||||
return (
|
||||
<Fragment>
|
||||
<SEO title="About" />
|
||||
<Markdown content={md.html!} />
|
||||
<HeaderBarebone title="About us" />
|
||||
|
||||
<PageContent content={<Markdown content={md.html!} />} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import React, { Fragment } from "react"
|
||||
|
||||
import { HeaderBarebone } from "../../components/HeaderBarebone"
|
||||
import { Link } from "../../components/Link"
|
||||
import { PageContent } from "../../components/PageContent"
|
||||
import { SEO } from "../../components/SEO"
|
||||
|
||||
function ArchivesPage() {
|
||||
return (
|
||||
<Fragment>
|
||||
<SEO title="Tech Spotlights Archives" />
|
||||
<p>Welcome to the TPH tech spotlights archives.</p>
|
||||
<p>
|
||||
This regroups the archives of our occasional, temporary channels that
|
||||
cover a piece of technology that might be unknown to part of our users.
|
||||
You can find those on <Link to="/about">The Programmer's Hangout</Link>.
|
||||
</p>
|
||||
<HeaderBarebone title="Welcome to the TPH tech spotlights archives." />
|
||||
|
||||
<PageContent
|
||||
content={
|
||||
<p>
|
||||
This regroups the archives of our occasional, temporary channels
|
||||
that cover a piece of technology that might be unknown to part of
|
||||
our users. You can find those on{" "}
|
||||
<Link to="/about">The Programmer's Hangout</Link>.
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,35 @@
|
||||
import React, { Fragment } from "react"
|
||||
import React from "react"
|
||||
|
||||
import packageJson from "../../../package.json"
|
||||
import { HeaderBarebone } from "../../components/HeaderBarebone"
|
||||
import { Link } from "../../components/Link"
|
||||
import { PageContent } from "../../components/PageContent"
|
||||
import { ResourcesList } from "../../components/ResourcesList"
|
||||
import { SEO } from "../../components/SEO"
|
||||
|
||||
function ResourcesPage() {
|
||||
return (
|
||||
<Fragment>
|
||||
<>
|
||||
<SEO title="Resources" />
|
||||
<p>Welcome to the TPH resources.</p>
|
||||
<p>
|
||||
This is meant as a small knowledge base for commonly answered questions
|
||||
on our Discord community,{" "}
|
||||
<Link to="/about">The Programmer's Hangout</Link>.
|
||||
</p>
|
||||
<p>
|
||||
All of it is open source, and you can contribute to it on{" "}
|
||||
<Link to={packageJson.repository.url}>GitHub</Link>.
|
||||
</p>
|
||||
<ResourcesList />
|
||||
</Fragment>
|
||||
<HeaderBarebone
|
||||
title="Welcome to the TPH resources"
|
||||
content={
|
||||
<>
|
||||
<p>
|
||||
This is meant as a small knowledge base for commonly answered
|
||||
questions on our Discord community,{" "}
|
||||
<Link to="/about">The Programmer's Hangout</Link>.
|
||||
</p>
|
||||
<p>
|
||||
All of it is open source, and you can contribute to it on{" "}
|
||||
<Link to={packageJson.repository.url}>GitHub</Link>.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<PageContent content={<ResourcesList />} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -2,7 +2,9 @@ import { graphql } from "gatsby"
|
||||
import React, { Fragment } from "react"
|
||||
import { MarkdownRemark } from "../../generated/graphql"
|
||||
import { ComponentQuery } from "../../typings"
|
||||
import { HeaderBarebone } from "../components/HeaderBarebone"
|
||||
import { Markdown } from "../components/Markdown"
|
||||
import { PageContent } from "../components/PageContent"
|
||||
import { SEO } from "../components/SEO"
|
||||
|
||||
function RulesPage({ data }: ComponentQuery<{ md: MarkdownRemark }>) {
|
||||
@@ -11,7 +13,9 @@ function RulesPage({ data }: ComponentQuery<{ md: MarkdownRemark }>) {
|
||||
return (
|
||||
<Fragment>
|
||||
<SEO title="Rules" />
|
||||
<Markdown content={md.html!} />
|
||||
<HeaderBarebone title="Rules" />
|
||||
|
||||
<PageContent content={<Markdown content={md.html!} />} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Header } from "../components/Header"
|
||||
import { Markdown } from "../components/Markdown"
|
||||
import { SEO } from "../components/SEO"
|
||||
import { humanize } from "../utils"
|
||||
import { PageContent } from "../components/PageContent"
|
||||
|
||||
// @todo maybe find alternative type for data
|
||||
const Archive: FC<any> = ({ data }) => {
|
||||
@@ -21,8 +22,9 @@ const Archive: FC<any> = ({ data }) => {
|
||||
title={title}
|
||||
createdAt={ctime}
|
||||
timeToRead={timeToRead}
|
||||
shifted={false}
|
||||
/>
|
||||
<Markdown content={html} />
|
||||
<PageContent content={<Markdown content={html} />} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,12 +4,18 @@ import { Header } from "../components/Header"
|
||||
import { Markdown } from "../components/Markdown"
|
||||
import { ResourcesList } from "../components/ResourcesList"
|
||||
import { SEO } from "../components/SEO"
|
||||
import { PageContent } from "../components/PageContent"
|
||||
import { Footer } from "../components/Footer"
|
||||
|
||||
// @todo maybe find alternative type for data
|
||||
const LanguageHome: FC<any> = ({ data, pageContext }) => {
|
||||
const { relativePath } = data.file
|
||||
const { html, excerpt, fields, frontmatter, timeToRead } = data.file.post
|
||||
|
||||
const shiftLayout = Boolean(
|
||||
frontmatter.recommended_reading || frontmatter.external_resources
|
||||
)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SEO title={frontmatter.title} description={excerpt} />
|
||||
@@ -20,11 +26,19 @@ const LanguageHome: FC<any> = ({ data, pageContext }) => {
|
||||
authors={fields.authors}
|
||||
createdAt={frontmatter.created_at}
|
||||
timeToRead={timeToRead}
|
||||
shifted={shiftLayout}
|
||||
/>
|
||||
<PageContent
|
||||
content={
|
||||
<>
|
||||
<Markdown content={html} />
|
||||
<ResourcesList relativeDirectory={pageContext.language} />
|
||||
<Footer />
|
||||
</>
|
||||
}
|
||||
recommendedReading={frontmatter.recommended_reading}
|
||||
externalResources={frontmatter.external_resources}
|
||||
/>
|
||||
<Markdown content={html} />
|
||||
<ResourcesList relativeDirectory={pageContext.language} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,18 @@ import { Markdown } from "../components/Markdown"
|
||||
import { SEO } from "../components/SEO"
|
||||
|
||||
import "katex/dist/katex.min.css"
|
||||
import { PageContent } from "../components/PageContent"
|
||||
import { Footer } from "../components/Footer"
|
||||
|
||||
// @todo maybe find alternative type for data
|
||||
const LanguagePost: FC<any> = ({ data }) => {
|
||||
const { relativePath } = data.file
|
||||
const { html, excerpt, fields, frontmatter, timeToRead } = data.file.post
|
||||
|
||||
const shiftLayout = Boolean(
|
||||
frontmatter.recommended_reading || frontmatter.external_resources
|
||||
)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<SEO title={frontmatter.title} description={excerpt} />
|
||||
@@ -21,10 +27,18 @@ const LanguagePost: FC<any> = ({ data }) => {
|
||||
authors={fields.authors}
|
||||
createdAt={frontmatter.created_at}
|
||||
timeToRead={timeToRead}
|
||||
shifted={shiftLayout}
|
||||
/>
|
||||
<PageContent
|
||||
content={
|
||||
<>
|
||||
<Markdown content={html} />
|
||||
<Footer />
|
||||
</>
|
||||
}
|
||||
recommendedReading={frontmatter.recommended_reading}
|
||||
externalResources={frontmatter.external_resources}
|
||||
/>
|
||||
<Markdown content={html} />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user