mirror of
https://github.com/muerwre/muerwre.github.io.git
synced 2025-04-25 10:56:40 +07:00
initial
This commit is contained in:
commit
5104c2518b
34 changed files with 6844 additions and 0 deletions
26
components/layout/LayoutFooter.vue
Normal file
26
components/layout/LayoutFooter.vue
Normal file
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<footer :class="[$style.footer, $attrs.class]">
|
||||
<div>btw, have a nice day</div>
|
||||
<div :class="$style.filler" />
|
||||
<div>
|
||||
(2018 - {{ new Date().getFullYear() }})
|
||||
<NuxtLink to="https://github.com/muerwre/" target="_blank"
|
||||
>muerwre</NuxtLink
|
||||
>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style lang="scss" module>
|
||||
.footer {
|
||||
color: var(--color-text-secondary);
|
||||
font-size: 0.8rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.filler {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
36
components/layout/LayoutMainMenu.vue
Normal file
36
components/layout/LayoutMainMenu.vue
Normal file
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<nav>
|
||||
<div :class="$style.section_title">Reference</div>
|
||||
|
||||
<div v-for="item in parentItems" key="item._path" :class="$style.row">
|
||||
<LayoutMainMenuRow
|
||||
:title="item.title"
|
||||
:url="item._path"
|
||||
:children="item.children"
|
||||
/>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const { data: navigation } = await useAsyncData("navigation", () => {
|
||||
return fetchContentNavigation();
|
||||
});
|
||||
|
||||
const parentItems = navigation.value.filter(
|
||||
(it) => it.children && Array.isArray(it.children) && it.children.length > 0
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.section_title {
|
||||
font-family: var(--family-roboto-slab);
|
||||
font-weight: 600;
|
||||
margin: 2rem 0 1.5rem;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
</style>
|
158
components/layout/LayoutMainMenuRow.vue
Normal file
158
components/layout/LayoutMainMenuRow.vue
Normal file
|
@ -0,0 +1,158 @@
|
|||
<template>
|
||||
<div
|
||||
v-if="children?.length || !url"
|
||||
:class="[$style.container, { [$style.secondary]: secondary }]"
|
||||
>
|
||||
<div :class="$style.heading">
|
||||
{{ title }}
|
||||
</div>
|
||||
|
||||
<div :class="$style.children">
|
||||
<LayoutMainMenuRow
|
||||
v-for="item in children"
|
||||
key="item._path"
|
||||
:title="item.title"
|
||||
:url="item._path"
|
||||
:children="item.children"
|
||||
secondary
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else :class="$style.row">
|
||||
<NuxtLink :to="url" :class="$style.link" :exactActiveClass="$style.active"
|
||||
>{{ title }}
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
title: string;
|
||||
url?: string;
|
||||
children?: Child[];
|
||||
secondary?: boolean;
|
||||
}
|
||||
|
||||
interface Child {
|
||||
title: string;
|
||||
_path: string;
|
||||
children: Child[];
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
mounted() {
|
||||
const active = document.querySelector(
|
||||
`.${this.$style.link}.${this.$style.active}`
|
||||
);
|
||||
if (!active) return;
|
||||
|
||||
active?.scrollIntoView({ block: "center" });
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
@mixin tree {
|
||||
&::before {
|
||||
content: " ";
|
||||
background-color: var(--color-menu-line);
|
||||
width: 10px;
|
||||
height: 1px;
|
||||
position: absolute;
|
||||
top: 0.6em;
|
||||
left: -17px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
|
||||
&.secondary {
|
||||
padding: 7px 2px 0;
|
||||
|
||||
&::before {
|
||||
content: " ";
|
||||
background-color: var(--color-menu-line);
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
top: -22px;
|
||||
bottom: 13px;
|
||||
left: -16px;
|
||||
}
|
||||
|
||||
&:first-child::before {
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
&:last-child::before {
|
||||
bottom: auto;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.row {
|
||||
padding: 3px 2px;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: " ";
|
||||
background-color: var(--color-menu-line);
|
||||
width: 1px;
|
||||
position: absolute;
|
||||
top: -14px;
|
||||
bottom: 13px;
|
||||
left: -16px;
|
||||
}
|
||||
|
||||
&:first-child::before {
|
||||
top: -4px;
|
||||
}
|
||||
|
||||
&:last-child::before {
|
||||
bottom: auto;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
&:only-child::before {
|
||||
height: 19px;
|
||||
}
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
color: var(--color-menu-title);
|
||||
|
||||
.secondary & {
|
||||
@include tree;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--color-menu-link);
|
||||
text-decoration: none;
|
||||
line-height: 1.4em;
|
||||
position: relative;
|
||||
|
||||
@include tree;
|
||||
|
||||
&.active {
|
||||
color: var(--color-menu-link-active);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.children {
|
||||
padding: 0 0 0 16px;
|
||||
margin: 10px 3px;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
67
components/layout/LayoutMainMenuToggle.vue
Normal file
67
components/layout/LayoutMainMenuToggle.vue
Normal file
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<button :class="[$attrs.class, $style.button]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
fill="#ffffff"
|
||||
:class="[$style.hamburger, { [$style.active]: active }]"
|
||||
>
|
||||
<rect x="0" y="3" width="24" height="2" />
|
||||
<rect x="0" y="11" width="24" height="2" />
|
||||
<rect x="0" y="19" width="24" height="2" />
|
||||
</svg>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
interface Props {
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
defineProps<Props>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
fill: var(--color-text);
|
||||
cursor: pointer;
|
||||
transition: all 250ms;
|
||||
|
||||
&:hover {
|
||||
fill: var(--color-link);
|
||||
}
|
||||
|
||||
& > rect {
|
||||
transition: transform 250ms;
|
||||
}
|
||||
|
||||
&.active {
|
||||
& > rect:nth-child(1) {
|
||||
transform: rotate(45deg);
|
||||
transform-origin: 2px 8px;
|
||||
}
|
||||
|
||||
& > rect:nth-child(2) {
|
||||
transform: scaleX(0);
|
||||
transform-origin: 13px 0;
|
||||
transition-delay: 100ms;
|
||||
}
|
||||
|
||||
& > rect:nth-child(3) {
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: 3px 16px;
|
||||
transition-delay: 50ms;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
52
components/layout/LayoutThemeToggle.vue
Normal file
52
components/layout/LayoutThemeToggle.vue
Normal file
|
@ -0,0 +1,52 @@
|
|||
<template>
|
||||
<button
|
||||
@click="toggleTheme"
|
||||
:class="[$attrs.class, $style.button, { [$style.visible]: visible }]"
|
||||
>
|
||||
<ClientOnly>
|
||||
<IconsMoon fill="currentColor" width="32" height="32" v-if="isDark" />
|
||||
<IconsSun fill="currentColor" width="32" height="32" v-if="!isDark" />
|
||||
</ClientOnly>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const visible = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
visible.value = true;
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default defineComponent({
|
||||
methods: {
|
||||
toggleTheme() {
|
||||
this.$colorMode.preference =
|
||||
this.$colorMode.preference === "dark" ? "light" : "dark";
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isDark() {
|
||||
return this.$colorMode.preference === "dark";
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.button {
|
||||
color: var(--color-text-secondary);
|
||||
cursor: pointer;
|
||||
transform: scale(0) rotate(180deg);
|
||||
transition: all 0.25s ease-out;
|
||||
|
||||
&.visible {
|
||||
transform: scale(1) rotate(0);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue