diff --git a/gatsby-browser.js b/gatsby-browser.js
index 60a275a..e0d8c12 100644
--- a/gatsby-browser.js
+++ b/gatsby-browser.js
@@ -16,3 +16,12 @@ export const onRouteUpdate = () => {
updateFavicon(e.matches);
});
};
+
+export const onInitialClientRender = () => {
+ const storage = localStorage.getItem('theme');
+ const theme = storage && JSON.parse(storage);
+ if (theme) {
+ const app = document.querySelector('.app');
+ app.setAttribute('data-theme', theme);
+ }
+};
diff --git a/gatsby-config.js b/gatsby-config.js
index 5f2f53d..615d49f 100644
--- a/gatsby-config.js
+++ b/gatsby-config.js
@@ -13,8 +13,8 @@ module.exports = {
short_name: 'Adam Graham',
start_url: '/',
display: 'standalone',
- theme_color: '#101214',
- background_color: '#101214',
+ theme_color: '#282e34',
+ background_color: '#ffffff',
icon: 'static/logo512.png',
},
},
diff --git a/gatsby-node.js b/gatsby-node.js
index 1962e7a..a9eb035 100644
--- a/gatsby-node.js
+++ b/gatsby-node.js
@@ -14,36 +14,19 @@ exports.onCreateWebpackConfig = ({ actions }) => {
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions;
const typeDefs = `
- type ProjectDetail {
- key: String!
- value: String!
- }
- type ProjectButton {
- name: String!
- link: String!
- icon: String
- }
- type ProjectSection {
- title: String
- link: String
- mainImage: File @fileByRelativePath
- mainVideo: String
- paragraphs: [String]
- gallery: [File] @fileByRelativePath
- videos: [String]
- }
type ArtJson implements Node {
id: String!
category: String!
title: String!
- date: String
description: String
description_short: String
description_long: [String]
+ date: String
+ role: String
+ tech: [String]
image: File! @fileByRelativePath
imageAltText: String
imageBorder: String
- details: [ProjectDetail]
buttons: [ProjectButton]
sections: [ProjectSection]
}
@@ -51,14 +34,15 @@ exports.createSchemaCustomization = ({ actions }) => {
id: String!
category: String!
title: String!
- date: String
description: String
description_short: String
description_long: [String]
+ date: String
+ role: String
+ tech: [String]
image: File! @fileByRelativePath
imageAltText: String
imageBorder: String
- details: [ProjectDetail]
buttons: [ProjectButton]
sections: [ProjectSection]
}
@@ -66,14 +50,15 @@ exports.createSchemaCustomization = ({ actions }) => {
id: String!
category: String!
title: String!
- date: String
description: String
description_short: String
description_long: [String]
+ date: String
+ role: String
+ tech: [String]
image: File! @fileByRelativePath
imageAltText: String
imageBorder: String
- details: [ProjectDetail]
buttons: [ProjectButton]
sections: [ProjectSection]
}
@@ -81,14 +66,15 @@ exports.createSchemaCustomization = ({ actions }) => {
id: String!
category: String!
title: String!
- date: String
description: String
description_short: String
description_long: [String]
+ date: String
+ role: String
+ tech: [String]
image: File! @fileByRelativePath
imageAltText: String
imageBorder: String
- details: [ProjectDetail]
buttons: [ProjectButton]
sections: [ProjectSection]
}
@@ -96,17 +82,45 @@ exports.createSchemaCustomization = ({ actions }) => {
id: String!
category: String!
title: String!
- date: String
description: String
description_short: String
description_long: [String]
+ date: String
+ role: String
+ tech: [String]
image: File! @fileByRelativePath
imageAltText: String
imageBorder: String
- details: [ProjectDetail]
buttons: [ProjectButton]
sections: [ProjectSection]
}
+ type ProjectsJson implements Node {
+ title: String!
+ projects: [ProjectsItem]
+ }
+ type ProjectsItem {
+ title: String
+ description: String
+ date: String
+ link: String
+ externalLink: String
+ tags: [String]
+ }
+ type ProjectButton {
+ name: String!
+ url: String!
+ icon: String
+ }
+ type ProjectSection {
+ title: String
+ link: String
+ mainImage: File @fileByRelativePath
+ mainImageLink: String
+ mainVideo: String
+ paragraphs: [String]
+ gallery: [File] @fileByRelativePath
+ videos: [String]
+ }
`;
createTypes(typeDefs);
};
diff --git a/src/components/Dock.js b/src/components/Dock.js
new file mode 100644
index 0000000..f8bed10
--- /dev/null
+++ b/src/components/Dock.js
@@ -0,0 +1,89 @@
+import '../styles/dock.css';
+import { Icon, Link, SocialIcon } from '@zigurous/react-components';
+import { Link as GatsbyLink } from 'gatsby';
+import React from 'react';
+import { dockLinks, socialLinks } from '../links';
+
+const Dock = ({ theme, toggleTheme, secondaryLinks }) => {
+ return (
+
+
+
+ {dockLinks.map((link) => (
+
+ ))}
+
+
+ {socialLinks.map((link) => (
+
+ ))}
+
+
+
+
+
Previous
+
+
+
+
Next
+
+
+
+
+
+
+ {theme === 'dark' ? 'Light Mode' : 'Dark Mode'}
+
+
+
+
+ {secondaryLinks && (
+
+ {secondaryLinks.map((link) => (
+
+ ))}
+
+ )}
+
+ );
+};
+
+const DockItem = ({ link, external = false }) => {
+ return (
+
+
+ {link.icon ? (
+
+ ) : (
+
+ )}
+
+
{link.name}
+
+ );
+};
+
+export default Dock;
diff --git a/src/components/Gallery.js b/src/components/Gallery.js
index 69bc048..89836ef 100644
--- a/src/components/Gallery.js
+++ b/src/components/Gallery.js
@@ -1,25 +1,57 @@
import '../styles/gallery.css';
import { useMediaQuery } from '@zigurous/react-components';
import classNames from 'classnames';
+import { navigate } from 'gatsby';
import PropTypes from 'prop-types';
-import React, { useContext } from 'react';
-import GalleryContext from './GalleryContext';
-import Slide from './Slide';
+import React, { useCallback, useEffect } from 'react';
+import Slide, { SlideProps } from './Slide';
+import { getSessionIndex, setSessionIndex } from '../utils/session';
-const Gallery = ({ className }) => {
- const context = useContext(GalleryContext);
+const Gallery = ({ category, location, slides = [] }) => {
const vertical = useMediaQuery('(max-width: 1365px)');
+
+ const urlParams = new URLSearchParams(location?.search);
+ const slideIndex =
+ (urlParams.has('index')
+ ? Number.parseInt(urlParams.get('index')) || 0
+ : getSessionIndex(category)) % slides.length;
+
+ const currentSlide =
+ slideIndex >= 0 && slideIndex < slides.length && slides[slideIndex];
+
+ const setSlideIndex = useCallback(
+ (index) => {
+ if (index >= slides.length) index = 0;
+ if (index < 0) index = slides.length - 1;
+ setSessionIndex(category, index);
+ navigate(`/${category}?index=${index}`, { replace: true });
+ },
+ [category, slides, slideIndex]
+ );
+
+ useEffect(() => {
+ if (!document) return;
+ const prev = () => setSlideIndex(slideIndex - 1);
+ const next = () => setSlideIndex(slideIndex + 1);
+ document.addEventListener('previous_slide', prev);
+ document.addEventListener('next_slide', next);
+ return () => {
+ document.removeEventListener('previous_slide', prev);
+ document.removeEventListener('next_slide', next);
+ };
+ }, [slideIndex]);
+
return (
- {context.currentSlide && }
+ {currentSlide && }