add blogs, move pictures to local + much more
This commit is contained in:
8
components/Nav.vue
Normal file
8
components/Nav.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<nav class="px-2 py-4">
|
||||
<ul class="flex gap-3 font-semibold">
|
||||
<li><nuxt-link class="text-white" to="/">Home</nuxt-link></li>
|
||||
<li><nuxt-link class="text-white" to="/blog">Blog</nuxt-link></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
33
components/TagButton.vue
Normal file
33
components/TagButton.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
iconMap: {
|
||||
'nuxtjs': 'nuxt-icon',
|
||||
'nuxt': 'nuxt-icon',
|
||||
'nuxtjs-3': 'nuxt-icon',
|
||||
'web-dev': 'web-dev-icon',
|
||||
'fullstack-development': 'jamstack-icon',
|
||||
'angular': 'angular-icon',
|
||||
'nodejs': 'nodejs-icon',
|
||||
'mongodb': 'mongodb-icon',
|
||||
'docker': 'docker-icon',
|
||||
'linux': 'linux-tux',
|
||||
'bittorrent': 'webtorrent',
|
||||
'web-server': 'nginx'
|
||||
},
|
||||
}
|
||||
},
|
||||
props: ['iconName', 'name']
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button :aria-label="name"
|
||||
class="font-inter md:text-lg w-fit max-h-9 min-w-fit bg-zinc-800 border border-zinc-700/30 py-1 px-2 rounded shadow flex items-center">
|
||||
<Icon size="20"
|
||||
class="mr-2"
|
||||
:name="('logos:' + (iconMap[iconName.toLowerCase().split(' ').join('-')] || iconName.toLowerCase()))" />
|
||||
{{name}}
|
||||
</button>
|
||||
</template>
|
||||
123
components/content/ProseCode.vue
Normal file
123
components/content/ProseCode.vue
Normal file
@@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<div class="container my-2 bg-neutral-900">
|
||||
<span v-if="filename"
|
||||
class="filename-text text-xs leading-none tracking-tight text-gray-400 font-jetbrains">
|
||||
{{ filename }}
|
||||
</span>
|
||||
<slot />
|
||||
<div class="bottom-container">
|
||||
<div class="copy-container">
|
||||
<button class="rounded hover:bg-zinc-800/60 transition-colors duration-200 flex p-1"
|
||||
@click="copy(code)">
|
||||
<div class="h-6"
|
||||
v-if="copied">
|
||||
<Icon size="24" name="tabler:check" />
|
||||
</div>
|
||||
<div class="h-6"
|
||||
v-else>
|
||||
<Icon size="24" name="tabler:copy" />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
const { copy, copied, text } = useClipboard();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
code?: string;
|
||||
language?: string | null;
|
||||
filename?: string | null;
|
||||
highlights?: Array<number>;
|
||||
}>(),
|
||||
{ code: '', language: null, filename: null, highlights: [] }
|
||||
);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.icon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
padding-top: 0.5em;
|
||||
overflow: hidden;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.container:hover .bottom-container {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.bottom-container {
|
||||
display: flex;
|
||||
transition-property: opacity;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 250ms;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
position: relative;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.copy-container {
|
||||
height: fit-content;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 15px;
|
||||
}
|
||||
|
||||
.filename-text {
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
right: 0.25rem;
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
:slotted(pre) {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex: 1 1 0%;
|
||||
overflow-x: auto;
|
||||
padding: 1rem;
|
||||
line-height: 1.625;
|
||||
counter-reset: lines;
|
||||
}
|
||||
|
||||
:slotted(pre code) {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:slotted(pre code .line) {
|
||||
min-height: 1em;
|
||||
}
|
||||
|
||||
:slotted(pre code .line::before) {
|
||||
counter-increment: lines;
|
||||
content: counter(lines);
|
||||
width: 1em;
|
||||
margin-right: 1.5rem;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
color: rgba(115, 138, 148, 0.4);
|
||||
}
|
||||
|
||||
:slotted(pre code .highlight) {
|
||||
background-color: #363b46;
|
||||
display: block;
|
||||
margin-right: -1em;
|
||||
margin-left: -1em;
|
||||
padding-right: 1em;
|
||||
padding-left: 0.75em;
|
||||
border-left: 0.25em solid red;
|
||||
}
|
||||
</style>
|
||||
17
components/content/ProseCodeInline.vue
Normal file
17
components/content/ProseCodeInline.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<code lang="js">
|
||||
<slot />
|
||||
</code>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
code {
|
||||
background-color: #252425;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem;
|
||||
overflow: hidden;
|
||||
padding: 3px 6px;
|
||||
}
|
||||
</style>
|
||||
41
components/content/ProseH2.vue
Normal file
41
components/content/ProseH2.vue
Normal file
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div :id="id"
|
||||
class="group flex mt-2">
|
||||
<div class="text-2xl">
|
||||
<slot />
|
||||
</div>
|
||||
<button @click="copy(location.origin + location.pathname + '#' + id)"
|
||||
class="group-hover:opacity-100 ml-2 hover:bg-zinc-800 flex items-center h-fit p-[2px] transition-opacity duration-200 rounded opacity-0">
|
||||
<div class="h-4"
|
||||
v-if="copied">
|
||||
<Icon size="16"
|
||||
name="tabler:check" />
|
||||
</div>
|
||||
<div class="h-4"
|
||||
v-else>
|
||||
<Icon size="16"
|
||||
name="tabler:link" />
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
useClipboard, useBrowserLocation
|
||||
} from '@vueuse/core';
|
||||
const { copy, copied, text } = useClipboard();
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
id?: string;
|
||||
}>(),
|
||||
{ id: '' }
|
||||
);
|
||||
const location = useBrowserLocation()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.icon {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
9
components/newsletterSignup.vue
Normal file
9
components/newsletterSignup.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="bg-[#1f1d1f] px-4 py-4 md:py-6 rounded-lg border border-neutral-800 flex flex-col">
|
||||
<h1 class="mb-2 text-2xl">Get notified</h1>
|
||||
<input type="email"
|
||||
placeholder="Email..."
|
||||
name="email"
|
||||
class="px-4 py-2 my-2 w-full sm:w-4/5 border shadow-sm rounded-md resize-none border-neutral-700 transition-colors bg-zinc-800 focus:border-neutral-500 focus:outline-none placeholder:italic placeholder:text-gray-300 text-white" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
export default {
|
||||
props: ['iconSrc', 'name']
|
||||
props: ['iconName', 'name']
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<button class="font-inter md:text-lg w-fit min-w-fit bg-zinc-800 py-1 px-2 rounded shadow flex items-center"><img
|
||||
:src="iconSrc"
|
||||
class="mr-2 w-5 h-5" />{{name}}</button>
|
||||
<button :aria-label="name" class="font-inter md:text-lg w-fit max-h-9 min-w-fit bg-zinc-800 border border-zinc-700/30 py-1 px-2 rounded shadow flex items-center">
|
||||
<Icon size="20" class="mr-2" :name="iconName" />
|
||||
{{name}}</button>
|
||||
</template>
|
||||
Reference in New Issue
Block a user