diff --git a/.vscode/settings.json b/.vscode/settings.json
index eaea662..5bfc7b9 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,9 @@
{
"eslint.enable": true,
- "editor.tabSize": 2
+ "editor.tabSize": 2,
+ "workbench.colorCustomizations": {
+ "activityBar.background": "#11332B",
+ "titleBar.activeBackground": "#17483C",
+ "titleBar.activeForeground": "#F6FCFA"
+ }
}
diff --git a/config/client.js b/config/client.js
new file mode 100644
index 0000000..b2cb5b9
--- /dev/null
+++ b/config/client.js
@@ -0,0 +1,6 @@
+module.exports = {
+ sanity: {
+ projectId: process.env.SANITY_PROJECT_ID || '<#< sanity.projectId >#>',
+ dataset: process.env.SANITY_DATASET || '<#< sanity.dataset >#>',
+ },
+};
diff --git a/package.json b/package.json
index 302ed49..89ac7be 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"@emotion/babel-preset-css-prop": "^10.0.23",
"@emotion/core": "^10.0.22",
"@emotion/styled": "^10.0.27",
+ "@sanity/block-content-to-react": "^2.0.7",
"framer-motion": "^1.10.3",
"gatsby": "^2.18.4",
"gatsby-image": "^2.2.34",
diff --git a/plopfile.js b/plopfile.js
index 2f45305..9969218 100644
--- a/plopfile.js
+++ b/plopfile.js
@@ -1,5 +1,7 @@
const componentGenerator = require('./templates/Component');
+const pageGenerator = require('./templates/Page');
module.exports = function(plop) {
plop.setGenerator('component', componentGenerator);
+ plop.setGenerator('page', pageGenerator);
};
diff --git a/src/components/constructs/Figure/Figure.js b/src/components/constructs/Figure/Figure.js
new file mode 100644
index 0000000..ec7564c
--- /dev/null
+++ b/src/components/constructs/Figure/Figure.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { getFluidGatsbyImage } from 'gatsby-source-sanity';
+import { withSpacing } from '@utilities/styles/spacing';
+import { figcaptionStyles } from './Figure.styles';
+import clientConfig from '../../../../config/client';
+
+import Image from '@elements/Image';
+
+const Figure = ({ className, node }) => {
+ console.log('Figure', node);
+ if (!node || !node.asset || !node.asset._ref) {
+ return null;
+ }
+ const fluid = getFluidGatsbyImage(
+ node.asset._ref,
+ { maxWidth: 675 },
+ clientConfig.sanity
+ );
+
+ return (
+
+ );
+};
+
+Figure.propTypes = {
+ className: PropTypes.string,
+ node: PropTypes.shape({
+ alt: PropTypes.string,
+ caption: PropTypes.string,
+ asset: PropTypes.shape({
+ _ref: PropTypes.string,
+ }),
+ }),
+};
+
+export default withSpacing(Figure);
diff --git a/src/components/constructs/Figure/Figure.notes.md b/src/components/constructs/Figure/Figure.notes.md
new file mode 100644
index 0000000..0f8d0d0
--- /dev/null
+++ b/src/components/constructs/Figure/Figure.notes.md
@@ -0,0 +1,9 @@
+# Figure
+
+---
+
+(description)
+
+### Usage
+- …
+- …
\ No newline at end of file
diff --git a/src/components/constructs/Figure/Figure.story.js b/src/components/constructs/Figure/Figure.story.js
new file mode 100644
index 0000000..d783cf0
--- /dev/null
+++ b/src/components/constructs/Figure/Figure.story.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import Figure from '@constructs/Figure';
+import notes from './Figure.notes.md';
+
+storiesOf('Constructs', module).add(
+ 'Figure',
+ () => (
+
+ ),
+ { notes }
+);
\ No newline at end of file
diff --git a/src/components/constructs/Figure/Figure.styles.js b/src/components/constructs/Figure/Figure.styles.js
new file mode 100644
index 0000000..dfdeb8b
--- /dev/null
+++ b/src/components/constructs/Figure/Figure.styles.js
@@ -0,0 +1 @@
+export const figcaptionStyles = { textAlign: 'right' };
diff --git a/src/components/constructs/Figure/Figure.test.js b/src/components/constructs/Figure/Figure.test.js
new file mode 100644
index 0000000..751c4b1
--- /dev/null
+++ b/src/components/constructs/Figure/Figure.test.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { render } from "@testing-library/react";
+
+import Figure from './Figure';
+
+describe('Figure', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create()
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+});
\ No newline at end of file
diff --git a/src/components/constructs/Figure/index.js b/src/components/constructs/Figure/index.js
new file mode 100644
index 0000000..d45c026
--- /dev/null
+++ b/src/components/constructs/Figure/index.js
@@ -0,0 +1,3 @@
+import Figure from './Figure';
+
+export default Figure;
diff --git a/src/components/constructs/Layout/Layout.js b/src/components/constructs/Layout/Layout.js
index d228383..93708e2 100644
--- a/src/components/constructs/Layout/Layout.js
+++ b/src/components/constructs/Layout/Layout.js
@@ -1,7 +1,9 @@
import React, { useMemo, useState, useCallback, createContext } from 'react';
import { Global } from '@emotion/core';
import { GLOBAL_STYLES } from '@global';
-import { useSpring, animated } from 'react-spring';
+// import { useSpring, animated } from 'react-spring';
+import { Spring } from 'react-spring/renderprops';
+
import {
asideStyles,
constructChildrenStyles,
@@ -41,76 +43,123 @@ const navLinks = [
export const LayoutContext = createContext({});
-const Layout = ({
- // asideLinks,
- children,
- className,
- // navLinks,
- withFooter,
- withNav,
-}) => {
- const onGetInvolved = useCallback(() => {});
- const childrenStyles = useMemo(
- () => constructChildrenStyles({ withFooter, withNav }),
- [withFooter, withNav]
- );
- const [isNextEventOpen, setNextEventOpen] = useState(false);
- const closeNextEvent = useCallback(() => setNextEventOpen(false), []);
+class Layout extends React.Component {
+ state = {
+ isNextEventOpen: false,
+ };
- const animation = useSpring({
- transform: `translate3d(${isNextEventOpen ? 2 : 100}%, 0, 0)`,
- config: { mass: 5, tension: 500, friction: 80 },
- });
+ // Context ===================================================================
+ openNextEvent = () => this.setState({ isNextEventOpen: true });
+ closeNextEvent = () => this.setState({ isNextEventOpen: false });
- const context = {
- isNextEventOpen,
- setNextEventOpen,
+ childContext = {
+ isNextEventOpen: this.state.isNextEventOpen,
+ openNextEvent: this.openNextEvent,
+ closeNextEvent: this.closeNextEvent,
};
- return (
- <>
-
-
-
-
-
-
-
-
- {/* NAV */}
-
-
- {/* CHILDREN */}
- {children}
-
- {/* FOOTER */}
- {withFooter && (
-
+
+
+ >
+ );
+ }
+}
+
+// const Layout = () => {
+// const childrenStyles = useMemo(
+// () => constructChildrenStyles({ withFooter, withNav: !isCollapsingNav }),
+// [withFooter, isCollapsingNav]
+// );
+// const [isNextEventOpen, setNextEventOpen] = useState(true);
+// Context ===================================================================
+// const openNextEvent = useCallback(() => setNextEventOpen(true), []);
+// const closeNextEvent = useCallback(() => setNextEventOpen(false), []);
+
+// const context = {
+// isNextEventOpen,
+// setNextEventOpen,
+// openNextEvent: this.openNextEvent,
+// closeNextEvent: this.closeNextEvent,
+// };
+
+// const animation = useSpring({
+// transform: `translate3d(${isNextEventOpen ? 2 : 100}%, 0, 0)`,
+// config: { mass: 5, tension: 500, friction: 80 },
+// });
+// };
Layout.defaultProps = {
withFooter: true,
- withNav: true,
+ isCollapsingNav: false,
};
Layout.propTypes = {
- className: PropTypes.string,
- children: PropTypes.node,
asideLinks: PropTypes.arrayOf(
PropTypes.shape({
brandName: PropTypes.string,
@@ -119,6 +168,8 @@ Layout.propTypes = {
out: PropTypes.string,
})
),
+ className: PropTypes.string,
+ children: PropTypes.node,
navLinks: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string,
@@ -126,12 +177,17 @@ Layout.propTypes = {
})
),
withFooter: PropTypes.bool,
- withNav: PropTypes.bool,
+ isCollapsingNav: PropTypes.bool,
};
-export const withLayout = (Component, { withNav, withLayout }) => {
+export const withLayout = (Component, options = {}) => {
+ const { isCollapsingNav, withFooter } = options;
const WithLayout = (props) => (
-
+
);
@@ -143,4 +199,4 @@ export const withLayout = (Component, { withNav, withLayout }) => {
return WithLayout;
};
-export default Layout;
+export default React.memo(Layout);
diff --git a/src/components/constructs/Layout/Layout.styles.js b/src/components/constructs/Layout/Layout.styles.js
index a9e51d5..88d971f 100644
--- a/src/components/constructs/Layout/Layout.styles.js
+++ b/src/components/constructs/Layout/Layout.styles.js
@@ -43,13 +43,18 @@ export const asideStyles = {
};
export const nextEventStyles = {
- position: 'fixed',
right: 0,
width: NEXT_EVENT_WIDTH,
height: '100vh',
paddingTop: S.calcSpace(4),
paddingBottom: S.calcSpace(4),
zIndex: 1000,
+ [`@media (max-width: ${S.LAYOUT_MOBILE_MAX})`]: {
+ position: 'fixed',
+ },
+ [`@media (min-width: ${S.LAYOUT_TABLET_MIN})`]: {
+ position: 'absolute',
+ },
};
export const wrapperStyles = {
@@ -62,9 +67,7 @@ export const wrapperStyles = {
};
const subtract = (amount) => `- ${amount}`;
-
export const constructChildrenStyles = ({ withFooter, withNav }) => ({
- minHeight: `calc(100vh ${withFooter ? subtract(FOOTER_HEIGHT) : ''} ${
- withNav ? subtract(NAV_HEIGHT) : ''
- })`,
+ paddingTop: withNav ? NAV_HEIGHT : 0,
+ minHeight: `calc(100vh ${withFooter ? subtract(FOOTER_HEIGHT) : ''})`,
});
diff --git a/src/components/constructs/Layout/partials/Nav/Nav.js b/src/components/constructs/Layout/partials/Nav/Nav.js
index b74ecc7..4b6d2b7 100644
--- a/src/components/constructs/Layout/partials/Nav/Nav.js
+++ b/src/components/constructs/Layout/partials/Nav/Nav.js
@@ -1,8 +1,10 @@
import React, { useState, useCallback } from 'react';
+import PropTypes from 'prop-types';
import {
asideStyles,
- mobileNavigationStyles,
menuButtonStyles,
+ mobileNavStyles,
+ navStyles,
} from './Nav.styles';
import { useSpring, animated } from 'react-spring';
import S from '@symbols';
@@ -19,7 +21,7 @@ import Text from '@elements/Text';
const MOBILE_BREAKPOINT = `(max-width: ${S.LAYOUT_MOBILE_MAX})`;
const SECONDARY_NAV_BREAKPOINT = '>56';
-const LayoutNav = ({ links, background, onButtonClick }) => {
+const LayoutNav = ({ links, background, onButtonClick, isCollapsing }) => {
const { [MOBILE_BREAKPOINT]: showMobileNav } = useMedia([MOBILE_BREAKPOINT]);
const { [SECONDARY_NAV_BREAKPOINT]: isSecondaryNav } = usePageOffset([
SECONDARY_NAV_BREAKPOINT,
@@ -35,8 +37,9 @@ const LayoutNav = ({ links, background, onButtonClick }) => {
friction: 100,
},
});
+ const START = isCollapsing ? -100 : 0;
const { translateY } = useSpring({
- translateY: isSecondaryNav ? 0 : -100,
+ translateY: isSecondaryNav ? 0 : START,
config: {
mass: 5,
tension: 500,
@@ -47,7 +50,7 @@ const LayoutNav = ({ links, background, onButtonClick }) => {
return showMobileNav ? (
<>
`translate3d(0,${y}%,0)`),
}}
@@ -87,8 +90,26 @@ const LayoutNav = ({ links, background, onButtonClick }) => {
>
) : (
-
+ `translate3d(0,${y}%,0)`),
+ }}
+ >
+
+
);
};
+LayoutNav.propTypes = {
+ background: PropTypes.oneOf('dark', 'light'),
+ isCollapsing: PropTypes.bool,
+ links: PropTypes.array,
+ onButtonClick: PropTypes.func,
+};
+
export default LayoutNav;
diff --git a/src/components/constructs/Layout/partials/Nav/Nav.styles.js b/src/components/constructs/Layout/partials/Nav/Nav.styles.js
index 9af8c61..8319320 100644
--- a/src/components/constructs/Layout/partials/Nav/Nav.styles.js
+++ b/src/components/constructs/Layout/partials/Nav/Nav.styles.js
@@ -1,5 +1,7 @@
import S from '@symbols';
+import { ASIDE_DESKTOP_WIDTH } from '@constructs/Layout/Layout.styles';
+
export const asideStyles = {
position: 'fixed',
width: '100vw',
@@ -8,7 +10,7 @@ export const asideStyles = {
top: 0,
};
-export const mobileNavigationStyles = {
+export const mobileNavStyles = {
position: 'fixed',
width: '100%',
zIndex: 100,
@@ -21,6 +23,13 @@ export const mobileNavigationStyles = {
},
};
+export const navStyles = {
+ position: 'fixed',
+ width: `calc(100% - ${ASIDE_DESKTOP_WIDTH})`,
+ zIndex: 100,
+ top: 0,
+};
+
export const menuButtonStyles = {
color: S.COLOR_GREYS.WHITE,
display: 'grid',
diff --git a/src/components/constructs/NextEvent/NextEvent.js b/src/components/constructs/NextEvent/NextEvent.js
index b169582..58c0d37 100644
--- a/src/components/constructs/NextEvent/NextEvent.js
+++ b/src/components/constructs/NextEvent/NextEvent.js
@@ -75,4 +75,4 @@ NextEvent.propTypes = {
onClose: PropTypes.func,
};
-export default withSpacing(NextEvent);
+export default React.memo(withSpacing(NextEvent));
diff --git a/src/components/constructs/SEO/SEO.js b/src/components/constructs/SEO/SEO.js
index 99e3020..f287676 100644
--- a/src/components/constructs/SEO/SEO.js
+++ b/src/components/constructs/SEO/SEO.js
@@ -5,7 +5,6 @@ import { useSiteMetadata } from '@data';
function SEO({ page, description, lang, meta }) {
const { title, author } = useSiteMetadata();
- const metaDescription = description;
return (
@@ -60,8 +59,7 @@ SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
- page: PropTypes.string,
- title: PropTypes.string.isRequired,
+ page: PropTypes.string.isRequired,
};
export default SEO;
diff --git a/src/components/elements/Box/Box.styles.js b/src/components/elements/Box/Box.styles.js
index 39583cc..279ab45 100644
--- a/src/components/elements/Box/Box.styles.js
+++ b/src/components/elements/Box/Box.styles.js
@@ -1,14 +1,13 @@
import { cssSwitch, cssMap } from '@utilities/styles';
-import { base as containerBase } from '@blocks/container';
+import { base as container, article } from '@blocks/container';
import S from '@symbols';
const colors = { ...S.COLOR_THEME, ...S.COLOR_GREYS };
const makeColorModifier = (backgroundColor) => ({ backgroundColor });
-const container = containerBase;
-
export const constructStyles = (props) => [
cssSwitch({ props, prop: 'container', css: container }),
+ cssSwitch({ props, prop: 'article', css: article }),
cssMap({
props,
prop: 'backgroundColor',
diff --git a/src/components/sections/Nav/Nav.js b/src/components/sections/Nav/Nav.js
index 3ddacad..5b0ff26 100644
--- a/src/components/sections/Nav/Nav.js
+++ b/src/components/sections/Nav/Nav.js
@@ -2,6 +2,8 @@ import React from 'react';
import PropTypes from 'prop-types';
import { withSpacing } from '@utilities/styles/spacing';
import { rootStyles } from './Nav.styles';
+import useMedia from '@utilities/hooks/use-media';
+import S from '@symbols';
import Box from '@elements/Box';
import ButtonWithIcon from '@elements/ButtonWithIcon';
@@ -9,6 +11,8 @@ import Link from '@elements/Link';
import Logo from '@elements/Logo';
import NavGroup from '@constructs/NavGroup';
+const MOBILE_BREAKPOINT = `(max-width: ${S.LAYOUT_MOBILE_MAX})`;
+
const Nav = ({
element: Element,
className,
@@ -18,6 +22,8 @@ const Nav = ({
}) => {
const isDarkBackground = background === 'dark';
+ const { [MOBILE_BREAKPOINT]: isMobile } = useMedia([MOBILE_BREAKPOINT]);
+
return (
@@ -27,13 +33,17 @@ const Nav = ({
type={isDarkBackground ? 'logotype-inverse' : 'logotype-primary'}
/>
-
-
- Get involved!
-
+ {!isMobile && (
+ <>
+
+
+ Get involved!
+
+ >
+ )}
diff --git a/src/components/sections/Nav/Nav.styles.js b/src/components/sections/Nav/Nav.styles.js
index 8791341..a8829c7 100644
--- a/src/components/sections/Nav/Nav.styles.js
+++ b/src/components/sections/Nav/Nav.styles.js
@@ -1,7 +1,12 @@
+import S from '@symbols';
+
export const rootStyles = {
display: 'grid',
gridTemplateColumns: '28rem auto 18rem',
gap: '4rem',
+ [`@media (max-width: ${S.LAYOUT_MOBILE_MAX})`]: {
+ gridTemplateColumns: '1fr',
+ },
['& > *']: {
display: 'flex',
height: '100%',
diff --git a/src/components/views/AboutUs/AboutUs.js b/src/components/views/AboutUs/AboutUs.js
new file mode 100644
index 0000000..dac5e9f
--- /dev/null
+++ b/src/components/views/AboutUs/AboutUs.js
@@ -0,0 +1,35 @@
+import React, { useMemo } from 'react';
+import PropTypes from 'prop-types';
+import { withSpacing } from '@utilities/styles/spacing';
+import { constructStyles } from './AboutUs.styles';
+
+import BlockContent from '@sanity/block-content-to-react';
+import Box from '@elements/Box';
+import Figure from '@constructs/Figure';
+import Text from '@elements/Text';
+
+const serializers = {
+ types: {
+ figure: Figure,
+ },
+};
+
+const AboutUs = ({ className, blocks, title, ...restProps }) => {
+ const styles = useMemo(() => constructStyles(restProps), [restProps]);
+ return (
+
+
+ {title}
+
+
+
+ );
+};
+
+AboutUs.propTypes = {
+ blocks: PropTypes.array,
+ className: PropTypes.string,
+ title: PropTypes.string,
+};
+
+export default withSpacing(AboutUs);
diff --git a/src/components/views/AboutUs/AboutUs.notes.md b/src/components/views/AboutUs/AboutUs.notes.md
new file mode 100644
index 0000000..607795c
--- /dev/null
+++ b/src/components/views/AboutUs/AboutUs.notes.md
@@ -0,0 +1,9 @@
+# AboutUs
+
+---
+
+(description)
+
+### Usage
+- …
+- …
\ No newline at end of file
diff --git a/src/components/views/AboutUs/AboutUs.story.js b/src/components/views/AboutUs/AboutUs.story.js
new file mode 100644
index 0000000..c02e677
--- /dev/null
+++ b/src/components/views/AboutUs/AboutUs.story.js
@@ -0,0 +1,12 @@
+import React from 'react';
+import { storiesOf } from '@storybook/react';
+import AboutUs from '@views/AboutUs';
+import notes from './AboutUs.notes.md';
+
+storiesOf('Views', module).add(
+ 'AboutUs',
+ () => (
+
+ ),
+ { notes }
+);
\ No newline at end of file
diff --git a/src/components/views/AboutUs/AboutUs.styles.js b/src/components/views/AboutUs/AboutUs.styles.js
new file mode 100644
index 0000000..52ce0de
--- /dev/null
+++ b/src/components/views/AboutUs/AboutUs.styles.js
@@ -0,0 +1,5 @@
+import S from '@symbols';
+
+const base = { };
+
+export const constructStyles = (props) => [ base ];
diff --git a/src/components/views/AboutUs/AboutUs.test.js b/src/components/views/AboutUs/AboutUs.test.js
new file mode 100644
index 0000000..f951c1b
--- /dev/null
+++ b/src/components/views/AboutUs/AboutUs.test.js
@@ -0,0 +1,14 @@
+import React from 'react';
+import renderer from 'react-test-renderer';
+import { render } from "@testing-library/react";
+
+import AboutUs from './AboutUs';
+
+describe('AboutUs', () => {
+ it('renders correctly', () => {
+ const tree = renderer
+ .create()
+ .toJSON()
+ expect(tree).toMatchSnapshot()
+ })
+});
\ No newline at end of file
diff --git a/src/components/views/AboutUs/index.js b/src/components/views/AboutUs/index.js
new file mode 100644
index 0000000..23b998f
--- /dev/null
+++ b/src/components/views/AboutUs/index.js
@@ -0,0 +1,3 @@
+import AboutUs from './AboutUs';
+
+export default AboutUs;
diff --git a/src/components/views/Home/Home.js b/src/components/views/Home/Home.js
index 798702a..4227b7c 100644
--- a/src/components/views/Home/Home.js
+++ b/src/components/views/Home/Home.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { withSpacing } from '@utilities/styles/spacing';
import { rootStyles, illustrationStyles } from './Home.styles';
@@ -16,26 +16,27 @@ import Text from '@elements/Text';
const Home = ({
className,
+ closeNextEvent,
creditsData,
currentEventData,
eventsData,
heroData,
navLinks,
- onGetInvolved,
- onGetTickets,
+ openNextEvent,
speakersData,
sponsorsData,
statsData,
}) => {
+ useEffect(() => openNextEvent?.(), []);
return (
{/* HERO */}
{/* SPONSORS */}
@@ -90,15 +91,16 @@ const Home = ({
Home.propTypes = {
className: PropTypes.string,
+ closeNextEvent: PropTypes.func,
creditsData: PropTypes.array,
currentEventData: PropTypes.object,
eventsData: PropTypes.array,
heroData: PropTypes.object,
navLinks: PropTypes.array,
- onGetInvolved: PropTypes.func,
+ openNextEvent: PropTypes.func,
speakersData: PropTypes.array,
sponsorsData: PropTypes.array,
statsData: PropTypes.array,
};
-export default withSpacing(Home);
+export default React.memo(withSpacing(Home));
diff --git a/src/components/views/Home/partials/Hero/Hero.js b/src/components/views/Home/partials/Hero/Hero.js
index d0ed5b1..2111a0b 100644
--- a/src/components/views/Home/partials/Hero/Hero.js
+++ b/src/components/views/Home/partials/Hero/Hero.js
@@ -30,8 +30,8 @@ const MOBILE_BREAKPOINT = `(max-width: ${S.LAYOUT_MOBILE_MAX})`;
const Hero = ({
className,
links,
- onButtonClick,
- onGetTickets,
+ openNextEvent,
+ closeNextEvent,
data,
event,
}) => {
@@ -45,7 +45,6 @@ const Hero = ({
name="glitch-one"
css={[illustrationStyles, { maxWidth: '144rem' }]}
/>
-
{!isMobile && (
@@ -54,7 +53,7 @@ const Hero = ({
Get involved!
@@ -69,7 +68,7 @@ const Hero = ({
{data?.description}
{isMobile && (
-