1
0
mirror of https://github.com/kremalicious/blog.git synced 2024-12-22 17:23:50 +01:00

modal tweaks

This commit is contained in:
Matthias Kretschmann 2018-10-13 18:13:36 +02:00
parent 0352c17054
commit 216debbf72
Signed by: m
GPG Key ID: 606EEEF3C479A91F
8 changed files with 170 additions and 98 deletions

View File

@ -18,7 +18,7 @@
- [🎉 Features](#-features) - [🎉 Features](#-features)
- [🎆 EXIF extraction](#-exif-extraction) - [🎆 EXIF extraction](#-exif-extraction)
- [💰 Cryptocurrency donation via Web3/MetaMask](#-cryptocurrency-donation-via-web3-metamask) - [💰 Cryptocurrency donation via Web3/MetaMask](#-cryptocurrency-donation-via-web3metamask)
- [🕸 Related Posts](#-related-posts) - [🕸 Related Posts](#-related-posts)
- [🐝 Coinhive](#-coinhive) - [🐝 Coinhive](#-coinhive)
- [🏆 SEO component](#-seo-component) - [🏆 SEO component](#-seo-component)
@ -55,11 +55,11 @@ If you want to know how this works, have a look at the respective component unde
### 💰 Cryptocurrency donation via Web3/MetaMask ### 💰 Cryptocurrency donation via Web3/MetaMask
Lets visitors say thanks with Bitcoin or Ether. Includes full Web3 client for sending Ether via MetaMask or Mist. Lets visitors say thanks with Bitcoin or Ether. Uses [web3.js](https://github.com/ethereum/web3.js) for sending Ether transactions via MetaMask, Brave or Mist. Component listens to account & network changes and adapts accordingly.
As a fallback, QR codes are generated with [react-qr-svg](https://github.com/no23reason/react-qr-svg) from the addresses defined in [`config.js`](config.js). As a fallback, QR codes are generated with [react-qr-svg](https://github.com/no23reason/react-qr-svg) from the addresses defined in [`config.js`](config.js).
<img width="743" alt="screen shot 2018-10-11 at 21 01 37" src="https://user-images.githubusercontent.com/90316/46827443-e1187680-cd98-11e8-9daf-00a37c0ee13a.png"> <img width="1091" alt="screen shot 2018-10-13 at 18 40 56" src="https://user-images.githubusercontent.com/90316/46907751-907b5780-cf17-11e8-902d-6c520b388292.png" />
If you want to know how this works, have a look at the respective components under If you want to know how this works, have a look at the respective components under
@ -70,7 +70,7 @@ If you want to know how this works, have a look at the respective components und
Under each post a list of related posts is displayed which are based on the tags of the currently viewed post. Also allows loading more related posts in place. Under each post a list of related posts is displayed which are based on the tags of the currently viewed post. Also allows loading more related posts in place.
<img width="691" alt="screen shot 2018-10-11 at 21 03 03" src="https://user-images.githubusercontent.com/90316/46827531-14f39c00-cd99-11e8-84aa-0e851c32c89c.png"> <img width="691" alt="screen shot 2018-10-11 at 21 03 03" src="https://user-images.githubusercontent.com/90316/46827531-14f39c00-cd99-11e8-84aa-0e851c32c89c.png" />
If you want to know how this works, have a look at the respective component under If you want to know how this works, have a look at the respective component under
@ -80,7 +80,7 @@ If you want to know how this works, have a look at the respective component unde
Includes a component for mining Monero with JavaScript via [Coinhive](https://coinhive.com). Includes a component for mining Monero with JavaScript via [Coinhive](https://coinhive.com).
<img width="166" alt="screen shot 2018-10-11 at 21 09 49" src="https://user-images.githubusercontent.com/90316/46827858-03f75a80-cd9a-11e8-84f1-65b7d0027124.png"> <img width="166" alt="screen shot 2018-10-11 at 21 09 49" src="https://user-images.githubusercontent.com/90316/46827858-03f75a80-cd9a-11e8-84f1-65b7d0027124.png" />
Functionality is opt-in on a post basis. Simply add this to any post's frontmatter to activate it for this post: Functionality is opt-in on a post basis. Simply add this to any post's frontmatter to activate it for this post:

View File

@ -10,14 +10,15 @@
bottom: 0; bottom: 0;
z-index: 10; z-index: 10;
background: rgba($body-background-color, .9); background: rgba($body-background-color, .9);
backdrop-filter: blur(5px); // backdrop-filter: blur(5px);
animation: fadein .3s; animation: fadein .3s;
padding: $spacer / 2; padding: $spacer;
@media (min-width: $screen-sm) { @media (min-width: $screen-sm) {
display: flex; display: flex;
align-items: center; align-items: flex-start;
justify-content: center; justify-content: center;
padding-top: 6vh;
} }
} }
@ -42,20 +43,31 @@
cursor: pointer; cursor: pointer;
background: transparent; background: transparent;
border: 0; border: 0;
-webkit-appearance: none; appearance: none;
line-height: 1; line-height: 1;
font-size: $font-size-large; font-size: $font-size-h2;
padding: 3px; padding: 4px;
position: absolute; position: absolute;
top: 0; top: 0;
right: ($spacer/4); right: ($spacer/4);
color: $brand-grey; color: $brand-grey-light;
font-weight: 500; font-weight: 500;
&:hover,
&:focus {
color: $brand-grey;
}
} }
// Prevent background scrolling when modal is open
.isModalOpen { .isModalOpen {
// Prevent background scrolling when modal is open
overflow: hidden; overflow: hidden;
// more cross-browser backdrop-filter
body > div:first-child {
transition: filter .85s ease-out;
filter: blur(5px);
}
} }
.modal__title { .modal__title {

View File

@ -7,6 +7,79 @@ import styles from './Web3Donation.module.scss'
const ONE_SECOND = 1000 const ONE_SECOND = 1000
const ONE_MINUTE = ONE_SECOND * 60 const ONE_MINUTE = ONE_SECOND * 60
const InputGroup = ({
networkId,
selectedAccount,
amount,
onAmountChange,
handleWeb3Button
}) => (
<div className={styles.inputGroup}>
<div className={styles.input}>
<Input
type="number"
disabled={!(networkId === '1') || !selectedAccount}
value={amount}
onChange={onAmountChange}
min="0"
step="0.01"
/>
<div className={styles.currency}>
<span>ETH</span>
</div>
</div>
<button
className="btn btn-primary"
onClick={handleWeb3Button}
disabled={!(networkId === '1') || !selectedAccount}
>
Make it rain
</button>
</div>
)
InputGroup.propTypes = {
networkId: PropTypes.string,
selectedAccount: PropTypes.string,
amount: PropTypes.number,
onAmountChange: PropTypes.func,
handleWeb3Button: PropTypes.func
}
const Alerts = ({ accounts, networkId, error, transactionHash }) => {
if (error || accounts.length === 0) {
return (
<div className={styles.alert}>
{accounts.length === 0 &&
'Web3 detected, but no account. Are you logged into your MetaMask account?'}
{networkId !== '1' && 'Please connect to Main network'}
{error && error.message}
</div>
)
}
if (transactionHash) {
return (
<div className={styles.success}>
You are awesome, thanks!
<br />
<a href={`https://etherscan.io/tx/${transactionHash}`}>
See your transaction on etherscan.io.
</a>
</div>
)
}
return null
}
Alerts.propTypes = {
accounts: PropTypes.array,
networkId: PropTypes.string,
error: PropTypes.object,
transactionHash: PropTypes.string
}
export default class Web3Donation extends PureComponent { export default class Web3Donation extends PureComponent {
state = { state = {
web3Connected: false, web3Connected: false,
@ -139,73 +212,38 @@ export default class Web3Donation extends PureComponent {
render() { render() {
return ( return (
<div className={styles.web3}> <div className={styles.web3}>
<h4>web3</h4> <header>
<p>Send Ether with MetaMask, Brave, or Mist.</p> <h4>web3</h4>
<p>Send Ether with MetaMask, Brave, or Mist.</p>
</header>
{this.state.web3Connected ? ( {this.state.web3Connected ? (
<div> <div className={styles.web3Row}>
{this.state.loading ? ( {this.state.loading ? (
'Hang on...' 'Hang on...'
) : ( ) : (
<div className={styles.inputGroup}> <InputGroup
<div className={styles.input}> networkId={this.state.networkId}
<Input selectedAccount={this.state.selectedAccount}
type="number" amount={this.state.amount}
disabled={ onAmountChange={this.onAmountChange}
!(this.state.networkId === '1') || handleWeb3Button={this.handleWeb3Button}
!this.state.selectedAccount />
}
value={this.state.amount}
onChange={this.onAmountChange}
min="0"
step="0.01"
/>
<div className={styles.currency}>
<span>ETH</span>
</div>
</div>
<button
className="btn btn-primary"
onClick={this.handleWeb3Button}
disabled={
!(this.state.networkId === '1') ||
!this.state.selectedAccount
}
>
Make it rain
</button>
</div>
)} )}
{this.state.accounts.length === 0 && ( <Alerts
<div className={styles.alert}> accounts={this.state.accounts}
Web3 detected, but no account. Are you logged into your MetaMask networkId={this.state.networkId}
account? error={this.state.error}
</div> transactionHash={this.state.transactionHash}
)} />
{this.state.networkId !== '1' && (
<div className={styles.alert}>Please connect to Main network</div>
)}
{this.state.error && (
<div className={styles.alert}>{this.state.error.message}</div>
)}
{this.state.transactionHash && (
<div className={styles.success}>
You are awesome, thanks!
<br />
<a
href={`https://etherscan.io/tx/${this.state.transactionHash}`}
>
See your transaction on etherscan.io.
</a>
</div>
)}
</div> </div>
) : ( ) : (
<div className={styles.alert}>No Web3 capable browser detected.</div> <small>
No Web3 detected. Install <a href="https://metamask.io">MetaMask</a>
, <a href="https://brave.com">Brave</a>, or{' '}
<a href="https://github.com/ethereum/mist">Mist</a>.
</small>
)} )}
</div> </div>
) )

View File

@ -10,17 +10,15 @@
margin-bottom: $spacer; margin-bottom: $spacer;
padding-bottom: $spacer * 1.5; padding-bottom: $spacer * 1.5;
h4 { small {
font-size: $font-size-large; color: darken($alert-info, 60%);
margin-top: 0; margin-top: -($spacer / 2);
margin-bottom: $spacer / 4; display: block;
color: $brand-grey;
text-align: center;
} }
}
p { .web3Row {
color: $brand-grey-light; min-height: 58px;
}
} }
.inputGroup { .inputGroup {
@ -30,17 +28,17 @@
@media (min-width: $screen-sm) { @media (min-width: $screen-sm) {
display: flex; display: flex;
max-width: 20rem; max-width: 18rem;
} }
button { button {
width: 100%; width: 100%;
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
border-color: lighten($brand-grey-light, 20%); border-color: lighten($brand-grey-light, 10%);
@media (min-width: $screen-sm) { @media (min-width: $screen-sm) {
width: 45%; width: 50%;
border-top-right-radius: $border-radius; border-top-right-radius: $border-radius;
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
@ -53,26 +51,29 @@
position: relative; position: relative;
@media (min-width: $screen-sm) { @media (min-width: $screen-sm) {
width: 55%; width: 50%;
} }
input { input {
text-align: center; text-align: center;
border: 1px solid lighten($brand-grey-light, 20%); border: 1px solid lighten($brand-grey-light, 20%);
font-size: $font-size-h3; font-size: $font-size-large;
padding: $spacer / 3 $spacer / 3 $spacer / 3 $spacer * 1.9; padding: $spacer / 3 $spacer / 3 $spacer / 3 $spacer * 1.7;
border-bottom: 0; border-bottom: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
@media (min-width: $screen-sm) { @media (min-width: $screen-sm) {
padding: $spacer / 4 0 $spacer / 3 $spacer * 1.9;
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-bottom-left-radius: $border-radius; border-bottom-left-radius: $border-radius;
border-bottom: 1px solid lighten($brand-grey-light, 20%); border-bottom: 1px solid lighten($brand-grey-light, 20%);
border-right: 0; border-right: 0;
} }
&::-webkit-inner-spin-button {
margin-left: -($spacer / 2);
}
} }
} }
@ -81,7 +82,7 @@
top: 1px; top: 1px;
bottom: 1px; bottom: 1px;
left: 1px; left: 1px;
font-size: $font-size-base; font-size: $font-size-small;
padding: $spacer / 3; padding: $spacer / 3;
color: $brand-grey-light; color: $brand-grey-light;
background: $brand-light; background: $brand-light;

View File

@ -36,6 +36,11 @@ class ModalThanks extends PureComponent {
<div className={styles.modalThanks}> <div className={styles.modalThanks}>
<Web3Donation address={author.ether} /> <Web3Donation address={author.ether} />
<header>
<h4>Other wallets</h4>
<p>Send Bitcoin or Ether from any wallet.</p>
</header>
{Object.keys(author).map((address, i) => ( {Object.keys(author).map((address, i) => (
<div key={i} className={styles.coin}> <div key={i} className={styles.coin}>
<Qr title={address} address={author[address]} /> <Qr title={address} address={author[address]} />

View File

@ -6,6 +6,30 @@
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
} }
h4 {
text-align: center;
margin: 0;
margin-bottom: $spacer / 2;
color: $brand-grey;
text-transform: capitalize;
}
header {
width: 100%;
text-align: center;
margin-bottom: $spacer;
h4 {
font-size: $font-size-large;
margin-top: 0;
margin-bottom: $spacer / 6;
}
p {
color: $brand-grey-light;
}
}
} }
.coin { .coin {
@ -16,14 +40,6 @@
margin-top: 0; margin-top: 0;
} }
h4 {
font-size: $font-size-large;
margin-top: 0;
margin-bottom: $spacer / 2;
color: $brand-grey;
text-align: center;
}
> svg { > svg {
margin-bottom: $spacer / 2; margin-bottom: $spacer / 2;
} }

View File

@ -103,7 +103,7 @@ class RelatedPosts extends PureComponent {
className={`${styles.button} btn`} className={`${styles.button} btn`}
onClick={this.shufflePosts} onClick={this.shufflePosts}
> >
More Related Posts Refresh Related Posts
</button> </button>
</aside> </aside>
) )

View File

@ -43,7 +43,7 @@ pre {
border-radius: $border-radius; border-radius: $border-radius;
// make 'em scrollable // make 'em scrollable
overflow: scroll; overflow: auto;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
max-height: 300px; max-height: 300px;