Repository navigation
Expand file tree
/
Copy patherror.vue
More file actions
133 lines (116 loc) · 3.02 KB
/
Copy patherror.vue
File metadata and controls
133 lines (116 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<template>
<NuxtLayout name="default">
<main class="mt-main container-fluid grid grid-cols-1 gap-container pb-container">
<section class="container card grid bg-secondary gap-card-sm style-card">
<div :title="error?.statusCode?.toString()" class="error-code text-accent">
{{ error?.statusCode }}
</div>
<h1 class="error-message" style="word-break: break-word">{{ t(messageKey) }}</h1>
<InputBtn class="w-full" @click="navigateTo('/')">{{ t("Links.BackToHome") }}</InputBtn>
</section>
</main>
</NuxtLayout>
<!-- The error entry replaces app.vue, so it owns the same single footer. -->
<LazyClientOnly>
<Footer />
<FeedbackLauncher />
</LazyClientOnly>
</template>
<script setup lang="ts">
import type { NuxtError } from "#app";
import { useI18n } from "vue-i18n";
import { pageTitle } from "~/utils/siteHead";
const props = defineProps({
error: Object as () => NuxtError,
});
const { t } = useI18n();
/*
The message Nuxt puts on the error is written by the framework and is always
English, which is the wrong language inside a German interface. The status
code is shown above it, so the sentence only has to say what happened.
*/
const messageKey = computed(() =>
props.error?.statusCode == 404 ? "Body.PageNotFound" : "Body.UnexpectedError"
);
// An address without a page must not end up in a search index. The host answers every
// address with the app and the status 200, so the page itself has to say so.
useHead(() => ({
title: pageTitle(t(messageKey.value)),
meta: [{ name: "robots", content: "noindex" }],
}));
</script>
<style scoped>
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.error-code {
text-align: center;
font-family: "Ubuntu Mono", monospace;
font-size: min(35vw, 200px);
animation: glitch 1s linear infinite;
}
.error-message {
text-align: center;
font-size: min(10vw, 80px);
margin-bottom: 50px;
}
/* https://codepen.io/pgalor/pen/OeRWJQ */
@keyframes glitch {
2%,
64% {
transform: translate(2px, 0) skew(0deg);
}
4%,
60% {
transform: translate(-2px, 0) skew(0deg);
}
62% {
transform: translate(0, 0) skew(5deg);
}
}
div:before,
div:after {
content: attr(title);
position: absolute;
left: 0;
}
div:before {
animation: glitchTop 1s linear infinite;
clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
-webkit-clip-path: polygon(0 0, 100% 0, 100% 33%, 0 33%);
}
@keyframes glitchTop {
2%,
64% {
transform: translate(2px, -2px);
}
4%,
60% {
transform: translate(-2px, 2px);
}
62% {
transform: translate(13px, -1px) skew(-13deg);
}
}
div:after {
animation: glitchBotom 1.5s linear infinite;
clip-path: polygon(0 67%, 100% 67%, 100% 100%, 0 100%);
-webkit-clip-path: polygon(0 67%, 100% 67%, 100% 100%, 0 100%);
}
@keyframes glitchBotom {
2%,
64% {
transform: translate(-2px, 0);
}
4%,
60% {
transform: translate(-2px, 0);
}
62% {
transform: translate(-22px, 5px) skew(21deg);
}
}
</style>