diff --git a/.eleventy.js b/.eleventy.js
new file mode 100644
index 0000000..ec53720
--- /dev/null
+++ b/.eleventy.js
@@ -0,0 +1,106 @@
+const fs = require('fs');
+const markdownIt = require('markdown-it');
+const syntaxHighlight = require('@11ty/eleventy-plugin-syntaxhighlight');
+const htmlmin = require('html-minifier');
+
+module.exports = function(eleventyConfig) {
+ // Copy the `img` and `css` folders to the output
+ eleventyConfig.addPassthroughCopy('assets');
+
+ eleventyConfig.addPlugin(syntaxHighlight);
+
+ let markdownLibrary = markdownIt({
+ html: true,
+ linkify: true
+ });
+ eleventyConfig.setLibrary('md', markdownLibrary);
+
+ // Get the first `n` elements of a collection.
+ eleventyConfig.addFilter("head", (array, n) => {
+ if (!Array.isArray(array) || array.length === 0) {
+ return [];
+ }
+ return (n < 0) ? array.slice(n) : array.slice(0, n);
+ });
+
+ eleventyConfig.addCollection('sortByTitle', function(collectionApi) {
+ return collectionApi.getAll()
+ .filter(function(item) {
+ let extension = item.inputPath.split('.').pop();
+ return extension === 'md';
+ })
+ .sort(function(a, b) {
+ return a.data.title - b.data.title;
+ });
+ });
+
+ eleventyConfig.addCollection('categories', function(collectionApi) {
+ const categories = [];
+ collectionApi.getAll()
+ .filter(function(item) {
+ let extension = item.inputPath.split('.').pop();
+ return extension === 'md';
+ })
+ .forEach((item) => {
+ const category = item.data.category;
+ if (category && !categories.includes(category)) {
+ categories.push(category);
+ }
+ });
+ return categories.sort();
+ });
+
+ eleventyConfig.addCollection('groupByCategories', function(collectionApi) {
+ const categories = {};
+ collectionApi.getAll()
+ .filter(function(item) {
+ let extension = item.inputPath.split('.').pop();
+ return extension === 'md';
+ })
+ .forEach((item) => {
+ const category = item.data.category;
+ if (!category) {
+ return;
+ }
+ Array.isArray(categories[category])
+ ? categories[category].push(item)
+ : categories[category] = [item];
+ });
+ return categories;
+ });
+
+ eleventyConfig.addTransform('minify-html', function(content) {
+ if (this.outputPath && this.outputPath.endsWith('.html')) {
+ return htmlmin.minify(content, {
+ useShortDoctype: true,
+ removeComments: true,
+ collapseWhitespace: true
+ });
+ }
+ return content;
+ });
+
+ return {
+ // Control which files Eleventy will process
+ // e.g.: *.md, *.njk, *.html, *.liquid
+ templateFormats: [
+ 'md',
+ 'njk',
+ 'html',
+ 'liquid',
+ ],
+ // Pre-process *.md files with: (default: `liquid`)
+ markdownTemplateEngine: 'njk',
+
+ // Pre-process *.html files with: (default: `liquid`)
+ htmlTemplateEngine: 'njk',
+
+ // These are all optional (defaults are shown):
+ dir: {
+ input: 'contents',
+ includes: '_includes',
+ data: '_data',
+ output: '_site'
+ }
+ };
+};
\ No newline at end of file
diff --git a/.eleventyignore b/.eleventyignore
new file mode 100644
index 0000000..42061c0
--- /dev/null
+++ b/.eleventyignore
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index 170f87a..0000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -1 +0,0 @@
-custom: ['https://paypal.me/phu0cng']
diff --git a/.gitignore b/.gitignore
index 35b0cc8..8d50cfd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,4 @@
-.DS_Store
.netlify
-.next
+_site
node_modules
-out
-package-lock.json
-tslint.log
\ No newline at end of file
+package-lock.json
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index c998432..c88c999 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,3 @@
.netlify
-.next
-node_modules
-out
\ No newline at end of file
+_site
+node_modules
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index f4efe5d..b98bdca 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2019 phuoc-ng
+Copyright (c) 2019 phuocng
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/public/favicon.png b/assets/favicon.png
similarity index 100%
rename from public/favicon.png
rename to assets/favicon.png
diff --git a/public/favicon.svg b/assets/favicon.svg
similarity index 100%
rename from public/favicon.svg
rename to assets/favicon.svg
diff --git a/public/assets/full-background.jpeg b/assets/full-background.jpeg
similarity index 100%
rename from public/assets/full-background.jpeg
rename to assets/full-background.jpeg
diff --git a/public/mask-favicon.svg b/assets/mask-favicon.svg
similarity index 100%
rename from public/mask-favicon.svg
rename to assets/mask-favicon.svg
diff --git a/public/assets/screenshot.png b/assets/screenshot.png
similarity index 100%
rename from public/assets/screenshot.png
rename to assets/screenshot.png
diff --git a/public/assets/video-background-demo.mp4 b/assets/video-background-demo.mp4
similarity index 100%
rename from public/assets/video-background-demo.mp4
rename to assets/video-background-demo.mp4
diff --git a/bin/generateScreenshot.ts b/bin/generateScreenshot.ts
deleted file mode 100644
index 6311ad9..0000000
--- a/bin/generateScreenshot.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env node
-
-// Run this script from the root folder
-// $ npm run screenshot slug-of-pattern-here
-
-const puppeteer = require('puppeteer');
-
-const main = () => {
- const args = process.argv;
- if (!args || !Array.isArray(args) || args.length < 2) {
- console.log('Please specific the pattern: npm run screenshot slug-of-pattern-here');
- return;
- }
-
- const pattern = args[2];
-
- (async () => {
- const browser = await puppeteer.launch();
-
- const page = await browser.newPage();
- await page.goto(`http://localhost:3000/${pattern}`);
-
- await page.waitForSelector('.demo__live');
- const element = await page.$('.demo__live');
- await element.screenshot({
- path: `public/assets/patterns/${pattern}.png`,
- });
- await page.close();
-
- await browser.close();
- })();
-};
-
-main();
diff --git a/contents/_data/github.js b/contents/_data/github.js
new file mode 100644
index 0000000..d834660
--- /dev/null
+++ b/contents/_data/github.js
@@ -0,0 +1,11 @@
+const fetch = require('node-fetch');
+
+module.exports = async function() {
+ return fetch('https://api.github.com/repos/phuocng/csslayout')
+ .then(res => res.json())
+ .then(json => {
+ return {
+ stargazers: json.stargazers_count
+ };
+ });
+};
diff --git a/contents/_includes/follow.njk b/contents/_includes/follow.njk
new file mode 100644
index 0000000..c4fe543
--- /dev/null
+++ b/contents/_includes/follow.njk
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/contents/_includes/layouts/base.njk b/contents/_includes/layouts/base.njk
new file mode 100644
index 0000000..5f87d72
--- /dev/null
+++ b/contents/_includes/layouts/base.njk
@@ -0,0 +1,65 @@
+
+
+
+ {{ title or metadata.title }} - CSS Layout
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ content | safe }}
+
+
+
+
+
diff --git a/contents/_includes/layouts/post.njk b/contents/_includes/layouts/post.njk
new file mode 100644
index 0000000..db0d5a1
--- /dev/null
+++ b/contents/_includes/layouts/post.njk
@@ -0,0 +1,23 @@
+---
+layout: layouts/base.njk
+---
+{% set previousPost = collections.sortByTitle | getPreviousCollectionItem(page) %}
+{% set nextPost = collections.sortByTitle | getNextCollectionItem(page) %}
+
+
+
+
+
{{ title }}
+
{{ content | safe }}
+
+
+ {% include "follow.njk" %}
+
\ No newline at end of file
diff --git a/contents/index.njk b/contents/index.njk
new file mode 100644
index 0000000..7f2e847
--- /dev/null
+++ b/contents/index.njk
@@ -0,0 +1,29 @@
+---
+layout: layouts/base.njk
+title: A collection of popular layouts and patterns made with CSS
+eleventyExcludeFromCollections: true
+---
+
+
+
+
+ {% for cat in collections.categories %}
+ {% set posts = collections.groupByCategories[cat] %}
+
+ {% endfor %}
+
+ {% include "follow.njk" %}
+
\ No newline at end of file
diff --git a/contents/robots.njk b/contents/robots.njk
new file mode 100644
index 0000000..95e8984
--- /dev/null
+++ b/contents/robots.njk
@@ -0,0 +1,8 @@
+---
+permalink: '/robots.txt'
+eleventyExcludeFromCollections: true
+---
+
+Sitemap: https://csslayout.io/sitemap.xml
+User-agent: *
+Disallow:
\ No newline at end of file
diff --git a/contents/sitemap.njk b/contents/sitemap.njk
new file mode 100644
index 0000000..5532ece
--- /dev/null
+++ b/contents/sitemap.njk
@@ -0,0 +1,13 @@
+---
+permalink: /sitemap.xml
+eleventyExcludeFromCollections: true
+---
+
+
+ {% for page in collections.all %}
+
+ https://csslayout.io{{ page.url | url }}
+ {{ page.date.toISOString() }}
+
+ {% endfor %}
+
\ No newline at end of file
diff --git a/hooks/useInterval.ts b/hooks/useInterval.ts
deleted file mode 100644
index e7db0ec..0000000
--- a/hooks/useInterval.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { useEffect } from 'react';
-
-const useInterval = (callback: () => void, delay?: number) => {
- useEffect(() => {
- const handler = () => callback();
- if (delay !== null) {
- const id = setInterval(handler, delay);
- return () => clearInterval(id);
- }
- }, [delay]);
-};
-
-export default useInterval;
diff --git a/next-env.d.ts b/next-env.d.ts
deleted file mode 100644
index 4f11a03..0000000
--- a/next-env.d.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-///
-///
-
-// NOTE: This file should not be edited
-// see https://nextjs.org/docs/basic-features/typescript for more information.
diff --git a/next.config.js b/next.config.js
deleted file mode 100644
index 38454c3..0000000
--- a/next.config.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const withMDX = require('@next/mdx')({
- extension: /\.mdx?$/,
-});
-
-module.exports = withMDX({
- // `true` will transform `/about` to `/about/index.html`
- trailingSlash: true,
- pageExtensions: ['js', 'jsx', 'tsx', 'mdx'],
-});
diff --git a/package.json b/package.json
index 4feb8a8..10cff14 100644
--- a/package.json
+++ b/package.json
@@ -15,43 +15,31 @@
],
"repository": {
"type": "git",
- "url": "https://github.com/1milligram/csslayout"
+ "url": "https://github.com/phuocng/csslayout"
},
"bugs": {
- "url": "https://github.com/1milligram/csslayout/issues"
+ "url": "https://github.com/phuocng/csslayout/issues"
},
"license": "MIT",
"scripts": {
- "build": "next build",
- "dev": "next dev",
- "format": "prettier --write \"**/*.+(css|html|json|js|jsx|mdx|scss|ts|tsx)\"",
- "preexport": "npm run build",
- "export": "next export",
- "deploy": "npm run export && netlify deploy --prod --dir=out",
- "lint": "tslint -c tslint.json -o tslint.log 'client/**/*.{ts,tsx}'",
- "screenshot": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node bin/generateScreenshot.ts"
- },
- "dependencies": {
- "@1milligram/design": "^0.4.1",
- "@mdx-js/loader": "^2.0.0",
- "@mdx-js/react": "^2.0.0",
- "@next/mdx": "^12.1.0",
- "next": "^12.1.0",
- "prism-react-renderer": "^1.3.1",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "build": "npm run build:eleventy && npm run build:sass",
+ "build:sass": "sass styles/index.scss _site/styles/index.min.css --no-source-map --style compressed",
+ "build:eleventy": "npx @11ty/eleventy",
+ "deploy": "npm run build && netlify deploy --prod --dir=_site",
+ "format": "prettier --write \"**/*.+(json|md|scss)\"",
+ "start": "npm run watch:eleventy & npm run watch:sass",
+ "watch:eleventy": "npx @11ty/eleventy --serve --port=8081",
+ "watch:sass": "sass styles/index.scss _site/styles/index.min.css --no-source-map --style compressed --watch"
},
"devDependencies": {
- "@types/react": "^17.0.39",
- "@types/react-dom": "^17.0.11",
- "puppeteer": "^13.4.0",
- "prettier": "^2.5.1",
- "sass": "^1.49.9",
- "serve": "^13.0.2",
- "typescript": "^4.5.5",
- "ts-loader": "^9.2.6",
- "ts-node": "^10.5.0",
- "tslint": "^6.1.3",
- "tslint-react": "^5.0.0"
+ "@11ty/eleventy-plugin-syntaxhighlight": "^4.1.0",
+ "html-minifier": "^4.0.0",
+ "node-fetch": "^2.6.7",
+ "prettier": "^2.7.1",
+ "sass": "^1.54.8"
+ },
+ "dependencies": {
+ "@11ty/eleventy": "^1.0.2",
+ "markdown-it": "^13.0.1"
}
}
diff --git a/public/robots.txt b/public/robots.txt
deleted file mode 100644
index 6c3f882..0000000
--- a/public/robots.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-User-agent: *
-Disallow:
-Sitemap: https://csslayout.io/sitemap.xml
\ No newline at end of file
diff --git a/public/sitemap.xml b/public/sitemap.xml
deleted file mode 100644
index 535ae92..0000000
--- a/public/sitemap.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-
- https://csslayout.io
-
-
- https://csslayout.io/accordion
- https://csslayout.io/arrow-buttons
- https://csslayout.io/avatar
- https://csslayout.io/avatar-list
- https://csslayout.io/badge
- https://csslayout.io/breadcrumb
- https://csslayout.io/button-with-icon
- https://csslayout.io/card
- https://csslayout.io/card-layout
- https://csslayout.io/centering
- https://csslayout.io/chip
- https://csslayout.io/circular-navigation
- https://csslayout.io/close-button
- https://csslayout.io/color-swatch
- https://csslayout.io/concave-corners
- https://csslayout.io/cookie-banner
- https://csslayout.io/corner-ribbon
- https://csslayout.io/curved-background
- https://csslayout.io/custom-checkbox-button
- https://csslayout.io/custom-radio-button
- https://csslayout.io/diagonal-section
- https://csslayout.io/docked-at-corner
- https://csslayout.io/dot-leader
- https://csslayout.io/dot-navigation
- https://csslayout.io/drawer
- https://csslayout.io/drop-area
- https://csslayout.io/drop-cap
- https://csslayout.io/dropdown
- https://csslayout.io/fading-long-section
- https://csslayout.io/feature-comparison
- https://csslayout.io/feature-list
- https://csslayout.io/fixed-at-corner
- https://csslayout.io/fixed-at-side
- https://csslayout.io/floating-label
- https://csslayout.io/folder-structure
- https://csslayout.io/full-background
- https://csslayout.io/full-screen-menu
- https://csslayout.io/holy-grail
- https://csslayout.io/initial-avatar
- https://csslayout.io/input-addon
- https://csslayout.io/inverted-corners
- https://csslayout.io/keyboard-shortcut
- https://csslayout.io/layered-card
- https://csslayout.io/lined-paper
- https://csslayout.io/masonry-grid
- https://csslayout.io/media-object
- https://csslayout.io/mega-menu
- https://csslayout.io/menu
- https://csslayout.io/modal
- https://csslayout.io/nested-dropdowns
- https://csslayout.io/notification
- https://csslayout.io/overlay-play-button
- https://csslayout.io/pagination
- https://csslayout.io/popover-arrow
- https://csslayout.io/presence-indicator
- https://csslayout.io/previous-next-buttons
- https://csslayout.io/price-tag
- https://csslayout.io/pricing-table
- https://csslayout.io/progress-bar
- https://csslayout.io/property-list
- https://csslayout.io/questions-and-answers
- https://csslayout.io/radial-progress-bar
- https://csslayout.io/radio-button-group
- https://csslayout.io/radio-switch
- https://csslayout.io/rating
- https://csslayout.io/resizable-element
- https://csslayout.io/ribbon
- https://csslayout.io/same-height-columns
- https://csslayout.io/search-box
- https://csslayout.io/separator
- https://csslayout.io/sidebar
- https://csslayout.io/simple-grid
- https://csslayout.io/slider
- https://csslayout.io/spin-button
- https://csslayout.io/split-navigation
- https://csslayout.io/split-screen
- https://csslayout.io/stacked-cards
- https://csslayout.io/stamp-border
- https://csslayout.io/statistic
- https://csslayout.io/status-light
- https://csslayout.io/stepper-input
- https://csslayout.io/sticky-footer
- https://csslayout.io/sticky-header
- https://csslayout.io/sticky-sections
- https://csslayout.io/sticky-table-column
- https://csslayout.io/sticky-table-headers
- https://csslayout.io/switch
- https://csslayout.io/tab
- https://csslayout.io/teardrop
- https://csslayout.io/three-dimensions-card
- https://csslayout.io/timeline
- https://csslayout.io/toggle-password-visibility
- https://csslayout.io/tooltip
- https://csslayout.io/tree-diagram
- https://csslayout.io/triangle-buttons
- https://csslayout.io/upload-button
- https://csslayout.io/validation-icon
- https://csslayout.io/video-background
- https://csslayout.io/voting
- https://csslayout.io/watermark
- https://csslayout.io/wizard
- https://csslayout.io/zigzag-timeline
-
\ No newline at end of file
diff --git a/styles/_common.scss b/styles/_common.scss
new file mode 100644
index 0000000..7052df8
--- /dev/null
+++ b/styles/_common.scss
@@ -0,0 +1,29 @@
+:root {
+ --container-width: auto;
+}
+
+body {
+ background: #e2e8f0;
+ font-family: Space Grotesk, -apple-system, Arial, ui-sans-serif, system-ui;
+ font-size: 1rem;
+ font-weight: 300;
+ line-height: 1.5;
+ margin: 0;
+}
+.container {
+ margin: 0 auto;
+ padding: 0 1rem;
+ width: var(--container-width);
+}
+.divider {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+}
+.text--primary {
+ color: #6366f1;
+}
+
+@media (min-width: 1024px) {
+ :root {
+ --container-width: 48rem;
+ }
+}
diff --git a/styles/_reset.scss b/styles/_reset.scss
deleted file mode 100644
index 34a0d52..0000000
--- a/styles/_reset.scss
+++ /dev/null
@@ -1,30 +0,0 @@
-body {
- -webkit-font-smoothing: antialiased;
- color: #333;
- font-family: 'Inter', sans-serif;
- line-height: 1.5;
- margin: 0;
-}
-* {
- box-sizing: border-box;
-}
-a {
- text-decoration: none;
-}
-h1,
-h2,
-h3,
-h4,
-h5,
-h6 {
- margin: 0;
-}
-img {
- max-width: 100%;
-}
-ol,
-ul {
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
diff --git a/styles/blocks/_ad.scss b/styles/blocks/_ad.scss
deleted file mode 100644
index 01e7eb2..0000000
--- a/styles/blocks/_ad.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.block-ad {
- background: #e6e6e6;
- border-radius: 0.25rem;
- padding: 1rem;
- margin: 0 auto;
- max-width: 15rem;
-}
-
-/* Ads */
-.carbon-img {
- display: block;
- text-align: center;
-}
-.carbon-poweredby {
- display: block;
- font-size: 0.75rem;
- text-align: right;
-}
-.carbon-text {
- display: block;
- font-size: 0.875rem;
-}
diff --git a/styles/blocks/_browser-frame.scss b/styles/blocks/_browser-frame.scss
deleted file mode 100644
index 476f78c..0000000
--- a/styles/blocks/_browser-frame.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-.demo__live {
- height: 32rem;
- overflow: auto;
-}
-
-.demo__html {
- border-bottom: 1px solid rgba(0, 0, 0, 0.5);
-}
diff --git a/styles/blocks/_card.scss b/styles/blocks/_card.scss
new file mode 100644
index 0000000..a1470e5
--- /dev/null
+++ b/styles/blocks/_card.scss
@@ -0,0 +1,15 @@
+.card__item {
+ background-color: #fff;
+ border-radius: 0.5rem;
+ box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.1);
+ padding: 0.5rem 1rem;
+ text-align: center;
+}
+
+.card__link {
+ color: #6366f1;
+ font-size: 1.25rem;
+ font-weight: 500;
+ text-align: center;
+ text-decoration: none;
+}
diff --git a/styles/blocks/_category.scss b/styles/blocks/_category.scss
new file mode 100644
index 0000000..0f52a88
--- /dev/null
+++ b/styles/blocks/_category.scss
@@ -0,0 +1,30 @@
+:root {
+ --category__name-font-size: 1.5rem;
+ --category__post-num-columns: 1;
+}
+.category__name {
+ font-size: var(--category__name-font-size);
+}
+.category__posts {
+ display: grid;
+ grid-template-columns: repeat(var(--category__post-num-columns), 1fr);
+ column-gap: 1rem;
+ row-gap: 1rem;
+}
+.category__link {
+ background: #4338ca;
+ border-radius: 9999px;
+ color: #fff;
+ display: block;
+ padding: 0.5rem 1rem;
+ text-align: center;
+ text-decoration: none;
+ margin: 1rem auto;
+ width: 12rem;
+}
+@media (min-width: 768px) {
+ :root {
+ --category__name-font-size: 2rem;
+ --category__post-num-columns: 2;
+ }
+}
diff --git a/styles/blocks/_code.scss b/styles/blocks/_code.scss
deleted file mode 100644
index 51ca443..0000000
--- a/styles/blocks/_code.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-.block-code {
- font-size: 0.875rem;
- font-family: 'Source code pro';
- height: auto;
- margin: 0;
- overflow: auto;
- padding: 1em;
-}
diff --git a/styles/blocks/_cover.scss b/styles/blocks/_cover.scss
deleted file mode 100644
index 0e2d30e..0000000
--- a/styles/blocks/_cover.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.block-cover {
- align-items: center;
- color: var(--color-gray-9);
- display: flex;
- flex-direction: column;
- justify-content: flex-start;
- padding: 1rem;
- text-decoration: none;
- width: 7rem;
-}
-.block-cover__name {
- font-weight: normal;
- margin: 0;
- padding-top: 0.5rem;
- text-align: center;
-}
-
-@media (min-width: 768px) {
- .block-cover {
- width: 8rem;
- }
-}
diff --git a/styles/blocks/_css-scan.scss b/styles/blocks/_css-scan.scss
deleted file mode 100644
index 403158d..0000000
--- a/styles/blocks/_css-scan.scss
+++ /dev/null
@@ -1,87 +0,0 @@
-.block-cssscan {
- font-family: -apple-system, system-ui, Roboto, sans-serif;
- -webkit-font-smoothing: antialiased;
- color: #000;
- text-decoration: none;
- display: block;
-}
-
-.block-cssscan__inner {
- max-width: 1024px;
- background: #c2fbd7;
- border-radius: 1rem;
- padding: 2.5rem;
- position: relative;
- overflow: hidden;
- box-shadow: rgba(0, 0, 0, 0.1) 0 1px 2px 0;
- cursor: pointer;
- text-align: left;
-}
-
-.block-cssscan__title {
- font-size: 28px;
- font-weight: bold;
- margin-bottom: 0;
- margin-top: 0;
-}
-
-.block-cssscan__desc {
- opacity: 0.8;
- color: #333;
- margin-top: 1em;
- margin-bottom: 1em;
-}
-
-.block-cssscan__more {
- margin: 0;
- margin-top: 2em;
-}
-
-.block-cssscan__image {
- position: absolute;
- transform: rotate(-7deg);
- transition: all 0.3s;
- top: 14%;
- right: -37%;
- width: 95%;
- height: 95%;
-}
-
-.block-cssscan__inner:hover {
- .block-cssscan__more {
- text-decoration: underline;
- }
-
- .block-cssscan__image {
- transform: scale(1.1) rotate(-7deg);
- top: 10%;
- right: -35%;
- }
-}
-
-@media screen and (min-width: 0px) and (max-width: 1010px) {
- .block-cssscan {
- padding: 0;
- }
-
- .block-cssscan__inner {
- margin-top: 2em;
- min-height: 300px;
- border-radius: 0;
- }
-
- .block-cssscan__image {
- top: initial;
- bottom: -14%;
- width: 45%;
- height: 45%;
- right: -5%;
- }
-
- .block-cssscan__inner:hover .block-cssscan__image {
- top: initial;
- bottom: -10%;
- right: -5%;
- transform: scale(1.1) rotate(-7deg);
- }
-}
diff --git a/styles/blocks/_follow.scss b/styles/blocks/_follow.scss
index 585fe21..511ec28 100644
--- a/styles/blocks/_follow.scss
+++ b/styles/blocks/_follow.scss
@@ -1,11 +1,29 @@
-.block-follow {
- background-color: #0465eb;
+.follow {
+ background: #fff;
border-radius: 0.5rem;
- color: #fff;
+ margin: 2rem auto;
padding: 1rem;
+ position: relative;
+ max-width: 20rem;
- a {
- color: #fff;
- text-decoration: underline;
+ &::after {
+ background-image: linear-gradient(45deg, #9333ea, #ea580c);
+ border-radius: inherit;
+ content: '';
+
+ /* Absolute position */
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ margin: -0.5rem;
+ z-index: -1;
}
}
+
+.follow__link {
+ color: #2563eb;
+ text-decoration: none;
+}
diff --git a/styles/blocks/_footer.scss b/styles/blocks/_footer.scss
index f23f0bc..0514419 100644
--- a/styles/blocks/_footer.scss
+++ b/styles/blocks/_footer.scss
@@ -1,11 +1,46 @@
-/* Footer */
-.block-footer {
- border-top: 1px solid #e1e1e1;
- padding-top: 4rem;
+:root {
+ --footer-num-columns: 1;
}
-.block-footer__copyright {
- color: #afafaf;
- margin: 2rem 0 4rem 0;
- padding: 1rem 0;
- text-align: center;
+
+.footer {
+ display: grid;
+ grid-template-columns: repeat(var(--footer-num-columns), 1fr);
+ column-gap: var(--footer-column-gap, 0);
+ font-size: 0.9rem;
+ row-gap: 1rem;
+ margin: 2rem 0;
+}
+.footer__heading {
+ font-size: 1rem;
+ font-weight: 600;
+ margin-bottom: 0.25rem;
+}
+.footer__list {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+.footer__item {
+ margin-bottom: 0.25rem;
+}
+.footer__link {
+ color: #000;
+ text-decoration: none;
+}
+.footer__link:hover {
+ text-decoration: underline;
+}
+.footer__author {
+ margin-top: 1rem;
+}
+
+@media (min-width: 640px) {
+ :root {
+ --footer-num-columns: 3;
+ }
+}
+@media (min-width: 1024px) {
+ :root {
+ --footer-column-gap: 1rem;
+ }
}
diff --git a/styles/blocks/_header.scss b/styles/blocks/_header.scss
index 24656eb..c771ec8 100644
--- a/styles/blocks/_header.scss
+++ b/styles/blocks/_header.scss
@@ -1,23 +1,25 @@
-.block-header {
- background: #fff;
- border-bottom: 1px solid #e4e4e4;
- position: sticky;
- top: 0;
- z-index: 9999;
-}
-.block-header__inner {
+.header {
align-items: center;
display: flex;
- height: 3rem;
justify-content: space-between;
+ padding: 1rem 0;
}
-.block-header__cta {
+.header__breadcrumb {
align-items: center;
- background-color: var(--mgd-color-primary);
+ display: flex;
+ justify-content: center;
+}
+.header__link {
+ align-items: center;
+ color: #222;
+ display: flex;
+ padding: 0.5rem;
+ text-decoration: none;
+}
+.header__link--primary {
+ background: #6366f1;
border-radius: 9999px;
color: #fff;
- display: flex;
- font-weight: 600;
- height: 2rem;
- padding: 0 1.5rem;
+ padding: 0.5rem 1rem;
+ text-decoration: none;
}
diff --git a/styles/blocks/_hero.scss b/styles/blocks/_hero.scss
new file mode 100644
index 0000000..29474b9
--- /dev/null
+++ b/styles/blocks/_hero.scss
@@ -0,0 +1,31 @@
+:root {
+ --hero-margin: 2rem;
+ --hero-width: 100%;
+ --hero__heading-font-size: 2rem;
+}
+.hero {
+ margin: var(--hero-margin) auto;
+ text-align: center;
+ width: var(--hero-width);
+}
+.hero__heading {
+ font-size: var(--hero__heading-font-size);
+ font-weight: 700;
+ line-height: 1.25;
+ margin: 2rem auto;
+ text-align: center;
+}
+.hero__button {
+ background: #6366f1;
+ border-radius: 9999px;
+ color: #fff;
+ padding: 1rem 2rem;
+ text-decoration: none;
+}
+@media (min-width: 768px) {
+ :root {
+ --hero-margin: 3rem;
+ --hero-width: 75%;
+ --hero__heading-font-size: 2.5rem;
+ }
+}
diff --git a/styles/blocks/_layout.scss b/styles/blocks/_layout.scss
deleted file mode 100644
index 0171c00..0000000
--- a/styles/blocks/_layout.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-.block-container {
- margin-left: auto;
- margin-right: auto;
- max-width: 64rem;
-}
-.block-hero {
- text-align: center;
-}
-.block-hero__heading--secondary {
- color: #808080;
- font-size: 1.25rem;
- font-weight: 600;
-}
diff --git a/styles/blocks/_nav.scss b/styles/blocks/_nav.scss
new file mode 100644
index 0000000..3151688
--- /dev/null
+++ b/styles/blocks/_nav.scss
@@ -0,0 +1,41 @@
+:root {
+ --nav-flex-direction: column;
+ --nav__item-margin-bottom: 1rem;
+ --nav__item--next-margin-left: 0;
+ --nav__item--prev-margin-right: 0;
+}
+.nav {
+ display: flex;
+ flex-direction: var(--nav-flex-direction);
+ justify-content: space-between;
+}
+.nav__item {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+
+ background: #60a5fa;
+ border-radius: 0.25rem;
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
+ color: #f9fafb;
+ margin-bottom: var(--nav__item-margin-bottom);
+ padding: 0.25rem 1rem;
+
+ text-decoration: none;
+}
+.nav__item--next {
+ margin-left: var(--nav__item--next-margin-left);
+}
+.nav__item--prev {
+ margin-right: var(--nav__item--prev-margin-right);
+}
+
+@media (min-width: 1024px) {
+ :root {
+ --nav-flex-direction: row;
+ --nav__item-margin-bottom: 0;
+ --nav__item--next-margin-left: 1rem;
+ --nav__item--prev-margin-right: 1rem;
+ }
+}
diff --git a/styles/blocks/_post.scss b/styles/blocks/_post.scss
new file mode 100644
index 0000000..78b465f
--- /dev/null
+++ b/styles/blocks/_post.scss
@@ -0,0 +1,127 @@
+:root {
+ --post__heading-font-size: 2rem;
+ --post__heading-line-height: 1.25;
+ --post__content-heading-line-height: 1.25;
+}
+
+.post {
+ background-color: #fff;
+ border-radius: 0.5rem;
+ box-shadow: 0 0 1.5rem rgba(0, 0, 0, 0.1);
+ margin: 2rem 0 2rem 0;
+ padding: 2rem 1rem 1rem 1rem;
+ position: relative;
+}
+
+.post__heading {
+ color: #6366f1;
+ font-size: var(--post__heading-font-size);
+ font-weight: 700;
+ line-height: var(--post__heading-line-height);
+ text-align: center;
+}
+
+.post__content {
+ line-height: 1.5;
+
+ a {
+ color: #6366f1;
+ text-decoration: none;
+ }
+ a:hover {
+ text-decoration: underline;
+ }
+
+ blockquote {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-radius: 0.5rem;
+ margin: 1rem 0;
+ padding: 0.25rem 1rem;
+ }
+
+ h1 {
+ font-size: 2.5rem;
+ font-weight: 600;
+ line-height: var(--post__content-heading-line-height);
+ }
+
+ h2 {
+ font-size: 2rem;
+ font-weight: 600;
+ line-height: var(--post__content-heading-line-height);
+ }
+
+ hr {
+ background: rgba(0, 0, 0, 0.1);
+ height: 1px;
+ border: none;
+ }
+
+ img {
+ max-width: 100%;
+ }
+
+ ol {
+ counter-reset: ol-step-counter;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ }
+
+ ol li {
+ counter-increment: ol-step-counter;
+ padding-bottom: 0.25rem;
+ padding-left: 2rem;
+ }
+ ol li::before {
+ background-color: #e5e7eb;
+ border-radius: 50%;
+ content: counter(ol-step-counter);
+ align-items: center;
+ display: inline-flex;
+ justify-content: center;
+ position: absolute;
+ margin-left: -2rem;
+ height: 1.5rem;
+ width: 1.5rem;
+ }
+
+ p {
+ margin: 1rem 0;
+ }
+
+ table {
+ border-collapse: collapse;
+ width: 100%;
+ }
+
+ td,
+ th {
+ padding: 0.5rem;
+ }
+
+ th {
+ font-weight: normal;
+ text-align: left;
+ }
+
+ thead {
+ background: #d1d5db;
+ }
+
+ tr {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.2);
+ }
+
+ ul {
+ margin: 0;
+ padding: 0 0 0 1.5rem;
+ }
+}
+
+@media (min-width: 1024px) {
+ :root {
+ --post__heading-font-size: 2.5rem;
+ --post__content-heading-line-height: 1.5;
+ }
+}
diff --git a/styles/index.scss b/styles/index.scss
index 752d1cd..ae62958 100644
--- a/styles/index.scss
+++ b/styles/index.scss
@@ -1,35 +1,13 @@
-@import './reset';
+@import './common';
-// Blocks
-@import 'blocks/ad';
-@import 'blocks/browser-frame';
-@import 'blocks/code';
-@import 'blocks/cover';
-@import 'blocks/css-scan';
-@import 'blocks/follow';
-@import 'blocks/footer';
-@import 'blocks/header';
-@import 'blocks/layout';
+@import './blocks/card';
+@import './blocks/category';
+@import './blocks/hero';
+@import './blocks/follow';
+@import './blocks/footer';
+@import './blocks/header';
+@import './blocks/nav';
+@import './blocks/post';
-// Pages
-@import 'pages/home';
-
-// Patterns
-@import 'patterns/concave-corners';
-@import 'patterns/dropcap';
-@import 'patterns/dropdown';
-@import 'patterns/floating-label';
-@import 'patterns/folder-structure';
-@import 'patterns/inverted-corners';
-@import 'patterns/layered-card';
-@import 'patterns/masonry-grid';
-@import 'patterns/mega-menu';
-@import 'patterns/menu';
-@import 'patterns/nested-dropdowns';
-@import 'patterns/price-tag';
-@import 'patterns/radio-button-group';
-@import 'patterns/star';
-@import 'patterns/three-dimensions-card';
-@import 'patterns/tooltip';
-@import 'patterns/tree-diagram';
-@import 'patterns/zigzag-timeline';
+// Themes
+@import './themes/dracula.scss';
diff --git a/styles/pages/_home.scss b/styles/pages/_home.scss
deleted file mode 100644
index 76a3429..0000000
--- a/styles/pages/_home.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-.page-home__hero {
- text-align: center;
-}
-
-.page-home__category {
- background: #fff;
- color: #808080;
- display: grid;
- grid-template-columns: 1fr auto 1fr;
- grid-gap: 1rem;
- margin: 2rem 0;
- position: sticky;
- text-align: center;
- top: 3rem;
- z-index: 1;
-}
-
-.page-home__category::before,
-.page-home__category::after {
- align-self: center;
- border-top: 1px solid #e6e6e6;
- content: '';
-}
-
-.page-home__collection {
- display: flex;
- flex-wrap: wrap;
-}
diff --git a/styles/patterns/_concave-corners.scss b/styles/patterns/_concave-corners.scss
deleted file mode 100644
index 36aa876..0000000
--- a/styles/patterns/_concave-corners.scss
+++ /dev/null
@@ -1,61 +0,0 @@
-:root {
- --concave-corners-background: rgba(0, 0, 0, 0.3);
- --concave-corners-size: 1rem;
-}
-
-.concave-corners {
- background-color: var(--concave-corners-background);
-
- /* Used to position the corners */
- position: relative;
-
- /* Misc */
- height: 100%;
-}
-
-.concave-corners__corner {
- /* Absolute position */
- position: absolute;
-
- /* Size */
- height: var(--concave-corners-size);
- width: var(--concave-corners-size);
-
- background: #fff;
-}
-
-.concave-corners__corner--tl {
- /* Position */
- left: 0;
- top: 0;
-
- /* Border radius */
- border-radius: 0 0 var(--concave-corners-size) 0;
-}
-
-.concave-corners__corner--tr {
- /* Position */
- right: 0;
- top: 0;
-
- /* Border radius */
- border-radius: 0 0 0 var(--concave-corners-size);
-}
-
-.concave-corners__corner--bl {
- /* Position */
- bottom: 0;
- left: 0;
-
- /* Border radius */
- border-radius: 0 var(--concave-corners-size) 0 0;
-}
-
-.concave-corners__corner--br {
- /* Position */
- bottom: 0;
- right: 0;
-
- /* Border radius */
- border-radius: var(--concave-corners-size) 0 0 0;
-}
diff --git a/styles/patterns/_dropcap.scss b/styles/patterns/_dropcap.scss
deleted file mode 100644
index 979928a..0000000
--- a/styles/patterns/_dropcap.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.p-drop-cap:first-letter {
- border: 2px solid rgba(0, 0, 0, 0.3);
- float: left;
- font-size: 64px;
- font-weight: 700;
- line-height: 1;
- margin: 0 8px 0 0;
- padding: 0 8px;
-}
diff --git a/styles/patterns/_dropdown.scss b/styles/patterns/_dropdown.scss
deleted file mode 100644
index 955fb6d..0000000
--- a/styles/patterns/_dropdown.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.p-dropdown-content {
- display: none;
-}
-
-.p-dropdown:hover .p-dropdown-content {
- display: block;
-}
diff --git a/styles/patterns/_floating-label.scss b/styles/patterns/_floating-label.scss
deleted file mode 100644
index b9bf8e4..0000000
--- a/styles/patterns/_floating-label.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-.p-floating-container label {
- opacity: 0;
-}
-
-.p-floating-container input:not(:placeholder-shown) + label {
- background: #fff;
- transform: translate(0, -50%);
- opacity: 1;
-}
diff --git a/styles/patterns/_folder-structure.scss b/styles/patterns/_folder-structure.scss
deleted file mode 100644
index ef217f3..0000000
--- a/styles/patterns/_folder-structure.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-:root {
- --folder-structure-item-height: 1rem;
- --folder-structure-item-margin-left: 2rem;
- --folder-structure-item-padding-top: 1rem;
-}
-
-.folder-structure ul {
- /* Reset */
- list-style-type: none;
- margin: 0;
-}
-
-.folder-structure li {
- padding: var(--folder-structure-item-padding-top) 0rem 0rem 0rem;
- position: relative;
-}
-
-.folder-structure li::before {
- border-left: 1px solid rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- left: 0;
- position: absolute;
- top: 0;
- transform: translate(calc(-1 * var(--folder-structure-item-margin-left)), 0);
-
- /* Size */
- height: 100%;
-}
-
-.folder-structure li::after {
- border-bottom: 1px solid rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- left: 0;
- position: absolute;
- top: calc(var(--folder-structure-item-padding-top) + var(--folder-structure-item-height) / 2);
- transform: translate(-100%, 0);
-
- /* Size */
- width: var(--folder-structure-item-margin-left);
-}
-
-/* Remove the border from the last item */
-.folder-structure li:last-child::before {
- height: calc(var(--folder-structure-item-padding-top) + var(--folder-structure-item-height) / 2);
-}
diff --git a/styles/patterns/_inverted-corners.scss b/styles/patterns/_inverted-corners.scss
deleted file mode 100644
index 830d8c2..0000000
--- a/styles/patterns/_inverted-corners.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-:root {
- --inverted-corners-background: #52525b;
- --inverted-corners-size: 2rem;
-}
-
-.inverted-corners {
- background-color: var(--inverted-corners-background);
-
- /* Used to position the corner */
- position: relative;
-
- /* Misc */
- height: 100%;
-}
-
-.inverted-corners::before {
- content: '';
-
- /* Absolute position */
- bottom: calc(-2 * var(--inverted-corners-size));
- left: 0;
- position: absolute;
-
- /* Size */
- height: calc(2 * var(--inverted-corners-size));
- width: var(--inverted-corners-size);
-
- /* Border */
- background-color: transparent;
- border-top-left-radius: var(--inverted-corners-size);
- box-shadow: var(--inverted-corners-background) 0px calc(-1 * var(--inverted-corners-size)) 0px 0px;
-}
-
-/* Use case */
-.inverted-corners--speech {
- /* Border radius */
- border-bottom-right-radius: var(--inverted-corners-size);
- border-top-left-radius: var(--inverted-corners-size);
- border-top-right-radius: var(--inverted-corners-size);
-
- /* Center the content */
- align-items: center;
- display: flex;
- justify-content: center;
-
- /* Misc */
- color: #fff;
-}
diff --git a/styles/patterns/_layered-card.scss b/styles/patterns/_layered-card.scss
deleted file mode 100644
index 1dd83e4..0000000
--- a/styles/patterns/_layered-card.scss
+++ /dev/null
@@ -1,21 +0,0 @@
-.layered-card {
- position: relative;
-}
-
-.layered-card::before {
- background: rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- top: 0;
- left: 0;
- position: absolute;
- transform: translate(1rem, 1rem);
-
- /* Size */
- height: 100%;
- width: 100%;
-
- /* Display under the main content */
- z-index: -1;
-}
diff --git a/styles/patterns/_masonry-grid.scss b/styles/patterns/_masonry-grid.scss
deleted file mode 100644
index ced6020..0000000
--- a/styles/patterns/_masonry-grid.scss
+++ /dev/null
@@ -1,15 +0,0 @@
-.masonry-grid {
- column-count: 3;
- column-gap: 1rem;
-
- /* Misc */
- width: 100%;
-}
-
-.masonry-grid__item {
- /* Prevent a column from breaking into multiple columns */
- break-inside: avoid;
-
- /* Misc */
- margin-bottom: 1rem;
-}
diff --git a/styles/patterns/_mega-menu.scss b/styles/patterns/_mega-menu.scss
deleted file mode 100644
index f7f4c56..0000000
--- a/styles/patterns/_mega-menu.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-.p-mega-menu-container {
- position: relative;
-}
-.p-mega-menu-content {
- background: #fff;
- border: 1px solid rgba(0, 0, 0, 0.3);
- display: none;
- left: 0px;
- margin-top: -1px;
- position: absolute;
- top: 100%;
- width: 100%;
- z-index: 9999;
-}
-.p-mega-menu-trigger:hover .p-mega-menu-content {
- display: block;
-}
diff --git a/styles/patterns/_menu.scss b/styles/patterns/_menu.scss
deleted file mode 100644
index 188aa84..0000000
--- a/styles/patterns/_menu.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.p-menu-item:hover {
- background-color: rgba(0, 0, 0, 0.1);
-}
diff --git a/styles/patterns/_nested-dropdowns.scss b/styles/patterns/_nested-dropdowns.scss
deleted file mode 100644
index 7e43fbd..0000000
--- a/styles/patterns/_nested-dropdowns.scss
+++ /dev/null
@@ -1,38 +0,0 @@
-.p-nested-dropdowns {
- border: 1px solid rgba(0, 0, 0, 0.3);
- display: flex;
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-
-.p-nested-dropdowns li {
- padding: 8px;
- position: relative;
-}
-
-.p-nested-dropdowns ul {
- border: 1px solid rgba(0, 0, 0, 0.3);
- display: none;
- left: 0;
- list-style-type: none;
- margin: 0;
- padding: 0;
- position: absolute;
- top: 100%;
- width: 200px;
-}
-
-.p-nested-dropdowns ul ul {
- left: 100%;
- position: absolute;
- top: 0;
-}
-
-.p-nested-dropdowns li:hover {
- background-color: rgba(0, 0, 0, 0.1);
-}
-
-.p-nested-dropdowns li:hover > ul {
- display: block;
-}
diff --git a/styles/patterns/_price-tag.scss b/styles/patterns/_price-tag.scss
deleted file mode 100644
index 7416226..0000000
--- a/styles/patterns/_price-tag.scss
+++ /dev/null
@@ -1,58 +0,0 @@
-:root {
- --price-tag-background: rgba(0, 0, 0, 0.3);
- --price-tag-height: 2rem;
-}
-
-.price-tag {
- background: var(--price-tag-background);
- color: #fff;
-
- /* Center the price */
- align-items: center;
- display: flex;
- justify-content: center;
-
- /* Used to position the triangle */
- position: relative;
-
- /* Size */
- height: var(--price-tag-height);
-
- /* Spacing */
- padding: 0.25rem 0.5rem;
-}
-
-/* The triangle */
-.price-tag::before {
- content: '';
-
- border-color: transparent var(--price-tag-background) transparent transparent;
- border-style: solid;
- border-width: calc(var(--price-tag-height) / 2) calc(var(--price-tag-height) / 2) calc(var(--price-tag-height) / 2)
- 0rem;
-
- /* Position */
- left: 0px;
- position: absolute;
- top: 0px;
- transform: translate(-100%, 0px);
-}
-
-/* The dot */
-.price-tag::after {
- content: '';
-
- /* Make it like a cirle */
- background: #fff;
- border-radius: 9999rem;
-
- /* Position */
- left: 0;
- position: absolute;
- top: 50%;
- transform: translate(-0.5rem, -50%);
-
- /* Size */
- height: 0.5rem;
- width: 0.5rem;
-}
diff --git a/styles/patterns/_radio-button-group.scss b/styles/patterns/_radio-button-group.scss
deleted file mode 100644
index a617574..0000000
--- a/styles/patterns/_radio-button-group.scss
+++ /dev/null
@@ -1,6 +0,0 @@
-.p-radio-button-group label {
- border-right: 1px solid rgba(0, 0, 0, 0.3);
-}
-.p-radio-button-group label:last-child {
- border-right-color: transparent;
-}
diff --git a/styles/patterns/_star.scss b/styles/patterns/_star.scss
deleted file mode 100644
index 049148d..0000000
--- a/styles/patterns/_star.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-.p-rating {
- align-items: center;
- display: flex;
- font-size: 32px;
- justify-content: center;
- flex-direction: row-reverse;
-}
-
-.p-rating .p-rating-star:hover,
-.p-rating .p-rating-star:hover ~ .p-rating-star {
- color: transparent;
-}
-
-.p-rating .p-rating-star:hover:before,
-.p-rating .p-rating-star:hover ~ .p-rating-star:before {
- color: #00449e;
- content: '\2605';
- left: 0;
- position: absolute;
-}
-
-.p-rating-star {
- background-color: transparent;
- border: transparent;
- margin: 0 2px;
- padding: 0;
- position: relative;
-}
diff --git a/styles/patterns/_three-dimensions-card.scss b/styles/patterns/_three-dimensions-card.scss
deleted file mode 100644
index 914c135..0000000
--- a/styles/patterns/_three-dimensions-card.scss
+++ /dev/null
@@ -1,41 +0,0 @@
-:root {
- --three-dimensions-card-left-side-width: 1rem;
-}
-
-.three-dimensions-card {
- position: relative;
-}
-
-/* The left side */
-.three-dimensions-card::before {
- background: rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- top: var(--three-dimensions-card-left-side-width);
- left: 0px;
- position: absolute;
- transform: translate(-100%, 0) skewY(-45deg);
- transform-origin: left top;
-
- /* Size */
- height: 100%;
- width: var(--three-dimensions-card-left-side-width);
-}
-
-/* The bottom side */
-.three-dimensions-card::after {
- background: rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- bottom: 0px;
- left: 0px;
- position: absolute;
- transform: translate(0, 100%) skewX(-45deg);
- transform-origin: left top;
-
- /* Size */
- height: var(--three-dimensions-card-left-side-width);
- width: 100%;
-}
diff --git a/styles/patterns/_tooltip.scss b/styles/patterns/_tooltip.scss
deleted file mode 100644
index aca9649..0000000
--- a/styles/patterns/_tooltip.scss
+++ /dev/null
@@ -1,32 +0,0 @@
-.p-tooltip {
- position: relative;
-}
-.p-tooltip:hover .p-tooltip-arrow,
-.p-tooltip:hover .p-tooltip-content {
- opacity: 1;
- pointer-events: initial;
-}
-.p-tooltip-arrow {
- border: 8px solid transparent;
- border-top-color: #00439e;
- bottom: 100%;
- height: 0;
- left: 50%;
- opacity: 0;
- pointer-events: none;
- position: absolute;
- transform: translate(-50%, 8px);
- width: 0;
- z-index: 10;
-}
-.p-tooltip-content {
- background-color: #00439e;
- border-radius: 2px;
- bottom: 100%;
- left: 50%;
- opacity: 0;
- pointer-events: none;
- position: absolute;
- transform: translate(-50%, -8px);
- z-index: 10;
-}
diff --git a/styles/patterns/_tree-diagram.scss b/styles/patterns/_tree-diagram.scss
deleted file mode 100644
index 9aadbae..0000000
--- a/styles/patterns/_tree-diagram.scss
+++ /dev/null
@@ -1,62 +0,0 @@
-.tree-diagram ul {
- display: flex;
- position: relative;
-
- /* Reset */
- list-style-type: none;
- margin: 0;
- padding: 1rem 0.5rem 0rem 0.5rem;
-}
-
-.tree-diagram ul ul::before {
- border-right: 1px solid rgba(0, 0, 0, 0.3);
- content: '';
- height: 1rem;
- position: absolute;
- top: 0;
- right: 50%;
- width: 50%;
-}
-
-.tree-diagram li {
- padding: 1rem 0.5rem 0rem 0.5rem;
- position: relative;
-
- /* Center the content */
- align-items: center;
- display: flex;
- flex-direction: column;
-}
-
-.tree-diagram li::before {
- border-right: 1px solid rgba(0, 0, 0, 0.3);
- border-top: 1px solid rgba(0, 0, 0, 0.3);
- content: '';
- height: 1rem;
-
- /* Position */
- position: absolute;
- top: 0;
- right: 50%;
- width: 50%;
-}
-
-.tree-diagram li::after {
- border-top: 1px solid rgba(0, 0, 0, 0.3);
- content: '';
-
- /* Position */
- position: absolute;
- top: 0;
- right: 0;
- width: 50%;
-}
-
-.tree-diagram li:first-child::before,
-.tree-diagram li:last-child::after {
- border-top: none;
-}
-
-li.tree-diagram__root::before {
- border-right: none;
-}
diff --git a/styles/patterns/_zigzag-timeline.scss b/styles/patterns/_zigzag-timeline.scss
deleted file mode 100644
index 60d979f..0000000
--- a/styles/patterns/_zigzag-timeline.scss
+++ /dev/null
@@ -1,42 +0,0 @@
-.zigzag-timeline__item {
- /* Used to position the milestone */
- position: relative;
-
- /* Border */
- border-bottom: 1px solid #71717a;
-
- /* Take full width */
- width: 100%;
-}
-
-.zigzag-timeline__milestone {
- /* Absolute position */
- position: absolute;
- top: 50%;
-
- /* Circle it */
- border-radius: 50%;
- height: 2rem;
- width: 2rem;
-
- /* Misc */
- background: #71717a;
-}
-
-/* Styles for even items */
-.zigzag-timeline__item:nth-child(2n) {
- border-left: 1px solid #71717a;
-}
-.zigzag-timeline__item:nth-child(2n) .zigzag-timeline__milestone {
- left: 0;
- transform: translate(-50%, -50%);
-}
-
-/* Styles for odd items */
-.zigzag-timeline__item:nth-child(2n + 1) {
- border-right: 1px solid #71717a;
-}
-.zigzag-timeline__item:nth-child(2n + 1) .zigzag-timeline__milestone {
- right: 0;
- transform: translate(50%, -50%);
-}
diff --git a/styles/themes/_dracula.scss b/styles/themes/_dracula.scss
new file mode 100644
index 0000000..fca1d8a
--- /dev/null
+++ b/styles/themes/_dracula.scss
@@ -0,0 +1,124 @@
+// https://github.com/PrismJS/prism-themes/blob/master/themes/prism-dracula.css
+
+/**
+ * Dracula Theme originally by Zeno Rocha [@zenorocha]
+ * https://draculatheme.com/
+ *
+ * Ported for PrismJS by Albert Vallverdu [@byverdu]
+ */
+
+code[class*='language-'],
+pre[class*='language-'] {
+ color: #f8f8f2;
+ background: none;
+ text-shadow: 0 1px rgba(0, 0, 0, 0.3);
+ font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+ text-align: left;
+ white-space: pre;
+ word-spacing: normal;
+ word-break: normal;
+ word-wrap: normal;
+ line-height: 1.5;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+/* Code blocks */
+pre[class*='language-'] {
+ padding: 1em;
+ margin: 0.5em 0;
+ overflow: auto;
+ border-radius: 0.3em;
+}
+
+:not(pre) > code[class*='language-'],
+pre[class*='language-'] {
+ background: #282a36;
+}
+
+/* Inline code */
+:not(pre) > code[class*='language-'] {
+ padding: 0.1em;
+ border-radius: 0.3em;
+ white-space: normal;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+ color: #6272a4;
+}
+
+.token.punctuation {
+ color: #f8f8f2;
+}
+
+.namespace {
+ opacity: 0.7;
+}
+
+.token.property,
+.token.tag,
+.token.constant,
+.token.symbol,
+.token.deleted {
+ color: #ff79c6;
+}
+
+.token.boolean,
+.token.number {
+ color: #bd93f9;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+ color: #50fa7b;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string,
+.token.variable {
+ color: #f8f8f2;
+}
+
+.token.atrule,
+.token.attr-value,
+.token.function,
+.token.class-name {
+ color: #f1fa8c;
+}
+
+.token.keyword {
+ color: #8be9fd;
+}
+
+.token.regex,
+.token.important {
+ color: #ffb86c;
+}
+
+.token.important,
+.token.bold {
+ font-weight: bold;
+}
+
+.token.italic {
+ font-style: italic;
+}
+
+.token.entity {
+ cursor: help;
+}
diff --git a/tsconfig.json b/tsconfig.json
deleted file mode 100644
index b9fc7d4..0000000
--- a/tsconfig.json
+++ /dev/null
@@ -1,23 +0,0 @@
-{
- "compilerOptions": {
- "outDir": "./dist/",
- "esModuleInterop": true,
- "sourceMap": true,
- "noImplicitAny": true,
- "module": "esnext",
- "moduleResolution": "node",
- "target": "esnext",
- "jsx": "preserve",
- "lib": ["dom", "dom.iterable", "esnext"],
- "allowJs": true,
- "skipLibCheck": true,
- "strict": false,
- "forceConsistentCasingInFileNames": true,
- "noEmit": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- "incremental": true
- },
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
- "exclude": ["bin", "node_modules"]
-}
diff --git a/tslint.json b/tslint.json
deleted file mode 100644
index 7240ac9..0000000
--- a/tslint.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "defaultSeverity": "error",
- "extends": ["tslint:latest", "tslint-react"],
- "jsRules": {},
- "rules": {
- "interface-name": false,
- "jsx-no-multiline-js": false,
- "quotemark": ["single"]
- },
- "rulesDirectory": []
-}
diff --git a/utils/random.ts b/utils/random.ts
deleted file mode 100644
index a2a4ce6..0000000
--- a/utils/random.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const random = (min: number, max: number) => min + Math.round(Math.random() * (max - min));
diff --git a/utils/randomFromArray.ts b/utils/randomFromArray.ts
deleted file mode 100644
index 2fcf84e..0000000
--- a/utils/randomFromArray.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export function randomFromArray(array: T[]): T {
- return array[Math.floor(Math.random() * array.length)];
-}
diff --git a/utils/randomIterms.ts b/utils/randomIterms.ts
deleted file mode 100644
index b7e0c30..0000000
--- a/utils/randomIterms.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-type Tuple = [number, T[]];
-
-export function randomItems(arr: T[], count: number): T[] {
- const result = arr.concat().reduce(
- (p, _, __, arr) => {
- const [a, b] = p;
- return a < count ? [a + 1, b.concat(arr.splice((Math.random() * arr.length) | 0, 1))] : p;
- },
- [0, []] as Tuple
- );
- return (result as Tuple)[1];
-}
diff --git a/utils/slug.ts b/utils/slug.ts
deleted file mode 100644
index 1cb5e26..0000000
--- a/utils/slug.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const slug = (item: string) => item.toLowerCase().split(' ').join('-');