Added stylelint, improved code readability, implemented swipe controls

This commit is contained in:
Andrew Illarionov 2023-11-23 02:53:30 +03:00
parent c509c770f6
commit 2a1bcfc3d2
26 changed files with 1454 additions and 139 deletions

View File

@ -1,4 +1,5 @@
> 1% > 1%
last 2 versions last 5 major versions
not dead not dead
not ie 11 not ie <= 11
not op_mini all

1
.stylelintcache Normal file
View File

@ -0,0 +1 @@
[{"D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\list-types.scss":"1","D:\\Software\\Development\\Websites\\enderman.ch\\index\\assets\\styles\\transitions.scss":"2","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\Logo.vue":"3","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\LinkButton.vue":"4","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\TransitionY.vue":"5","D:\\Software\\Development\\Websites\\enderman.ch\\index\\app.vue":"6","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\EMail.vue":"7","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\Navigation.vue":"8","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\Separator.vue":"9","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\Flooter.vue":"10","D:\\Software\\Development\\Websites\\enderman.ch\\index\\components\\Portal.vue":"11","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\about.vue":"12","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\index.vue":"13","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\projects.vue":"14","D:\\Software\\Development\\Websites\\enderman.ch\\index\\pages\\social.vue":"15"},{"size":389,"mtime":1700689887460,"hashOfConfig":"16"},{"size":165,"mtime":1700688268778,"hashOfConfig":"16"},{"size":1113,"mtime":1700251498711,"hashOfConfig":"16"},{"size":986,"mtime":1700324714794,"hashOfConfig":"16"},{"size":1513,"mtime":1700430002840,"hashOfConfig":"16"},{"size":2315,"mtime":1700689012136,"hashOfConfig":"16"},{"size":804,"mtime":1700688952880,"hashOfConfig":"16"},{"size":1183,"mtime":1700689030040,"hashOfConfig":"16"},{"size":300,"mtime":1700689033070,"hashOfConfig":"16"},{"size":1853,"mtime":1700508715727,"hashOfConfig":"16"},{"size":16880,"mtime":1700502035614,"hashOfConfig":"16"},{"size":2135,"mtime":1700689265787,"hashOfConfig":"16"},{"size":3117,"mtime":1700689271383,"hashOfConfig":"16"},{"size":2304,"mtime":1700689265769,"hashOfConfig":"16"},{"size":3232,"mtime":1700689265781,"hashOfConfig":"16"},"5tgxr3"]

2
.stylelintignore Normal file
View File

@ -0,0 +1,2 @@
node_modules/
assets/styles/**/*.css

11
.stylelintrc.cjs Normal file
View File

@ -0,0 +1,11 @@
module.exports = {
defaultSeverity: 'warning',
extends: [
'stylelint-config-standard-scss',
'stylelint-config-recommended-vue',
],
plugins: [],
rules: {
'declaration-empty-line-before': null,
},
}

View File

@ -17,6 +17,7 @@ useHead({
class="d-flex flex-column align-items-center pt-sm-5 h-100 animate__animated-sm animate__delay-1-5s animate__fadeInDown" class="d-flex flex-column align-items-center pt-sm-5 h-100 animate__animated-sm animate__delay-1-5s animate__fadeInDown"
> >
<NuxtLayout name="card"> <NuxtLayout name="card">
<template #header> </template>
<template #footer> <template #footer>
<ClientOnly> <ClientOnly>
<template #fallback> </template> <template #fallback> </template>
@ -52,5 +53,3 @@ useHead({
/> />
</Transition> </Transition>
</template> </template>
<style></style>

BIN
assets/images/icons/cog.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -15570,16 +15570,6 @@ textarea.form-control-lg {
filter: blur(1em); filter: blur(1em);
} }
.expand-enter-active,
.expand-leave-active {
transition-property: opacity, height;
}
.expand-enter,
.expand-leave-to {
opacity: 0;
}
@counter-style do { @counter-style do {
system: fixed; system: fixed;
symbols: "💻" "📌" "👻" "📷"; symbols: "💻" "📌" "👻" "📷";
@ -15623,7 +15613,7 @@ body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: white; color: white;
font-family: "Lato", sans-serif; font-family: Lato, sans-serif;
font-size: 18px; font-size: 18px;
height: 100%; height: 100%;
} }
@ -15655,7 +15645,7 @@ body {
} }
.alex { .alex {
font-family: "Alexandria", sans-serif; font-family: Alexandria, sans-serif;
} }
.smooth-glide { .smooth-glide {
@ -15776,7 +15766,6 @@ body {
} }
.animate__animated-sm { .animate__animated-sm {
animation-duration: var(--animate-duration); animation-duration: var(--animate-duration);
-webkit-animation-fill-mode: both;
animation-fill-mode: both; animation-fill-mode: both;
} }
.animate__delay-1-5s { .animate__delay-1-5s {

File diff suppressed because one or more lines are too long

15
assets/styles/main.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -33,24 +33,18 @@ html {
body { body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background-color: rgb(6 25 28);
background-color: rgb(6, 25, 28);
background-image: url('~/assets/images/sky.png'); background-image: url('~/assets/images/sky.png');
background-attachment: fixed; background-attachment: fixed;
background-blend-mode: multiply; background-blend-mode: multiply;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
image-rendering: pixelated; image-rendering: pixelated;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: white; color: white;
font-family: 'Lato', sans-serif; font-family: Lato, sans-serif;
font-size: 18px; font-size: 18px;
height: 100%; height: 100%;
} }
@ -83,7 +77,7 @@ body {
} }
.alex { .alex {
font-family: 'Alexandria', sans-serif; font-family: Alexandria, sans-serif;
} }
.smooth-glide { .smooth-glide {
@ -92,7 +86,7 @@ body {
// Query-overridable classes. // Query-overridable classes.
.background { .background {
background-color: rgba(0, 0, 0, 0.5); background-color: rgb(0 0 0 / 50%);
} }
.dimensions { .dimensions {
@ -111,6 +105,7 @@ body {
&-hi { &-hi {
@extend .link; @extend .link;
color: cornflowerblue; color: cornflowerblue;
&:hover { &:hover {
@ -132,17 +127,16 @@ body {
.radial-gradient { .radial-gradient {
background: radial-gradient( background: radial-gradient(
circle at left, circle at left,
rgba(255, 255, 255, 0.8), rgb(255 255 255 / 80%),
rgba(255, 255, 255, 0.75), rgb(255 255 255 / 75%),
rgba(255, 255, 255, 0) rgb(255 255 255 / 0%)
); );
} }
.scrollbar { .scrollbar {
min-height: 128px; min-height: 128px;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.15) rgba(0, 0, 0, 0.2); scrollbar-color: rgb(255 255 255 / 15%) rgb(0 0 0 / 20%);
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 8px; width: 8px;
@ -150,12 +144,12 @@ body {
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
border-radius: 8px; border-radius: 8px;
background-color: rgba(0, 0, 0, 0.2); background-color: rgb(0 0 0 / 20%);
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
border-radius: 8px; border-radius: 8px;
background-color: rgba(255, 255, 255, 0.15); background-color: rgb(255 255 255 / 15%);
} }
} }
@ -165,20 +159,20 @@ body {
} }
.scrollbar { .scrollbar {
scrollbar-color: rgba(0, 0, 0, 0.2) rgba(255, 255, 255, 0.2); scrollbar-color: rgb(0 0 0 / 20%) rgb(255 255 255 / 20%);
&::-webkit-scrollbar-track { &::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0.2); background-color: rgb(255 255 255 / 20%);
} }
&::-webkit-scrollbar-thumb { &::-webkit-scrollbar-thumb {
border-radius: 8px; border-radius: 8px;
background-color: rgba(0, 0, 0, 0.2); background-color: rgb(0 0 0 / 20%);
} }
} }
.background { .background {
background-color: rgba(255, 255, 255, 0.8); background-color: rgb(255 255 255 / 80%);
} }
.link { .link {
@ -198,23 +192,20 @@ body {
.radial-gradient { .radial-gradient {
background: radial-gradient( background: radial-gradient(
circle at left, circle at left,
rgba(0, 0, 0, 0.95), rgb(0 0 0 / 95%),
rgba(0, 0, 0, 0.8), rgb(0 0 0 / 80%),
rgba(0, 0, 0, 0) rgb(0 0 0 / 0%)
); );
} }
} }
.floaty { .floaty {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
width: fit-content; width: fit-content;
height: fit-content; height: fit-content;
margin: auto; margin: auto;
} }
@ -231,12 +222,11 @@ body {
.dimensions { .dimensions {
width: 80%; width: 80%;
min-height: fit-content; min-height: fit-content;
max-height: 90%; max-height: 90%;
} }
.fade-mask-sm { .fade-mask-sm {
mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1) 5%, rgba(0, 0, 0, 1) 95%, rgba(0, 0, 0, 0)); mask-image: linear-gradient(to bottom, rgb(0 0 0 / 0%), rgb(0 0 0 / 100%) 5%, rgb(0 0 0 / 100%) 95%, rgb(0 0 0 / 0%));
} }
.rounded-1 { .rounded-1 {
@ -249,7 +239,6 @@ body {
.animate__animated-sm { .animate__animated-sm {
animation-duration: var(--animate-duration); animation-duration: var(--animate-duration);
-webkit-animation-fill-mode: both;
animation-fill-mode: both; animation-fill-mode: both;
} }

View File

@ -1,14 +0,0 @@
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
body::-webkit-scrollbar-thumb {
background-color: darkgrey;
outline: 1px solid slategrey;
}
/*# sourceMappingURL=scrollbar.css.map */

View File

@ -1 +0,0 @@
{"version":3,"sourceRoot":"","sources":["scrollbar.scss"],"names":[],"mappings":"AAAA;EACI;;;AAGJ;EACI;;;AAGJ;EACE;EACA","file":"scrollbar.css"}

View File

@ -10,13 +10,3 @@
filter: blur(1em); filter: blur(1em);
} }
} }
.expand-enter-active,
.expand-leave-active {
transition-property: opacity, height;
}
.expand-enter,
.expand-leave-to {
opacity: 0;
}

View File

@ -39,5 +39,3 @@ const href =
</slot> </slot>
</a> </a>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -17,7 +17,10 @@ const mailTemplate = `I've just found a bug on https://enderman.ch and would lik
<template> <template>
<footer class="user-select-none text-align-center line-height-1-5"> <footer class="user-select-none text-align-center line-height-1-5">
<span class="font-small text-shadow" :class="{ transpaque: !props.opaque }"> <span
class="font-small"
:class="{ transpaque: !props.opaque, 'text-shadow': !props.opaque }"
>
<EMail <EMail
class="link-hi-force-dark" class="link-hi-force-dark"
address="contact@enderman.ch" address="contact@enderman.ch"

View File

@ -10,6 +10,7 @@ import socialIcon from '~/assets/images/icons/user.png'
const pageStore = usePageStore() const pageStore = usePageStore()
const { pages } = storeToRefs(pageStore) const { pages } = storeToRefs(pageStore)
const links = toRaw(pages.value).filter((page) => page.path !== '/')
const icons = [aboutIcon, projectIcon, socialIcon] const icons = [aboutIcon, projectIcon, socialIcon]
</script> </script>
@ -26,7 +27,7 @@ const icons = [aboutIcon, projectIcon, socialIcon]
<ul <ul
class="navbar-nav flex-row align-items-center align-items-sm-start align-items-lg-center justify-content-center gap-3 m-2 m-sm-0 mx-lg-2 my-sm-2 my-lg-0" class="navbar-nav flex-row align-items-center align-items-sm-start align-items-lg-center justify-content-center gap-3 m-2 m-sm-0 mx-lg-2 my-sm-2 my-lg-0"
> >
<li v-for="(page, index) in pages" :key="index" class="nav-item"> <li v-for="(page, index) in links" :key="index" class="nav-item">
<LinkButton <LinkButton
:path="page.path" :path="page.path"
:name="page.name" :name="page.name"
@ -37,5 +38,3 @@ const icons = [aboutIcon, projectIcon, socialIcon]
</ul> </ul>
</nav> </nav>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -17,5 +17,3 @@ const props = defineProps({
:style="{ height: props.height + 'px' }" :style="{ height: props.height + 'px' }"
/> />
</template> </template>
<style scoped lang="scss"></style>

View File

@ -1,7 +1,53 @@
<script setup lang="ts"></script> <script setup lang="ts">
import type { UseSwipeDirection } from '@vueuse/core'
import { useSwipe } from '@vueuse/core'
import { storeToRefs } from 'pinia'
import { usePageStore } from '~/stores/pages'
const router = useRouter()
const route = useRoute()
const card = ref<HTMLElement | null>(null)
const pageStore = usePageStore()
const { pages } = storeToRefs(pageStore)
const swipe = useSwipe(card, {
passive: true,
onSwipe: (touch: TouchEvent) => {
console.log(card.value?.offsetWidth, swipe.lengthX.value)
},
onSwipeEnd: (touch: TouchEvent, direction: UseSwipeDirection) => {
const currentPage = pages.value.find(
(page) => page.path === route.fullPath,
)!
const currentIndex = pages.value.indexOf(currentPage)
if (
card.value?.offsetWidth &&
Math.abs(swipe.lengthX.value) / card.value?.offsetWidth >= 0.5
) {
if (swipe.lengthX.value > 0) {
router.push(
toRaw(pages.value)[
currentIndex - 1 < 0
? pages.value.length - (currentIndex + 1)
: currentIndex - 1
].path,
)
} else {
router.push(
toRaw(pages.value)[(currentIndex + 1) % pages.value.length].path,
)
}
}
},
})
</script>
<template> <template>
<main <main
ref="card"
class="dimensions background rounded-1 overflow-auto d-flex flex-column gap-3 gap-sm-2 px-4 pt-4 pb-3" class="dimensions background rounded-1 overflow-auto d-flex flex-column gap-3 gap-sm-2 px-4 pt-4 pb-3"
> >
<Navigation /> <Navigation />
@ -12,5 +58,3 @@
<slot name="footer" /> <slot name="footer" />
</main> </main>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -41,7 +41,7 @@ export default defineNuxtConfig({
], ],
}, },
css: [ css: [
'~/assets/styles/main.css', '~/assets/styles/main.min.css',
'@fortawesome/fontawesome-svg-core/styles.css', '@fortawesome/fontawesome-svg-core/styles.css',
], ],
plugins: [], plugins: [],
@ -51,6 +51,7 @@ export default defineNuxtConfig({
'@nuxtjs/eslint-module', '@nuxtjs/eslint-module',
'@pinia/nuxt', '@pinia/nuxt',
'nuxt-quasar-ui', 'nuxt-quasar-ui',
'@nuxtjs/stylelint-module',
], ],
quasar: { quasar: {
lang: 'en-US', lang: 'en-US',

1298
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,10 @@
"@nuxt/types": "^2.17.2", "@nuxt/types": "^2.17.2",
"@nuxtjs/eslint-config-typescript": "^12.1.0", "@nuxtjs/eslint-config-typescript": "^12.1.0",
"@nuxtjs/eslint-module": "^4.1.0", "@nuxtjs/eslint-module": "^4.1.0",
"@nuxtjs/stylelint-module": "^5.1.0",
"@pinia/nuxt": "^0.5.1", "@pinia/nuxt": "^0.5.1",
"@typescript-eslint/parser": "^6.10.0", "@typescript-eslint/parser": "^6.10.0",
"csso": "^5.0.5",
"eslint": "^8.53.0", "eslint": "^8.53.0",
"eslint-config-prettier": "^9.0.0", "eslint-config-prettier": "^9.0.0",
"eslint-plugin-nuxt": "^4.0.0", "eslint-plugin-nuxt": "^4.0.0",
@ -30,6 +32,9 @@
"nuxt-quasar-ui": "^2.0.6", "nuxt-quasar-ui": "^2.0.6",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"sass": "^1.69.5", "sass": "^1.69.5",
"stylelint": "^15.11.0",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard-scss": "^11.1.0",
"typescript": "^5.2.2", "typescript": "^5.2.2",
"vite-plugin-require": "^0.0.3", "vite-plugin-require": "^0.0.3",
"vue": "^3.3.8", "vue": "^3.3.8",
@ -50,6 +55,7 @@
"@quasar/extras": "^1.16.8", "@quasar/extras": "^1.16.8",
"animate.css": "^4.1.1", "animate.css": "^4.1.1",
"bootstrap": "^5.3.2", "bootstrap": "^5.3.2",
"caniuse-lite": "^1.0.30001564",
"humps": "^2.0.1", "humps": "^2.0.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"quasar": "^2.14.0" "quasar": "^2.14.0"

View File

@ -52,9 +52,9 @@ useHead({
<hr /> <hr />
<p> <p>
Nice to meet you! I'm Andrew, a {{ age }}-year-old guy from Kaluga, Nice to meet you! I'm Andrew, a {{ age }}-year-old guy from Kaluga,
Russia. I have been developing software since I was 10 years old, and I Russia. I have been developing software since I was 10, and I have always
have always been interested in technology. I'm a middle-senior C/++ been interested in technology. I'm a middle-senior C/++ developer and a
developer and a junior full-stack engineer. junior full-stack engineer.
<sup>1</sup> <sup>1</sup>
</p> </p>
<p class="font-small"> <p class="font-small">
@ -75,5 +75,3 @@ useHead({
</p> </p>
</section> </section>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -99,5 +99,3 @@ useHead({
</p> </p>
</section> </section>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -91,5 +91,3 @@ useHead({
</p> </p>
</section> </section>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -88,7 +88,7 @@ useHead({
<template> <template>
<section> <section>
<h3 class="alex">Social media</h3> <h3 class="alex">Online presence</h3>
<hr /> <hr />
<p> <p>
<strong>🚧 This page is currently under construction.</strong> Expect a <strong>🚧 This page is currently under construction.</strong> Expect a
@ -97,30 +97,43 @@ useHead({
I will make sure to sand them down. I will make sure to sand them down.
</p> </p>
<hr /> <hr />
<ul class="list-style-type-none p-0"> <div class="row">
<li v-for="(page, index) in socials" :key="index"> <div class="col-12 col-md-3">
<div class="d-flex flex-row align-items-center gap-1"> <h5 class="alex">Social media</h5>
<ClientOnly> <ul class="list-style-type-none p-0">
<FontAwesomeIcon :icon="`fa-brands fa-${page.icon}`" fixed-width /> <li v-for="(page, index) in socials" :key="index">
</ClientOnly> <div class="d-flex flex-row align-items-center gap-1">
<a class="link-hi" target="_blank" rel="noopener" :href="page.url"> <ClientOnly>
{{ page.name }} <FontAwesomeIcon
</a> :icon="`fa-brands fa-${page.icon}`"
</div> fixed-width
</li> />
</ul> </ClientOnly>
<h3 class="alex">Contact me</h3> <a
<p> class="link-hi"
Personal: target="_blank"
<EMail rel="noopener"
class="link-hi" :href="page.url"
address="contact@enderman.ch" >
subject="Hey Enderman!" {{ page.name }}
/><br /> </a>
Manager: <EMail class="link-hi" address="manager@enderman.ch" /><br /> </div>
Abuse: <EMail class="link-hi" address="abuse@enderman.ch" /> </li>
</p> </ul>
</div>
<div class="col-12 col-md-9">
<h5 class="alex">Contact me</h5>
<p>
Personal:
<EMail
class="link-hi"
address="contact@enderman.ch"
subject="Hey Enderman!"
/><br />
Manager: <EMail class="link-hi" address="manager@enderman.ch" /><br />
Abuse: <EMail class="link-hi" address="abuse@enderman.ch" />
</p>
</div>
</div>
</section> </section>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -7,6 +7,10 @@ export const usePageStore = defineStore('page', () => {
'endermanch, enderman, developer, youtuber, filmmaker, artist, engineer' 'endermanch, enderman, developer, youtuber, filmmaker, artist, engineer'
const pages = ref([ const pages = ref([
{
name: 'Home',
path: '/',
},
{ {
name: 'About', name: 'About',
path: '/about', path: '/about',
@ -26,13 +30,12 @@ export const usePageStore = defineStore('page', () => {
useRouter() useRouter()
.getRoutes() .getRoutes()
.forEach((route) => { .forEach((route) =>
if (route.path !== '/') pages.value.push({
pages.value.push({ name: route.path.slice(1)[0].toUpperCase() + route.path.slice(2),
name: route.path.slice(1)[0].toUpperCase() + route.path.slice(2), path: route.path,
path: route.path, }),
}) )
})
} }
return { return {