mirror of
https://github.com/kremalicious/blog.git
synced 2024-11-23 02:10:01 +01:00
add thank you modal
This commit is contained in:
parent
0ddc52425b
commit
62d98d0c19
17
package.json
17
package.json
@ -24,14 +24,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"clipboard": "^2.0.1",
|
"clipboard": "^2.0.1",
|
||||||
"exif-js": "^2.3.0",
|
"exif-js": "^2.3.0",
|
||||||
"gatsby": "^2.0.0-beta.98",
|
"gatsby": "^2.0.0-beta.100",
|
||||||
"gatsby-image": "^2.0.0-beta.7",
|
"gatsby-image": "^2.0.0-beta.7",
|
||||||
"gatsby-plugin-catch-links": "^2.0.2-beta.7",
|
"gatsby-plugin-catch-links": "^2.0.2-beta.8",
|
||||||
"gatsby-plugin-matomo": "^0.4.1",
|
"gatsby-plugin-matomo": "^0.4.1",
|
||||||
"gatsby-plugin-react-helmet": "^3.0.0-beta.4",
|
"gatsby-plugin-react-helmet": "^3.0.0-beta.4",
|
||||||
"gatsby-plugin-sass": "^2.0.0-beta.10",
|
"gatsby-plugin-sass": "^2.0.0-beta.10",
|
||||||
"gatsby-plugin-sharp": "^2.0.0-beta.7",
|
"gatsby-plugin-sharp": "^2.0.0-beta.7",
|
||||||
"gatsby-plugin-sitemap": "^2.0.0-beta.3",
|
"gatsby-plugin-sitemap": "^2.0.0-beta.4",
|
||||||
"gatsby-remark-autolink-headers": "^2.0.0-beta.5",
|
"gatsby-remark-autolink-headers": "^2.0.0-beta.5",
|
||||||
"gatsby-remark-copy-linked-files": "^2.0.0-beta.3",
|
"gatsby-remark-copy-linked-files": "^2.0.0-beta.3",
|
||||||
"gatsby-remark-images": "^2.0.1-beta.10",
|
"gatsby-remark-images": "^2.0.1-beta.10",
|
||||||
@ -39,7 +39,7 @@
|
|||||||
"gatsby-remark-smartypants": "^2.0.0-beta.3",
|
"gatsby-remark-smartypants": "^2.0.0-beta.3",
|
||||||
"gatsby-source-filesystem": "^2.0.1-beta.10",
|
"gatsby-source-filesystem": "^2.0.1-beta.10",
|
||||||
"gatsby-transformer-remark": "^2.1.1-beta.6",
|
"gatsby-transformer-remark": "^2.1.1-beta.6",
|
||||||
"gatsby-transformer-sharp": "^2.1.1-beta.6",
|
"gatsby-transformer-sharp": "^2.1.1-beta.7",
|
||||||
"gatsby-transformer-yaml": "^2.1.1-beta.3",
|
"gatsby-transformer-yaml": "^2.1.1-beta.3",
|
||||||
"graphql": "^0.13.2",
|
"graphql": "^0.13.2",
|
||||||
"intersection-observer": "^0.5.0",
|
"intersection-observer": "^0.5.0",
|
||||||
@ -48,21 +48,24 @@
|
|||||||
"prismjs": "^1.15.0",
|
"prismjs": "^1.15.0",
|
||||||
"qrious": "^4.0.2",
|
"qrious": "^4.0.2",
|
||||||
"react": "^16.4.2",
|
"react": "^16.4.2",
|
||||||
|
"react-clipboard.js": "^2.0.0",
|
||||||
"react-dom": "^16.4.2",
|
"react-dom": "^16.4.2",
|
||||||
"react-helmet": "^5.2.0",
|
"react-helmet": "^5.2.0",
|
||||||
|
"react-modal": "^3.5.1",
|
||||||
|
"react-qr-svg": "^2.1.0",
|
||||||
"react-time": "^4.3.0",
|
"react-time": "^4.3.0",
|
||||||
"slugify": "^1.3.1",
|
"slugify": "^1.3.1",
|
||||||
"vex-js": "^4.1.0"
|
"vex-js": "^4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@svgr/cli": "^2.1.1",
|
"@svgr/cli": "^2.2.0",
|
||||||
"babel-eslint": "^8.2.6",
|
"babel-eslint": "^8.2.6",
|
||||||
"eslint": "^5.3.0",
|
"eslint": "^5.3.0",
|
||||||
"eslint-config-prettier": "^2.9.0",
|
"eslint-config-prettier": "^2.10.0",
|
||||||
"eslint-loader": "^2.1.0",
|
"eslint-loader": "^2.1.0",
|
||||||
"eslint-plugin-graphql": "^2.1.1",
|
"eslint-plugin-graphql": "^2.1.1",
|
||||||
"eslint-plugin-prettier": "^2.6.2",
|
"eslint-plugin-prettier": "^2.6.2",
|
||||||
"eslint-plugin-react": "^7.10.0",
|
"eslint-plugin-react": "^7.11.0",
|
||||||
"prettier": "^1.14.1",
|
"prettier": "^1.14.1",
|
||||||
"prettier-stylelint": "^0.4.2",
|
"prettier-stylelint": "^0.4.2",
|
||||||
"stylelint": "^9.4.0",
|
"stylelint": "^9.4.0",
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
@include transition;
|
@include transition;
|
||||||
|
|
||||||
margin-top: $spacer * 2.65;
|
margin-top: $spacer * 2.65;
|
||||||
margin-bottom: $spacer * 20;
|
margin-bottom: $spacer * 20; // height of footer
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
|
|
||||||
|
42
src/components/atoms/Modal.jsx
Normal file
42
src/components/atoms/Modal.jsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import ReactModal from 'react-modal'
|
||||||
|
|
||||||
|
import styles from './Modal.module.scss'
|
||||||
|
|
||||||
|
ReactModal.setAppElement('#___gatsby')
|
||||||
|
|
||||||
|
class Modal extends PureComponent {
|
||||||
|
render() {
|
||||||
|
if (!this.props.isOpen) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, title, handleCloseModal } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ReactModal
|
||||||
|
overlayClassName={styles.modal}
|
||||||
|
className={styles.modal__content}
|
||||||
|
htmlOpenClassName={styles.isModalOpen}
|
||||||
|
shouldReturnFocusAfterClose={false}
|
||||||
|
{...this.props}
|
||||||
|
>
|
||||||
|
{title && <h1 className={styles.modal__title}>{title}</h1>}
|
||||||
|
{children}
|
||||||
|
<button className={styles.modal__close} onClick={handleCloseModal}>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</ReactModal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Modal.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
isOpen: PropTypes.bool,
|
||||||
|
handleCloseModal: PropTypes.func.isRequired,
|
||||||
|
children: PropTypes.node.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Modal
|
98
src/components/atoms/Modal.module.scss
Normal file
98
src/components/atoms/Modal.module.scss
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
@import 'variables';
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
overflow: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 10;
|
||||||
|
background: rgba($body-background-color, .9);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
animation: fadein .3s;
|
||||||
|
padding: $spacer / 2;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal__content {
|
||||||
|
outline: 0;
|
||||||
|
background: transparent;
|
||||||
|
position: relative;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
border: 1px solid rgba($brand-grey-light, .4);
|
||||||
|
box-shadow: 0 5px 30px rgba($brand-grey-light, .2);
|
||||||
|
padding: 0 $spacer / 2 $spacer / 2;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
@media (min-width: $screen-md) {
|
||||||
|
max-width: $screen-sm;
|
||||||
|
padding: 0 $spacer $spacer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal__close {
|
||||||
|
display: block;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: $font-size-large;
|
||||||
|
padding: 3px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: ($spacer/4);
|
||||||
|
color: $brand-grey;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent background scrolling when modal is open
|
||||||
|
.isModalOpen {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal__title {
|
||||||
|
font-size: $font-size-h4;
|
||||||
|
margin-top: $spacer / 2;
|
||||||
|
margin-bottom: $spacer / 2;
|
||||||
|
margin-left: -($spacer / 2);
|
||||||
|
margin-right: -($spacer / 2);
|
||||||
|
border-bottom: 1px solid rgba($brand-grey-light, .4);
|
||||||
|
padding: 0 $spacer;
|
||||||
|
padding-bottom: ($spacer/2);
|
||||||
|
|
||||||
|
@media (min-width: $screen-md) {
|
||||||
|
margin-left: -($spacer);
|
||||||
|
margin-right: -($spacer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Overlay/content animations
|
||||||
|
//
|
||||||
|
@keyframes fadein {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeout {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
60
src/components/molecules/ModalThanks.jsx
Normal file
60
src/components/molecules/ModalThanks.jsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { StaticQuery, graphql } from 'gatsby'
|
||||||
|
import { QRCode } from 'react-qr-svg'
|
||||||
|
import Clipboard from 'react-clipboard.js'
|
||||||
|
|
||||||
|
import Modal from '../atoms/Modal'
|
||||||
|
import IconClipboard from '../svg/Clipboard'
|
||||||
|
import styles from './ModalThanks.module.scss'
|
||||||
|
|
||||||
|
const ModalThanks = ({ ...props }) => (
|
||||||
|
<StaticQuery
|
||||||
|
query={graphql`
|
||||||
|
query {
|
||||||
|
contentYaml {
|
||||||
|
author {
|
||||||
|
bitcoin
|
||||||
|
ether
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
render={data => {
|
||||||
|
const { author } = data.contentYaml
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
{...props}
|
||||||
|
contentLabel="Say thanks with Bitcoin or Ether"
|
||||||
|
title="Say thanks"
|
||||||
|
>
|
||||||
|
<div className={styles.modalThanks}>
|
||||||
|
{Object.keys(author).map((address, i) => (
|
||||||
|
<div key={i} className={styles.coin}>
|
||||||
|
<h4>{address}</h4>
|
||||||
|
<QRCode
|
||||||
|
bgColor="transparent"
|
||||||
|
fgColor="#6b7f88"
|
||||||
|
level="Q"
|
||||||
|
style={{ width: 150 }}
|
||||||
|
value={author[address]}
|
||||||
|
/>
|
||||||
|
<pre>
|
||||||
|
<code>{author[address]}</code>
|
||||||
|
<Clipboard
|
||||||
|
data-clipboard-text={author[address]}
|
||||||
|
button-title="Copy to clipboard"
|
||||||
|
>
|
||||||
|
<IconClipboard />
|
||||||
|
</Clipboard>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default ModalThanks
|
69
src/components/molecules/ModalThanks.module.scss
Normal file
69
src/components/molecules/ModalThanks.module.scss
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
@import 'variables';
|
||||||
|
|
||||||
|
.modalThanks {
|
||||||
|
@media (min-width: $screen-sm) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.coin {
|
||||||
|
margin-top: $spacer;
|
||||||
|
|
||||||
|
@media (min-width: $screen-sm) {
|
||||||
|
width: 48%;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: $font-size-large;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: $spacer / 2;
|
||||||
|
color: $brand-grey;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
margin-bottom: $spacer / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
padding-right: 2rem;
|
||||||
|
|
||||||
|
code {
|
||||||
|
padding: $spacer / 2;
|
||||||
|
font-size: .65rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border: 0;
|
||||||
|
box-shadow: none;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
background: rgba($brand-grey, .3);
|
||||||
|
padding: $spacer / 3;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 1rem;
|
||||||
|
height: 1rem;
|
||||||
|
fill: $brand-grey;
|
||||||
|
transition: .15s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
svg {
|
||||||
|
fill: $brand-grey-dimmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ import { StaticQuery, graphql } from 'gatsby'
|
|||||||
import Img from 'gatsby-image'
|
import Img from 'gatsby-image'
|
||||||
|
|
||||||
import Container from '../atoms/Container'
|
import Container from '../atoms/Container'
|
||||||
|
import ModalThanks from '../molecules/ModalThanks'
|
||||||
|
|
||||||
import Twitter from '../svg/Twitter'
|
import Twitter from '../svg/Twitter'
|
||||||
import Github from '../svg/Github'
|
import Github from '../svg/Github'
|
||||||
import Facebook from '../svg/Facebook'
|
import Facebook from '../svg/Facebook'
|
||||||
@ -16,7 +18,14 @@ class Footer extends PureComponent {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
||||||
this.state = { year: null }
|
this.state = {
|
||||||
|
year: null,
|
||||||
|
showModal: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleModal = () => {
|
||||||
|
this.setState({ showModal: !this.state.showModal })
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -46,7 +55,6 @@ class Footer extends PureComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bitcoin
|
bitcoin
|
||||||
ether
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,11 +133,20 @@ class Footer extends PureComponent {
|
|||||||
<Github />
|
<Github />
|
||||||
View source
|
View source
|
||||||
</a>
|
</a>
|
||||||
<a href="#" className={styles.btc}>
|
<a
|
||||||
|
href="#"
|
||||||
|
className={styles.btc}
|
||||||
|
onClick={this.toggleModal}
|
||||||
|
>
|
||||||
<Bitcoin />
|
<Bitcoin />
|
||||||
<code>{author.bitcoin}</code>
|
<code>{author.bitcoin}</code>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<ModalThanks
|
||||||
|
isOpen={this.state.showModal}
|
||||||
|
handleCloseModal={this.toggleModal}
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
</Container>
|
</Container>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -37,6 +37,7 @@ pre {
|
|||||||
background-color: $code-bg;
|
background-color: $code-bg;
|
||||||
margin-left: -($spacer);
|
margin-left: -($spacer);
|
||||||
margin-right: -($spacer);
|
margin-right: -($spacer);
|
||||||
|
border-radius: $border-radius;
|
||||||
|
|
||||||
// make 'em scrollable
|
// make 'em scrollable
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
@ -59,6 +60,7 @@ pre {
|
|||||||
overflow-wrap: normal;
|
overflow-wrap: normal;
|
||||||
word-wrap: normal;
|
word-wrap: normal;
|
||||||
word-break: normal;
|
word-break: normal;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,14 @@
|
|||||||
&:first-child {
|
&:first-child {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:only-child {
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post/photo teaser
|
// Post/photo teaser
|
||||||
|
Loading…
Reference in New Issue
Block a user