1use dioxus::prelude::*;
5
6use crate::router::Route;
7
8const LINKS: &[(&str, &str, &str)] = &[(
10 "/doc/yggdrasil/index.html",
11 "站点文档",
12 "这棵树是如何长成的",
13)];
14
15#[component]
16pub fn About() -> Element {
17 rsx! {
18 article { class: "about-page",
19 header { class: "about-hero",
20 div { class: "about-hero-copy",
21 p { class: "about-eyebrow", span {} "ABOUT / 关于这里" }
22 h1 {
23 "世界遗忘的,"
24 span { "树记得。" }
25 }
26 p { class: "about-hero-description",
27 "在时间的缝隙里,种下一些文字。"
28 br {}
29 "让想法生根,让记忆有迹可循。"
30 }
31 Link { class: "about-reading-link", to: Route::Archives {},
32 "翻阅这里的故事"
33 span { class: "about-arrow", aria_hidden: "true", "↗" }
34 }
35 }
36 WorldTree {}
37 }
38
39 section { class: "about-story about-enter", style: "--about-delay: 120ms",
40 aria_labelledby: "about-name-title",
41 div { class: "about-section-label",
42 span { class: "about-index", aria_hidden: "true", "01 / ROOTS" }
43 h2 { id: "about-name-title", "名字的根须" }
44 }
45 div { class: "about-story-copy",
46 p { class: "about-name", "Yggdrasil" span { "世界树" } }
47 p { "北欧神话中的世界树,根须贯穿九界,枝叶承载记忆。" }
48 p { "这里是它的一小片枝叶。写下所见、所想,也收留那些不想忘记的瞬间。" }
49 }
50 }
51
52 section { class: "about-memory about-enter", style: "--about-delay: 200ms",
53 aria_label: "关于记忆与书写",
54 span { class: "about-quote-mark", aria_hidden: "true", "“" }
55 blockquote {
56 p { "世界……遗忘我……" }
57 footer { "—— 大慈树王" }
58 }
59 div { class: "about-memory-response",
60 span { class: "about-small-rule", aria_hidden: "true" }
61 p { "人会遗忘,也终将被遗忘。" }
62 p { "而写下的,会替我们记得。" }
63 }
64 details { class: "about-footnote",
65 summary {
66 span { "这句引文,与这棵树" }
67 span { class: "about-plus", aria_hidden: "true" }
68 }
69 div { class: "about-footnote-copy",
70 p { "这句话来自大慈树王将自己从世界树(Irminsul)中抹除时的请求。" }
71 p { "一个故事里的世界树选择遗忘,另一个名字里的世界树收留记忆。于是,这里有了一个小小的回应:世界遗忘的,树记得。" }
72 }
73 }
74 }
75
76 section { class: "about-rings about-enter", style: "--about-delay: 280ms",
77 aria_labelledby: "about-rings-title",
78 div { class: "about-rings-heading",
79 div { class: "about-section-label",
80 span { class: "about-index", aria_hidden: "true", "02 / GROWTH" }
81 h2 { id: "about-rings-title", "生长的年轮" }
82 }
83 p { "每一次记录,都留下一圈纹路。" }
84 }
85 div { class: "about-link-grid",
86 Link { class: "about-ring-card", to: Route::Changelog {},
87 span { class: "about-card-top", aria_hidden: "true",
88 span { class: "about-ring-symbol", span {} span {} span {} }
89 span { class: "about-card-kicker", "THE CHANGELOG" }
90 }
91 span { class: "about-card-title", "更新日志" }
92 span { class: "about-card-description", "每一圈年轮,都是一次生长" }
93 span { class: "about-card-arrow about-arrow", aria_hidden: "true", "→" }
94 }
95 for (href, name, description) in LINKS.iter().copied() {
96 a {
97 key: "{href}",
98 class: "about-ring-card about-doc-card",
99 href,
100 target: "_blank",
101 rel: "noopener noreferrer",
102 aria_label: "{name}:{description}(在新标签页打开)",
103 span { class: "about-card-top", aria_hidden: "true",
104 svg { class: "about-book-symbol", view_box: "0 0 40 40", fill: "none",
105 path { d: "M20 10C15 6 9 6 4 8V31C9 29 15 29 20 33C25 29 31 29 36 31V8C31 6 25 6 20 10ZM20 10V33M9 13C12 12 15 13 16 14M9 19C12 18 15 19 16 20M25 14C28 12 30 12 32 13", stroke: "currentColor", stroke_width: "1.3", stroke_linecap: "round", stroke_linejoin: "round" }
106 }
107 span { class: "about-card-kicker", "FIELD NOTES" }
108 }
109 span { class: "about-card-title", "{name}" }
110 span { class: "about-card-description", "{description}" }
111 span { class: "about-card-arrow about-arrow", aria_hidden: "true", "↗" }
112 }
113 }
114 }
115 }
116
117 footer { class: "about-colophon about-enter", style: "--about-delay: 340ms",
118 span { class: "about-colophon-star", aria_hidden: "true", "✳" }
119 p { "生长未完,故事继续。" }
120 span { class: "about-colophon-name", "YGGDRASIL · A PLACE TO REMEMBER" }
121 }
122 }
123 }
124}
125
126#[component]
128fn WorldTree() -> Element {
129 let mut grown = use_signal(|| false);
130 let leaves = [
131 (200, 80, -40),
132 (184, 99, -110),
133 (218, 106, -10),
134 (168, 120, -135),
135 (235, 128, -5),
136 (143, 139, -135),
137 (256, 146, 5),
138 (114, 159, -145),
139 (281, 169, 15),
140 (154, 171, -100),
141 (244, 181, -5),
142 (177, 151, -120),
143 (222, 159, -25),
144 (132, 190, -150),
145 (263, 204, 20),
146 (100, 206, -150),
147 (298, 218, 25),
148 (168, 210, -120),
149 (229, 219, -15),
150 (144, 226, -160),
151 (250, 239, 25),
152 (186, 188, -110),
153 (212, 198, -30),
154 (199, 126, -55),
155 ];
156
157 rsx! {
158 figure { class: "about-tree-figure about-enter", style: "--about-delay: 100ms",
159 button {
160 class: "about-tree",
161 r#type: "button",
162 aria_label: "让记忆生长",
163 aria_pressed: "{grown}",
164 aria_describedby: "about-tree-caption",
165 "data-grown": "{grown}",
166 onclick: move |_| grown.toggle(),
167 span { class: "about-tree-glow", aria_hidden: "true" }
168 svg {
169 class: "about-tree-art",
170 view_box: "0 0 400 440",
171 fill: "none",
172 "aria-hidden": "true",
173 g { class: "about-tree-orbits", stroke: "currentColor", stroke_width: "0.7",
174 circle { cx: "200", cy: "208", r: "154" }
175 circle { cx: "200", cy: "208", r: "137", stroke_dasharray: "2 7" }
176 ellipse { cx: "200", cy: "208", rx: "170", ry: "115", transform: "rotate(-42 200 208)" }
177 path { d: "M200 40V51M200 365V376M32 208H43M357 208H368" }
178 }
179 g { class: "about-tree-stars", fill: "currentColor",
180 path { d: "M307 81L309 88L316 90L309 92L307 99L305 92L298 90L305 88ZM79 274L81 279L86 281L81 283L79 288L77 283L72 281L77 279Z" }
181 circle { cx: "94", cy: "111", r: "2.5" }
182 circle { cx: "330", cy: "247", r: "2" }
183 circle { cx: "263", cy: "62", r: "1.5" }
184 }
185 g { class: "about-tree-roots", stroke: "currentColor", stroke_width: "1.2", stroke_linecap: "round",
186 path { d: "M198 284C193 308 177 310 156 327L133 341M202 284C207 307 227 315 251 332L267 341M199 292L191 324L177 348M203 297L216 329L221 353M200 314V359M184 306L160 311L143 320M221 310L245 314L265 326M163 322L156 342M240 326L247 348M191 324L181 330M216 329L233 339" }
187 path { class: "about-tree-ground", d: "M102 286C155 282 243 282 298 286" }
188 }
189 g { class: "about-tree-branches", stroke: "currentColor", stroke_linecap: "round", stroke_linejoin: "round",
190 path { stroke_width: "3", d: "M198 287C202 263 194 244 201 221C207 198 193 182 200 159C205 136 195 111 200 84" }
191 path { stroke_width: "1.7", d: "M201 263C180 240 150 245 128 224L104 209M199 246C220 232 261 241 281 226L296 219M200 224C180 207 157 207 145 188L117 162M200 206C222 195 258 198 278 174M198 183C172 171 163 148 146 142M202 170C217 159 239 154 253 149M200 149C179 140 178 128 171 122M201 137L231 131M198 113L187 102M199 123L215 110" }
192 path { stroke_width: "1.1", d: "M158 240L146 229M165 241L170 214M256 239L252 241M233 235L230 223M147 189L134 192M159 202L155 174M247 197L246 184M259 195L263 204M179 167L179 154M218 161L221 161M192 201L187 191M203 219L211 202" }
193 }
194 g { class: "about-tree-leaves",
195 for (index, (x, y, angle)) in leaves.iter().enumerate() {
196 g { key: "{index}", transform: "translate({x} {y}) rotate({angle})",
197 path {
198 class: if index % 3 == 0 { "about-tree-leaf about-tree-new-leaf" } else { "about-tree-leaf" },
199 style: "--leaf-delay: {index % 6 * 45}ms",
200 d: "M0 0C-6-10-4-22 0-27C8-20 10-8 0 0Z",
201 }
202 }
203 }
204 }
205 circle { class: "about-tree-seed", cx: "200", cy: "284", r: "4", fill: "currentColor" }
206 }
207 span { class: "about-tree-touch", aria_hidden: "true", "✳" }
208 }
209 figcaption { id: "about-tree-caption", class: "about-tree-caption", aria_live: "polite",
210 if grown() {
211 "一片新叶,一段被留下的记忆"
212 } else {
213 "轻触这棵树,让记忆生长"
214 }
215 }
216 }
217 }
218}