diff --git a/src/components/builder/left/LeftNavbar.js b/src/components/builder/left/LeftNavbar.js index 1194e393..8a1022e5 100644 --- a/src/components/builder/left/LeftNavbar.js +++ b/src/components/builder/left/LeftNavbar.js @@ -14,7 +14,7 @@ const LeftNavbar = () => (
-
+
{sections.map((x) => ( { return (
-
+
{sections.map((x) => ( { switch (id) { @@ -18,6 +19,8 @@ const getComponent = (id) => { return Colors; case 'fonts': return Fonts; + case 'actions': + return Actions; default: throw new Error(); } diff --git a/src/components/builder/right/sections/Actions.js b/src/components/builder/right/sections/Actions.js new file mode 100644 index 00000000..90750ea6 --- /dev/null +++ b/src/components/builder/right/sections/Actions.js @@ -0,0 +1,83 @@ +import React, { memo } from 'react'; +import { MdImportExport } from 'react-icons/md'; +import Heading from '../../../shared/Heading'; +import Button from '../../../shared/Button'; +import styles from './Actions.module.css'; +import Input from '../../../shared/Input'; + +const Actions = () => { + return ( +
+ Actions + +
+
Import from Other Sources
+ +

+ You can import your information from various sources like JSON Resume + or your LinkedIn profile to autofill most of the data for your resume. +

+ +
+
+
+ +
+
Export Your Resume
+ +

+ Export your resume as a PDF to share with recruiters or a JSON that + you will be able to import back onto this app on another computer. +

+ +
+
+
+ +
+
Share Your Resume
+ +

+ The link below will be accessible publicly if you choose, and you can + share the latest version of your resume to anyone in the world. +

+ +
+ {}} /> +
+
+ +
+
Load Demo Data
+ +

+ Unclear on what to do with a fresh blank page? Load some demo data to + see how a resume should look and you can start editing from there. +

+ +
+
+
+ +
+
Delete Account
+ +

+ If you would like to delete your account and erase all your resumes, + it’s just one button away. Please be weary as this is an irreversible + process. +

+ +
+
+
+
+ ); +}; + +export default memo(Actions); diff --git a/src/components/builder/right/sections/Actions.module.css b/src/components/builder/right/sections/Actions.module.css new file mode 100644 index 00000000..7943f429 --- /dev/null +++ b/src/components/builder/right/sections/Actions.module.css @@ -0,0 +1,11 @@ +.container { + @apply bg-primary-100 rounded grid gap-5 p-8; +} + +.container h5 { + @apply text-lg font-semibold; +} + +.container p { + @apply text-sm font-medium; +} \ No newline at end of file diff --git a/src/components/builder/right/sections/Fonts.js b/src/components/builder/right/sections/Fonts.js index b63315d6..a9ba7108 100644 --- a/src/components/builder/right/sections/Fonts.js +++ b/src/components/builder/right/sections/Fonts.js @@ -1,9 +1,9 @@ import cx from 'classnames'; import React, { memo } from 'react'; import { useDispatch, useSelector } from '../../../../contexts/ResumeContext'; +import fonts from '../../../../data/fonts'; import { handleKeyUp } from '../../../../utils'; import Heading from '../../../shared/Heading'; -import fonts from '../../../../data/fonts'; import styles from './Fonts.module.css'; const Fonts = () => { diff --git a/src/components/builder/right/sections/Fonts.module.css b/src/components/builder/right/sections/Fonts.module.css index 03f4f9ed..4c7facdd 100644 --- a/src/components/builder/right/sections/Fonts.module.css +++ b/src/components/builder/right/sections/Fonts.module.css @@ -1,19 +1,15 @@ .font { - @apply px-6 py-6 text-xl font-medium truncate text-center bg-secondary rounded shadow; - @apply transition-colors duration-200 ease-in-out; + @apply px-6 py-6 text-xl font-medium truncate text-center border border-transparent bg-primary-100 rounded; } .font:focus { - @apply outline-none bg-secondary-light; - @apply transition-colors duration-200 ease-in-out; + @apply outline-none border border-primary-400; } .font:hover { - @apply bg-secondary-light; - @apply transition-colors duration-200 ease-in-out; + @apply border border-primary-400; } .font.selected { - @apply outline-none bg-secondary-light; - @apply transition-colors duration-200 ease-in-out; + @apply outline-none border border-primary-600; } \ No newline at end of file diff --git a/src/components/builder/right/sections/Layout.module.css b/src/components/builder/right/sections/Layout.module.css index a6a55734..a8a575dd 100644 --- a/src/components/builder/right/sections/Layout.module.css +++ b/src/components/builder/right/sections/Layout.module.css @@ -1,7 +1,7 @@ .droppable { - @apply p-6 bg-secondary-light col-span-1 rounded; + @apply p-6 bg-primary-100 col-span-1 rounded; } .draggable { - @apply px-4 py-2 capitalize font-medium rounded bg-secondary; + @apply px-4 py-2 capitalize font-medium rounded bg-primary-200; } diff --git a/src/components/builder/right/sections/Templates.js b/src/components/builder/right/sections/Templates.js index 7f86d0fd..8d44b906 100644 --- a/src/components/builder/right/sections/Templates.js +++ b/src/components/builder/right/sections/Templates.js @@ -1,16 +1,19 @@ import cx from 'classnames'; -import React, { memo } from 'react'; +import React, { memo, useContext } from 'react'; import { useDispatch, useSelector } from '../../../../contexts/ResumeContext'; import templates from '../../../../data/templates'; import { handleKeyUp } from '../../../../utils'; import Heading from '../../../shared/Heading'; import styles from './Templates.module.css'; +import ThemeContext from '../../../../contexts/ThemeContext'; const Templates = () => { const dispatch = useDispatch(); const template = useSelector('metadata.template'); + const { toggleDarkMode } = useContext(ThemeContext); const handleClick = (value) => { + toggleDarkMode(); dispatch({ type: 'on_input', payload: { diff --git a/src/components/builder/right/sections/Templates.module.css b/src/components/builder/right/sections/Templates.module.css index e1cd3f7c..2e078285 100644 --- a/src/components/builder/right/sections/Templates.module.css +++ b/src/components/builder/right/sections/Templates.module.css @@ -8,12 +8,12 @@ .template img { height: 240px; - @apply w-full object-cover border-2 border-transparent rounded; + @apply w-full object-cover border border-transparent rounded; @apply transition-opacity duration-200 ease-in-out; } .template.selected img { - @apply border-2 border-primary; + @apply border-primary-600; } .template:hover img { diff --git a/src/components/dashboard/CreateResume.module.css b/src/components/dashboard/CreateResume.module.css index 83028b81..29a2b9e0 100644 --- a/src/components/dashboard/CreateResume.module.css +++ b/src/components/dashboard/CreateResume.module.css @@ -12,7 +12,7 @@ .resume > .page { max-width: 184px; height: 260px; - @apply rounded absolute w-full bg-secondary-light; + @apply rounded absolute w-full bg-primary-100 text-primary-400; @apply transition-opacity duration-200 ease-in-out; @apply cursor-pointer absolute flex justify-center items-center; } diff --git a/src/components/dashboard/ResumePreview.module.css b/src/components/dashboard/ResumePreview.module.css index 3c3faafa..cfed814a 100644 --- a/src/components/dashboard/ResumePreview.module.css +++ b/src/components/dashboard/ResumePreview.module.css @@ -19,7 +19,7 @@ height: 260px; @apply rounded absolute w-full bg-black; @apply opacity-0 transition-opacity duration-200 ease-in-out; - @apply absolute text-gray-500 flex flex-col justify-evenly items-center; + @apply absolute text-primary-500 flex flex-col justify-evenly items-center; } .resume > .page:hover { diff --git a/src/components/dashboard/TopNavbar.js b/src/components/dashboard/TopNavbar.js index 567040ff..bb7f3302 100644 --- a/src/components/dashboard/TopNavbar.js +++ b/src/components/dashboard/TopNavbar.js @@ -1,18 +1,10 @@ -import { Link, navigate } from 'gatsby'; -import React, { memo, useContext } from 'react'; -import UserContext from '../../contexts/UserContext'; +import { Link } from 'gatsby'; +import React, { memo } from 'react'; import Avatar from '../shared/Avatar'; import Logo from '../shared/Logo'; import styles from './TopNavbar.module.css'; const TopNavbar = () => { - const { logout } = useContext(UserContext); - - const handleLogout = async () => { - await logout(); - navigate('/'); - }; - return (
@@ -20,16 +12,7 @@ const TopNavbar = () => { -
- - - -
+
); diff --git a/src/components/landing/Hero.js b/src/components/landing/Hero.js index dc2d497c..9b855499 100644 --- a/src/components/landing/Hero.js +++ b/src/components/landing/Hero.js @@ -22,7 +22,7 @@ const Hero = () => {

Reactive Resume

-

+

A free and open-source resume builder.

diff --git a/src/components/shared/Avatar.js b/src/components/shared/Avatar.js index 863defbc..3036e670 100644 --- a/src/components/shared/Avatar.js +++ b/src/components/shared/Avatar.js @@ -11,9 +11,9 @@ const Avatar = ({ className }) => { return ( {user.displayName} ); }; diff --git a/src/components/shared/Button.js b/src/components/shared/Button.js index be4d98b5..1be02e03 100644 --- a/src/components/shared/Button.js +++ b/src/components/shared/Button.js @@ -1,21 +1,20 @@ -import classNames from 'classnames'; +import cx from 'classnames'; import React, { memo } from 'react'; import { handleKeyUp } from '../../utils'; import styles from './Button.module.css'; const Button = ({ icon, title, onClick, outline, className, isLoading }) => { const Icon = icon; - const classes = classNames(styles.container, className, { - [styles.outline]: outline, - }); return ( ); diff --git a/src/components/shared/Button.module.css b/src/components/shared/Button.module.css index 616e9588..0d613204 100644 --- a/src/components/shared/Button.module.css +++ b/src/components/shared/Button.module.css @@ -1,16 +1,31 @@ .container { - padding: 6px 24px; - @apply flex items-center cursor-pointer inline-flex rounded font-semibold bg-primary border border-primary text-inverse; + font-size: 11px; + padding: 6px 18px; + @apply relative flex items-center cursor-pointer rounded font-semibold bg-primary-900 border border-primary-900 text-primary-50; + @apply transition-colors duration-200 ease-in-out; } .container:hover { - @apply bg-primary-dark; + @apply bg-primary-700 border-primary-700; + @apply transition-colors duration-200 ease-in-out; +} + +.container:active { + top: 1px; +} + +.container:focus { + @apply outline-none; } .container.outline { - @apply border border-primary bg-inverse text-primary; + @apply border border-primary-900 bg-transparent text-primary-900; } .container.outline:hover { - @apply bg-inverse-dark; + @apply bg-primary-200; +} + +.container.outline:focus { + @apply outline-none; } diff --git a/src/components/shared/Input.js b/src/components/shared/Input.js index 2e48e040..512ded05 100644 --- a/src/components/shared/Input.js +++ b/src/components/shared/Input.js @@ -2,8 +2,9 @@ import cx from 'classnames'; import { isFunction } from 'lodash'; import React, { memo, useEffect, useState } from 'react'; import { FaAngleDown } from 'react-icons/fa'; -import { MdClose } from 'react-icons/md'; +import { MdClose, MdOpenInNew } from 'react-icons/md'; import { v4 as uuidv4 } from 'uuid'; +import { IoIosCopy } from 'react-icons/io'; import { useDispatch, useSelector } from '../../contexts/ResumeContext'; import { handleKeyUp } from '../../utils'; import styles from './Input.module.css'; @@ -17,12 +18,11 @@ const Input = ({ onBlur, options, touched, + onClick, onChange, className, isRequired, placeholder, - onDeleteItem, - showDeleteItemButton, type = 'text', }) => { const [uuid, setUuid] = useState(null); @@ -68,12 +68,12 @@ const Input = ({ placeholder={placeholder} /> - {showDeleteItemButton && isFunction(onDeleteItem) && ( + {isFunction(onClick) && ( handleKeyUp(e, onDeleteItem)} + onClick={onClick} + onKeyUp={(e) => handleKeyUp(e, onClick)} className="absolute right-0 cursor-pointer opacity-50 hover:opacity-75 mx-4" /> )} @@ -143,6 +143,21 @@ const Input = ({
)} + {type === 'action' && ( +
+ + +
handleKeyUp(e, onClick)} + > + +
+
+ )} + {error && touched &&

{error}

}
diff --git a/src/components/shared/Input.module.css b/src/components/shared/Input.module.css index dfd09688..78787715 100644 --- a/src/components/shared/Input.module.css +++ b/src/components/shared/Input.module.css @@ -5,25 +5,25 @@ .container label input, .container label textarea, .container label select { - @apply py-3 px-4 rounded bg-secondary text-primary border border-secondary appearance-none; + @apply py-3 px-4 rounded text-primary-900 bg-primary-200 border border-transparent appearance-none; } .container label input::placeholder, .container label textarea::placeholder, .container label select::placeholder { - @apply text-primary opacity-50; + @apply opacity-50; } .container label input:hover, .container label textarea:hover, .container label select:hover { - @apply outline-none border-secondary-dark; + @apply outline-none border-primary-400; } .container label input:focus, .container label textarea:focus, .container label select:focus { - @apply outline-none border-primary; + @apply outline-none border-primary-600; } .container label > p { @@ -32,9 +32,30 @@ .circle { left: 14px; - @apply absolute bg-white rounded-full w-6 h-6; + @apply absolute bg-primary-900 rounded-full w-6 h-6; } div.circle + input { padding-left: 44px; -} \ No newline at end of file +} + +.read-only input:hover { + cursor: default; + border-color: transparent !important; +} + +.read-only input:focus { + border-color: transparent !important; +} + +.read-only div { + @apply absolute rounded-r top-0 right-0 bottom-0 w-20 flex justify-center items-center bg-primary-50; +} + +.read-only div:hover { + @apply bg-primary-100; +} + +.read-only div:focus { + @apply outline-none; +} diff --git a/src/components/shared/InputArray.js b/src/components/shared/InputArray.js index 2e1a8753..7e27ea85 100644 --- a/src/components/shared/InputArray.js +++ b/src/components/shared/InputArray.js @@ -21,8 +21,7 @@ const InputArray = ({ formik, schema, helpers, label, path, placeholder }) => { {({ field, meta }) => ( helpers.remove(i)} + onClick={() => helpers.remove(i)} {...field} {...meta} /> diff --git a/src/components/shared/PhotoUpload.module.css b/src/components/shared/PhotoUpload.module.css index 7845c5ac..66ca9129 100644 --- a/src/components/shared/PhotoUpload.module.css +++ b/src/components/shared/PhotoUpload.module.css @@ -2,7 +2,7 @@ width: 60px; height: 60px; flex: 0 0 60px; - @apply flex items-center justify-center cursor-pointer bg-secondary text-secondary-dark rounded-full; + @apply flex items-center justify-center cursor-pointer bg-primary-200 text-primary-500 rounded-full; @apply transition-opacity duration-200 ease-in-out; } diff --git a/src/components/shared/SectionIcon.js b/src/components/shared/SectionIcon.js index 6c717d3c..a7796764 100644 --- a/src/components/shared/SectionIcon.js +++ b/src/components/shared/SectionIcon.js @@ -18,8 +18,8 @@ const SectionIcon = ({ section, containerId, tooltipPlacement }) => { offset={-18} duration={500} containerId={containerId} - activeClass="text-primary" - className="py-2 cursor-pointer focus:outline-none focus:text-primary hover:text-primary animate__animated animate__fadeIn" + activeClass="text-primary-900" + className="py-2 cursor-pointer focus:outline-none focus:text-primary-900 hover:text-primary-900" > diff --git a/src/contexts/ThemeContext.js b/src/contexts/ThemeContext.js index 7e2f611b..7398b39d 100644 --- a/src/contexts/ThemeContext.js +++ b/src/contexts/ThemeContext.js @@ -2,22 +2,28 @@ import React, { createContext, memo, useEffect, useState } from 'react'; const COLOR_CONFIG = { light: { - '--color-primary': '#444', - '--color-primary-dark': '#333', - '--color-inverse': '#fff', - '--color-inverse-dark': '#f5f5f5', - '--color-secondary-light': '#f7fafc', - '--color-secondary': '#edf2f7', - '--color-secondary-dark': '#718096', + '--color-primary-50': '#FFFFFF', + '--color-primary-100': '#FAFAFA', + '--color-primary-200': '#F1F0F0', + '--color-primary-300': '#D8D2CD', + '--color-primary-400': '#CDC4BA', + '--color-primary-500': '#ABA59D', + '--color-primary-600': '#8A8680', + '--color-primary-700': '#686663', + '--color-primary-800': '#484745', + '--color-primary-900': '#282727', }, dark: { - '--color-primary': '#f5f5f5', - '--color-primary-dark': '#eeeeee', - '--color-inverse': '#212121', - '--color-inverse-dark': '#181818', - '--color-secondary-light': '#2c2c2c', - '--color-secondary': '#444', - '--color-secondary-dark': '#888', + '--color-primary-50': '#212121', + '--color-primary-100': '#2c2c2c', + '--color-primary-200': '#424242', + '--color-primary-300': '#616161', + '--color-primary-400': '#757575', + '--color-primary-500': '#9e9e9e', + '--color-primary-600': '#bdbdbd', + '--color-primary-700': '#e0e0e0', + '--color-primary-800': '#eeeeee', + '--color-primary-900': '#f5f5f5', }, }; diff --git a/src/data/rightSections.js b/src/data/rightSections.js index 3a9b66f6..a699c3fe 100644 --- a/src/data/rightSections.js +++ b/src/data/rightSections.js @@ -1,8 +1,9 @@ import { MdColorLens, MdDashboard, - MdStyle, MdFontDownload, + MdImportExport, + MdStyle, } from 'react-icons/md'; export default [ @@ -26,4 +27,9 @@ export default [ name: 'Fonts', icon: MdFontDownload, }, + { + id: 'actions', + name: 'Actions', + icon: MdImportExport, + }, ]; diff --git a/src/modals/BaseModal.module.css b/src/modals/BaseModal.module.css index 7a0d809f..848826dd 100644 --- a/src/modals/BaseModal.module.css +++ b/src/modals/BaseModal.module.css @@ -4,7 +4,7 @@ .modal { width: min(600px, calc(100vw - 100px)); - @apply p-8 rounded bg-inverse text-primary outline-none; + @apply p-8 rounded bg-primary-50 outline-none; } .modal .title { diff --git a/src/pages/app/builder.js b/src/pages/app/builder.js index 90656636..be29ee8a 100644 --- a/src/pages/app/builder.js +++ b/src/pages/app/builder.js @@ -40,7 +40,7 @@ const Builder = ({ id }) => {
-
+
diff --git a/src/pages/index.js b/src/pages/index.js index da8e7dbe..7d018d42 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -49,8 +49,10 @@ const Home = () => {
diff --git a/src/styles/colors.css b/src/styles/colors.css index 4a404383..df0cd48d 100644 --- a/src/styles/colors.css +++ b/src/styles/colors.css @@ -1,9 +1,12 @@ :root { - --color-primary: #444; - --color-primary-dark: #333; - --color-inverse: #fff; - --color-inverse-dark: #f5f5f5; - --color-secondary-light: #f7fafc; - --color-secondary: #e2e8f0; - --color-secondary-dark: #a0aec0; -} + --color-primary-50: #FFFFFF; + --color-primary-100: #FAFAFA; + --color-primary-200: #F1F0F0; + --color-primary-300: #D8D2CD; + --color-primary-400: #CDC4BA; + --color-primary-500: #ABA59D; + --color-primary-600: #8A8680; + --color-primary-700: #686663; + --color-primary-800: #484745; + --color-primary-900: #282727; +} \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index 537672cb..d35d5d97 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1,12 +1,9 @@ -:root { - @apply transition-colors duration-200 ease-in-out; -} - html, body { font-size: 12px; font-family: "Montserrat", sans-serif; - @apply text-primary bg-inverse; + @apply text-primary-900 bg-primary-50; + @apply transition-colors duration-200 ease-in-out; } p { @@ -22,7 +19,7 @@ a:hover { } hr { - @apply w-full border-secondary h-1; + @apply w-full border-primary-200 h-1; } section { @@ -34,15 +31,7 @@ label { } label > span:first-child { - @apply mb-1 text-secondary-dark font-semibold tracking-wide text-xs uppercase; -} - -#artboard { - color: #444; -} - -#artboard hr { - border-color: #eee; + @apply mb-1 text-primary-500 font-semibold tracking-wide text-xs uppercase; } .MuiTooltip-tooltip { diff --git a/src/styles/toastify.css b/src/styles/toastify.css index 1fcd4537..174e01a9 100644 --- a/src/styles/toastify.css +++ b/src/styles/toastify.css @@ -5,7 +5,7 @@ } .Toastify__toast--default { - @apply bg-primary text-inverse; + @apply bg-primary-900 text-primary-50; } .Toastify__toast-body { diff --git a/tailwind.config.js b/tailwind.config.js index 08c50214..253dd21a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,5 +1,5 @@ module.exports = { - purge: ['./src/**/*.js', './src/**/*.jsx', './src/**/*.ts', './src/**/*.tsx'], + purge: ['./src/**/*.js'], theme: { container: { center: true, @@ -9,13 +9,16 @@ module.exports = { 'context-menu': 'context-menu', }, colors: { - primary: 'var(--color-primary)', - 'primary-dark': 'var(--color-primary-dark)', - inverse: 'var(--color-inverse)', - 'inverse-dark': 'var(--color-inverse-dark)', - 'secondary-light': 'var(--color-secondary-light)', - secondary: 'var(--color-secondary)', - 'secondary-dark': 'var(--color-secondary-dark)', + 'primary-50': 'var(--color-primary-50)', + 'primary-100': 'var(--color-primary-100)', + 'primary-200': 'var(--color-primary-200)', + 'primary-300': 'var(--color-primary-300)', + 'primary-400': 'var(--color-primary-400)', + 'primary-500': 'var(--color-primary-500)', + 'primary-600': 'var(--color-primary-600)', + 'primary-700': 'var(--color-primary-700)', + 'primary-800': 'var(--color-primary-800)', + 'primary-900': 'var(--color-primary-900)', }, }, },