aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar piotrruss <mail@pruss.it> 2021-08-16 21:22:32 +0200
committerGravatar piotrruss <mail@pruss.it> 2021-08-16 21:24:42 +0200
commiteb28244fc8f98e28728c7b3f951e102b9cc56590 (patch)
tree76237e414671730371f87c8e263a18c2d2e8c17f
parentb43d34c0136552cd2d83258fb5523bb873177908 (diff)
downloadmy_apps-eb28244fc8f98e28728c7b3f951e102b9cc56590.tar.gz
my_apps-eb28244fc8f98e28728c7b3f951e102b9cc56590.tar.bz2
my_apps-eb28244fc8f98e28728c7b3f951e102b9cc56590.zip
styles moved to scss
-rw-r--r--apps/Notes/Notes.module.scss231
-rw-r--r--apps/Notes/components/Import.js88
-rw-r--r--apps/Notes/components/List.js45
-rw-r--r--apps/Notes/components/ListItem.js115
-rw-r--r--apps/Notes/components/NoteEdit.js83
-rw-r--r--apps/Notes/components/NoteView.js31
-rw-r--r--apps/Notes/helpers/import.js41
-rw-r--r--components/Form.js26
-rw-r--r--components/Header.js68
-rw-r--r--components/Layout.js38
-rw-r--r--pages/_app.js2
-rw-r--r--pages/index.js25
-rw-r--r--pages/verify.js33
-rw-r--r--styles/Main.module.scss125
-rw-r--r--styles/_animations.scss4
-rw-r--r--styles/global.scss39
-rw-r--r--styles/styles.scss3
17 files changed, 503 insertions, 494 deletions
diff --git a/apps/Notes/Notes.module.scss b/apps/Notes/Notes.module.scss
new file mode 100644
index 0000000..e91dab9
--- /dev/null
+++ b/apps/Notes/Notes.module.scss
@@ -0,0 +1,231 @@
+.notesList {
+ @keyframes fade-in {
+ from {opacity: 0;}
+ to {opacity: 1;}
+ }
+
+ display: block;
+ overflow: auto;
+ width: 100%;
+ table-layout: fixed;
+ word-wrap: break-word;
+ height: 100%;
+ margin-top: -1em;
+ padding-top: 1em;
+
+ & > tbody,
+ & > thead {
+ display: block;
+ }
+
+ & tr {
+ display: flex;
+ padding: .5em;
+ }
+
+ & th {
+ font-weight: 600;
+ text-align: left;
+ min-width: 10em;
+ white-space: nowrap;
+ padding-bottom: .5em;
+ cursor: pointer;
+ line-height: 1.1em;
+
+ &:first-of-type {
+ width: 99%;
+ }
+
+ svg {
+ animation: fade-in .3s;
+ }
+ }
+}
+
+.listItem {
+ td {
+ min-width: 10em;
+ white-space: nowrap;
+
+ &:first-of-type {
+ width: 99%;
+ display: flex;
+ padding-right: 1em;
+
+ & > span:nth-child(1) {
+ text-overflow: ellipsis;
+ flex-grow: 1;
+ }
+
+ & > span:nth-child(2),
+ & > span:nth-child(3) {
+ margin-left: .5em;
+ padding: .15em .5em;
+ line-height: 1em;
+ border-radius: 50%;
+ visibility: hidden;
+ opacity: 0;
+ font-size: 80%;
+ transition: .3s opacity linear .3s;
+ }
+ }
+ }
+
+ &:hover {
+ background: #eee;
+ border-radius: .5em;
+ cursor: pointer;
+
+ & > td:first-of-type > span:nth-child(2),
+ & > td:first-of-type > span:nth-child(3) {
+ color: #666;
+ visibility: visible;
+ opacity: 1;
+ }
+ }
+
+
+ & > td:first-of-type > span:nth-child(2):hover {
+ color: #333;
+ background-color: #deffde;
+ }
+
+ & > td:first-of-type > span:nth-child(3):hover {
+ background-color: #ffdede;
+ color: #333;
+ }
+}
+
+.noteView {
+ @keyframes fade-in {
+ from {opacity: 0;}
+ to {opacity: 1;}
+ }
+
+ background: white;
+ padding: 1rem;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ animation: fade-in .3s;
+
+ h2 {
+ font-size: 1.25em;
+ font-weight: 600;
+ padding: 1rem;
+ user-select: text;
+ }
+
+ p {
+ padding: 0 1rem 1rem;
+ white-space: pre-line;
+ user-select: text;
+ }
+}
+
+.noteEdit {
+ @keyframes fade-in {
+ from {opacity: 0;}
+ to {opacity: 1;}
+ }
+
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: white;
+ padding: 1em 1em 2em;
+ animation: fade-in .3s;
+
+ h2 {
+ font-size: 1.2em;
+ margin-bottom: .5em;
+ }
+
+ form {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ flex-grow: 1;
+
+ & > div {
+ text-align: right;
+ }
+ }
+
+ input[type=text] {
+ margin-bottom: .5rem;
+ height: 3rem;
+ border: none;
+ padding: 0.5rem;
+ font-size: 1rem;
+ // font-weight: 600;
+ border: 1px dashed #666;
+
+ &:placeholder {
+ font: inherit;
+ }
+ }
+
+ textarea {
+ font-size: 1rem;
+ flex-grow: 1;
+ resize: none;
+ height: 100%;
+ width: 100%;
+ border: none;
+ border: 1px dashed #666;
+ padding: 0.5rem;
+
+ &:placeholder {
+ font: inherit;
+ }
+ }
+}
+
+.import {
+ @keyframes fade-in {
+ from {opacity: 0;}
+ to {opacity: 1;}
+ }
+
+ background: white;
+ padding: 1rem;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ animation: fade-in .3s;
+
+ form {
+ padding: 1em;
+ }
+
+ input[type=file] {
+ display: none;
+ }
+
+ label {
+ display: inline-block;
+ cursor: pointer;
+ }
+
+ li {
+ padding: .25em;
+ }
+
+ p {
+ padding: 1em 0;
+ }
+
+ .fa-check ~ span {
+ color: green;
+ }
+}
+
diff --git a/apps/Notes/components/Import.js b/apps/Notes/components/Import.js
index 71c08d6..2e2e5c7 100644
--- a/apps/Notes/components/Import.js
+++ b/apps/Notes/components/Import.js
@@ -1,58 +1,21 @@
+import styles from '../Notes.module.scss'
import React, {useState} from 'react'
import fetchJson from 'lib/fetchJson'
import useNotes from '../hooks/useNotes'
-import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons'
-import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
+import {state, color, handleImport, handleChange} from '../helpers/import'
const Import = ({action, setAction}) => {
const [files, setFiles] = useState()
const [done, setDone] = useState([])
const {mutateNotes} = useNotes()
- const state = i => done[i] && <span><FontAwesomeIcon icon={done[i] === 1 ? faCheck : faTimes} /></span>
-
- const readFileAsText = (file) => new Promise((resolve,reject) => {
- let fr = new FileReader()
-
- fr.onload = () => resolve(fr.result)
- fr.onerror = () => reject(fr)
-
- fr.readAsText(file)
- })
-
- const handleImport = async e => {
- e.preventDefault();
-
- Array.from(files).forEach(async (file, i) => {
- const title = file.name.replace(/\.[^/.]+$/, "")
- const content = await readFileAsText(file);
-
- try {
- const notes = await fetchJson('/api/notes', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({title, content}),
- })
- if (i === files.length - 1) await mutateNotes(notes)
- setDone((prev) => ({...prev, [i]: 1}))
- } catch (e) {
- setDone((prev) => ({...prev, [i]: 0}))
- }
- })
- }
-
- const handleChange = e => {
- setFiles(e.currentTarget.files)
- setDone([])
- }
-
return (
- <section>
+ <section className={styles.import}>
<div className='window__submenu'>
- <div onClick={() => { setAction('') }}>Back</div>
+ <div onClick={() => {setAction('')}}>Back</div>
</div>
<div className='window__scroll'>
- <form onSubmit={handleImport}>
+ <form onSubmit={e => handleImport(e, files, mutateNotes, setDone)}>
Import new notes:
<div>
<label className="window__button">
@@ -62,7 +25,7 @@ const Import = ({action, setAction}) => {
type="file"
multiple="multiple"
accept="text/plain"
- onChange={handleChange}
+ onChange={e => handleChange(e, setFiles, setDone)}
/>
</label>
</div>
@@ -70,7 +33,7 @@ const Import = ({action, setAction}) => {
<>
<p>Notes to import:</p>
<ul>
- {[...files].map((f, i) => <li key={f.name}>{f.name} {state(i)}</li>)}
+ {[...files].map((f, i) => <li style={color(done[i])} key={f.name}>{f.name} {state(done[i])}</li>)}
</ul>
{
done.length === 0
@@ -81,43 +44,6 @@ const Import = ({action, setAction}) => {
)}
</form>
</div>
- <style jsx>{`
- section {
- background: white;
- padding: 1rem;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- animation: fade-in .3s;
- }
-
- form {
- padding: 1em;
- }
-
- input[type=file] {
- display: none;
- }
-
- label {
- display: inline-block;
- cursor: pointer;
- }
-
- ul {
- list-style: disc inside none;
- }
-
- li {
- padding: .25em;
- }
-
- p {
- padding: 1em 0;
- }
- `}</style>
</section>
)
}
diff --git a/apps/Notes/components/List.js b/apps/Notes/components/List.js
index ec19639..b9fde02 100644
--- a/apps/Notes/components/List.js
+++ b/apps/Notes/components/List.js
@@ -1,8 +1,8 @@
+import styles from '../Notes.module.scss'
import React, {useState, useEffect, useRef} from 'react'
import useUser from 'lib/useUser'
import useNotes from '../hooks/useNotes'
import useSort from '../hooks/useSort'
-import fetchJson from 'lib/fetchJson'
import {Layout} from 'components'
import ListItem from './ListItem'
import Actions from './Actions'
@@ -33,12 +33,12 @@ const List = () => {
<div onClick={() => setAction('import')}>Import</div>
<div onClick={() => {}}>Export</div>
</div>
- <table className="list">
+ <table className={styles.notesList}>
<thead>
<tr>
- <th className='list__title' onClick={() => sortBy(1)}>Title {sortedBy(1)}</th>
- <th className='list__date' onClick={() => sortBy(2)}>Created {sortedBy(2)}</th>
- <th className='list__date' onClick={() => sortBy(3)}>Modified {sortedBy(3)}</th>
+ <th onClick={() => sortBy(1)}>Title {sortedBy(1)}</th>
+ <th onClick={() => sortBy(2)}>Created {sortedBy(2)}</th>
+ <th onClick={() => sortBy(3)}>Modified {sortedBy(3)}</th>
</tr>
</thead>
<tbody>
@@ -68,41 +68,6 @@ const List = () => {
/>
)
}
- <style jsx>{`
- table {
- display: block;
- overflow: auto;
- width: 100%;
- table-layout: fixed;
- word-wrap: break-word;
- height: 100%;
- margin-top: -1em;
- padding-top: 1em;
- }
-
- tbody, thead {
- display: block;
- }
-
- tr {
- display: flex;
- padding: 0 .5em;
- }
-
- th {
- font-weight: 600;
- text-align: left;
- min-width: 10em;
- white-space: nowrap;
- padding-bottom: .5em;
- cursor: pointer;
- line-height: 1.1em;
- }
-
- th:first-of-type {
- width: 99%;
- }
- `}</style>
</>
)
}
diff --git a/apps/Notes/components/ListItem.js b/apps/Notes/components/ListItem.js
index 42d67c0..5d3b91f 100644
--- a/apps/Notes/components/ListItem.js
+++ b/apps/Notes/components/ListItem.js
@@ -1,3 +1,4 @@
+import styles from '../Notes.module.scss'
import React, { useContext } from 'react'
import fetchJson from 'lib/fetchJson'
import {getNote, removeNote} from '../helpers/noteActions.js'
@@ -22,97 +23,33 @@ const ListItem = ({note, setAction, setFetchedNote}) => {
}
return (
- <>
- <tr key={note._id}>
- <td
- onClick={() => handleNoteAction('showNote', note)}
+ <tr className={styles.listItem} key={note._id}>
+ <td
+ onClick={() => handleNoteAction('showNote', note)}
+ >
+ <span>{`${note.title}`}</span>
+ <span
+ onClick={e => handleNoteAction('editNote', note, e)}
>
- <span>{`${note.title}`}</span>
- <span
- onClick={e => handleNoteAction('editNote', note, e)}
- >
- <FontAwesomeIcon icon={faEdit} />
- </span>
- <span
- onClick={(e) => removeNote(e, note._id, mutateNotes, setPopup, setAction)}
- >
- <FontAwesomeIcon icon={faTrash} />
- </span>
- </td>
- <td
- onClick={() => handleNoteAction('showNote', note)}
+ <FontAwesomeIcon icon={faEdit} />
+ </span>
+ <span
+ onClick={(e) => removeNote(e, note._id, mutateNotes, setPopup, setAction)}
>
- {datestring(note.created_at)}
- </td>
- <td
- onClick={() => handleNoteAction('showNote', note)}
- >
- {datestring(note.updated_at)}
- </td>
- </tr>
- <style jsx>{`
- tr {
- display: flex;
- padding: .5em;
- }
-
- td {
- min-width: 10em;
- white-space: nowrap;
- }
-
- td:first-of-type {
- width: 99%;
- display: flex;
- padding-right: 1em;
- }
-
- td:first-of-type > span:nth-child(2),
- td:first-of-type > span:nth-child(3) {
- margin-left: .5em;
- padding: .15em .5em;
- line-height: 1em;
- border-radius: 50%;
- visibility: hidden;
- opacity: 0;
- font-size: 80%;
- transition: .3s opacity linear .3s;
- }
-
- td:first-of-type > span:nth-child(1) {
- text-overflow: ellipsis;
- flex-grow: 1;
- }
-
- // td:first-of-type > span:nth-child(2) {
- // margin-left: 1.25em;
- // }
-
- tr:hover {
- background: #eee;
- border-radius: .5em;
- cursor: pointer;
- }
-
- tr:hover > td:first-of-type > span:nth-child(2),
- tr:hover > td:first-of-type > span:nth-child(3) {
- color: #666;
- visibility: visible;
- opacity: 1;
- }
-
- tr > td:first-of-type > span:nth-child(2):hover {
- color: #333;
- background-color: #deffde;
- }
-
- tr > td:first-of-type > span:nth-child(3):hover {
- background-color: #ffdede;
- color: #333;
- }
-
- `}</style>
- </>
+ <FontAwesomeIcon icon={faTrash} />
+ </span>
+ </td>
+ <td
+ onClick={() => handleNoteAction('showNote', note)}
+ >
+ {datestring(note.created_at)}
+ </td>
+ <td
+ onClick={() => handleNoteAction('showNote', note)}
+ >
+ {datestring(note.updated_at)}
+ </td>
+ </tr>
)
}
diff --git a/apps/Notes/components/NoteEdit.js b/apps/Notes/components/NoteEdit.js
index b568aa9..42eee46 100644
--- a/apps/Notes/components/NoteEdit.js
+++ b/apps/Notes/components/NoteEdit.js
@@ -1,3 +1,4 @@
+import styles from '../Notes.module.scss'
import React, {useState, useContext} from 'react'
import Context from 'context';
import fetchJson from 'lib/fetchJson'
@@ -24,11 +25,10 @@ const NoteEdit = ({action, setAction, fetchedNote}) => {
// }
return (
- <div className='note'>
+ <div className={styles.noteEdit}>
<h2>{fetchedNote ? 'Edit note:' : 'Add new note:'}</h2>
- <form onSubmit={handleSubmit} className='note__form'>
+ <form onSubmit={handleSubmit}>
<input
- className='note__title'
name='title'
type='text'
placeholder='Title'
@@ -36,7 +36,6 @@ const NoteEdit = ({action, setAction, fetchedNote}) => {
/>
<textarea
required
- className='note__text'
placeholder='Note'
name='content'
defaultValue={fetchedNote ? fetchedNote.content : ''}
@@ -56,82 +55,6 @@ const NoteEdit = ({action, setAction, fetchedNote}) => {
</div>
</form>
<style jsx>{`
- .note {
- display: flex;
- flex-direction: column;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background: white;
- padding: 1em 1em 2em;
- animation: fade-in .3s;
- }
-
- @keyframes fade-in {
- from {opacity: 0;}
- to {opacity: 1;}
- }
-
- h2 {
- font-size: 1.2em;
- margin-bottom: .5em;
- }
-
- .note__form {
- display: flex;
- flex-direction: column;
- width: 100%;
- flex-grow: 1;
- }
-
- .note__title {
- margin-bottom: .5rem;
- height: 3rem;
- border: none;
- padding: 0.5rem;
- font-size: 1rem;
- // font-weight: 600;
- border: 1px dashed #666;
- }
-
- .note__title:placeholder {
- font: inherit;
- }
-
- .note__text {
- font-size: 1rem;
- flex-grow: 1;
- resize: none;
- height: 100%;
- width: 100%;
- border: none;
- border: 1px dashed #666;
- padding: 0.5rem;
- }
-
- .note__text:placeholder {
- font: inherit;
- }
-
- .note__close {
- position: absolute;
- top: 8px;
- right: 15px;
- transform: rotate(45deg);
- font-size: 26px;
- cursor: pointer;
- transition: .3s transform;
- }
-
- .note__close:hover {
- transform: rotate(135deg);
- }
-
- .note__buttons {
- text-align: right;
- }
`}</style>
</div>
)
diff --git a/apps/Notes/components/NoteView.js b/apps/Notes/components/NoteView.js
index 1735579..7d93b16 100644
--- a/apps/Notes/components/NoteView.js
+++ b/apps/Notes/components/NoteView.js
@@ -1,3 +1,4 @@
+import styles from '../Notes.module.scss'
import React, {useContext} from 'react';
import Context from 'context';
import useNotes from '../hooks/useNotes'
@@ -17,7 +18,7 @@ const NoteView = ({fetchedNote, setFetchedNote, setAction}) => {
const {_id, content, title} = fetchedNote
return (
- <section>
+ <section className={styles.noteView}>
<div className='window__submenu'>
<div onClick={() => { setFetchedNote(); setAction('') }}>Back</div>
<div onClick={() => copyToClipboard(content, setPopup)}>Copy</div>
@@ -30,34 +31,6 @@ const NoteView = ({fetchedNote, setFetchedNote, setAction}) => {
<p>{content}</p>
</div>
<style jsx>{`
- section {
- background: white;
- padding: 1rem;
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- animation: fade-in .3s;
- }
-
- @keyframes fade-in {
- from {opacity: 0;}
- to {opacity: 1;}
- }
-
- h2 {
- font-size: 1.25em;
- font-weight: 600;
- padding: 1rem;
- user-select: text;
- }
-
- p {
- padding: 0 1rem 1rem;
- white-space: pre-line;
- user-select: text;
- }
`}</style>
</section>
)
diff --git a/apps/Notes/helpers/import.js b/apps/Notes/helpers/import.js
new file mode 100644
index 0000000..b05a458
--- /dev/null
+++ b/apps/Notes/helpers/import.js
@@ -0,0 +1,41 @@
+import fetchJson from 'lib/fetchJson'
+import {faCheck, faTimes} from '@fortawesome/free-solid-svg-icons'
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
+
+export const state = s => s && <span><FontAwesomeIcon icon={s === 1 ? faCheck : faTimes} /></span>
+export const color = s => s && {color: s === 1 ? 'green' : 'brown'}
+
+const readFileAsText = (file) => new Promise((resolve,reject) => {
+ let fr = new FileReader()
+
+ fr.onload = () => resolve(fr.result)
+ fr.onerror = () => reject(fr)
+
+ fr.readAsText(file)
+})
+
+export const handleImport = async (e, files, mutateNotes, setDone) => {
+ e.preventDefault();
+
+ Array.from(files).forEach(async (file, i) => {
+ const title = file.name.replace(/\.[^/.]+$/, "")
+ const content = await readFileAsText(file);
+
+ try {
+ const notes = await fetchJson('/api/notes', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({title, content}),
+ })
+ if (i === files.length - 1) await mutateNotes(notes)
+ setDone((prev) => ({...prev, [i]: 1}))
+ } catch (e) {
+ setDone((prev) => ({...prev, [i]: 0}))
+ }
+ })
+}
+
+export const handleChange = (e, setFiles, setDone) => {
+ setFiles(e.currentTarget.files)
+ setDone([])
+}
diff --git a/components/Form.js b/components/Form.js
index fc14a75..f41c958 100644
--- a/components/Form.js
+++ b/components/Form.js
@@ -1,8 +1,9 @@
+import styles from 'styles/Main.module.scss'
import React from 'react'
import PropTypes from 'prop-types'
const Form = ({errorMessage, onSubmit, isLogin}) => (
- <form className='window window--popup' onSubmit={onSubmit}>
+ <form className={`window window--popup ${styles.userForm}`} onSubmit={onSubmit}>
<div className="window__content--popup">
{isLogin ? 'Login to access your notes' : 'Register new user'}
</div>
@@ -12,29 +13,6 @@ const Form = ({errorMessage, onSubmit, isLogin}) => (
<input className='window__button' type="submit" value={isLogin ? 'Login' : 'Register'} />
{errorMessage && <p className="error">{errorMessage}</p>}
-
- <style jsx>{`
- form,
- label {
- display: flex;
- flex-flow: column;
- }
- label > span {
- font-weight: 600;
- }
- input[type=email],
- input[type=password] {
- padding: .5em;
- margin: .5em 0;
- border: 1px solid #ccc;
- border-radius: .25px;
- }
- .error {
- text-align: center;
- color: brown;
- margin: 1rem 0 0;
- }
- `}</style>
</form>
)
diff --git a/components/Header.js b/components/Header.js
index 4302af9..3d1f471 100644
--- a/components/Header.js
+++ b/components/Header.js
@@ -1,3 +1,4 @@
+import styles from 'styles/Main.module.scss'
import React, {useState} from 'react'
import Link from 'next/link'
import useUser from 'lib/useUser'
@@ -20,9 +21,9 @@ const Header = ({apps, setApps}) => {
}
return (
- <header>
+ <header className={styles.header}>
<nav>
- <ul className='header__apps'>
+ <ul>
{
apps && apps.map(app => (
<li
@@ -53,12 +54,17 @@ const Header = ({apps, setApps}) => {
{user?.isLoggedIn && (
<li>
<p
- className='user-menu'
+ className={styles.user}
onClick={() => setUserMenu(!userMenu)}
>{user?.email}</p>
{
userMenu && (
- <ul className='user-submenu'>
+ <ul className={styles.submenu}>
+ <li>
+ <span onClick={() => {}}>
+ Settings
+ </span>
+ </li>
<li>
<a href="/api/logout" onClick={handleLogout}>
Logout
@@ -71,60 +77,6 @@ const Header = ({apps, setApps}) => {
)}
</ul>
</nav>
- <style jsx>{`
- header {
- height: 2em;
- padding: 0.5rem;
- background-color: rgba(255, 255, 255, 0.4);
- border-bottom: 1px solid rgba(255, 255, 255, 0.5)
- }
-
- nav {
- display: flex;
- }
-
- .header__apps {
- flex-grow: 1;
- overflow: auto;
- }
-
- li {
- margin-left: 1em;
- margin-right: 1em;
- display: inline-block;
- cursor: pointer;
- }
-
- .header__separator {
- margin-right: auto;
- }
-
- a {
- color: #333;
- font-weight: 600;
- text-decoration: none;
- align-items: center;
- }
-
- .user-menu {
- font-weight: 600;
- cursor: pointer;
- position: relative;
- }
-
- .user-submenu {
- position: absolute;
- right: 0;
- top: 2.1em;
- width: 10em;
- padding: .5em;
- background-color: rgba(255, 255, 255, .9);
- border: 1px solid rgba(255, 255, 255, .5)
- }
- .user-submenu a {
- text-align: right;
- }
- `}</style>
</header>
)
}
diff --git a/components/Layout.js b/components/Layout.js
index f77ea0c..8b6cf87 100644
--- a/components/Layout.js
+++ b/components/Layout.js
@@ -18,44 +18,6 @@ const Layout = ({ children, apps, setApps}) => {
</main>
<Header apps={apps} setApps={setApps} />
<Popup popup={popup} />
- <style jsx global>{`
- main {
- position: fixed;
- top: 2em;
- left: 0;
- bottom: 0;
- right: 0;
- }
-
- body {
- margin: 0;
- color: #222;
- height: 100vh;
- overflow: hidden;
-
- background: #50a3a2;
- background: -webkit-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
- background: -moz-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
- background: -o-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
- background: linear-gradient(to bottom right, #50a3a2 0%, #53e3a6 100%);
-
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
- 'Helvetica Neue', Arial, Noto Sans, sans-serif, 'Apple Color Emoji',
- 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
- }
-
- textarea, input {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
- 'Helvetica Neue', Arial, Noto Sans, sans-serif, 'Apple Color Emoji',
- 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
- }
-
- .container {
- margin: 1.5rem auto;
- padding-left: 2rem;
- padding-right: 2rem;
- }
- `}</style>
</Context.Provider>
)
}
diff --git a/pages/_app.js b/pages/_app.js
index 5196b22..4625291 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -1,6 +1,6 @@
import { SWRConfig } from 'swr'
import fetchJson from 'lib/fetchJson'
-import '/styles/styles.scss'
+import '/styles/global.scss'
function MyApp({Component, pageProps}) {
return (
diff --git a/pages/index.js b/pages/index.js
index 9df0acf..52421ea 100644
--- a/pages/index.js
+++ b/pages/index.js
@@ -1,3 +1,4 @@
+import styles from 'styles/Main.module.scss'
import React, { useState ,useRef } from 'react'
import useUser from 'lib/useUser'
import {Layout, App} from 'components'
@@ -21,7 +22,11 @@ const Home = () => {
<>
{
Object.keys(appList).map(appName => (
- <div key={`${appName}_icon`} onClick={() => open(appName, apps, setApps)}>
+ <div
+ key={`${appName}_icon`}
+ className={styles.icon}
+ onClick={() => open(appName, apps, setApps)}
+ >
<img src={`./${appName.toLowerCase()}.svg`} alt={`${appName} Icon`} />
<p>{appName}</p>
</div>
@@ -41,24 +46,6 @@ const Home = () => {
</App>
);
})}
- <style jsx>{`
- div {
- text-decoration: none;
- display: inline-block;
- width: 4em;
- cursor: pointer;
- }
-
- img {
- width: 4em;
- }
-
- p {
- padding-top: .5em;
- text-align: center;
- color: #333;
- }
- `}</style>
</>
</Layout>
)
diff --git a/pages/verify.js b/pages/verify.js
index 1d89e22..9d92390 100644
--- a/pages/verify.js
+++ b/pages/verify.js
@@ -1,3 +1,4 @@
+import styles from 'styles/Main.module.scss'
import {useState, useEffect} from 'react'
import {useRouter} from 'next/router'
import useUser from 'lib/useUser'
@@ -52,12 +53,12 @@ const Verify = () => {
<p>Loading...</p>
</div>
) : (
- <div className="window window--popup">
+ <div className={`window window--popup ${styles.verify}`}>
<p>One last step missing</p>
<p>{`To start using Notes App type the verification code we sent to your email (${user.email}):`}</p>
<form onSubmit={handleKey}>
<input type="text" placeholder="Verification key" name="key" />
- <button className="window__button" type="submit">Send</button>
+ <button className="window__button" type="submit">Verify</button>
</form>
{
sending
@@ -69,39 +70,15 @@ const Verify = () => {
<p>Mail was successfully sent again, check your mailbox!</p>
) : (
<p>If you didn't get verification email&nbsp;
- <span className="verify__sendEmail" onClick={handleSendMail}>send it again</span>.
+ <span className={styles.email} onClick={handleSendMail}>send it again</span>.
</p>
)
)
}
- {errorMsg && <p className="verify__errorMsg">{errorMsg}</p>}
+ {errorMsg && <p className={styles.error}>{errorMsg}</p>}
</div>
)
}
- <style jsx>{`
- form {
- padding .5em 0;
- }
-
- input {
- padding: .75em;
- border: 1px dashed #333;
- border-radius: .5em;
- }
-
- p {
- line-height: 1.33;
- padding: .5em 0;
- }
-
- .verify__sendEmail {
- color: blue;
- cursor: pointer;
- }
- .verify__errorMsg {
- color: brown;
- }
- `}</style>
</Layout>
)
}
diff --git a/styles/Main.module.scss b/styles/Main.module.scss
new file mode 100644
index 0000000..15be72a
--- /dev/null
+++ b/styles/Main.module.scss
@@ -0,0 +1,125 @@
+.icon {
+ text-decoration: none;
+ display: inline-block;
+ width: 4em;
+ cursor: pointer;
+
+ img {
+ width: 4em;
+ }
+
+ p {
+ padding-top: .5em;
+ text-align: center;
+ color: #333;
+ }
+}
+
+.userForm {
+ label,
+ & {
+ display: flex;
+ flex-flow: column;
+ }
+
+ label > span {
+ font-weight: 600;
+ }
+
+ input[type=email],
+ input[type=password] {
+ padding: .5em;
+ margin: .5em 0;
+ border: 1px solid #ccc;
+ border-radius: .25px;
+ }
+ .error {
+ text-align: center;
+ color: brown;
+ margin: 1rem 0 0;
+ }
+}
+
+.header {
+ height: 2em;
+ padding: 0.5rem;
+ background-color: rgba(255, 255, 255, 0.4);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.5);
+
+ nav {
+ display: flex;
+
+ & > ul:first-of-type {
+ flex-grow: 1;
+ overflow: auto;
+ }
+ }
+
+ li {
+ margin-left: 1em;
+ margin-right: 1em;
+ display: inline-block;
+ cursor: pointer;
+
+ & > span,
+ & > a {
+ color: #333;
+ font-weight: 600;
+ text-decoration: none;
+ align-items: center;
+ }
+ }
+}
+
+.user {
+ font-weight: 600;
+ cursor: pointer;
+ position: relative;
+
+}
+
+.submenu {
+ position: absolute;
+ right: 4px;
+ top: 2.1em;
+ width: 10em;
+ padding: .5em;
+ background-color: rgba(255, 255, 255, .9);
+ border: 1px solid rgba(255, 255, 255, .5);
+
+ & > li {
+ margin: 0;
+ padding:.5em;
+ width: 100%;
+ line-height: em;
+
+ &:hover {
+ background-color: #ddd;
+ }
+ }
+}
+
+.verify {
+ & > form {
+ padding: .5em 0;
+
+ & > input {
+ padding: .75em;
+ border: 1px dashed #333;
+ border-radius: .5em;
+ }
+ }
+
+ p {
+ line-height: 1.33;
+ padding: .5em 0;
+ }
+
+ .email {
+ color: blue;
+ cursor: pointer;
+ }
+ .error {
+ color: brown;
+ }
+}
diff --git a/styles/_animations.scss b/styles/_animations.scss
deleted file mode 100644
index b195c60..0000000
--- a/styles/_animations.scss
+++ /dev/null
@@ -1,4 +0,0 @@
-@keyframes fade-in {
- from {opacity: 0;}
- to {opacity: 1;}
-}
diff --git a/styles/global.scss b/styles/global.scss
new file mode 100644
index 0000000..222bc44
--- /dev/null
+++ b/styles/global.scss
@@ -0,0 +1,39 @@
+@import "reset";
+@import "window";
+
+main {
+ position: fixed;
+ top: 2em;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+
+body {
+ margin: 0;
+ color: #222;
+ height: 100vh;
+ overflow: hidden;
+
+ background: #50a3a2;
+ background: -webkit-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
+ background: -moz-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
+ background: -o-linear-gradient(top left, #50a3a2 0%, #53e3a6 100%);
+ background: linear-gradient(to bottom right, #50a3a2 0%, #53e3a6 100%);
+
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
+ 'Helvetica Neue', Arial, Noto Sans, sans-serif, 'Apple Color Emoji',
+ 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+}
+
+textarea, input {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
+ 'Helvetica Neue', Arial, Noto Sans, sans-serif, 'Apple Color Emoji',
+ 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+}
+
+.container {
+ margin: 1.5rem auto;
+ padding-left: 2rem;
+ padding-right: 2rem;
+}
diff --git a/styles/styles.scss b/styles/styles.scss
deleted file mode 100644
index 73ef2ee..0000000
--- a/styles/styles.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-@import "reset";
-@import "animations";
-@import "window";