1
0
mirror of https://github.com/kremalicious/blog.git synced 2025-02-14 21:10:25 +01:00

Merge pull request #498 from kremalicious/feature/css-modules-plugin-image

Gatsby v3
This commit is contained in:
Matthias Kretschmann 2021-03-22 23:39:46 +01:00 committed by GitHub
commit f976a5581a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
195 changed files with 12362 additions and 14868 deletions

View File

@ -5,7 +5,7 @@
"stylelint-prettier/recommended" "stylelint-prettier/recommended"
], ],
"plugins": ["stylelint-prettier"], "plugins": ["stylelint-prettier"],
"syntax": "scss", "syntax": "css",
"rules": { "rules": {
"prettier/prettier": true, "prettier/prettier": true,
"property-no-unknown": [ "property-no-unknown": [

View File

@ -42,9 +42,5 @@ module.exports = {
title: '/Uses', title: '/Uses',
link: '/uses' link: '/uses'
} }
], ]
darkModeConfig: {
classNameDark: 'dark',
classNameLight: 'light'
}
} }

View File

@ -29,7 +29,7 @@ These icons are free for your personal use and include icons for all file types
Get them and have fun. Get them and have fun.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/aperturefiletypes_by_kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/aperturefiletypes_by_kremalicious.zip">Download</a>
</p> </p>
And don't forget to read my article about [how to change the generic image icons in Mac OS X Leopard](/changing-the-image-icons-in-mac-os-x-leopard/). And don't forget to read my article about [how to change the generic image icons in Mac OS X Leopard](/changing-the-image-icons-in-mac-os-x-leopard/).

View File

@ -19,5 +19,5 @@ I have added my first wallpaper to the Goodies section on this website. It's a s
You can get the wallpaper by browsing [my Goodies section](http://www.kremalicious.com/goodies/) and clicking on the download link for the wallpaper. The download package also includes a custom folder icon (512px as .icns, .png, .ico) with the Chives wallpaper on it. You can get the wallpaper by browsing [my Goodies section](http://www.kremalicious.com/goodies/) and clicking on the download link for the wallpaper. The download package also includes a custom folder icon (512px as .icns, .png, .ico) with the Chives wallpaper on it.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/chives_by_kremalicious.zip">Download Chives Wallpaper</a> <a class="icon-download btn btn-primary" href="../media/chives_by_kremalicious.zip">Download Chives Wallpaper</a>
</p> </p>

View File

@ -92,7 +92,7 @@ Brief description of Daguerres role in the invention of photography process by T
This icon package was exclusively announced first on [MacThemes](http://macthemes2.net) and you can download it from the [Goodies section on this website](/goodies/) or directly via this link: This icon package was exclusively announced first on [MacThemes](http://macthemes2.net) and you can download it from the [Goodies section on this website](/goodies/) or directly via this link:
<p class="content-download"> <p class="content-download">
<a class="btn icon-download" href="../media/niepces_camera_obscura_by_kremalicious.zip">Download</a> <a class="btn btn-primary icon-download" href="../media/niepces_camera_obscura_by_kremalicious.zip">Download</a>
</p> </p>
In addition to these icons you can download the [associated wallpapers for your desktop or your iPhone](http://www.kremalicious.com/2008/06/new-goodie-niepces-camera-obscura-wallpaper-pack/). In addition to these icons you can download the [associated wallpapers for your desktop or your iPhone](http://www.kremalicious.com/2008/06/new-goodie-niepces-camera-obscura-wallpaper-pack/).

View File

@ -19,7 +19,7 @@ In addition to my Niépce's Camera Obscura icons for Aperture and iPhoto I have
All Wallpapers are using a custom designed background which imitates the look of a metal plate like it was used in Niépce's experiments although it wasn't golden. To make it more Mac style I have added a stenciled dots pattern (which is a commonly used reference to the front design of the MacPro). All Wallpapers are using a custom designed background which imitates the look of a metal plate like it was used in Niépce's experiments although it wasn't golden. To make it more Mac style I have added a stenciled dots pattern (which is a commonly used reference to the front design of the MacPro).
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/niepces_camera_obscura_wallpaper_pack_by_kremalicious.zip">Download Niépce's Camera Obscura Wallpaper</a> <a class="icon-download btn btn-primary" href="../media/niepces_camera_obscura_wallpaper_pack_by_kremalicious.zip">Download Niépce's Camera Obscura Wallpaper</a>
</p> </p>
Here are the details: Here are the details:

View File

@ -376,7 +376,7 @@ Here you can see the icons included in the Server Displays icon pack:
Because I've just modified Apple's standard icons these icons are just available via this blog post and they will not show up in my Goodies section. Just download the whole package directly via this link: Because I've just modified Apple's standard icons these icons are just available via this blog post and they will not show up in my Goodies section. Just download the whole package directly via this link:
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/server_displays_by_kremalicious.zip">Download Server Display Icons <span>zip</span></a> <a class="icon-download btn btn-primary" href="../media/server_displays_by_kremalicious.zip">Download Server Display Icons <span>zip</span></a>
</p> </p>
### How to use the icons ### How to use the icons

View File

@ -20,7 +20,7 @@ As always these desktop icons are free for you personal and non-commercial use.
The whole package includes 7 icons either packed in a nice tagged iContainer for use with Candybar or in Mac + Win + Linux compatible formats. If you have such an Icy Box case grab the icons. Have fun! The whole package includes 7 icons either packed in a nice tagged iContainer for use with Candybar or in Mac + Win + Linux compatible formats. If you have such an Icy Box case grab the icons. Have fun!
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/icybox_by_kremalicious.zip">Download Icy Box Icons <span>zip</span></a> <a class="icon-download btn btn-primary" href="../media/icybox_by_kremalicious.zip">Download Icy Box Icons <span>zip</span></a>
</p> </p>
- Replacement icons for the silver and black Icy Box external aluminium case with USB interface - Replacement icons for the silver and black Icy Box external aluminium case with USB interface

View File

@ -18,6 +18,6 @@ Show your geeky love for extraterrestrial universities! This is a simple Futuram
As usual you can [grab the whole zip package from my Goodies page](http://www.kremalicious.com/goodies/#wall) and have fun. As usual you can [grab the whole zip package from my Goodies page](http://www.kremalicious.com/goodies/#wall) and have fun.
<p class="content-download"> <p class="content-download ">
<a class="icon-download" href="../media/mars-u-wall-by-kremalicious.zip">Download Futurama Mars U Wallpaper <span>zip</span></a> <a class="icon-download btn btn-primary" href="../media/mars-u-wall-by-kremalicious.zip">Download Futurama Mars U Wallpaper <span>zip</span></a>
</p> </p>

View File

@ -22,5 +22,5 @@ Ive just released my own coffee cup icon, enjoy:
## Download ## Download
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/coffee_cup_by_kremalicious.zip">Download Coffee Cup Icons</a> <a class="icon-download btn btn-primary" href="../media/coffee_cup_by_kremalicious.zip">Download Coffee Cup Icons</a>
</p> </p>

View File

@ -29,5 +29,5 @@ Simple, high-resolution Futurama tribute wallpaper pack inspired by the latest F
Seriously, the pink versions are burning my eyes but the pink is a good reference to the events in the recent movie. Seriously, the pink versions are burning my eyes but the pink is a good reference to the events in the recent movie.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/out-of-whale-oil-wall-by-kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/out-of-whale-oil-wall-by-kremalicious.zip">Download</a>
</p> </p>

View File

@ -16,7 +16,7 @@ Here's a quick twitter icon for use on your websites which is kind of a by-produ
This icon comes in various formats (PNG, ICNS, iContainer) and in 4 different sizes (128px, 48px, 32px, 16px) with each icon size redrawn (of course). Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab these icons while they're hot. This icon comes in various formats (PNG, ICNS, iContainer) and in 4 different sizes (128px, 48px, 32px, 16px) with each icon size redrawn (of course). Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab these icons while they're hot.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/twitter-crisp-by-kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/twitter-crisp-by-kremalicious.zip">Download</a>
</p> </p>
Use them on any web project you like and/or [convert them into a send to twitter link](http://kremalicious.com/ultimate-coda-wordpress-share-link-bonanza/). Have fun! Use them on any web project you like and/or [convert them into a send to twitter link](http://kremalicious.com/ultimate-coda-wordpress-share-link-bonanza/). Have fun!

View File

@ -26,7 +26,7 @@ The icon comes in various formats (iContainer, icns, png) in sizes from 512px-16
Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab this icon while it's hot. Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab this icon while it's hot.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/adiumeetie-by-kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/adiumeetie-by-kremalicious.zip">Download</a>
</p> </p>
## Adium Icon Usage ## Adium Icon Usage

View File

@ -20,7 +20,7 @@ tags:
Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab these replacement icons. Just head over [to my Goodies page](http://www.kremalicious.com/goodies/) or click the following download button and grab these replacement icons.
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/delibar-by-kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/delibar-by-kremalicious.zip">Download</a>
</p> </p>
## Icon Usage ## Icon Usage

View File

@ -27,7 +27,7 @@ The homescreen icons pixels in the 16px version needed all more vivid colors to
The icons come in various formats: iContainer, ICNS, ICO and PNG files for each size. Just click the following download button to grab the whole pack: The icons come in various formats: iContainer, ICNS, ICO and PNG files for each size. Just click the following download button to grab the whole pack:
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/ipixelpad_by_kremalicious.zip">Download</a> <a class="icon-download btn btn-primary" href="../media/ipixelpad_by_kremalicious.zip">Download</a>
</p> </p>
## License ## License

View File

@ -23,6 +23,6 @@ The wallpaper comes in four versions with two color variations and two text vari
You can grab the full zip-package with versions for Desktop, iPad, iPhone & Android included: You can grab the full zip-package with versions for Desktop, iPad, iPhone & Android included:
<p class="content-download"> <p class="content-download">
<a class="btn-primary icon-download" href="../media/momcorp_wall_by_kremalicious.zip">Download</a> <a class="btn btn-primary icon-download" href="../media/momcorp_wall_by_kremalicious.zip">Download</a>
<a href="http://krlc.us/givecoffee" class="icon-heart">Donate</a> <a href="http://krlc.us/givecoffee" class="btn icon-heart">Donate</a>
</p> </p>

View File

@ -24,7 +24,7 @@ The plugin is localized in english, german & spanish (thanks to Andrew Kurtis fr
You can just install the plugin via the automatic backend installer under _Plugins > Add New_, activate and enjoy the red badges. You can just install the plugin via the automatic backend installer under _Plugins > Add New_, activate and enjoy the red badges.
<p class="content-download"> <p class="content-download">
<a href="http://wordpress.org/extend/plugins/badged" class="btn-primary icon-wordpress">Plugin Page</a> <a class="btn-primary icon-github" href="https://github.com/kremalicious/Badged">GitHub</a> <a href="http://krlc.us/givecoffee" class="icon-heart btn">Donate</a> <a href="http://wordpress.org/extend/plugins/badged" class="btn btn-primary icon-wordpress">Plugin Page</a> <a class="btn btn-primary icon-github" href="https://github.com/kremalicious/Badged">GitHub</a> <a href="http://krlc.us/givecoffee" class="icon-heart btn">Donate</a>
</p> </p>
The plugin is hosted on GitHub and will always be mirrored in the WordPress plugins directory. But in case you want to install the plugin manually: The plugin is hosted on GitHub and will always be mirrored in the WordPress plugins directory. But in case you want to install the plugin manually:

View File

@ -33,7 +33,7 @@ So if you value quality and want pixel perfect icons in your admin area you need
Ive put the template along with the implementation examples from the next section on [github](https://github.com/kremalicious/wp-icons-template). You can just download the whole package right away: Ive put the template along with the implementation examples from the next section on [github](https://github.com/kremalicious/wp-icons-template). You can just download the whole package right away:
<p class="content-download"> <p class="content-download">
<a href="https://github.com/kremalicious/wp-icons-template/zipball/master" class="btn-primary icon-download">Download</a> <a href="https://github.com/kremalicious/wp-icons-template" class="icon-github">GitHub</a> <a href="http://krlc.us/givecoffee" class="icon-heart">Donate</a> <a href="https://github.com/kremalicious/wp-icons-template/zipball/master" class="btn btn-primary icon-download">Download</a> <a href="https://github.com/kremalicious/wp-icons-template" class="icon-github btn btn-primary">GitHub</a> <a href="http://krlc.us/givecoffee" class="icon-heart btn">Donate</a>
</p> </p>
### Usage ### Usage

View File

@ -21,8 +21,8 @@ The above picture might be blurry depending on the device you're using so here's
They are completely styled with CSS3 so they're sharp on all screens no matter how high the dpi. Have a look at the [full demo](http://lab.kremalicious.com/kbdfun/) or grab the project folder with the CSS & LESS files from GitHub. The code is under the MIT license so you're free to use it in any personal or commercial project. They are completely styled with CSS3 so they're sharp on all screens no matter how high the dpi. Have a look at the [full demo](http://lab.kremalicious.com/kbdfun/) or grab the project folder with the CSS & LESS files from GitHub. The code is under the MIT license so you're free to use it in any personal or commercial project.
<p class="content-download"> <p class="content-download">
<a class="btn-primary icon-compass" href="http://lab.kremalicious.com/kbdfun/">Demo</a> <a class="btn btn-primary icon-compass" href="http://lab.kremalicious.com/kbdfun/">Demo</a>
<a class="icon-github" href="https://github.com/kremalicious/kbdfun/">Github</a> <a class="icon-github btn" href="https://github.com/kremalicious/kbdfun/">Github</a>
</p> </p>
## Usage ## Usage

View File

@ -30,7 +30,7 @@ The full size I designed the wallpaper in is 3200x2048px. I don't know why Apple
Download the whole package with all the sizes included or grab the individual ones from the list, all linked to the image files: Download the whole package with all the sizes included or grab the individual ones from the list, all linked to the image files:
<p class="content-download"> <p class="content-download">
<a class="icon-download" href="../media/project-purple-kremalicious.zip">Download <span> zip</span></a> <a class="icon-download btn btn-primary" href="../media/project-purple-kremalicious.zip">Download <span> zip</span></a>
</p> </p>
- [Desktop/rMBP/iPad 3 (3200x2048)](../media/project-purple-kremalicious.png) - [Desktop/rMBP/iPad 3 (3200x2048)](../media/project-purple-kremalicious.png)

View File

@ -15,9 +15,9 @@ tags:
The badges provided by all app store providers just don't play well together with their varying typography and different sizing. So let's make them all visually unified, infinitely scalable, with pure text for easier localization and some web interaction styles. And while were at it: different sizes with the same markup by using some modifier classes. The badges provided by all app store providers just don't play well together with their varying typography and different sizing. So let's make them all visually unified, infinitely scalable, with pure text for easier localization and some web interaction styles. And while were at it: different sizes with the same markup by using some modifier classes.
<p class="content-download"> <p class="content-download">
<a class="btn-primary icon-compass" href="https://lab.kremalicious.com/appstorebadges/">Demo</a> <a class="btn btn-primary icon-compass" href="https://lab.kremalicious.com/appstorebadges/">Demo</a>
<a class="icon-github" href="https://github.com/kremalicious/appstorebadges/">GitHub</a> <a class="icon-github btn" href="https://github.com/kremalicious/appstorebadges/">GitHub</a>
<a class="icon-code" href="http://codepen.io/kremalicious/details/EVVraP/">Codepen</a> <a class="icon-code btn" href="http://codepen.io/kremalicious/details/EVVraP/">Codepen</a>
</p> </p>
## Styling ## Styling

View File

@ -41,5 +41,5 @@ hpm install hyper-mac-pro
Head over to GitHub to take a peek into the code or report some issues. Head over to GitHub to take a peek into the code or report some issues.
<p class="content-download"> <p class="content-download">
<a class="icon-github btn-primary" href="https://github.com/kremalicious/hyper-mac-pro">GitHub</a> <a class="icon-github btn btn-primary" href="https://github.com/kremalicious/hyper-mac-pro">GitHub</a>
</p> </p>

View File

@ -59,5 +59,5 @@ plugins: [
Head over to GitHub for more documentation, take a peek into the code, or to report some bugs. Head over to GitHub for more documentation, take a peek into the code, or to report some bugs.
<p class="content-download"> <p class="content-download">
<a class="icon-github btn-primary" href="https://github.com/kremalicious/gatsby-plugin-matomo">GitHub</a> <a class="icon-github btn btn-primary" href="https://github.com/kremalicious/gatsby-plugin-matomo">GitHub</a>
</p> </p>

View File

@ -110,5 +110,5 @@ plugins: [
Head over to GitHub for more documentation, take a peek into the code, or to report some bugs. Head over to GitHub for more documentation, take a peek into the code, or to report some bugs.
<p class="content-download"> <p class="content-download">
<a class="icon-github btn-primary" href="https://github.com/kremalicious/gatsby-redirect-from">GitHub</a> <a class="icon-github btn btn-primary" href="https://github.com/kremalicious/gatsby-redirect-from">GitHub</a>
</p> </p>

View File

@ -1,4 +1,4 @@
import './src/styles/global.scss' import './src/global/global.css'
import wrapPageElementWithLayout from './src/helpers/wrapPageElement' import wrapPageElementWithLayout from './src/helpers/wrapPageElement'
export const wrapPageElement = wrapPageElementWithLayout export const wrapPageElement = wrapPageElementWithLayout

View File

@ -23,6 +23,7 @@ module.exports = {
}, },
plugins: [ plugins: [
...sources, ...sources,
'gatsby-plugin-image',
{ {
resolve: 'gatsby-plugin-sharp', resolve: 'gatsby-plugin-sharp',
options: { options: {
@ -77,7 +78,7 @@ module.exports = {
}, },
injectStyles: false, injectStyles: false,
extensions: [ extensions: [
`${__dirname}/vendor/nord-visual-studio-code-0.15.0.vsix`, 'nord-visual-studio-code',
`${__dirname}/vendor/polar-0.0.6.vsix` `${__dirname}/vendor/polar-0.0.6.vsix`
], ],
languageAliases: {} languageAliases: {}
@ -86,14 +87,6 @@ module.exports = {
] ]
} }
}, },
{
resolve: 'gatsby-plugin-sass',
options: {
sassOptions: {
includePaths: [`${__dirname}/node_modules`, `${__dirname}/src/styles`]
}
}
},
{ {
resolve: 'gatsby-plugin-svgr', resolve: 'gatsby-plugin-svgr',
options: { options: {
@ -227,13 +220,6 @@ module.exports = {
exclude: ['/archive', '/archive/**/*', '/thanks', '/tags'] exclude: ['/archive', '/archive/**/*', '/thanks', '/tags']
} }
}, },
{
resolve: 'gatsby-plugin-use-dark-mode',
options: {
...siteConfig.darkModeConfig,
minify: true
}
},
'gatsby-plugin-react-helmet', 'gatsby-plugin-react-helmet',
'gatsby-plugin-catch-links', 'gatsby-plugin-catch-links',
'gatsby-redirect-from', 'gatsby-redirect-from',

View File

@ -64,7 +64,7 @@ exports.createPages = async ({ graphql, actions, reporter }) => {
} }
archive: allMarkdownRemark( archive: allMarkdownRemark(
filter: { fields: { type: { ne: "photo" } } } filter: { fields: { type: { nin: "photo" } } }
) { ) {
edges { edges {
node { node {
@ -95,15 +95,15 @@ exports.createPages = async ({ graphql, actions, reporter }) => {
// Generate post pages // Generate post pages
generatePostPages(createPage, all) generatePostPages(createPage, all)
// Generate archive pages
generateArchivePages(createPage, archiveLength)
// Generate photos archive pages // Generate photos archive pages
generatePhotosPages(createPage, photosLength) generatePhotosPages(createPage, photosLength)
// Generate tag pages // Generate tag pages
generateTagPages(createPage, tags) generateTagPages(createPage, tags)
// Generate archive pages
generateArchivePages(createPage, archiveLength)
// Create manual redirects // Create manual redirects
generateRedirectPages(createRedirect) generateRedirectPages(createRedirect)
} }

View File

@ -47,7 +47,7 @@ exports.generatePostPages = (createPage, posts) => {
}) })
} }
function generateIndexPages(createPage, length, slug, template) { function generateIndexPages(createPage, length, slug, template, tag) {
const numPages = Math.ceil(length / itemsPerPage) const numPages = Math.ceil(length / itemsPerPage)
Array.from({ length: numPages }).forEach((_, i) => { Array.from({ length: numPages }).forEach((_, i) => {
@ -67,7 +67,8 @@ function generateIndexPages(createPage, length, slug, template) {
numPages: numPages, numPages: numPages,
currentPageNumber: i + 1, currentPageNumber: i + 1,
prevPagePath, prevPagePath,
nextPagePath nextPagePath,
...(tag && { tag })
} }
}) })
}) })
@ -90,7 +91,8 @@ exports.generateTagPages = (createPage, tags) => {
createPage, createPage,
totalCount, totalCount,
`/archive/${tag}/`, `/archive/${tag}/`,
archiveTemplate archiveTemplate,
tag
) )
}) })
} }

View File

@ -44,10 +44,10 @@ module.exports = [
url: 'https://api.github.com/graphql', url: 'https://api.github.com/graphql',
headers: { headers: {
Authorization: `bearer ${process.env.GATSBY_GITHUB_TOKEN}` Authorization: `bearer ${process.env.GATSBY_GITHUB_TOKEN}`
}, }
// Additional options to pass to node-fetch // Additional options to pass to node-fetch
fetchOptions: {}, // fetchOptions: {},
refetchInterval: 300 // 5 min. // refetchInterval: 300 // 5 min.
} }
} }
] ]

20125
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,16 +8,15 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "gatsby develop --host 0.0.0.0", "start": "gatsby develop --host 0.0.0.0",
"build": "gatsby build && npm run copy", "build": "gatsby build",
"ssr": "npm run build && serve -s public/", "ssr": "npm run build && serve -s public/",
"test": "npm run lint && jest -c jest/jest.config.js --coverage --silent", "test": "npm run lint && jest -c jest/jest.config.js --coverage --silent",
"test:watch": "npm run lint && jest -c jest/jest.config.js --coverage --watch", "test:watch": "npm run lint && jest -c jest/jest.config.js --coverage --watch",
"copy": "cp -R content/media/ public",
"lint": "run-p --continue-on-error lint:js lint:css lint:md", "lint": "run-p --continue-on-error lint:js lint:css lint:md",
"lint:js": "eslint --ignore-path .gitignore --ext .js,.jsx,.ts,.tsx .", "lint:js": "eslint --ignore-path .gitignore --ext .js,.jsx,.ts,.tsx .",
"lint:css": "stylelint 'src/**/*.{css,scss}'", "lint:css": "stylelint 'src/**/*.css'",
"lint:md": "markdownlint './**/*.{md,markdown}' --ignore './{node_modules,public,.cache,.git,coverage}/**/*'", "lint:md": "markdownlint './**/*.{md,markdown}' --ignore './{node_modules,public,.cache,.git,coverage}/**/*'",
"format": "prettier --ignore-path .gitignore --write '**/*.{js,jsx,ts,tsx,md,json,css,scss}'", "format": "prettier --ignore-path .gitignore --write '**/*.{js,jsx,ts,tsx,md,json,css}'",
"tsc": "tsc --noEmit", "tsc": "tsc --noEmit",
"deploy": "./scripts/deploy-s3.sh", "deploy": "./scripts/deploy-s3.sh",
"new": "ts-node ./scripts/new.ts" "new": "ts-node ./scripts/new.ts"
@ -29,106 +28,104 @@
"not op_mini all" "not op_mini all"
], ],
"dependencies": { "dependencies": {
"@ethersproject/providers": "^5.0.23", "@ethersproject/providers": "^5.0.24",
"@ethersproject/units": "^5.0.10", "@ethersproject/units": "^5.0.11",
"@loadable/component": "^5.14.1", "@loadable/component": "^5.14.1",
"@web3-react/core": "^6.1.9", "@web3-react/core": "^6.1.9",
"@web3-react/injected-connector": "^6.0.7", "@web3-react/injected-connector": "^6.0.7",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"date-fns": "^2.17.0", "date-fns": "^2.19.0",
"dms2dec": "^1.1.0", "dms2dec": "^1.1.0",
"ethereum-blockies": "github:MyEtherWallet/blockies", "ethereum-blockies": "github:MyEtherWallet/blockies",
"fast-exif": "^1.0.1", "fast-exif": "^1.0.1",
"feather-icons": "^4.28.0", "feather-icons": "^4.28.0",
"fraction.js": "^4.0.13", "fraction.js": "^4.0.13",
"gatsby": "^2.32.8", "gatsby": "^3.1.1",
"gatsby-image": "^2.11.0", "gatsby-plugin-catch-links": "^3.1.0",
"gatsby-plugin-catch-links": "^2.10.0", "gatsby-plugin-feed": "^3.1.0",
"gatsby-plugin-feed": "^2.13.1", "gatsby-plugin-image": "^1.1.1",
"gatsby-plugin-lunr": "^1.5.2", "gatsby-plugin-lunr": "^1.5.2",
"gatsby-plugin-manifest": "^2.12.0", "gatsby-plugin-manifest": "^3.1.0",
"gatsby-plugin-matomo": "^0.9.0", "gatsby-plugin-matomo": "^0.9.0",
"gatsby-plugin-meta-redirect": "^1.1.1", "gatsby-plugin-meta-redirect": "^1.1.1",
"gatsby-plugin-offline": "^3.10.2", "gatsby-plugin-offline": "^4.1.0",
"gatsby-plugin-react-helmet": "^3.10.0", "gatsby-plugin-react-helmet": "^4.1.0",
"gatsby-plugin-sass": "^3.2.0", "gatsby-plugin-sharp": "^3.1.1",
"gatsby-plugin-sharp": "^2.14.3", "gatsby-plugin-sitemap": "^3.1.0",
"gatsby-plugin-sitemap": "^2.12.0", "gatsby-plugin-svgr": "^3.0.0-beta.0",
"gatsby-plugin-svgr": "^2.1.0", "gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.21",
"gatsby-plugin-use-dark-mode": "^1.2.0", "gatsby-plugin-webpack-size": "^2.0.1",
"gatsby-plugin-webpack-size": "^1.0.0",
"gatsby-redirect-from": "^0.3.0", "gatsby-redirect-from": "^0.3.0",
"gatsby-remark-autolink-headers": "^2.11.0", "gatsby-remark-autolink-headers": "^3.1.0",
"gatsby-remark-breaks": "^1.0.0", "gatsby-remark-breaks": "^1.0.0",
"gatsby-remark-copy-linked-files": "^2.10.0", "gatsby-remark-copy-linked-files": "^3.1.0",
"gatsby-remark-images": "^3.11.1", "gatsby-remark-images": "^4.1.0",
"gatsby-remark-images-medium-zoom": "^1.7.0", "gatsby-remark-images-medium-zoom": "^1.7.0",
"gatsby-remark-smartypants": "^2.10.0", "gatsby-remark-smartypants": "^3.1.0",
"gatsby-remark-vscode": "^3.2.0", "gatsby-remark-vscode": "^3.2.1",
"gatsby-source-filesystem": "^2.11.1", "gatsby-source-filesystem": "^3.1.0",
"gatsby-source-graphql": "^2.14.0", "gatsby-source-graphql": "^3.1.0",
"gatsby-transformer-remark": "^2.16.1", "gatsby-transformer-remark": "^3.1.0",
"gatsby-transformer-sharp": "^2.12.0", "gatsby-transformer-sharp": "^3.1.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"pigeon-maps": "^0.17.1", "nord-visual-studio-code": "github:arcticicestudio/nord-visual-studio-code",
"pigeon-maps": "^0.19.5",
"pigeon-marker": "^0.3.4", "pigeon-marker": "^0.3.4",
"react": "^16.14.0", "react": "^17.0.1",
"react-clipboard.js": "^2.0.16", "react-clipboard.js": "^2.0.16",
"react-dom": "^16.14.0", "react-dom": "^17.0.1",
"react-feather": "^2.0.9", "react-feather": "^2.0.9",
"react-helmet": "^6.1.0", "react-helmet": "^6.1.0",
"react-qr-svg": "^2.3.0", "react-qr-svg": "^2.3.0",
"react-transition-group": "^4.4.1", "react-transition-group": "^4.4.1",
"remark": "^13.0.0", "remark": "^13.0.0",
"remark-react": "^8.0.0", "remark-react": "^8.0.0",
"slugify": "^1.4.7", "slugify": "^1.5.0"
"use-dark-mode": "^2.3.1"
}, },
"devDependencies": { "devDependencies": {
"@svgr/webpack": "^5.5.0", "@svgr/webpack": "^5.5.0",
"@testing-library/jest-dom": "^5.11.9", "@testing-library/jest-dom": "^5.11.9",
"@testing-library/react": "^11.2.5", "@testing-library/react": "^11.2.5",
"@types/classnames": "^2.2.11", "@types/classnames": "^2.2.11",
"@types/fs-extra": "^9.0.7", "@types/fs-extra": "^9.0.8",
"@types/jest": "^26.0.20", "@types/jest": "^26.0.21",
"@types/loadable__component": "^5.13.3", "@types/loadable__component": "^5.13.3",
"@types/lunr": "^2.3.3", "@types/lunr": "^2.3.3",
"@types/node": "^14.14.28", "@types/node": "^14.14.35",
"@types/node-fetch": "^2.5.8", "@types/node-fetch": "^2.5.8",
"@types/react": "^17.0.2", "@types/react": "^17.0.3",
"@types/react-dom": "^17.0.1", "@types/react-dom": "^17.0.2",
"@types/react-helmet": "^6.1.0", "@types/react-helmet": "^6.1.0",
"@types/react-transition-group": "^4.4.0", "@types/react-transition-group": "^4.4.0",
"@types/shortid": "^0.0.29", "@types/shortid": "^0.0.29",
"@typescript-eslint/eslint-plugin": "^4.15.2", "@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.15.2", "@typescript-eslint/parser": "^4.18.0",
"@welldone-software/why-did-you-render": "^6.0.5", "@welldone-software/why-did-you-render": "^6.1.1",
"eslint": "^7.21.0", "eslint": "^7.22.0",
"eslint-config-prettier": "^8.1.0", "eslint-config-prettier": "^8.1.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-graphql": "^4.0.0", "eslint-plugin-graphql": "^4.0.0",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-prettier": "^3.3.1", "eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0", "eslint-plugin-react": "^7.22.0",
"eslint-plugin-testing-library": "^3.10.1", "eslint-plugin-testing-library": "^3.10.2",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.20",
"identity-obj-proxy": "^3.0.0", "identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3", "jest": "^26.6.3",
"markdownlint-cli": "^0.26.0", "markdownlint-cli": "^0.27.1",
"node-iptc": "^1.0.5", "node-iptc": "^1.0.5",
"node-sass": "^5.0.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"ora": "^5.3.0", "ora": "^5.4.0",
"postcss": "^8.2.8",
"prettier": "^2.2.1", "prettier": "^2.2.1",
"shortid": "^2.2.16", "shortid": "^2.2.16",
"stylelint": "^13.11.0", "stylelint": "^13.12.0",
"stylelint-config-css-modules": "^2.2.0", "stylelint-config-css-modules": "^2.2.0",
"stylelint-config-prettier": "^8.0.2", "stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0", "stylelint-config-standard": "^21.0.0",
"stylelint-prettier": "^1.2.0", "stylelint-prettier": "^1.2.0",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",
"typescript": "^4.2.2" "typescript": "^4.2.3",
"typescript-plugin-css-modules": "^3.2.0"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

15
src/@types/Image.d.ts vendored
View File

@ -1,17 +1,14 @@
import { FixedObject, FluidObject } from 'gatsby-image' import { GatsbyImageProps, IGatsbyImageData } from 'gatsby-plugin-image'
export interface ImageProps { export interface ImageProps extends GatsbyImageProps {
title?: string title?: string
fluid?: FluidObject
fixed?: FixedObject
alt?: string
original?: { src: string } original?: { src: string }
className?: string
} }
export interface ImageNode { export interface ImageNode extends IGatsbyImageData {
childImageSharp: ImageProps fields?: {
fields: { exif?: Exif
exif: Exif
} }
} }

4
src/@types/css.d.ts vendored Normal file
View File

@ -0,0 +1,4 @@
declare module '*.module.css' {
const classes: { [key: string]: string }
export default classes
}

View File

@ -1,13 +1,3 @@
declare module '*.module.css' {
const classes: { [key: string]: string }
export default classes
}
declare module '*.module.scss' {
const classes: { [key: string]: string }
export default classes
}
declare module '*.svg' { declare module '*.svg' {
import * as React from 'react' import * as React from 'react'
export const ReactComponent: React.FunctionComponent< export const ReactComponent: React.FunctionComponent<

View File

@ -0,0 +1,75 @@
.content {
padding: 0 calc(var(--spacer) / 1.5);
width: 100%;
max-width: var(--maxWidthContainer);
margin-left: auto;
margin-right: auto;
}
/* topbar and footer as fixed
site background
///////////////////////////////////// */
.document {
width: 100%;
padding-top: var(--spacer);
background-color: var(--body-background-color);
padding-bottom: calc(var(--spacer) * 2);
transform: translate3d(0, 0, 0);
transition: 0.4s var(--easing);
transition-property: transform, background, border, box-shadow;
border-top: 1px solid rgba(255, 255, 255, 0.85);
box-shadow: 0 1px 10px rgba(1, 85, 101, 0.1),
0 -1px 4px rgba(1, 85, 101, 0.05);
}
:global(.has-menu-open) .document {
transform: translate3d(0, calc(var(--spacer) * 2), 0);
}
:global(.dark) .document {
border-top-color: rgba(255, 255, 255, 0.05);
box-shadow: 0 1px 8px rgba(0, 7, 8, 0.3), 0 -1px 4px rgba(0, 21, 25, 0.8);
}
@media (min-width: 60rem) {
.document {
padding-top: calc(var(--spacer) * 2);
}
}
@media (min-width: 40rem) and (min-height: 500px) {
.document {
margin-top: calc(var(--spacer) * 2.5);
/* height of footer */
margin-bottom: calc(var(--spacer) * 12);
position: relative;
z-index: 2;
min-height: 500px;
}
}
.container {
width: 100%;
max-width: var(--maxWidthContent);
margin-left: auto;
margin-right: auto;
}
.wide {
composes: container;
max-width: none;
}
.breakout {
margin-left: calc(-50vw + 50%);
margin-right: calc(-50vw + 50%);
}
@media (min-width: 1000px) {
.breakout {
margin-left: -8rem;
margin-right: -8rem;
}
}

View File

@ -1,61 +0,0 @@
@import 'variables';
@import 'mixins';
#___gatsby {
// display: flex;
// min-height: 100vh;
// flex-direction: column;
position: relative;
}
.content {
padding: 0 $spacer / $line-height;
width: 100%;
@media (min-width: $screen-sm) {
padding: 0 ($spacer * 2);
}
}
// topbar and footer as fixed
// site background
/////////////////////////////////////
.document {
width: 100%;
padding-top: $spacer;
background-color: $body-background-color;
border-top: 1px solid rgba(255, 255, 255, 0.7);
border-bottom: 1px solid rgba(255, 255, 255, 0.7);
padding-bottom: $spacer * 2;
box-shadow: 0 1px 4px rgba($brand-main, 0.1),
0 -1px 4px rgba($brand-main, 0.2);
transform: translate3d(0, 0, 0);
transition: 0.4s $easing;
transition-property: transform, background;
:global(.has-menu-open) & {
transform: translate3d(0, ($spacer * 3.5), 0);
}
:global(.dark) & {
background-color: $body-background-color--dark;
color: $text-color--dark;
border-top-color: darken($brand-grey, 15%);
border-bottom-color: darken($body-background-color--dark, 3%);
box-shadow: 0 1px 8px rgba(darken($brand-main, 15%), 0.1),
0 -1px 4px darken($brand-main, 15%);
}
@media (min-width: $screen-md) {
padding-top: $spacer * 2;
}
@media (min-width: $screen-sm) and (min-height: 500px) {
margin-top: $spacer * 2.65;
margin-bottom: $spacer * 18; // height of footer
position: relative;
z-index: 2;
min-height: 500px;
}
}

View File

@ -1,9 +1,8 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Container from './atoms/Container'
import Typekit from './atoms/Typekit' import Typekit from './atoms/Typekit'
import Header from './organisms/Header' import Header from './organisms/Header'
import Footer from './organisms/Footer' import Footer from './organisms/Footer'
import styles from './Layout.module.scss' import { document, content } from './Layout.module.css'
// if (process.env.NODE_ENV !== 'production') { // if (process.env.NODE_ENV !== 'production') {
// // eslint-disable-next-line // // eslint-disable-next-line
@ -17,10 +16,8 @@ export default function Layout({ children }: { children: any }): ReactElement {
<Typekit /> <Typekit />
<Header /> <Header />
<main className={styles.document} id="document"> <main className={document} id="document">
<div className={styles.content}> <div className={content}>{children}</div>
<Container>{children}</Container>
</div>
</main> </main>
<Footer /> <Footer />

View File

@ -0,0 +1,88 @@
.title {
margin-top: calc(var(--spacer) * 3);
margin-bottom: 0;
}
.content {
padding-top: var(--spacer);
padding-left: calc(var(--spacer) / 2);
margin-left: calc(var(--spacer) / 2);
border-left: var(--stroke-width) solid var(--border-color);
}
.content h2,
.content h3,
.content h4 {
position: relative;
margin-bottom: calc(var(--spacer) / 4);
}
.content h2::before,
.content h3::before,
.content h4::before {
content: '';
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
display: inline-block;
background: var(--color-headings);
position: absolute;
left: -1.275rem;
top: calc(var(--font-size-large) / 3);
}
.content h2 + blockquote,
.content h3 + blockquote,
.content h4 + blockquote {
padding-left: 0;
font-size: var(--font-size-small);
}
.content h2 + blockquote::before,
.content h3 + blockquote::before,
.content h4 + blockquote::before {
display: none;
}
.content h2,
.content h3 {
font-size: var(--font-size-large);
background: none;
padding: 0;
margin-left: 0;
margin-top: calc(var(--spacer) / 8);
margin-bottom: calc(var(--spacer) / var(--line-height));
}
.content ul {
font-size: var(--font-size-small);
margin-left: calc(var(--spacer) / 8);
}
.content ul li {
margin-bottom: calc(var(--spacer) / 8);
}
.source {
font-size: var(--font-size-mini);
font-family: var(--font-family-base);
font-weight: var(--font-weight-base);
padding-bottom: calc(var(--spacer) / 2);
}
.source,
.source a {
color: var(--text-color-light);
}
.source a {
margin-left: calc(var(--spacer) / 8);
}
.source code {
font-size: calc(var(--font-size-mini) * 0.9);
}
.source a:hover {
color: var(--link-color);
}

View File

@ -1,92 +0,0 @@
@import 'variables';
.title {
margin-top: $spacer * 3;
margin-bottom: 0;
}
.content {
padding-top: $spacer;
padding-left: $spacer / 2;
margin-left: $spacer / 2;
border-left: 1px solid $brand-grey-dimmed;
:global(.dark) & {
border-left-color: rgba($color-headings--dark, 0.2);
}
h2,
h3,
h4 {
position: relative;
margin-bottom: $spacer / 4;
&::before {
content: '';
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
display: inline-block;
background: $color-headings;
position: absolute;
left: -($spacer / 1.5);
top: $font-size-large / 3;
:global(.dark) & {
background: $color-headings--dark;
}
}
+ blockquote {
padding-left: 0;
font-size: $font-size-small;
&::before {
display: none;
}
}
}
h2,
h3 {
font-size: $font-size-large;
background: none;
padding: 0;
margin-left: 0;
margin-top: $spacer / 8;
margin-bottom: $spacer / $line-height;
}
ul {
font-size: $font-size-small;
margin-left: $spacer / 8;
li {
margin-bottom: $spacer / 8;
}
}
}
.source {
font-size: $font-size-mini;
font-family: $font-family-base;
font-weight: $font-weight-base;
padding-bottom: $spacer / 2;
&,
a {
color: $brand-grey-light;
}
a {
margin-left: $spacer / 8;
code {
font-size: ($font-size-mini * 0.9);
}
&:hover {
color: $link-color;
}
}
}

View File

@ -2,7 +2,7 @@ import React, { ReactElement } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import remark from 'remark' import remark from 'remark'
import remarkReact from 'remark-react' import remarkReact from 'remark-react'
import styles from './Changelog.module.scss' import { title, content, source } from './Changelog.module.css'
import { GitHub, GitHubRepo } from '../../@types/GitHub' import { GitHub, GitHubRepo } from '../../@types/GitHub'
export function PureChangelog({ export function PureChangelog({
@ -30,22 +30,20 @@ export function PureChangelog({
const filePathDisplay = `${owner.login}/${repo}:CHANGELOG.md` const filePathDisplay = `${owner.login}/${repo}:CHANGELOG.md`
return ( return (
<div className={styles.changelog}> <>
<h2 className={styles.title} id="changelog"> <h2 className={title} id="changelog">
Changelog Changelog
</h2> </h2>
<div className={styles.content}> <div className={content}>
<p className={styles.source}> {changelogHtml}
<em> <p className={source}>
sourced from{' '} sourced from{' '}
<a href={filePathUrl}> <a href={filePathUrl}>
<code>{filePathDisplay}</code> <code>{filePathDisplay}</code>
</a> </a>
</em>
</p> </p>
{changelogHtml}
</div>
</div> </div>
</>
) )
} }

View File

@ -1,5 +0,0 @@
.container {
max-width: 37rem;
margin-left: auto;
margin-right: auto;
}

View File

@ -1,10 +0,0 @@
import React, { ReactElement } from 'react'
import styles from './Container.module.scss'
export default function Container({
children
}: {
children: any
}): ReactElement {
return <section className={styles.container}>{children}</section>
}

View File

@ -0,0 +1,30 @@
.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(var(--brand-grey), 0.3);
padding: calc(var(--spacer) / 3);
}
.button svg {
stroke: var(--text-color-light);
transition: 0.15s ease-out;
}
.copied {
background: green;
}
.copied svg {
stroke: var(--text-color-dimmed);
}
.button:hover svg {
stroke: var(--text-color-dimmed);
}

View File

@ -1,35 +0,0 @@
@import 'variables';
.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, 0.3);
padding: $spacer / 3;
svg {
stroke: $brand-grey-light;
transition: 0.15s ease-out;
}
&:hover {
svg {
stroke: $brand-grey-dimmed;
}
}
}
.copied {
background: green;
// stylelint-disable-next-line no-descending-specificity
svg {
stroke: $brand-grey-dimmed;
}
}

View File

@ -1,12 +1,12 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import loadable from '@loadable/component' import loadable from '@loadable/component'
import styles from './Copy.module.scss' import { copied, button } from './Copy.module.css'
import Icon from './Icon' import Icon from './Icon'
const Clipboard = loadable(() => import('react-clipboard.js')) const Clipboard = loadable(() => import('react-clipboard.js'))
const onCopySuccess = (e: any) => { const onCopySuccess = (e: any) => {
e.trigger.classList.add(styles.copied) e.trigger.classList.add(copied)
} }
export default function Copy({ text }: { text: string }): ReactElement { export default function Copy({ text }: { text: string }): ReactElement {
@ -15,7 +15,7 @@ export default function Copy({ text }: { text: string }): ReactElement {
data-clipboard-text={text} data-clipboard-text={text}
button-title="Copy to clipboard" button-title="Copy to clipboard"
onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)} onSuccess={(e: ClipboardJS.Event) => onCopySuccess(e)}
className={styles.button} className={button}
> >
<Icon name="Copy" /> <Icon name="Copy" />
</Clipboard> </Clipboard>

View File

@ -0,0 +1,18 @@
.divider {
position: relative;
border-bottom: 1px dashed var(--border-color);
}
.divider::before {
content: '';
position: absolute;
left: 0;
height: 1px;
bottom: -2px;
width: 100%;
border-bottom: 1px dashed #fff;
}
:global(.dark) .divider::before {
border-bottom-color: var(--brand-grey);
}

View File

@ -0,0 +1,69 @@
.exif {
margin-top: -3rem;
margin-bottom: calc(var(--spacer) * 2);
}
.data {
font-size: var(--font-size-mini);
color: var(--text-color-light);
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
}
.data span {
display: block;
flex: 1 1 auto;
white-space: nowrap;
padding: var(--spacer) calc(var(--spacer) / 1.5);
border-bottom: 1px dashed var(--border-color);
}
.data span svg {
display: block;
margin-bottom: calc(var(--spacer) / 8);
opacity: 0.65;
}
.data span:first-child {
flex-basis: 100%;
}
@media (min-width: 40rem) {
.data {
margin-bottom: 0;
font-size: var(--font-size-small);
}
.data span {
border-left: 1px dashed var(--border-color);
border-bottom: 0;
}
.data span:first-child {
flex-basis: auto;
border-left: 0;
}
}
.map {
composes: breakout from '../Layout.module.css';
composes: frame from './Image.module.css';
height: 180px;
margin-top: calc(var(--spacer) * 2);
}
@media (min-width: 40rem) {
.map {
margin-top: 0;
}
}
.map img {
border-radius: 0 !important;
}
.map > div:first-child {
background: none !important;
}

View File

@ -1,84 +0,0 @@
@import 'variables';
@import 'mixins';
.exif {
margin-top: -($spacer * $line-height);
margin-bottom: $spacer * 2;
}
.data {
@include breakoutviewport;
font-size: $font-size-mini;
color: $brand-grey-light;
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
span {
display: block;
flex: 1 1 20%;
white-space: nowrap;
padding: $spacer;
border-bottom: 1px dashed $brand-grey-dimmed;
svg {
display: block;
margin-bottom: $spacer / 8;
opacity: 0.65;
}
&:first-child {
flex-basis: 100%;
}
:global(.dark) & {
border-bottom-color: rgba($brand-grey, 0.6);
}
}
@media (min-width: $screen-sm) {
margin-bottom: 0;
font-size: $font-size-small;
span {
border-left: 1px dashed $brand-grey-dimmed;
border-bottom: 0;
&,
&:first-child {
flex: 1 1 auto;
}
&:first-child {
border-left: 0;
}
:global(.dark) & {
border-left-color: rgba($brand-grey, 0.6);
}
}
}
}
.map {
@include breakoutviewport;
@include media-frame;
overflow: hidden;
height: 220px;
margin-top: $spacer * 2;
@media (min-width: $screen-sm) {
margin-top: 0;
}
img {
border-radius: 0 !important;
}
> div:first-child {
background: none !important;
}
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import ExifMap from './ExifMap' import ExifMap from './ExifMap'
import styles from './Exif.module.scss' import { exif as styleExif, data, map } from './Exif.module.css'
import { Exif as ExifMeta } from '../../@types/Image' import { Exif as ExifMeta } from '../../@types/Image'
import Icon from './Icon' import Icon from './Icon'
@ -31,8 +31,8 @@ export default function Exif({ exif }: { exif: ExifMeta }): ReactElement {
} = exif.formatted } = exif.formatted
return ( return (
<aside className={styles.exif}> <aside className={styleExif}>
<div className={styles.data}> <div className={data}>
{model && <ExifData title="Camera model" value={model} icon="Camera" />} {model && <ExifData title="Camera model" value={model} icon="Camera" />}
{focalLength && ( {focalLength && (
<ExifData title="Focal length" value={focalLength} icon="Crosshair" /> <ExifData title="Focal length" value={focalLength} icon="Crosshair" />
@ -49,7 +49,7 @@ export default function Exif({ exif }: { exif: ExifMeta }): ReactElement {
{iso && <ExifData title="ISO" value={iso} icon="Maximize" />} {iso && <ExifData title="ISO" value={iso} icon="Maximize" />}
</div> </div>
{gps && gps.latitude && ( {gps && gps.latitude && (
<div className={styles.map}> <div className={map}>
<ExifMap gps={gps} /> <ExifMap gps={gps} />
</div> </div>
)} )}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useState } from 'react' import React, { ReactElement, useState } from 'react'
import Map from 'pigeon-maps' import { Map } from 'pigeon-maps'
import Marker from 'pigeon-marker' import Marker from 'pigeon-marker'
import useDarkMode from 'use-dark-mode' import useDarkMode from '../../hooks/useDarkMode'
const mapbox = (mapboxId: string) => ( const mapbox = (mapboxId: string) => (
x: string, x: string,
@ -23,10 +23,7 @@ export default function ExifMap({
}: { }: {
gps: { latitude: string; longitude: string } gps: { latitude: string; longitude: string }
}): ReactElement { }): ReactElement {
const { value } = useDarkMode(false, { const { value } = useDarkMode()
classNameDark: 'dark',
classNameLight: 'light'
})
const isDarkMode = value const isDarkMode = value
const [zoom, setZoom] = useState(12) const [zoom, setZoom] = useState(12)
@ -40,7 +37,7 @@ export default function ExifMap({
<Map <Map
center={[latitude, longitude]} center={[latitude, longitude]}
zoom={zoom} zoom={zoom}
height={220} height={180}
dprs={[1, 2]} dprs={[1, 2]}
attribution={false} attribution={false}
provider={isDarkMode ? providers['dark'] : providers['light']} provider={isDarkMode ? providers['dark'] : providers['light']}

View File

@ -0,0 +1,70 @@
.hamburger {
width: 24px;
height: 24px;
display: inline-block;
position: relative;
transform: rotate(0deg);
cursor: pointer;
margin-top: calc(var(--spacer) / 2);
}
.line {
display: block;
position: absolute;
height: 1px;
width: 100%;
border-bottom: var(--stroke-width) solid var(--text-color-light);
opacity: 1;
left: 0;
transform: rotate(0deg);
transition: 0.2s var(--easing);
}
.line:nth-child(1) {
top: 0;
transform-origin: left center;
}
.line:nth-child(2) {
top: 7px;
transform-origin: left center;
}
.line:nth-child(3) {
top: 14px;
transform-origin: left center;
}
/* open state */
:global(.has-menu-open) .line:nth-child(1) {
transform: rotate(45deg);
top: -1px;
}
:global(.has-menu-open) .line:nth-child(2) {
width: 0%;
opacity: 0;
}
:global(.has-menu-open) .line:nth-child(3) {
transform: rotate(-45deg);
top: 16px;
}
.button {
padding: calc(var(--spacer) / 2);
vertical-align: middle;
display: inline-block;
margin: 0;
margin-right: -1rem;
}
.button:hover,
.button:focus {
outline: 0;
}
.button:hover .line,
.button:focus .line {
border-color: var(--link-color);
}

View File

@ -1,75 +0,0 @@
@import 'variables';
@import 'mixins';
.hamburger {
width: 24px;
height: 24px;
display: inline-block;
position: relative;
transform: rotate(0deg);
cursor: pointer;
margin-top: $spacer / 2;
}
.hamburgerLine {
@include transition;
display: block;
position: absolute;
height: 1px;
width: 100%;
border-bottom: $stroke-width solid $brand-grey-light;
opacity: 1;
left: 0;
transform: rotate(0deg);
&:nth-child(1) {
top: 0;
transform-origin: left center;
}
&:nth-child(2) {
top: 7px;
transform-origin: left center;
}
&:nth-child(3) {
top: 14px;
transform-origin: left center;
}
// open state
:global(.has-menu-open) & {
&:nth-child(1) {
transform: rotate(45deg);
top: -1px;
}
&:nth-child(2) {
width: 0%;
opacity: 0;
}
&:nth-child(3) {
transform: rotate(-45deg);
top: 16px;
}
}
}
.hamburgerButton {
padding: $spacer / 2;
vertical-align: middle;
display: inline-block;
margin: 0;
margin-right: -($spacer / 2);
&:hover,
&:focus {
outline: 0;
.hamburgerLine {
border-color: $brand-cyan;
}
}
}

View File

@ -1,5 +1,5 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styles from './Hamburger.module.scss' import { button, hamburger, line } from './Hamburger.module.css'
export default function Hamburger({ export default function Hamburger({
onClick onClick
@ -7,16 +7,11 @@ export default function Hamburger({
onClick(): void onClick(): void
}): ReactElement { }): ReactElement {
return ( return (
<button <button type="button" title="Menu" className={button} onClick={onClick}>
type="button" <span className={hamburger}>
title="Menu" <span className={line} />
className={styles.hamburgerButton} <span className={line} />
onClick={onClick} <span className={line} />
>
<span className={styles.hamburger}>
<span className={styles.hamburgerLine} />
<span className={styles.hamburgerLine} />
<span className={styles.hamburgerLine} />
</span> </span>
</button> </button>
) )

View File

@ -1,10 +1,8 @@
@import 'variables';
.icon { .icon {
width: 1em; width: 1em;
height: 1em; height: 1em;
stroke: currentColor; stroke: currentColor;
stroke-width: $stroke-width; stroke-width: var(--stroke-width);
stroke-linecap: round; stroke-linecap: round;
stroke-linejoin: round; stroke-linejoin: round;
fill: none; fill: none;

View File

@ -27,7 +27,7 @@ import {
import { ReactComponent as Jsonfeed } from '../../images/jsonfeed.svg' import { ReactComponent as Jsonfeed } from '../../images/jsonfeed.svg'
import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg' import { ReactComponent as Bitcoin } from '../../images/bitcoin.svg'
import { ReactComponent as Stopwatch } from '../../images/stopwatch.svg' import { ReactComponent as Stopwatch } from '../../images/stopwatch.svg'
import styles from './Icon.module.scss' import { icon } from './Icon.module.css'
const components: any = { const components: any = {
Download: ArrowDownCircle, Download: ArrowDownCircle,
@ -55,12 +55,12 @@ const components: any = {
Crosshair Crosshair
} }
const Icon = ({ name }: { name: string }): ReactElement => { const Icon = ({ name, ...props }: { name: string }): ReactElement => {
const IconMapped = components[name] const IconMapped = components[name]
// const IconFeather = (Feather as any)[name] // const IconFeather = (Feather as any)[name]
if (!IconMapped) return null if (!IconMapped) return null
return <IconMapped className={styles.icon} /> return <IconMapped className={icon} {...props} />
} }
export default Icon export default Icon

View File

@ -0,0 +1,53 @@
.frame {
border: var(--stroke-width) solid rgba(255, 255, 255, 0.2);
border-radius: var(--border-radius);
overflow: hidden;
transition: 0.2s ease-out;
box-shadow: var(--box-shadow);
}
a:hover .frame,
a:focus .frame {
border-color: var(--link-color);
}
.image {
composes: frame;
max-width: none;
margin-top: calc(var(--spacer) * var(--line-height));
margin-bottom: calc(var(--spacer) * var(--line-height));
position: relative;
display: block;
}
/* single photo post teasers */
.image:only-child {
margin-top: 0;
margin-bottom: 0;
}
.imageTitle {
font-size: var(--font-size-h3);
font-family: var(--font-family-headings);
line-height: var(--line-height-headings);
font-weight: var(--font-weight-headings);
font-style: normal;
text-align: left;
margin: 0;
position: absolute;
top: 10%;
padding: calc(var(--spacer) / 3) var(--spacer);
background: var(--link-color);
color: #fff !important;
text-shadow: 0 1px 0 #000;
left: 0;
opacity: 0;
transform: translate3d(0, -20px, 0);
transition: 0.2s var(--easing);
}
a:hover .imageTitle,
a:focus .imageTitle {
opacity: 1;
transform: translate3d(0, 0, 0);
}

View File

@ -1,54 +0,0 @@
@import 'variables';
@import 'mixins';
.imageTitle {
@include transition();
font-size: $font-size-h3;
font-family: $font-family-headings;
line-height: $line-height-headings;
font-weight: $font-weight-headings;
font-style: normal;
text-align: left;
margin: 0;
position: absolute;
top: 10%;
padding: $spacer / 3 $spacer;
background: rgba($link-color, 0.85);
color: #fff !important;
text-shadow: 0 1px 0 #000;
left: 0;
opacity: 0;
transform: translate3d(0, -20px, 0);
}
.image {
@include media-frame;
@include breakoutviewport;
max-width: none;
margin-top: $spacer * $line-height;
margin-bottom: $spacer * $line-height;
display: block;
a & {
position: relative;
display: block;
}
// single photo post teasers
&:only-child {
margin-top: 0;
margin-bottom: 0;
}
a:hover &,
a:focus & {
border-color: $link-color !important;
.imageTitle {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
}

View File

@ -1,19 +1,22 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { graphql } from 'gatsby' import { graphql } from 'gatsby'
import Img from 'gatsby-image' import { GatsbyImage } from 'gatsby-plugin-image'
import { ImageProps } from '../../@types/Image' import { ImageProps } from '../../@types/Image'
import styles from './Image.module.scss' import { image as styleImage, imageTitle } from './Image.module.css'
export const Image = ({ export const Image = ({
title, title,
fluid, image,
fixed,
alt, alt,
original original,
className
}: ImageProps): ReactElement => ( }: ImageProps): ReactElement => (
<figure className={styles.image} data-original={original && original.src}> <figure
<Img backgroundColor="transparent" fluid={fluid} fixed={fixed} alt={alt} /> className={`${styleImage} ${className ? className : ''}`}
{title && <figcaption className={styles.imageTitle}>{title}</figcaption>} data-original={original?.src}
>
<GatsbyImage image={image} alt={alt} />
{title && <figcaption className={imageTitle}>{title}</figcaption>}
</figure> </figure>
) )
@ -22,9 +25,7 @@ export const imageSizeDefault = graphql`
original { original {
src src
} }
fluid(maxWidth: 940, quality: 85) { gatsbyImageData(layout: CONSTRAINED, width: 1040, quality: 85)
...GatsbyImageSharpFluid_withWebp_noBase64
}
} }
` `
@ -33,9 +34,13 @@ export const imageSizeThumb = graphql`
original { original {
src src
} }
fluid(maxWidth: 420, maxHeight: 140, quality: 85, cropFocus: CENTER) { gatsbyImageData(
...GatsbyImageSharpFluid_withWebp_noBase64 layout: CONSTRAINED
} width: 480
height: 180
quality: 85
transformOptions: { cropFocus: CENTER }
)
} }
` `
@ -44,8 +49,12 @@ export const photoSizeThumb = graphql`
original { original {
src src
} }
fluid(maxWidth: 300, maxHeight: 300, quality: 85, cropFocus: CENTER) { gatsbyImageData(
...GatsbyImageSharpFluid_withWebp_noBase64 layout: CONSTRAINED
} width: 316
height: 316
quality: 85
transformOptions: { cropFocus: CENTER }
)
} }
` `

View File

@ -0,0 +1,32 @@
.input {
display: block;
width: 100%;
padding: var(--padding-base-vertical) var(--padding-base-horizontal);
font-size: var(--input-font-size);
font-weight: var(--input-font-weight);
line-height: var(--line-height);
color: var(--input-color);
background-color: var(--input-bg);
background-image: none;
border: var(--stroke-width) solid transparent;
border-radius: var(--border-radius);
box-shadow: none;
transition: all ease-in-out 0.15s;
appearance: none;
}
.input::-moz-placeholder,
.input::-webkit-input-placeholder,
.input:-ms-input-placeholder {
color: var(--input-color-placeholder);
opacity: 1;
}
.input:focus {
border-color: var(--input-border-focus);
outline: 0;
}
.input[disabled] {
color: var(--text-color-dimmed);
}

View File

@ -1,36 +0,0 @@
@import 'variables';
@import 'mixins';
.input {
display: block;
width: 100%;
padding: $padding-base-vertical $padding-base-horizontal;
font-size: $input-font-size;
font-weight: $input-font-weight;
line-height: $line-height;
color: $input-color;
background-color: $input-bg;
background-image: none; // Reset unusual Firefox-on-Android default style
border: 0;
border-radius: $input-border-radius;
box-shadow: none;
transition: all ease-in-out 0.15s;
appearance: none;
@include placeholder();
:global(.dark) & {
color: $input-color--dark;
background-color: $input-bg--dark;
@include placeholder($input-color-placeholder--dark);
}
&:focus {
border-color: $input-border-focus;
outline: 0;
}
&[disabled] {
color: $brand-grey-dimmed;
}
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styles from './Input.module.scss' import { input } from './Input.module.css'
export default function Input(props: any): ReactElement { export default function Input({ className, ...props }: any): ReactElement {
return <input className={styles.input} {...props} /> return <input className={`${input} ${className || ''}`} {...props} />
} }

View File

@ -0,0 +1,17 @@
.qr {
margin-bottom: calc(var(--spacer) / 2);
}
.code {
margin: 0 auto;
position: relative;
padding: 0;
padding-right: 2rem;
width: fit-content;
}
.code code {
padding: calc(var(--spacer) / 2);
font-size: 0.65rem;
text-align: center;
}

View File

@ -1,19 +0,0 @@
@import 'variables';
.qr {
margin-bottom: $spacer / 2;
}
.code {
margin: 0 auto;
position: relative;
padding: 0;
padding-right: 2rem;
width: fit-content;
code {
padding: $spacer / 2;
font-size: 0.65rem;
text-align: center;
}
}

View File

@ -1,5 +1,5 @@
import React, { Suspense } from 'react' import React, { Suspense } from 'react'
import { render, fireEvent, waitForElement } from '@testing-library/react' import { render, fireEvent, waitFor } from '@testing-library/react'
import Qr from './Qr' import Qr from './Qr'
@ -10,10 +10,8 @@ describe('Qr', () => {
<Qr address="xxx" /> <Qr address="xxx" />
</Suspense> </Suspense>
) )
const lazyElement = await waitForElement(() => expect(container.firstChild).toBeInTheDocument()
container.querySelector('button') await waitFor(() => container.querySelector('button'))
)
expect(lazyElement).toBeInTheDocument()
fireEvent.click(container.querySelector('button')) fireEvent.click(container.querySelector('button'))
}) })
}) })

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { QRCode } from 'react-qr-svg' import { QRCode } from 'react-qr-svg'
import styles from './Qr.module.scss' import { qr, code } from './Qr.module.css'
import Copy from './Copy' import Copy from './Copy'
export default function Qr({ export default function Qr({
@ -19,10 +19,10 @@ export default function Qr({
level="Q" level="Q"
style={{ width: 120 }} style={{ width: 120 }}
value={address} value={address}
className={styles.qr} className={qr}
/> />
<pre className={styles.code}> <pre className={code}>
<code>{address}</code> <code>{address}</code>
<Copy text={address} /> <Copy text={address} />
</pre> </pre>

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import { getSrc } from 'gatsby-plugin-image'
import { useSiteMetadata } from '../../../hooks/use-site-metadata' import { useSiteMetadata } from '../../../hooks/use-site-metadata'
import { Post } from '../../../@types/Post' import { Post } from '../../../@types/Post'
import MetaTags from './MetaTags' import MetaTags from './MetaTags'
@ -39,9 +39,7 @@ export default function SEO({
const postMeta = post.frontmatter const postMeta = post.frontmatter
title = `${postMeta.title} ¦ ${siteTitle}` title = `${postMeta.title} ¦ ${siteTitle}`
description = postMeta.description ? postMeta.description : post.excerpt description = postMeta.description ? postMeta.description : post.excerpt
image = postMeta.image image = postMeta.image ? getSrc(postMeta.image) : `/${logo}`
? postMeta.image.childImageSharp.fluid.src
: `/${logo}`
postURL = `${siteUrl}${slug}` postURL = `${siteUrl}${slug}`
} else { } else {
title = `${siteTitle} ¦ ${siteDescription}` title = `${siteTitle} ¦ ${siteDescription}`

View File

@ -0,0 +1,20 @@
.tag {
color: var(--text-color-light);
margin-left: calc(var(--spacer) / 2);
margin-right: calc(var(--spacer) / 2);
margin-bottom: calc(var(--spacer) / 2);
white-space: nowrap;
display: inline-block;
}
.tag::before {
content: '#';
margin-right: 1px;
opacity: 0.65;
}
.count {
font-size: var(--font-size-small);
margin-left: calc(var(--spacer) / 6);
opacity: 0.65;
}

View File

@ -1,22 +0,0 @@
@import 'variables';
.tag {
color: $brand-grey-light;
margin-left: $spacer / 2;
margin-right: $spacer / 2;
margin-bottom: $spacer / 2;
white-space: nowrap;
display: inline-block;
&::before {
content: '#';
margin-right: 1px;
opacity: 0.65;
}
}
.count {
font-size: $font-size-small;
margin-left: $spacer / 6;
opacity: 0.65;
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import styles from './Tag.module.scss' import { tag, count as styleCount } from './Tag.module.css'
export default function Tag({ export default function Tag({
name, name,
@ -14,9 +14,9 @@ export default function Tag({
style?: any style?: any
}): ReactElement { }): ReactElement {
return ( return (
<Link className={styles.tag} to={url} style={style}> <Link className={tag} to={url} style={style}>
{name} {name}
{count && <span className={styles.count}>{count}</span>} {count && <span className={styleCount}>{count}</span>}
</Link> </Link>
) )
} }

View File

@ -0,0 +1,45 @@
.menu {
margin-top: 0;
position: absolute;
top: 100%;
left: 0;
width: 100%;
}
.menu ul {
margin: 0;
padding: 0;
text-align: center;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
}
.menu li {
list-style: none;
display: inline-block;
}
.menu li::before {
display: none;
}
.menu a {
color: var(--text-color);
line-height: 1;
text-transform: uppercase;
margin: 0 calc(var(--spacer) / 4);
font-size: var(--font-size-small);
text-shadow: 0 1px 0 rgba(255 255 255 0.5);
padding: var(--padding-base-horizontal);
display: block;
text-align: center;
}
.menu::-webkit-scrollbar,
.menu::-moz-scrollbar,
.menu::-webkit-scrollbar-thumb,
.menu::-webkit-scrollbar-track {
display: none;
}

View File

@ -1,66 +0,0 @@
@import 'variables';
@import 'mixins';
.menu {
@include divider-top;
margin-top: 0;
padding-top: $spacer / 2;
position: absolute;
top: calc(100% + #{$spacer / 1.5});
left: 0;
width: 100%;
ul {
margin: 0;
padding: 0;
text-align: center;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
white-space: nowrap;
}
li {
list-style: none;
display: inline-block;
&::before {
display: none;
}
}
a {
color: $text-color;
line-height: 1;
text-transform: uppercase;
margin: 0 $spacer / 4;
font-size: $font-size-small;
text-shadow: 0 1px 0 rgba(#fff, 0.5);
padding: $padding-base-horizontal;
display: block;
text-align: center;
&:hover,
&:focus {
color: $link-color-hover;
}
:global(.dark) & {
color: $text-color--dark;
text-shadow: 0 -1px 0 rgba(#000, 0.5);
&:hover,
&:focus {
color: $link-color-hover;
}
}
}
&::-webkit-scrollbar,
&::-moz-scrollbar,
&::-webkit-scrollbar-thumb,
&::-webkit-scrollbar-track {
display: none;
}
}

View File

@ -2,7 +2,7 @@ import React, { ReactElement, useState } from 'react'
import { Helmet } from 'react-helmet' import { Helmet } from 'react-helmet'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import Hamburger from '../atoms/Hamburger' import Hamburger from '../atoms/Hamburger'
import styles from './Menu.module.scss' import { menu as styleMenu } from './Menu.module.css'
import { useSiteMetadata } from '../../hooks/use-site-metadata' import { useSiteMetadata } from '../../hooks/use-site-metadata'
import { MenuItem } from '../../@types/Site' import { MenuItem } from '../../@types/Site'
@ -10,17 +10,19 @@ export default function Menu(): ReactElement {
const [menuOpen, setMenuOpen] = useState(false) const [menuOpen, setMenuOpen] = useState(false)
const { menu } = useSiteMetadata() const { menu } = useSiteMetadata()
const toggleMenu = () => { function toggleMenu(): void {
setMenuOpen(!menuOpen) setMenuOpen(!menuOpen)
} }
const MenuItems = menu.map((item: MenuItem) => ( const MenuItems = menu.map(
(item: MenuItem): JSX.Element => (
<li key={item.title}> <li key={item.title}>
<Link onClick={toggleMenu} to={item.link}> <Link onClick={toggleMenu} to={item.link}>
{item.title} {item.title}
</Link> </Link>
</li> </li>
)) )
)
return ( return (
<> <>
@ -28,7 +30,7 @@ export default function Menu(): ReactElement {
<html className={menuOpen ? 'has-menu-open' : undefined} lang="en" /> <html className={menuOpen ? 'has-menu-open' : undefined} lang="en" />
</Helmet> </Helmet>
<Hamburger onClick={toggleMenu} /> <Hamburger onClick={toggleMenu} />
<nav className={styles.menu}> <nav className={styleMenu}>
<ul>{MenuItems}</ul> <ul>{MenuItems}</ul>
</nav> </nav>
</> </>

View File

@ -0,0 +1,25 @@
.link {
text-align: center;
width: 2rem;
padding: calc(var(--spacer) / 4);
margin-left: calc(var(--spacer) / 4);
margin-right: calc(var(--spacer) / 4);
display: inline-block;
color: var(--text-color-light);
}
.link:first-child {
margin-left: 0;
}
.link:last-child {
margin-right: 0;
}
.link svg {
width: 24px;
height: 24px;
transition: stroke 0.3s ease-in-out;
display: block;
margin: 0 auto;
}

View File

@ -1,27 +0,0 @@
@import 'variables';
.link {
text-align: center;
width: 2rem;
padding: $spacer / 4;
margin-left: $spacer / 4;
margin-right: $spacer / 4;
display: inline-block;
color: $text-color-light;
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
svg {
width: 24px;
height: 24px;
transition: stroke 0.3s ease-in-out;
display: block;
margin: 0 auto;
}
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import styles from './Networks.module.scss' import { link as styleLink } from './Networks.module.css'
function NetworkIcon({ link }: { link: string }) { function NetworkIcon({ link }: { link: string }) {
let IconComp let IconComp
@ -28,7 +28,7 @@ export default function IconLinks({
return ( return (
<p> <p>
{links.map((link: string) => ( {links.map((link: string) => (
<a key={link} className={styles.link} href={link} title={link}> <a key={link} className={styleLink} href={link} title={link}>
<NetworkIcon link={link} /> <NetworkIcon link={link} />
</a> </a>
))} ))}

View File

@ -0,0 +1,41 @@
.pagination {
margin-top: calc(var(--spacer) * 3);
margin-bottom: var(--spacer);
display: flex;
justify-content: center;
}
.number {
text-align: center;
padding: calc(var(--spacer) / 6) calc(var(--spacer) / 2);
border: 1px solid var(--text-color-dimmed);
font-variant-numeric: lining-nums;
margin-left: -1px;
display: flex;
align-items: center;
justify-content: center;
min-width: 2.5rem;
color: var(--text-color);
}
.number:hover,
.number:focus {
background: rgba(255, 255, 255, 0.1);
}
.number:first-child {
border-top-left-radius: var(--border-radius);
border-bottom-left-radius: var(--border-radius);
}
.number:last-child {
border-top-right-radius: var(--border-radius);
border-bottom-right-radius: var(--border-radius);
}
.current {
composes: number;
cursor: default;
pointer-events: none;
color: var(--text-color-dimmed);
}

View File

@ -1,58 +0,0 @@
@import 'variables';
@import 'mixins';
.pagination {
@include breakoutviewport;
margin-top: $spacer * 3;
margin-bottom: $spacer;
display: flex;
justify-content: center;
}
.number {
text-align: center;
padding: $spacer / 6 $spacer / 2;
border: 1px solid $brand-grey-dimmed;
font-variant-numeric: lining-nums;
margin-left: -1px;
display: flex;
align-items: center;
justify-content: center;
min-width: 2.5rem;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
color: $brand-grey;
:global(.dark) & {
color: $brand-grey-dimmed;
border-color: darken($body-background-color--dark, 5%);
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.1);
}
&:hover,
&:focus {
background: rgba(255, 255, 255, 0.1);
}
&:first-child {
border-top-left-radius: $border-radius;
border-bottom-left-radius: $border-radius;
}
&:last-child {
border-top-right-radius: $border-radius;
border-bottom-right-radius: $border-radius;
}
}
.current {
composes: number;
cursor: default;
pointer-events: none;
color: $brand-grey-dimmed;
background: rgba(255, 255, 255, 0.1);
:global(.dark) & {
color: $brand-grey-light;
}
}

View File

@ -1,11 +1,15 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import styles from './Pagination.module.scss'
import shortid from 'shortid' import shortid from 'shortid'
import { PageContext } from '../../@types/Post' import { PageContext } from '../../@types/Post'
import Icon from '../atoms/Icon' import Icon from '../atoms/Icon'
import {
current as styleCurrent,
number as styleNumber,
pagination
} from './Pagination.module.css'
const PageNumber = ({ function PageNumber({
i, i,
slug, slug,
current current
@ -13,8 +17,8 @@ const PageNumber = ({
i: number i: number
slug: string slug: string
current?: boolean current?: boolean
}) => { }): JSX.Element {
const classes = current ? styles.current : styles.number const classes = current ? styleCurrent : styleNumber
const link = i === 0 ? slug : `${slug}page/${i + 1}` const link = i === 0 ? slug : `${slug}page/${i + 1}`
return ( return (
@ -30,13 +34,13 @@ function PrevNext({
}: { }: {
prevPagePath?: string prevPagePath?: string
nextPagePath?: string nextPagePath?: string
}) { }): JSX.Element {
const link = prevPagePath || nextPagePath const link = prevPagePath || nextPagePath
const rel = prevPagePath ? 'prev' : 'next' const rel = prevPagePath ? 'prev' : 'next'
const title = prevPagePath ? 'Newer Posts' : 'Older Posts' const title = prevPagePath ? 'Newer Posts' : 'Older Posts'
return ( return (
<Link to={link} rel={rel} title={title} className={styles.number}> <Link to={link} rel={rel} title={title} className={styleNumber}>
{prevPagePath ? ( {prevPagePath ? (
<Icon name="ChevronLeft" /> <Icon name="ChevronLeft" />
) : ( ) : (
@ -62,7 +66,7 @@ export default function Pagination({
const isLast = currentPageNumber === numPages const isLast = currentPageNumber === numPages
return ( return (
<div className={styles.pagination}> <div className={pagination}>
{!isFirst && <PrevNext prevPagePath={prevPagePath} />} {!isFirst && <PrevNext prevPagePath={prevPagePath} />}
{Array.from({ length: numPages }, (_, i) => ( {Array.from({ length: numPages }, (_, i) => (
<PageNumber <PageNumber

View File

@ -0,0 +1,6 @@
.time {
font-style: italic;
font-size: var(--font-size-small);
color: var(--text-color-light);
margin-bottom: calc(var(--spacer) / var(--line-height));
}

View File

@ -1,8 +0,0 @@
@import 'variables';
.time {
font-style: italic;
font-size: $font-size-small;
color: $text-color-light;
margin-bottom: $spacer / $line-height;
}

View File

@ -1,6 +1,6 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Time from '../atoms/Time' import Time from '../atoms/Time'
import styles from './PostDate.module.scss' import { time } from './PostDate.module.css'
export default function PostDate({ export default function PostDate({
date, date,
@ -10,7 +10,7 @@ export default function PostDate({
updated?: string updated?: string
}): ReactElement { }): ReactElement {
return ( return (
<div className={styles.time}> <div className={time}>
<Time date={date} /> <Time date={date} />
{updated && ' • updated '} {updated && ' • updated '}
{updated && <Time date={updated} />} {updated && <Time date={updated} />}

View File

@ -1,40 +1,40 @@
@import 'variables';
@import 'mixins';
.title { .title {
padding-left: 0.2rem; padding-left: 0.2rem;
padding-right: 0.2rem; padding-right: 0.2rem;
margin-top: $spacer / 2; margin-top: calc(var(--spacer) / 3);
margin-bottom: 0; margin-bottom: 0;
font-size: $font-size-base; font-size: var(--font-size-base);
transition: color 0.2s ease-out; transition: color 0.2s ease-out;
color: $text-color-light; }
.title + div {
padding-left: 0.2rem;
padding-right: 0.2rem;
} }
.post { .post {
display: block; display: block;
figure {
margin: 0;
}
} }
.time { .post:hover {
font-style: italic; text-decoration: none;
font-size: $font-size-small; }
color: $text-color-light;
padding-left: 0.2rem; .post:hover .title {
padding-right: 0.2rem; color: var(--link-color);
}
.post figure {
margin: 0;
} }
.empty { .empty {
@include media-frame; composes: frame from '../atoms/Image.module.css';
display: block; display: block;
min-height: 95px; min-height: 95px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAACaADAAQAAAABAAAACQAAAAAvQpmhAAAAHElEQVQYGWNgoBL4T8gcggoIGcBA0ASCCmhsBQBhFwX7u70C8QAAAABJRU5ErkJggg==); background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAACaADAAQAAAABAAAACQAAAAAvQpmhAAAAHElEQVQYGWNgoBL4T8gcggoIGcBA0ASCCmhsBQBhFwX7u70C8QAAAABJRU5ErkJggg==);
}
a:hover & {
border-color: $link-color; a:hover .empty {
} border-color: var(--link-color);
} }

View File

@ -3,7 +3,11 @@ import { Link, graphql } from 'gatsby'
import { Image } from '../atoms/Image' import { Image } from '../atoms/Image'
import { Post } from '../../@types/Post' import { Post } from '../../@types/Post'
import PostTitle from '../templates/Post/Title' import PostTitle from '../templates/Post/Title'
import styles from './PostTeaser.module.scss' import {
post as stylePost,
empty,
title as styleTitle
} from './PostTeaser.module.css'
export const postTeaserQuery = graphql` export const postTeaserQuery = graphql`
fragment PostTeaser on MarkdownRemark { fragment PostTeaser on MarkdownRemark {
@ -42,21 +46,24 @@ export default function PostTeaser({
return ( return (
<Link <Link
className={styles.post} className={stylePost}
to={slug} to={slug}
onClick={toggleSearch && toggleSearch} onClick={toggleSearch && toggleSearch}
> >
{image ? ( {image ? (
<Image fluid={image.childImageSharp.fluid} alt={title} /> <Image
image={(image as any).childImageSharp.gatsbyImageData}
alt={title}
/>
) : ( ) : (
<span className={styles.empty} /> <span className={empty} />
)} )}
<PostTitle <PostTitle
title={title} title={title}
date={hideDate ? null : date} date={hideDate ? null : date}
updated={updated} updated={updated}
className={styles.title} className={styleTitle}
/> />
</Link> </Link>
) )

View File

@ -0,0 +1,61 @@
.title {
font-size: var(--font-size-h3);
margin-bottom: var(--spacer);
}
.relatedPosts ul {
display: grid;
gap: calc(var(--spacer) / 2);
grid-template-columns: repeat(2, 1fr);
padding: 0;
margin: 0;
}
@media (min-width: 40rem) {
.relatedPosts ul {
grid-template-columns: repeat(3, 1fr);
gap: var(--spacer);
}
}
.relatedPosts li {
display: block;
margin: 0;
}
.relatedPosts li::before {
display: none;
}
.relatedPosts figure {
margin: 0;
}
.relatedPosts img {
margin-bottom: 0;
}
.relatedPosts a {
display: block;
}
.relatedPosts a > div {
margin-bottom: 0;
}
.relatedPosts a h4 {
color: var(--text-color-light);
}
.relatedPosts a:hover h4,
.relatedPosts a:focus h4 {
color: var(--link-color);
}
.button {
font-size: var(--font-size-mini);
display: inline-block;
color: var(--text-color-light);
text-transform: uppercase;
margin-left: calc(var(--spacer) / 2);
}

View File

@ -1,72 +0,0 @@
@import 'variables';
@import 'mixins';
.title {
font-size: $font-size-h3;
margin-bottom: $spacer;
}
.relatedPosts {
margin-top: -($spacer * 2);
@media (min-width: $screen-md) {
@include breakoutviewport;
}
ul {
display: grid;
gap: $spacer / 2;
grid-template-columns: repeat(2, 1fr);
padding: 0;
margin: 0;
@media (min-width: $screen-sm) {
grid-template-columns: repeat(3, 1fr);
gap: $spacer;
}
}
li {
display: block;
margin: 0;
&::before {
display: none;
}
}
figure {
margin: 0;
}
img {
margin-bottom: 0;
}
a {
display: block;
> div {
margin-bottom: 0;
}
h4 {
color: $text-color-light;
}
&:hover,
&:focus {
h4 {
color: $link-color;
}
}
}
}
.button {
font-size: $font-size-mini;
display: inline-block;
color: $brand-grey-light;
text-transform: uppercase;
margin-left: $spacer / 2;
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement, useState } from 'react' import React, { ReactElement, useState } from 'react'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import PostTeaser from './PostTeaser' import PostTeaser from './PostTeaser'
import styles from './RelatedPosts.module.scss' import { relatedPosts, title, button } from './RelatedPosts.module.css'
import { Post, Frontmatter } from '../../@types/Post' import { Post, Frontmatter } from '../../@types/Post'
import { PhotoThumb } from '../templates/Photos' import { PhotoThumb } from '../templates/Photos'
@ -21,7 +21,7 @@ function postsWithDataFilter(
posts: [{ node: Post }], posts: [{ node: Post }],
key: keyof Frontmatter, key: keyof Frontmatter,
valuesToFind: string[] valuesToFind: string[]
) { ): { node: Post }[] {
const newArray = posts const newArray = posts
.filter(({ node }: { node: Post }) => { .filter(({ node }: { node: Post }) => {
const frontmatterKey = node.frontmatter[key] as [] const frontmatterKey = node.frontmatter[key] as []
@ -39,7 +39,7 @@ function postsWithDataFilter(
return newArray return newArray
} }
function photosWithDataFilter(posts: []) { function photosWithDataFilter(posts: [{ node: Post }]): { node: Post }[] {
const newArray = posts const newArray = posts
.filter((post: { node: Post }) => { .filter((post: { node: Post }) => {
const { fileAbsolutePath } = post.node const { fileAbsolutePath } = post.node
@ -78,10 +78,10 @@ export default function RelatedPosts({
} }
return ( return (
<aside className={styles.relatedPosts}> <aside className={relatedPosts}>
<h1 className={styles.title}> <h1 className={title}>
Related {isPhotos ? 'Photos' : 'Posts'}{' '} Related {isPhotos ? 'Photos' : 'Posts'}{' '}
<button className={styles.button} onClick={() => refreshPosts()}> <button className={button} onClick={() => refreshPosts()}>
Refresh Refresh
</button> </button>
</h1> </h1>

View File

@ -0,0 +1,22 @@
.searchButton {
padding: calc(var(--spacer) / 2);
vertical-align: middle;
display: inline-block;
margin: 0;
margin-right: calc(var(--spacer) / 4);
}
.searchButton:focus {
outline: 0;
}
.searchButton svg {
stroke: var(--text-color-light);
width: 24px;
height: 24px;
}
.searchButton:hover svg,
.searchButton:focus svg {
stroke: var(--link-color);
}

View File

@ -1,32 +0,0 @@
@import 'variables';
.searchButton {
padding: $spacer / 2;
vertical-align: middle;
display: inline-block;
margin: 0;
margin-right: $spacer / 4;
&:focus {
outline: 0;
}
svg {
stroke: $brand-grey-light;
width: 24px;
height: 24px;
}
&:hover,
&:focus {
svg {
stroke: $brand-cyan;
}
}
&:active {
svg {
stroke: darken($brand-cyan, 30%);
}
}
}

View File

@ -1,13 +1,13 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styles from './SearchButton.module.scss' import { searchButton } from './SearchButton.module.css'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
const SearchButton = (props: any): ReactElement => ( const SearchButton = ({ onClick }: { onClick: () => void }): ReactElement => (
<button <button
type="button" type="button"
title="Search" title="Search"
className={styles.searchButton} className={searchButton}
{...props} onClick={onClick}
> >
<Icon name="Search" /> <Icon name="Search" />
</button> </button>

View File

@ -0,0 +1,20 @@
.searchInput::-webkit-search-cancel-button {
display: none;
}
.searchInputClose {
position: absolute;
right: calc(var(--spacer) / 2);
top: calc(var(--spacer) / 2);
}
.searchInputClose svg {
stroke: var(--brand-grey-light);
width: 24px;
height: 24px;
}
.searchInputClose:hover svg,
.searchInputClose:focus svg {
stroke: var(--link-color);
}

View File

@ -1,28 +0,0 @@
@import 'variables';
.searchInput {
composes: input from '../../atoms/Input.module.scss';
&::-webkit-search-cancel-button {
display: none;
}
}
.searchInputClose {
position: absolute;
right: $spacer / 2;
top: $spacer / 2;
svg {
stroke: $brand-grey-light;
width: 24px;
height: 24px;
}
&:hover,
&:focus {
svg {
stroke: $link-color;
}
}
}

View File

@ -1,7 +1,7 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import Input from '../../atoms/Input' import Input from '../../atoms/Input'
import Icon from '../../atoms/Icon' import Icon from '../../atoms/Icon'
import styles from './SearchInput.module.scss' import { searchInput, searchInputClose } from './SearchInput.module.css'
export default function SearchInput({ export default function SearchInput({
value, value,
@ -15,7 +15,7 @@ export default function SearchInput({
return ( return (
<> <>
<Input <Input
className={styles.searchInput} className={searchInput}
type="search" type="search"
placeholder="Search everything" placeholder="Search everything"
autoFocus // eslint-disable-line autoFocus // eslint-disable-line
@ -23,7 +23,7 @@ export default function SearchInput({
onChange={onChange} onChange={onChange}
/> />
<button <button
className={styles.searchInputClose} className={searchInputClose}
onClick={onToggle} onClick={onToggle}
title="Close search" title="Close search"
> >

View File

@ -0,0 +1,72 @@
.searchResults {
position: absolute;
left: 0;
right: 0;
z-index: 10;
top: 0;
bottom: 0;
background: var(--body-background-color);
animation: fadein 0.3s;
overflow: scroll;
-webkit-overflow-scrolling: touch;
height: 91vh;
}
.results {
composes: container from '../../Layout.module.css';
padding: var(--spacer) calc(var(--spacer) / 2);
margin-bottom: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
@media (min-width: 60rem) {
.results {
padding-left: 0;
padding-right: 0;
}
}
.results li {
display: block;
flex: 0 0 48%;
margin-bottom: var(--spacer);
}
@media (min-width: 40rem) {
.results li {
flex-basis: 31%;
}
}
.results li::before {
display: none;
}
.results img {
margin-bottom: 0;
}
.results a {
display: block;
}
.results a > div {
margin-bottom: 0;
}
.results a:hover h4,
.results a:focus h4 {
color: var(--link-color);
}
@keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -1,79 +0,0 @@
@import 'variables';
@import 'mixins';
.searchResults {
position: absolute;
left: 0;
right: 0;
z-index: 10;
top: 0;
bottom: 0;
background: rgba($body-background-color, 0.95);
backdrop-filter: blur(5px);
animation: fadein 0.3s;
overflow: scroll;
-webkit-overflow-scrolling: touch;
height: 91vh;
:global(.dark) & {
background: rgba($body-background-color--dark, 0.95);
}
ul {
@include breakoutviewport;
padding: $spacer $spacer / 2;
margin-bottom: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
@media (min-width: $screen-md) {
padding-left: 0;
padding-right: 0;
}
li {
display: block;
flex: 0 0 48%;
margin-bottom: $spacer;
@media (min-width: $screen-sm) {
flex-basis: 31%;
}
&::before {
display: none;
}
}
}
img {
margin-bottom: 0;
}
a {
display: block;
> div {
margin-bottom: 0;
}
&:hover,
&:focus {
h4 {
color: $link-color;
}
}
}
}
@keyframes fadein {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}

View File

@ -1,10 +1,12 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import ReactDOM from 'react-dom' import ReactDOM from 'react-dom'
import { graphql, useStaticQuery } from 'gatsby' import { graphql, useStaticQuery } from 'gatsby'
import Container from '../../atoms/Container'
import PostTeaser from '../PostTeaser' import PostTeaser from '../PostTeaser'
import SearchResultsEmpty from './SearchResultsEmpty' import SearchResultsEmpty from './SearchResultsEmpty'
import styles from './SearchResults.module.scss' import {
searchResults,
results as styleResults
} from './SearchResults.module.css'
import { Post } from '../../../@types/Post' import { Post } from '../../../@types/Post'
export interface Results { export interface Results {
@ -35,10 +37,9 @@ function SearchResultsPure({
toggleSearch(): void toggleSearch(): void
}) { }) {
return ( return (
<div className={styles.searchResults}> <div className={searchResults}>
<Container>
{results.length > 0 ? ( {results.length > 0 ? (
<ul> <ul className={styleResults}>
{results.map((page: { slug: string }) => {results.map((page: { slug: string }) =>
posts posts
.filter( .filter(
@ -54,7 +55,6 @@ function SearchResultsPure({
) : ( ) : (
<SearchResultsEmpty searchQuery={searchQuery} results={results} /> <SearchResultsEmpty searchQuery={searchQuery} results={results} />
)} )}
</Container>
</div> </div>
) )
} }

View File

@ -0,0 +1,34 @@
.empty {
padding-top: 15vh;
display: flex;
justify-content: center;
}
.emptyMessage {
color: var(--text-color-light);
}
.emptyMessageText {
margin-bottom: 0;
position: relative;
}
.emptyMessageText::after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4, end) 1s infinite;
/* ascii code for the ellipsis character */
content: '\2026';
width: 0;
position: absolute;
left: 101%;
bottom: 0;
}
@keyframes ellipsis {
to {
width: 1rem;
}
}

View File

@ -1,34 +0,0 @@
@import 'variables';
.empty {
padding-top: 15vh;
display: flex;
justify-content: center;
}
.emptyMessage {
color: $brand-grey-light;
}
.emptyMessageText {
margin-bottom: 0;
position: relative;
&::after {
overflow: hidden;
display: inline-block;
vertical-align: bottom;
animation: ellipsis steps(4, end) 1s infinite;
content: '\2026'; // ascii code for the ellipsis character
width: 0;
position: absolute;
left: 101%;
bottom: 0;
}
}
@keyframes ellipsis {
to {
width: 1rem;
}
}

View File

@ -1,5 +1,9 @@
import React, { ReactElement } from 'react' import React, { ReactElement } from 'react'
import styles from './SearchResultsEmpty.module.scss' import {
empty,
emptyMessage,
emptyMessageText
} from './SearchResultsEmpty.module.css'
import { Results } from './SearchResults' import { Results } from './SearchResults'
const SearchResultsEmpty = ({ const SearchResultsEmpty = ({
@ -9,9 +13,9 @@ const SearchResultsEmpty = ({
searchQuery: string searchQuery: string
results: Results[] results: Results[]
}): ReactElement => ( }): ReactElement => (
<div className={styles.empty}> <div className={empty}>
<header className={styles.emptyMessage}> <header className={emptyMessage}>
<p className={styles.emptyMessageText}> <p className={emptyMessageText}>
{searchQuery.length > 0 && results.length === 0 {searchQuery.length > 0 && results.length === 0
? 'No results found' ? 'No results found'
: 'Awaiting your input'} : 'Awaiting your input'}

View File

@ -0,0 +1,46 @@
.search {
position: absolute;
left: calc(var(--spacer) / 2);
right: calc(var(--spacer) / 2);
top: calc(var(--spacer) / 4);
z-index: 10;
}
.search input {
width: 100%;
}
@media (min-width: 40rem) {
.search {
left: 0;
right: 0;
}
}
.appear,
.enter {
opacity: 0.01;
transform: translate3d(0, -100px, 0);
}
.appearActive,
.enterActive {
opacity: 1;
transition: 0.2s ease-out;
transform: translate3d(0, 0, 0);
}
.exit {
opacity: 1;
transform: translate3d(0, 0, 0);
}
.exitActive {
opacity: 0.01;
transition: 0.2s ease-in;
transform: translate3d(0, -100px, 0);
}
:global(.hasSearchOpen) {
overflow: hidden;
}

View File

@ -1,46 +0,0 @@
@import 'variables';
.search {
position: absolute;
left: $spacer / 2;
right: $spacer / 2;
top: $spacer / 4;
z-index: 10;
input {
width: 100%;
}
@media (min-width: $screen-md) {
left: 0;
right: 0;
}
}
.appear,
.enter {
opacity: 0.01;
transform: translate3d(0, -100px, 0);
&.appearActive,
&.enterActive {
opacity: 1;
transition: 0.2s ease-out;
transform: translate3d(0, 0, 0);
}
}
.exit {
opacity: 1;
transform: translate3d(0, 0, 0);
&.exitActive {
opacity: 0.01;
transition: 0.2s ease-in;
transform: translate3d(0, -100px, 0);
}
}
:global(.hasSearchOpen) {
overflow: hidden;
}

Some files were not shown because too many files have changed in this diff Show More