tangled
alpha
login
or
join now
vielle.dev
/
site-archive
0
fork
atom
[Archived] Archived WIP of vielle.dev
0
fork
atom
overview
issues
pulls
pipelines
Move <code-heading /> definition to seperate component
vielle.dev
8 months ago
99a60361
098959cc
verified
This commit was signed with the committer's
known signature
.
vielle.dev
SSH Key Fingerprint:
SHA256:/4bvxqoEh9iMdjAPgcgAgXKZZQTROL3ULiPt6nH9RSs=
+152
-130
2 changed files
expand all
collapse all
unified
split
src
components
blog
CodeHeading.astro
pages
blog
[id].astro
+150
src/components/blog/CodeHeading.astro
···
1
1
+
---
2
2
+
import Copy from "@/assets/copy.svg";
3
3
+
4
4
+
interface Props {
5
5
+
colours: { text: string; border: string };
6
6
+
}
7
7
+
8
8
+
const { colours } = Astro.props;
9
9
+
---
10
10
+
11
11
+
<template id="code-heading">
12
12
+
<!-- slots need to be set using set:html
13
13
+
else it is treated as astro slot -->
14
14
+
<span class="lang"><Fragment set:html={"<slot>.txt</slot>"} /></span>
15
15
+
<span id="copied" style="visibility:hidden" role="alert">Copied!</span>
16
16
+
<button id="copy"><Copy /></button>
17
17
+
18
18
+
<!-- define:vars didnt work :( -->
19
19
+
<style
20
20
+
set:html={`
21
21
+
:host {
22
22
+
--text: ${colours.text};
23
23
+
--border: ${colours.border};
24
24
+
}
25
25
+
`}
26
26
+
></style>
27
27
+
28
28
+
<style>
29
29
+
@keyframes teeter {
30
30
+
from,
31
31
+
to {
32
32
+
rotate: 0deg;
33
33
+
}
34
34
+
25% {
35
35
+
rotate: 15deg;
36
36
+
}
37
37
+
75% {
38
38
+
rotate: -15deg;
39
39
+
}
40
40
+
}
41
41
+
42
42
+
.lang {
43
43
+
color: var(--text);
44
44
+
}
45
45
+
46
46
+
button {
47
47
+
border: none;
48
48
+
background: none;
49
49
+
aspect-ratio: 1;
50
50
+
border-radius: 100%;
51
51
+
52
52
+
display: flex;
53
53
+
align-items: center;
54
54
+
justify-content: center;
55
55
+
56
56
+
&:hover,
57
57
+
&:focus {
58
58
+
scale: 1.2;
59
59
+
outline: none;
60
60
+
background-color: #ffffff20;
61
61
+
}
62
62
+
63
63
+
&:active {
64
64
+
scale: 1.4;
65
65
+
animation: teeter 0.2s;
66
66
+
}
67
67
+
68
68
+
& svg {
69
69
+
stroke: var(--text);
70
70
+
margin: 0.2rem;
71
71
+
}
72
72
+
}
73
73
+
74
74
+
:host {
75
75
+
display: flex block;
76
76
+
justify-content: space-between;
77
77
+
align-items: center;
78
78
+
/* gets overridden by * because why not ig */
79
79
+
padding: 1rem !important;
80
80
+
position: sticky;
81
81
+
top: 0;
82
82
+
left: 0;
83
83
+
border-bottom: 0.4rem solid var(--border);
84
84
+
user-select: none;
85
85
+
}
86
86
+
</style>
87
87
+
</template>
88
88
+
89
89
+
<script>
90
90
+
class CodeHeading extends HTMLElement {
91
91
+
contents = "";
92
92
+
static observedAttributes = ["contents"];
93
93
+
94
94
+
template: HTMLTemplateElement;
95
95
+
content: DocumentFragment;
96
96
+
shadowRoot: ShadowRoot;
97
97
+
98
98
+
constructor() {
99
99
+
super();
100
100
+
const template = document.getElementById("code-heading");
101
101
+
if (!template || !(template instanceof HTMLTemplateElement))
102
102
+
throw new Error("Could not get #code-heading");
103
103
+
this.template = template;
104
104
+
this.content = template.content;
105
105
+
106
106
+
this.shadowRoot = this.attachShadow({ mode: "open" });
107
107
+
this.shadowRoot.appendChild(this.content.cloneNode(true));
108
108
+
109
109
+
const copy = this.shadowRoot.getElementById("copy");
110
110
+
if (!copy) throw new Error("No #copy in #code-heading");
111
111
+
112
112
+
const copied = this.shadowRoot.getElementById("copied");
113
113
+
if (!copied) throw new Error("No #copied in #code-heading");
114
114
+
115
115
+
const copied_animation = {
116
116
+
opacity: [0, 1],
117
117
+
visibility: ["hidden", "visible"],
118
118
+
};
119
119
+
120
120
+
copy.addEventListener("click", () => {
121
121
+
navigator.clipboard
122
122
+
.writeText(this.contents)
123
123
+
.catch((e) => {
124
124
+
console.error("Encountered error copying to clipboard;", e);
125
125
+
})
126
126
+
.then(async () => {
127
127
+
await copied.animate(copied_animation, {
128
128
+
duration: 200,
129
129
+
fill: "forwards",
130
130
+
}).finished;
131
131
+
132
132
+
copied.animate(copied_animation, {
133
133
+
duration: 200,
134
134
+
delay: 2000,
135
135
+
fill: "forwards",
136
136
+
direction: "reverse",
137
137
+
});
138
138
+
});
139
139
+
});
140
140
+
}
141
141
+
142
142
+
attributeChangedCallback(name: string, _: any, newV?: string) {
143
143
+
if (name == "contents") {
144
144
+
this.contents = newV ?? "";
145
145
+
}
146
146
+
}
147
147
+
}
148
148
+
149
149
+
customElements.define("code-heading", CodeHeading);
150
150
+
</script>
+2
-130
src/pages/blog/[id].astro
···
3
3
import Nav from "@/components/generic/Nav.astro";
4
4
import LightDarkToggle from "@/components/generic/LightDarkToggle.astro";
5
5
6
6
-
import Copy from "@/assets/copy.svg";
7
7
-
8
6
import { blog } from "@/config";
9
7
const {
10
8
post: { light, dark, rainbow },
···
15
13
import { parse } from "node:path";
16
14
17
15
import "@/components/blog/post.css";
16
16
+
import CodeHeading from "@/components/blog/CodeHeading.astro";
18
17
19
18
const { id } = Astro.params;
20
19
if (!id) return Astro.redirect("/404");
···
54
53
</main>
55
54
</Base>
56
55
57
57
-
<template id="code-heading">
58
58
-
<!-- slots need to be set using set:html
59
59
-
else it is treated as astro slot -->
60
60
-
<span class="lang"><Fragment set:html={"<slot>.txt</slot>"} /></span>
61
61
-
<span id="copied" style="visibility:hidden" role="alert">Copied!</span>
62
62
-
<button id="copy"><Copy /></button>
63
63
-
64
64
-
<style>
65
65
-
@keyframes teeter {
66
66
-
from,
67
67
-
to {
68
68
-
rotate: 0deg;
69
69
-
}
70
70
-
25% {
71
71
-
rotate: 15deg;
72
72
-
}
73
73
-
75% {
74
74
-
rotate: -15deg;
75
75
-
}
76
76
-
}
77
77
-
78
78
-
.lang {
79
79
-
color: var(--typo-body);
80
80
-
}
81
81
-
82
82
-
button {
83
83
-
border: none;
84
84
-
background: none;
85
85
-
aspect-ratio: 1;
86
86
-
border-radius: 100%;
87
87
-
88
88
-
display: flex;
89
89
-
align-items: center;
90
90
-
justify-content: center;
91
91
-
92
92
-
&:hover,
93
93
-
&:focus {
94
94
-
scale: 1.2;
95
95
-
outline: none;
96
96
-
background-color: #ffffff20;
97
97
-
}
98
98
-
99
99
-
&:active {
100
100
-
scale: 1.4;
101
101
-
animation: teeter 0.2s;
102
102
-
}
103
103
-
104
104
-
& svg {
105
105
-
stroke: var(--typo-body);
106
106
-
margin: 0.2rem;
107
107
-
}
108
108
-
}
109
109
-
110
110
-
:host {
111
111
-
display: flex block;
112
112
-
justify-content: space-between;
113
113
-
align-items: center;
114
114
-
/* gets overridden by * because why not ig */
115
115
-
padding: 1rem !important;
116
116
-
position: sticky;
117
117
-
top: 0;
118
118
-
left: 0;
119
119
-
border-bottom: 0.4rem solid var(--bg-main);
120
120
-
user-select: none;
121
121
-
}
122
122
-
</style>
123
123
-
</template>
56
56
+
<CodeHeading colours={{ text: "var(--typo-body)", border: "var(--bg-main)" }} />
124
57
125
58
<script>
126
126
-
class CodeHeading extends HTMLElement {
127
127
-
contents = "";
128
128
-
static observedAttributes = ["contents"];
129
129
-
130
130
-
template: HTMLTemplateElement;
131
131
-
content: DocumentFragment;
132
132
-
shadowRoot: ShadowRoot;
133
133
-
134
134
-
constructor() {
135
135
-
super();
136
136
-
const template = document.getElementById("code-heading");
137
137
-
if (!template || !(template instanceof HTMLTemplateElement))
138
138
-
throw new Error("Could not get #code-heading");
139
139
-
this.template = template;
140
140
-
this.content = template.content;
141
141
-
142
142
-
this.shadowRoot = this.attachShadow({ mode: "open" });
143
143
-
this.shadowRoot.appendChild(this.content.cloneNode(true));
144
144
-
145
145
-
const copy = this.shadowRoot.getElementById("copy");
146
146
-
if (!copy) throw new Error("No #copy in #code-heading");
147
147
-
148
148
-
const copied = this.shadowRoot.getElementById("copied");
149
149
-
if (!copied) throw new Error("No #copied in #code-heading");
150
150
-
151
151
-
const copied_animation = {
152
152
-
opacity: [0, 1],
153
153
-
visibility: ["hidden", "visible"],
154
154
-
};
155
155
-
156
156
-
copy.addEventListener("click", () => {
157
157
-
navigator.clipboard
158
158
-
.writeText(this.contents)
159
159
-
.catch((e) => {
160
160
-
console.error("Encountered error copying to clipboard;", e);
161
161
-
})
162
162
-
.then(async () => {
163
163
-
await copied.animate(copied_animation, {
164
164
-
duration: 200,
165
165
-
fill: "forwards",
166
166
-
}).finished;
167
167
-
168
168
-
copied.animate(copied_animation, {
169
169
-
duration: 200,
170
170
-
delay: 2000,
171
171
-
fill: "forwards",
172
172
-
direction: "reverse",
173
173
-
});
174
174
-
});
175
175
-
});
176
176
-
}
177
177
-
178
178
-
attributeChangedCallback(name: string, _: any, newV?: string) {
179
179
-
if (name == "contents") {
180
180
-
this.contents = newV ?? "";
181
181
-
}
182
182
-
}
183
183
-
}
184
184
-
185
185
-
customElements.define("code-heading", CodeHeading);
186
186
-
187
59
document.querySelectorAll(".astro-code").forEach((code) => {
188
60
if (!(code instanceof HTMLElement)) return;
189
61