mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2025-11-13 16:22:59 +10:00
- integrating sign in with google
- set up dark mode context and other services
This commit is contained in:
@ -1,5 +1,18 @@
|
|||||||
import "./src/styles/global.css";
|
import React from "react";
|
||||||
|
|
||||||
import "firebase/auth";
|
import "firebase/auth";
|
||||||
import "firebase/analytics";
|
import "firebase/analytics";
|
||||||
import "firebase/firestore";
|
import "firebase/firestore";
|
||||||
|
import { ThemeProvider } from "./src/contexts/ThemeContext";
|
||||||
|
|
||||||
|
import "./src/styles/tailwind.css";
|
||||||
|
import "./src/styles/global.css";
|
||||||
|
import { ModalProvider } from "./src/contexts/ModalContext";
|
||||||
|
import { UserProvider } from "./src/contexts/UserContext";
|
||||||
|
|
||||||
|
export const wrapRootElement = ({ element }) => (
|
||||||
|
<ThemeProvider>
|
||||||
|
<ModalProvider>
|
||||||
|
<UserProvider>{element}</UserProvider>
|
||||||
|
</ModalProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
|||||||
10
package-lock.json
generated
10
package-lock.json
generated
@ -15207,6 +15207,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
||||||
"integrity": "sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg=="
|
"integrity": "sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg=="
|
||||||
},
|
},
|
||||||
|
"react-toastify": {
|
||||||
|
"version": "6.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-6.0.8.tgz",
|
||||||
|
"integrity": "sha512-NSqCNwv+C4IfR+c92PFZiNyeBwOJvigrP2bcRi2f6Hg3WqcHhEHOknbSQOs9QDFuqUjmK3SOrdvScQ3z63ifXg==",
|
||||||
|
"requires": {
|
||||||
|
"classnames": "^2.2.6",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
|
"react-transition-group": "^4.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-transition-group": {
|
"react-transition-group": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz",
|
||||||
|
|||||||
@ -32,7 +32,8 @@
|
|||||||
"react-firebase-hooks": "^2.2.0",
|
"react-firebase-hooks": "^2.2.0",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-icons": "^3.10.0",
|
"react-icons": "^3.10.0",
|
||||||
"react-loader-spinner": "^3.1.14"
|
"react-loader-spinner": "^3.1.14",
|
||||||
|
"react-toastify": "^6.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "2.0.5",
|
"prettier": "2.0.5",
|
||||||
|
|||||||
66
src/components/landing/Hero.js
Normal file
66
src/components/landing/Hero.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import React, { useContext } from "react";
|
||||||
|
import { useStaticQuery, graphql } from "gatsby";
|
||||||
|
import GatsbyImage from "gatsby-image";
|
||||||
|
import ThemeContext from "../../contexts/ThemeContext";
|
||||||
|
import ModalContext from "../../contexts/ModalContext";
|
||||||
|
import UserContext from "../../contexts/UserContext";
|
||||||
|
import Button from "../shared/Button";
|
||||||
|
|
||||||
|
const Hero = () => {
|
||||||
|
const { user, loading } = useContext(UserContext);
|
||||||
|
const { toggleDarkMode } = useContext(ThemeContext);
|
||||||
|
const { authModal } = useContext(ModalContext);
|
||||||
|
const { file } = useStaticQuery(graphql`
|
||||||
|
query {
|
||||||
|
file(relativePath: { eq: "logo.png" }) {
|
||||||
|
childImageSharp {
|
||||||
|
fixed(width: 256, height: 256) {
|
||||||
|
...GatsbyImageSharpFixed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const handleLogin = () => authModal.setOpen(true);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex items-center">
|
||||||
|
<GatsbyImage
|
||||||
|
className="shadow-md rounded"
|
||||||
|
fixed={file.childImageSharp.fixed}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="ml-12">
|
||||||
|
<h1 className="text-5xl font-bold">Reactive Resume</h1>
|
||||||
|
<h2 className="mt-1 text-3xl text-gray-500">
|
||||||
|
A free and open-source resume builder.
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="mt-12 flex">
|
||||||
|
{user ? (
|
||||||
|
<Button
|
||||||
|
title="Go to App"
|
||||||
|
onClick={handleLogin}
|
||||||
|
isLoading={loading || authModal.isOpen}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Button
|
||||||
|
title="Login"
|
||||||
|
onClick={handleLogin}
|
||||||
|
isLoading={loading || authModal.isOpen}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Button
|
||||||
|
outline
|
||||||
|
className="ml-8"
|
||||||
|
title="Source Code"
|
||||||
|
onClick={toggleDarkMode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Hero;
|
||||||
@ -16,7 +16,7 @@ const Button = ({ title, isLoading, onClick, outline, className }) => {
|
|||||||
<div
|
<div
|
||||||
tabIndex="0"
|
tabIndex="0"
|
||||||
role="button"
|
role="button"
|
||||||
onClick={onClick}
|
onClick={isLoading ? undefined : onClick}
|
||||||
className={classes}
|
className={classes}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
>
|
>
|
||||||
|
|||||||
23
src/components/shared/Wrapper.js
Normal file
23
src/components/shared/Wrapper.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import React, { Fragment } from "react";
|
||||||
|
import { ToastContainer, Slide } from "react-toastify";
|
||||||
|
import ModalRegistrar from "../../modals/ModalRegistrar";
|
||||||
|
|
||||||
|
const Wrapper = ({ children }) => {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
{children}
|
||||||
|
|
||||||
|
<ModalRegistrar />
|
||||||
|
<ToastContainer
|
||||||
|
role="alert"
|
||||||
|
hideProgressBar
|
||||||
|
transition={Slide}
|
||||||
|
closeButton={false}
|
||||||
|
position="bottom-right"
|
||||||
|
pauseOnFocusLoss={false}
|
||||||
|
/>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Wrapper;
|
||||||
25
src/contexts/ModalContext.js
Normal file
25
src/contexts/ModalContext.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import React, { createContext, useState } from "react";
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
authModal: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModalContext = createContext(defaultState);
|
||||||
|
|
||||||
|
const ModalProvider = ({ children }) => {
|
||||||
|
const [authOpen, setAuthOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalContext.Provider
|
||||||
|
value={{
|
||||||
|
authModal: { isOpen: authOpen, setOpen: setAuthOpen },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ModalContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalContext;
|
||||||
|
|
||||||
|
export { ModalProvider };
|
||||||
59
src/contexts/ThemeContext.js
Normal file
59
src/contexts/ThemeContext.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import React, { useState, useEffect, createContext } from "react";
|
||||||
|
|
||||||
|
const COLOR_CONFIG = {
|
||||||
|
light: {
|
||||||
|
"--color-primary": "#444",
|
||||||
|
"--color-primary-dark": "#333",
|
||||||
|
"--color-inverse": "#fff",
|
||||||
|
"--color-inverse-dark": "#f5f5f5",
|
||||||
|
},
|
||||||
|
dark: {
|
||||||
|
"--color-primary": "#f5f5f5",
|
||||||
|
"--color-primary-dark": "#eee",
|
||||||
|
"--color-inverse": "#212121",
|
||||||
|
"--color-inverse-dark": "#121212",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
darkMode: false,
|
||||||
|
toggleDarkMode: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ThemeContext = createContext(defaultState);
|
||||||
|
|
||||||
|
const ThemeProvider = ({ children }) => {
|
||||||
|
const [darkMode, setDarkMode] = useState(defaultState.darkMode);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const isDarkMode = JSON.parse(localStorage.getItem("darkMode"));
|
||||||
|
isDarkMode ? setDarkMode(true) : setDarkMode(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const colorConfig = darkMode ? COLOR_CONFIG.dark : COLOR_CONFIG.light;
|
||||||
|
for (const [key, value] of Object.entries(colorConfig)) {
|
||||||
|
document.documentElement.style.setProperty(key, value);
|
||||||
|
}
|
||||||
|
}, [darkMode]);
|
||||||
|
|
||||||
|
const toggleDarkMode = () => {
|
||||||
|
setDarkMode(!darkMode);
|
||||||
|
localStorage.setItem("darkMode", JSON.stringify(!darkMode));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeContext.Provider
|
||||||
|
value={{
|
||||||
|
darkMode,
|
||||||
|
toggleDarkMode,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</ThemeContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeContext;
|
||||||
|
|
||||||
|
export { ThemeProvider };
|
||||||
52
src/contexts/UserContext.js
Normal file
52
src/contexts/UserContext.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import React, { createContext, useState, useEffect } from "react";
|
||||||
|
import { useAuthState } from "react-firebase-hooks/auth";
|
||||||
|
import firebase from "gatsby-plugin-firebase";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
const defaultState = {
|
||||||
|
user: null,
|
||||||
|
logout: () => {},
|
||||||
|
loginWithGoogle: async () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
const UserContext = createContext(defaultState);
|
||||||
|
|
||||||
|
const UserProvider = ({ children }) => {
|
||||||
|
const [firebaseUser, loading] = useAuthState(firebase.auth());
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setUser(firebaseUser);
|
||||||
|
}, [firebaseUser]);
|
||||||
|
|
||||||
|
const loginWithGoogle = async () => {
|
||||||
|
const provider = new firebase.auth.GoogleAuthProvider();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await firebase.auth().signInWithPopup(provider);
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
firebase.auth().signOut();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<UserContext.Provider
|
||||||
|
value={{
|
||||||
|
user,
|
||||||
|
loading,
|
||||||
|
logout,
|
||||||
|
loginWithGoogle,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</UserContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserContext;
|
||||||
|
|
||||||
|
export { UserProvider };
|
||||||
@ -1,10 +1,45 @@
|
|||||||
import React from "react";
|
import React, { useState, useContext, Fragment } from "react";
|
||||||
import BaseModal from "./BaseModal";
|
import BaseModal from "./BaseModal";
|
||||||
import Button from "../components/shared/Button";
|
import Button from "../components/shared/Button";
|
||||||
|
import ModalContext from "../contexts/ModalContext";
|
||||||
|
import UserContext from "../contexts/UserContext";
|
||||||
|
|
||||||
|
const AuthModal = () => {
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const { authModal } = useContext(ModalContext);
|
||||||
|
const { user, loginWithGoogle, logout } = useContext(UserContext);
|
||||||
|
|
||||||
|
const handleSignInWithGoogle = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
await loginWithGoogle();
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGoToApp = () => {
|
||||||
|
console.log("Go to App");
|
||||||
|
};
|
||||||
|
|
||||||
|
const loggedInAction = (
|
||||||
|
<Fragment>
|
||||||
|
<Button className="mr-6" title="Go to App" onClick={handleGoToApp} />
|
||||||
|
<Button title="Logout" onClick={logout} />
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
|
||||||
|
const loggedOutAction = (
|
||||||
|
<Button
|
||||||
|
isLoading={isLoading}
|
||||||
|
title="Sign in with Google"
|
||||||
|
onClick={handleSignInWithGoogle}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
const AuthModal = ({ state }) => {
|
|
||||||
return (
|
return (
|
||||||
<BaseModal state={state} title="Who are you?" action={action}>
|
<BaseModal
|
||||||
|
state={authModal}
|
||||||
|
title="Who are you?"
|
||||||
|
action={user ? loggedInAction : loggedOutAction}
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
Reactive Resume needs to know who you are so it can securely
|
Reactive Resume needs to know who you are so it can securely
|
||||||
authenticate you into the app and show you only your information. Once
|
authenticate you into the app and show you only your information. Once
|
||||||
@ -15,6 +50,4 @@ const AuthModal = ({ state }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = <Button title="Sign in with Google" />;
|
|
||||||
|
|
||||||
export default AuthModal;
|
export default AuthModal;
|
||||||
|
|||||||
@ -1,16 +1,25 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Modal from "@material-ui/core/Modal";
|
import Modal from "@material-ui/core/Modal";
|
||||||
|
import Backdrop from "@material-ui/core/Backdrop";
|
||||||
|
import Fade from "@material-ui/core/Fade";
|
||||||
import { MdClose } from "react-icons/md";
|
import { MdClose } from "react-icons/md";
|
||||||
import styles from "./BaseModal.module.css";
|
import styles from "./BaseModal.module.css";
|
||||||
import Button from "../components/shared/Button";
|
import Button from "../components/shared/Button";
|
||||||
|
|
||||||
const BaseModal = ({ title, state, children, action }) => {
|
const BaseModal = ({ title, state, children, action }) => {
|
||||||
const [isOpen, setOpen] = state;
|
const { isOpen, setOpen } = state;
|
||||||
|
|
||||||
const handleClose = () => setOpen(false);
|
const handleClose = () => setOpen(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={isOpen} onClose={handleClose} className={styles.root}>
|
<Modal
|
||||||
|
open={isOpen}
|
||||||
|
onClose={handleClose}
|
||||||
|
closeAfterTransition
|
||||||
|
className={styles.root}
|
||||||
|
BackdropComponent={Backdrop}
|
||||||
|
>
|
||||||
|
<Fade in={isOpen}>
|
||||||
<div className={styles.modal}>
|
<div className={styles.modal}>
|
||||||
<div className={styles.title}>
|
<div className={styles.title}>
|
||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
@ -30,6 +39,7 @@ const BaseModal = ({ title, state, children, action }) => {
|
|||||||
{action}
|
{action}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Fade>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
12
src/modals/ModalRegistrar.js
Normal file
12
src/modals/ModalRegistrar.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import React, { Fragment } from "react";
|
||||||
|
import AuthModal from "./AuthModal";
|
||||||
|
|
||||||
|
const ModalRegistrar = () => {
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<AuthModal />
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModalRegistrar;
|
||||||
12
src/pages/404.js
Normal file
12
src/pages/404.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { navigate } from "gatsby";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const NotFoundPage = () => {
|
||||||
|
useEffect(() => {
|
||||||
|
navigate("/");
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NotFoundPage;
|
||||||
@ -1,61 +1,38 @@
|
|||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { graphql } from "gatsby";
|
import Wrapper from "../components/shared/Wrapper";
|
||||||
import GatsbyImage from "gatsby-image";
|
import Hero from "../components/landing/Hero";
|
||||||
import Button from "../components/shared/Button";
|
|
||||||
import AuthModal from "../modals/AuthModal";
|
|
||||||
|
|
||||||
const Home = ({ data }) => {
|
|
||||||
const [isAuthModalOpen, setAuthModalOpen] = useState(false);
|
|
||||||
|
|
||||||
const handleLogin = () => setAuthModalOpen(true);
|
|
||||||
|
|
||||||
|
const Home = () => {
|
||||||
return (
|
return (
|
||||||
|
<Wrapper>
|
||||||
<div className="container mt-24">
|
<div className="container mt-24">
|
||||||
<div className="flex items-center">
|
<Hero />
|
||||||
<GatsbyImage
|
|
||||||
className="shadow-md rounded"
|
|
||||||
fixed={data.file.childImageSharp.fixed}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="ml-12">
|
|
||||||
<h1 className="text-5xl font-bold">Reactive Resume</h1>
|
|
||||||
<h2 className="mt-1 text-3xl text-gray-500">
|
|
||||||
A free and open-source resume builder.
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="mt-12 flex">
|
|
||||||
<Button title="Login" onClick={handleLogin} />
|
|
||||||
<AuthModal state={[isAuthModalOpen, setAuthModalOpen]} />
|
|
||||||
<Button className="ml-8" outline title="Source Code" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="pt-8">
|
<div className="pt-8">
|
||||||
<Feature title="Create a resume that’s worthy of who you are.">
|
<Feature title="Create a resume that’s worthy of who you are.">
|
||||||
Keep up with the latest trends in resume design without having to
|
Keep up with the latest trends in resume design without having to
|
||||||
start from scratch. With new templates being designed every week and
|
start from scratch. With new templates being designed every week and
|
||||||
having made it that easy to design your own templates and submit them
|
having made it that easy to design your own templates and submit
|
||||||
to the community, you’ll never have to copy and edit your friend’s
|
them to the community, you’ll never have to copy and edit your
|
||||||
resume again.
|
friend’s resume again.
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
<Feature title="Updating your resume shouldn’t be a chore.">
|
<Feature title="Updating your resume shouldn’t be a chore.">
|
||||||
The biggest problem I’ve faced was when I had to update my resume when
|
The biggest problem I’ve faced was when I had to update my resume
|
||||||
I learned a new skill or found a new job. The ever-shifting layouts
|
when I learned a new skill or found a new job. The ever-shifting
|
||||||
and inconsistency with design over a number of years made it difficult
|
layouts and inconsistency with design over a number of years made it
|
||||||
to update your own resume, but Reactive Resume makes it as easy as few
|
difficult to update your own resume, but Reactive Resume makes it as
|
||||||
clicks.
|
easy as few clicks.
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
<Feature title="Kickstarting your career shouldn’t come at a cost.">
|
<Feature title="Kickstarting your career shouldn’t come at a cost.">
|
||||||
There are brilliant alternatives to this app like{" "}
|
There are brilliant alternatives to this app like{" "}
|
||||||
<a href="/">Novoresume</a> and <a href="/">Zety</a>, but they come at
|
<a href="/">Novoresume</a> and <a href="/">Zety</a>, but they come
|
||||||
a cost, mainly because of the time the developers and the marketing
|
at a cost, mainly because of the time the developers and the
|
||||||
they had to incur to make the product. This app might not be better
|
marketing they had to incur to make the product. This app might not
|
||||||
than them, but it does cater to people who are just not in a position
|
be better than them, but it does cater to people who are just not in
|
||||||
to pay hundreds of dollars to create a resume to bootstrap their
|
a position to pay hundreds of dollars to create a resume to
|
||||||
career.
|
bootstrap their career.
|
||||||
</Feature>
|
</Feature>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -66,6 +43,7 @@ const Home = ({ data }) => {
|
|||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,16 +56,4 @@ const Feature = ({ title, children }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const query = graphql`
|
|
||||||
query {
|
|
||||||
file(relativePath: { eq: "logo.png" }) {
|
|
||||||
childImageSharp {
|
|
||||||
fixed(width: 256, height: 256) {
|
|
||||||
...GatsbyImageSharpFixed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Home;
|
export default Home;
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
:root {
|
|
||||||
--color-primary: #444;
|
|
||||||
--color-primary-dark: #333;
|
|
||||||
--color-inverse: #fff;
|
|
||||||
--color-inverse-dark: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
|
|
||||||
@import "~react-loader-spinner/dist/loader/css/react-spinner-loader.css";
|
@import "~react-loader-spinner/dist/loader/css/react-spinner-loader.css";
|
||||||
|
@import "~react-toastify/dist/ReactToastify.css";
|
||||||
|
@import "./toastify.css";
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@apply text-primary;
|
|
||||||
font-family: "Montserrat", sans-serif;
|
font-family: "Montserrat", sans-serif;
|
||||||
|
@apply text-primary bg-inverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
|
|||||||
5
src/styles/tailwind.css
Normal file
5
src/styles/tailwind.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@tailwind base;
|
||||||
|
|
||||||
|
@tailwind components;
|
||||||
|
|
||||||
|
@tailwind utilities;
|
||||||
12
src/styles/toastify.css
Normal file
12
src/styles/toastify.css
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.Toastify__toast {
|
||||||
|
@apply px-8 py-6 shadow-lg rounded;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Toastify__toast--default {
|
||||||
|
@apply bg-primary text-inverse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Toastify__toast-body {
|
||||||
|
font-family: "Montserrat", sans-serif;
|
||||||
|
@apply font-medium;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user