Rewrite to TailwindCSS, enhance the DOM, uninstall Vuetify, improve styles
This commit is contained in:
@@ -47,9 +47,10 @@ onMounted(() => setTimeout(type, 1500))
|
||||
|
||||
<template>
|
||||
<section>
|
||||
<h3 class="alex">Page not found!</h3>
|
||||
<pre
|
||||
class="whitespace-pre-wrap break-keep">{{ buffer }}<span class="blinker">▊</span></pre>
|
||||
<h3>Page not found!</h3>
|
||||
<pre class="whitespace-pre-wrap break-keep font-small">{{
|
||||
buffer
|
||||
}}<span class="blinker">▊</span></pre>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import sky from '~/assets/images/textures/sky.png'
|
||||
import particles from '~/assets/images/textures/particles.png'
|
||||
|
||||
const { $local } = useNuxtApp()
|
||||
const config = useAppConfig()
|
||||
const fqdn = config.url.split('//')[1]
|
||||
const fqdn = config.url.split('//').at(1)
|
||||
|
||||
const resources: string[] = [sky, particles]
|
||||
|
||||
const pages = storeToRefs(usePageStore())
|
||||
const animated = defineModel<boolean>({
|
||||
required: true,
|
||||
})
|
||||
|
||||
const props = defineProps({
|
||||
layout: {
|
||||
@@ -138,7 +140,7 @@ class Portal {
|
||||
constructor(
|
||||
directory: string = '/',
|
||||
create: boolean = true,
|
||||
animate: boolean = true,
|
||||
animate: boolean = false,
|
||||
randomize: boolean = false,
|
||||
fade: boolean = false,
|
||||
speed: number = 1,
|
||||
@@ -563,9 +565,6 @@ class Portal {
|
||||
// Run the scene.
|
||||
this.scene()
|
||||
|
||||
// TODO: Make it into a composable? The toggle will not work. Hardcoded.
|
||||
if (!pages.animate.value) this.pause()
|
||||
|
||||
// Request the next animation frame if animation is enabled.
|
||||
if (this.animate) requestAnimationFrame(this.render.bind(this))
|
||||
}
|
||||
@@ -573,10 +572,6 @@ class Portal {
|
||||
resize() {
|
||||
if (!this.canvas.full()) this.canvas.fill()
|
||||
|
||||
// Pause the animation if the viewport becomes too small.
|
||||
if (window.innerWidth <= 600) this.pause()
|
||||
else this.continue()
|
||||
|
||||
// If we have animation disabled, we still have to re-render the scene once on resize.
|
||||
if (!this.animate) requestAnimationFrame(this.render.bind(this))
|
||||
}
|
||||
@@ -585,8 +580,8 @@ class Portal {
|
||||
this.clickTime = Date.now()
|
||||
}
|
||||
|
||||
continue() {
|
||||
if (this.pauseTime === 0) return
|
||||
play() {
|
||||
if (this.pauseTime === 0) this.pauseTime = this.currentTime
|
||||
|
||||
// Add the time that has passed since the pause to the current time.
|
||||
this.currentTime += Date.now() - this.pauseTime
|
||||
@@ -619,47 +614,50 @@ class Portal {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// If the localStorage value is null, trigger the setup.
|
||||
// If the viewport is too small, disable by default.
|
||||
const ecmaportal: string | null | undefined = $local.getItem('ecmaportal')
|
||||
|
||||
if (ecmaportal === null) {
|
||||
const notMobile = window.innerWidth > 600
|
||||
|
||||
$local.setItem('ecmaportal', notMobile)
|
||||
animated.value = notMobile
|
||||
} else animated.value = ecmaportal === 'true'
|
||||
|
||||
const layout = document.querySelector(props.layout)
|
||||
const portal = new Portal(
|
||||
props.directory,
|
||||
props.create,
|
||||
props.animate && window.innerWidth > 600,
|
||||
animated.value,
|
||||
props.randomize,
|
||||
props.fade,
|
||||
props.speed,
|
||||
)
|
||||
|
||||
layout!.addEventListener('mousedown', ((e: UIEvent) => {
|
||||
if (e.target === e.currentTarget && e.detail >= 2) {
|
||||
const click: EventListener = (e: Event) => {
|
||||
if (e.target === e.currentTarget) {
|
||||
e.preventDefault()
|
||||
portal.click()
|
||||
}
|
||||
}) as EventListener)
|
||||
}
|
||||
|
||||
for (const event of ['dblclick', 'touchstart'])
|
||||
layout!.addEventListener(event, click)
|
||||
|
||||
// Save the new value to local storage.
|
||||
watch(animated, (newAnimate) => {
|
||||
$local.setItem('ecmaportal', newAnimate)
|
||||
newAnimate ? portal.play() : portal.pause()
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<canvas id="ecmaportal" class="parallax">
|
||||
<canvas id="ecmaportal" class="fixed top-0 left-0 opacity-0 parallax -z-10">
|
||||
<span>
|
||||
Your browser does not support the <canvas /> element, which is
|
||||
required for parallax animation.
|
||||
</span>
|
||||
</canvas>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.parallax {
|
||||
position: fixed;
|
||||
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
opacity: 0;
|
||||
transition: all 0.6942s ease-in;
|
||||
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<hr class="accent-text accent-gradient border-0 h-px my-4" />
|
||||
<p>
|
||||
<strong>🚧 This page is currently under construction.</strong> Expect a
|
||||
lot more content to be added as time passes.
|
||||
<em>Please report all bugs you encounter via the link in the footer</em>,
|
||||
I will make sure to sand them down.
|
||||
</p>
|
||||
<hr class="accent-text accent-gradient border-0 h-px my-4" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,59 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps({
|
||||
opaque: Boolean,
|
||||
})
|
||||
|
||||
const config = useAppConfig()
|
||||
const currentYear = new Date().getFullYear()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer
|
||||
class="user-select-none pass-through text-align-center line-height-1-5"
|
||||
>
|
||||
<span
|
||||
class="font-small"
|
||||
:class="{
|
||||
'footer-transparent': !props.opaque,
|
||||
'text-shadow': !props.opaque,
|
||||
}"
|
||||
>
|
||||
© 2018-{{ currentYear }},
|
||||
<a
|
||||
:class="{
|
||||
'link-hi-force-dark': !props.opaque,
|
||||
'link-hi': props.opaque,
|
||||
}"
|
||||
:href="config.url"
|
||||
>Enderman</a
|
||||
>. All rights reserved.
|
||||
<wbr />
|
||||
<sub class="nobr">
|
||||
β{{ config.build.version ? config.build.version : '?.?.?' }} ({{
|
||||
config.build.date ? config.build.date : '1970-01-01'
|
||||
}})
|
||||
</sub>
|
||||
</span>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.footer-transparent {
|
||||
color: white;
|
||||
|
||||
opacity: 0.25;
|
||||
transition: ease 0.3s;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.line-height-1-5 {
|
||||
line-height: 14px * 1.5;
|
||||
}
|
||||
|
||||
.text-shadow {
|
||||
text-shadow: black 0 2px 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -29,10 +29,11 @@ const props = defineProps({
|
||||
|
||||
<template>
|
||||
<NuxtLink
|
||||
class="flex flex-row items-center text-inherit hover:text-inherit select-none sm:m-auto lg:m-0"
|
||||
class="flex flex-row items-center text-inherit hover:text-inherit select-none sm:m-auto lm:m-0 lt:m-0 lg:m-0"
|
||||
to="/"
|
||||
>
|
||||
<img
|
||||
class="transition-all"
|
||||
draggable="false"
|
||||
:width="props.width"
|
||||
:height="props.height"
|
||||
@@ -41,22 +42,14 @@ const props = defineProps({
|
||||
/>
|
||||
<div>
|
||||
<h2>{{ props.title }}</h2>
|
||||
<hr class="accent accent-gradient border-0 h-px" />
|
||||
<hr class="accent-text accent-gradient border-0 h-px" />
|
||||
<p>{{ props.description }}</p>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
a {
|
||||
> img {
|
||||
transition: ease 0.3s;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> img {
|
||||
transform: scale(105%);
|
||||
}
|
||||
}
|
||||
a:hover > img {
|
||||
transform: scale(105%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,7 +12,7 @@ const links = toRaw(pages.value).filter((page) => page.path !== '/')
|
||||
|
||||
<template>
|
||||
<nav
|
||||
class="flex flex-row flex-wrap sm:flex-col lg:flex-row justify-around sm:justify-start lg:justify-between gap-2 lg:gap-3"
|
||||
class="flex flex-row flex-wrap lm:flex-row lt:flex-row sm:flex-col lg:flex-row justify-around sm:justify-start lm:justify-between lt:justify-between lg:justify-between gap-2 lg:gap-4"
|
||||
>
|
||||
<Logo
|
||||
:src="logo"
|
||||
@@ -21,7 +21,7 @@ const links = toRaw(pages.value).filter((page) => page.path !== '/')
|
||||
description="official website"
|
||||
/>
|
||||
<ul
|
||||
class="flex flex-row flex-wrap items-center sm:items-start lg:items-center justify-center gap-3 m-2 sm:m-0 lg:mx-2 sm:my-2 lg:my-0"
|
||||
class="flex flex-row flex-wrap items-center sm:items-start lm:items-center lt:items-center lg:items-center justify-center gap-4 m-2 sm:m-0 lm:mx-2 lt:mx-2 lg:mx-2 sm:my-2 lg:my-0"
|
||||
>
|
||||
<li v-for="(page, index) in links" :key="index" class="nav-item">
|
||||
<Route
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import cogIcon from '~/assets/images/icons/cog.png'
|
||||
import pearlIcon from '~/assets/images/icons/pearl.gif'
|
||||
|
||||
const theme = useVThemeSSR()
|
||||
const config = useAppConfig()
|
||||
const fqdn = config.url.split('//')[1]
|
||||
|
||||
const mailTemplate = `I've just found a bug on ${config.url} and would like to report it.%0D%0A%0D%0AWebsite version: ${
|
||||
config.build.version
|
||||
}%0D%0ABuild date: ${
|
||||
config.build.date
|
||||
}%0D%0ATimestamp: ${new Date().toISOString()}%0D%0A%0D%0A%0D%0ASteps to reproduce:%0D%0A{ Explain in detail what happened here, or attach a video/screenshot }%0D%0A%0D%0AAdditional information:%0D%0A{ Helpful information, such as developer console output / Leave empty if none }%0D%0A%0D%0A%0D%0A// Keep in mind that it's just a template, you can change it as you wish! :)`
|
||||
|
||||
const pages = storeToRefs(usePageStore())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VDialog width="auto">
|
||||
<template #activator="{ props }">
|
||||
<div v-bind="props" class="options clickable">
|
||||
<img
|
||||
draggable="false"
|
||||
:src="cogIcon"
|
||||
alt="Options"
|
||||
class="logo user-select-none"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template #default="{ isActive }">
|
||||
<VCard>
|
||||
<img
|
||||
draggable="false"
|
||||
:src="pearlIcon"
|
||||
alt="Pearl"
|
||||
class="icon-badge user-select-none"
|
||||
/>
|
||||
|
||||
<template #title>
|
||||
<h3 class="alex text-align-center">Site options</h3>
|
||||
</template>
|
||||
|
||||
<div class="overlay background"></div>
|
||||
<template #text>
|
||||
<p class="center mb-3">
|
||||
This tab is experimental and isn't ready for production.
|
||||
<em>I was too lazy to exclude it from the build.</em><br />
|
||||
<strong>Features provided here may or may not work.</strong>
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<VRow>
|
||||
<VCol>
|
||||
<strong>Theme</strong>
|
||||
<p>Available in all flavors, vanilla and chocolate.</p>
|
||||
<VBtn variant="flat" color="secondary" @click="theme.toggle()">
|
||||
Toggle theme
|
||||
</VBtn>
|
||||
</VCol>
|
||||
<VCol>
|
||||
<strong>Animation</strong>
|
||||
<p>
|
||||
Some computers may have issues rendering that gorgeous
|
||||
background animation. Disabling it substantially decreases
|
||||
power consumption, but also makes the website less cool.
|
||||
</p>
|
||||
<VBtn
|
||||
variant="flat"
|
||||
color="primary"
|
||||
@click="pages.animate.value = !pages.animate.value"
|
||||
>
|
||||
Stop animation
|
||||
</VBtn>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
<span class="mt-3">
|
||||
Since you're so curious and thus here, why not report a bug from the
|
||||
production environment behind this tab?<br />
|
||||
It will greatly help me improve the website!
|
||||
<EMail
|
||||
class="link-hi"
|
||||
:address="`contact@${fqdn}`"
|
||||
:cc="`admin@${fqdn}`"
|
||||
:subject="`Bug report: ${fqdn}`"
|
||||
:body="mailTemplate"
|
||||
>
|
||||
<strong>Report a bug</strong>
|
||||
</EMail>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<VSpacer />
|
||||
<VBtn
|
||||
variant="outlined"
|
||||
prepend-icon="close"
|
||||
@click="isActive.value = false"
|
||||
>
|
||||
Close
|
||||
</VBtn>
|
||||
</template>
|
||||
</VCard>
|
||||
</template>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.options {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.icon-badge {
|
||||
position: fixed;
|
||||
|
||||
top: -48px;
|
||||
left: -32px;
|
||||
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
</style>
|
||||
+16
-13
@@ -17,23 +17,32 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'Link',
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 32,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 32,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLink
|
||||
class="flex flex-row items-center gap-2 select-none no-decoration"
|
||||
active-class="icon-active sm:px-3"
|
||||
class="flex flex-row items-center gap-2 select-none text-inherit no-underline"
|
||||
active-class="active"
|
||||
:to="!props.external ? props.path : undefined"
|
||||
:href="props.external ? props.path : undefined"
|
||||
>
|
||||
<img
|
||||
class="icon-image"
|
||||
draggable="false"
|
||||
:src="props.icon"
|
||||
:alt="props.alt"
|
||||
:width="props.width"
|
||||
:height="props.height"
|
||||
/>
|
||||
<span class="display-sm">
|
||||
<span class="hidden lm:hidden lt:hidden sm:block">
|
||||
<strong>
|
||||
{{ props.name }}
|
||||
</strong>
|
||||
@@ -42,14 +51,8 @@ const props = defineProps({
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.icon {
|
||||
&-active {
|
||||
transform: translate(2px, 2px) rotate3d(1, 1, 1, 5deg) scale(1.25);
|
||||
}
|
||||
|
||||
&-image {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.active {
|
||||
@apply px-4;
|
||||
transform: translate(2px, 2px) rotate3d(1, 1, 1, 5deg) scale(1.25);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
<script setup lang="ts">
|
||||
import cogIcon from '~/assets/images/icons/cog.png'
|
||||
import pearlIcon from '~/assets/images/icons/pearl.gif'
|
||||
|
||||
const config = useAppConfig()
|
||||
const { animate } = storeToRefs(usePageStore())
|
||||
|
||||
const fqdn = config.url.split('//').at(1)
|
||||
const mailTemplate = `I've just found a bug on ${config.url} and would like to report it.%0D%0A%0D%0AWebsite version: ${
|
||||
config.build.version
|
||||
}%0D%0ABuild date: ${
|
||||
config.build.date
|
||||
}%0D%0ATimestamp: ${new Date().toISOString()}%0D%0A%0D%0A%0D%0ASteps to reproduce:%0D%0A{ Explain in detail what happened here, or attach a video/screenshot }%0D%0A%0D%0AAdditional information:%0D%0A{ Helpful information, such as developer console output / Leave empty if none }%0D%0A%0D%0A%0D%0A// Keep in mind that it's just a template, you can change it as you wish! :)`
|
||||
|
||||
const active = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="absolute top-0 right-0 flex flex-col cursor-pointer select-none p-2"
|
||||
@click="active = true"
|
||||
>
|
||||
<img
|
||||
draggable="false"
|
||||
:src="cogIcon"
|
||||
alt="Options"
|
||||
width="16"
|
||||
height="16"
|
||||
/>
|
||||
</div>
|
||||
<Transition
|
||||
enter-active-class="animate__animated animate__fadeIn"
|
||||
leave-active-class="animate__animated animate__fadeOut"
|
||||
>
|
||||
<div
|
||||
v-if="active"
|
||||
class="fixed top-0 left-0 flex flex-row justify-center items-center w-full h-full z-20"
|
||||
>
|
||||
<div
|
||||
class="relative flex flex-col gap-4 accent-overlay-background rounded-xl max-w-[800px] mx-4 p-4"
|
||||
>
|
||||
<img
|
||||
draggable="false"
|
||||
:src="pearlIcon"
|
||||
alt="Pearl"
|
||||
class="absolute -top-8 -left-6 badge select-none w-16 lg:w-auto"
|
||||
/>
|
||||
|
||||
<h3 class="text-center">Site settings</h3>
|
||||
|
||||
<div class="overlay accent-overlay-background" />
|
||||
<div class="overlay">
|
||||
<p class="mb-3">
|
||||
The site settings are experimental. Suggest what you want to see
|
||||
here next!
|
||||
<strong>Please report any bugs that may occur.</strong>
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-4">
|
||||
<div class="md:basis-0 flex-grow">
|
||||
<strong>Theme</strong>
|
||||
<p>Available in vanilla and chocolate flavors.</p>
|
||||
|
||||
<select
|
||||
v-model="$colorMode.preference"
|
||||
class="accent accent-overlay-background"
|
||||
>
|
||||
<option value="system">System</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="sepia">Sepia</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="md:basis-0 flex-grow">
|
||||
<strong>Animation</strong>
|
||||
<p>
|
||||
Some computers may have issues rendering that gorgeous
|
||||
background animation. Disabling it substantially decreases power
|
||||
consumption, but also makes the website less cool.
|
||||
</p>
|
||||
<input v-model="animate" type="checkbox" color="primary" />
|
||||
</div>
|
||||
</div>
|
||||
<span class="mt-3">
|
||||
<EMail
|
||||
:address="`contact@${fqdn}`"
|
||||
:cc="`admin@${fqdn}`"
|
||||
:subject="`Bug report: ${fqdn}`"
|
||||
:body="mailTemplate"
|
||||
>
|
||||
<strong>Report a bug</strong>
|
||||
</EMail>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<button @click="active = false">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.badge {
|
||||
transform: rotate(-15deg);
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { usePageStore } from '~/stores/pages'
|
||||
|
||||
const pageStore = usePageStore()
|
||||
const { pages } = storeToRefs(pageStore)
|
||||
const { pages } = storeToRefs(usePageStore())
|
||||
|
||||
const route = useRoute()
|
||||
const state = computed(() => {
|
||||
@@ -24,39 +20,18 @@ const state = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="control-layout pass-through">
|
||||
<NuxtLink class="control-icon no-decoration" :to="state.prev">
|
||||
<Icon name="iconoir:nav-arrow-left" />
|
||||
<div
|
||||
class="flex fixed flex-row justify-between items-center w-full h-full pass-through"
|
||||
>
|
||||
<NuxtLink
|
||||
class="opacity-25 hover:opacity-100 text-inherit no-underline transition-all"
|
||||
:to="state.prev"
|
||||
>
|
||||
<iconify-icon icon="iconoir:nav-arrow-left" inline />
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink class="control-icon no-decoration" :to="state.next">
|
||||
<Icon name="iconoir:nav-arrow-right" />
|
||||
<NuxtLink class="control-icon text-inherit no-underline" :to="state.next">
|
||||
<iconify-icon icon="iconoir:nav-arrow-right" inline />
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.control {
|
||||
&-layout {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
position: fixed;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
opacity: 0.25;
|
||||
transition: 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -68,7 +68,7 @@ switch (props.icon) {
|
||||
:alt="`Download`"
|
||||
class="icon-image"
|
||||
/>
|
||||
<h3 class="mb-0 nobr">{{ props.title }}</h3>
|
||||
<h3 class="whitespace-nowrap mb-0">{{ props.title }}</h3>
|
||||
</div>
|
||||
<div class="box p-4 rounded-xl mb-4">
|
||||
<slot />
|
||||
|
||||
@@ -30,7 +30,7 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const sentence = computed(() => {
|
||||
return props.description.split('.')[0] + '...'
|
||||
return props.description.split('.').at(0) + '...'
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -50,9 +50,9 @@ const sentence = computed(() => {
|
||||
|
||||
<div class="mb-5 px-5" style="text-shadow: black 1px 1px 10px">
|
||||
<h1 class="m-0 text-[60px]">{{ title }}</h1>
|
||||
<strong class="min-h-[90px] m-0 text-[24px]" style="font-family: Lato">{{
|
||||
sentence
|
||||
}}</strong>
|
||||
<strong class="min-h-[90px] m-0 text-[24px]" style="font-family: Lato">
|
||||
{{ sentence }}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user