diff options
Diffstat (limited to 'source/_assets')
| -rw-r--r-- | source/_assets/js/components/Search.vue | 133 | ||||
| -rw-r--r-- | source/_assets/js/main.js | 30 | ||||
| -rw-r--r-- | source/_assets/sass/_base.scss | 147 | ||||
| -rw-r--r-- | source/_assets/sass/_blog.scss | 1 | ||||
| -rw-r--r-- | source/_assets/sass/_mailchimp.scss | 78 | ||||
| -rw-r--r-- | source/_assets/sass/_navigation.scss | 17 | ||||
| -rw-r--r-- | source/_assets/sass/main.scss | 13 |
7 files changed, 419 insertions, 0 deletions
diff --git a/source/_assets/js/components/Search.vue b/source/_assets/js/components/Search.vue new file mode 100644 index 0000000..c5715a9 --- /dev/null +++ b/source/_assets/js/components/Search.vue @@ -0,0 +1,133 @@ +<template> + <div class="flex flex-1 justify-end items-center text-right px-4"> + <div + class="absolute md:relative w-full justify-end bg-white left-0 top-0 z-10 mt-7 md:mt-0 px-4 md:px-0" + :class="{'hidden md:flex': ! searching}" + > + <label for="search" class="hidden">Search</label> + + <input + id="search" + v-model="query" + ref="search" + class="transition-fast relative block h-10 w-full lg:w-1/2 lg:focus:w-3/4 bg-gray-100 border border-gray-500 focus:border-blue-400 outline-none cursor-pointer text-gray-700 px-4 pb-0 pt-px" + :class="{ 'transition-border': query }" + autocomplete="off" + name="search" + placeholder="Search" + type="text" + @keyup.esc="reset" + @blur="reset" + > + + <button + v-if="query || searching" + class="absolute top-0 right-0 leading-snug font-400 text-3xl text-blue-500 hover:text-blue-600 focus:outline-none pr-7 md:pr-3" + @click="reset" + >×</button> + + <transition name="fade"> + <div v-if="query" class="absolute left-0 right-0 md:inset-auto w-full lg:w-3/4 text-left mb-4 md:mt-10"> + <div class="flex flex-col bg-white border border-b-0 border-t-0 border-blue-400 rounded-b-lg shadow-lg mx-4 md:mx-0"> + <a + v-for="(result, index) in results" + class="bg-white hover:bg-blue-100 border-b border-blue-400 text-xl cursor-pointer p-4" + :class="{ 'rounded-b-lg' : (index === results.length - 1) }" + :href="result.link" + :title="result.title" + :key="result.link" + @mousedown.prevent + > + {{ result.title }} + + <span class="block font-normal text-gray-700 text-sm my-1" v-html="result.snippet"></span> + </a> + + <div + v-if="! results.length" + class="bg-white w-full hover:bg-blue-100 border-b border-blue-400 rounded-b-lg shadow cursor-pointer p-4" + > + <p class="my-0">No results for <strong>{{ query }}</strong></p> + </div> + </div> + </div> + </transition> + </div> + + <button + title="Start searching" + type="button" + class="flex md:hidden bg-gray-100 hover:bg-blue-100 justify-center items-center border border-gray-500 rounded-full focus:outline-none h-10 px-3" + @click.prevent="showInput" + > + <img src="/assets/img/magnifying-glass.svg" alt="search icon" class="h-4 w-4 max-w-none"> + </button> + </div> +</template> + +<script> +export default { + data() { + return { + fuse: null, + searching: false, + query: '', + }; + }, + computed: { + results() { + return this.query ? this.fuse.search(this.query) : []; + }, + }, + methods: { + showInput() { + this.searching = true; + this.$nextTick(() => { + this.$refs.search.focus(); + }) + }, + reset() { + this.query = ''; + this.searching = false; + }, + }, + created() { + axios('/index.json').then(response => { + this.fuse = new fuse(response.data, { + minMatchCharLength: 6, + keys: ['title', 'snippet', 'categories'], + }); + }); + }, +}; +</script> + +<style> +input[name='search'] { + background-image: url('/assets/img/magnifying-glass.svg'); + background-position: 0.8em; + background-repeat: no-repeat; + border-radius: 25px; + text-indent: 1.2em; +} + +input[name='search'].transition-border { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-top-left-radius: .5rem; + border-top-right-radius: .5rem; +} + +.fade-enter-active { + transition: opacity .5s; +} + +.fade-leave-active { + transition: opacity 0s; +} + +.fade-enter, +.fade-leave-to { + opacity: 0; +} +</style> diff --git a/source/_assets/js/main.js b/source/_assets/js/main.js new file mode 100644 index 0000000..d3a9909 --- /dev/null +++ b/source/_assets/js/main.js @@ -0,0 +1,30 @@ +window.axios = require('axios'); +window.fuse = require('fuse.js'); +window.Vue = require('vue'); + +import Search from './components/Search.vue'; +import hljs from 'highlight.js/lib/highlight'; + +// Syntax highlighting +hljs.registerLanguage('bash', require('highlight.js/lib/languages/bash')); +hljs.registerLanguage('css', require('highlight.js/lib/languages/css')); +hljs.registerLanguage('html', require('highlight.js/lib/languages/xml')); +hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript')); +hljs.registerLanguage('json', require('highlight.js/lib/languages/json')); +hljs.registerLanguage('markdown', require('highlight.js/lib/languages/markdown')); +hljs.registerLanguage('php', require('highlight.js/lib/languages/php')); +hljs.registerLanguage('scss', require('highlight.js/lib/languages/scss')); +hljs.registerLanguage('yaml', require('highlight.js/lib/languages/yaml')); + +document.querySelectorAll('pre code').forEach((block) => { + hljs.highlightBlock(block); +}); + +Vue.config.productionTip = false; + +new Vue({ + components: { + Search, + }, +}).$mount('#vue-search'); + diff --git a/source/_assets/sass/_base.scss b/source/_assets/sass/_base.scss new file mode 100644 index 0000000..8dc4fd8 --- /dev/null +++ b/source/_assets/sass/_base.scss @@ -0,0 +1,147 @@ +body { + font-size: 17px; +} + +a { + @apply .font-semibold; + @apply .no-underline; + @apply .text-blue-600; + + &:hover { + @apply .text-blue-800; + } +} + +blockquote { + @apply .border-blue-400; + @apply .border-l-4; + @apply .font-normal; + @apply .italic; + @apply .my-8; + @apply .pl-6; + @apply .text-gray-800; + @apply .text-lg; +} + +code { + @apply .bg-gray-300; + @apply .px-2; + @apply .py-px; + @apply .rounded; + @apply .text-sm; +} + +code.hljs { + @apply .bg-transparent; + @apply .p-0; + + .hljs-comment, + .hljs-keyword, + .hljs-meta { + @apply .font-normal; + @apply .not-italic; + } +} + +h1, +h2, +h3, +h4, +h5, +h6 { + @apply .leading-tight; + @apply .mb-4; + @apply .mt-8; + @apply .text-gray-900; + + &:first-child { + @apply .mt-0; + } +} + +h1 { + @apply .font-extrabold; + @apply .text-5xl; +} + +h2 { + @apply .font-bold; + @apply .text-4xl; +} + +h3 { + @apply .font-bold; + @apply .text-3xl; +} + +h4 { + @apply .font-normal; + @apply .text-2xl; +} + +h5 { + @apply .font-normal; + @apply .text-xl; +} + +h6 { + @apply .font-light; + @apply .text-lg; +} + +hr { + @apply .border-b; + @apply .border-blue-200; + @apply .my-12; + @apply .rounded-full; +} + +li { + ul, + ol { + @apply .my-0; + } +} + +ol, +ul { + @apply .my-4; +} + +ol { + @apply .list-decimal; +} + +ul { + @apply .list-disc; +} + +p { + @apply .my-3; + + @screen md { + @apply .my-6; + } +} + +pre { + @apply .bg-gray-200; + @apply .leading-loose; + @apply .my-6; + @apply .overflow-x-auto; + @apply .p-4; + @apply .rounded; + @apply .shadow; + @apply .text-base; + + code { + @apply .bg-transparent; + @apply .block; + @apply .p-0; + } +} + +::selection { + @apply .bg-blue-500; + @apply .text-white; +} diff --git a/source/_assets/sass/_blog.scss b/source/_assets/sass/_blog.scss new file mode 100644 index 0000000..911af1d --- /dev/null +++ b/source/_assets/sass/_blog.scss @@ -0,0 +1 @@ +// Your custom blog styles here diff --git a/source/_assets/sass/_mailchimp.scss b/source/_assets/sass/_mailchimp.scss new file mode 100644 index 0000000..0993e0a --- /dev/null +++ b/source/_assets/sass/_mailchimp.scss @@ -0,0 +1,78 @@ +#mc_embed_signup { + @apply .w-full; + + // increase selector specificity for + // in-line errors + div.mc-field-group { + > div.mce_inline_error { + @apply .bg-transparent; + @apply .float-left; + @apply .font-semibold; + @apply .p-0; + @apply .text-gray-800; + + clear: both; + } + } + + @screen md { + @apply .w-2/3; + } + + @screen lg { + @apply .w-1/2; + } +} + +#mc_embed_signup_scroll { + > h2:first-of-type { + @apply .block; + @apply .mb-6; + @apply .text-2xl; + @apply .text-center; + @apply .text-gray-900; + } +} + +.mc-field-group { + input { + @apply .float-left; + @apply .leading-normal; + @apply .mb-6; + @apply .outline-none; + @apply .px-4; + @apply .py-2; + @apply .rounded-l; + @apply .w-2/3; + + @screen md { + @apply .mb-3; + @apply .rounded-l; + @apply .rounded-r-none; + @apply .w-3/4; + } + } + + label { + @apply .hidden; + } +} + +#mc-embedded-subscribe { + @apply .bg-blue-500; + @apply .cursor-pointer; + @apply .leading-normal; + @apply .px-6; + @apply .py-2; + @apply .rounded-r; + @apply .text-white; + @apply .w-1/3; + + &:hover { + @apply .bg-blue-600; + } + + @screen md { + @apply .w-1/4; + } +} diff --git a/source/_assets/sass/_navigation.scss b/source/_assets/sass/_navigation.scss new file mode 100644 index 0000000..a3e8164 --- /dev/null +++ b/source/_assets/sass/_navigation.scss @@ -0,0 +1,17 @@ +.nav-menu { + @apply .bg-gray-200; + @apply .pb-2; + @apply .pt-6; + @apply .px-2; + @apply .shadow; + @apply .w-auto; +} + +.nav-menu__item { + @apply .block; + @apply .no-underline; + @apply .mb-4; + @apply .mt-0; + @apply .text-gray-800; + @apply .text-sm; +} diff --git a/source/_assets/sass/main.scss b/source/_assets/sass/main.scss new file mode 100644 index 0000000..5a94a45 --- /dev/null +++ b/source/_assets/sass/main.scss @@ -0,0 +1,13 @@ +@tailwind base; +@tailwind components; + +// Code syntax highlighting, +// powered by https://highlightjs.org +@import '~highlight.js/styles/a11y-light.css'; + +@import 'base'; +@import 'navigation'; +@import 'mailchimp'; +@import 'blog'; + +@tailwind utilities; |
