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 Link { class: "about-writing-card about-enter", to: Route::WritingGuide {},
118 style: "--about-delay: 320ms",
119 div {
120 span { class: "about-index", "03 / COLLABORATE" }
121 h2 { "与 Agent 一起,种下文字。" }
122 p { "把这里的写作方式,交给你的 AI。" }
123 span { class: "about-writing-tags", "SKILL.md · MCP · 可运行代码 · 图表与公式" }
124 }
125 span { class: "about-writing-action", "打开写作指南" span { aria_hidden: "true", "↗" } }
126 }
127
128 Link { class: "showcase-entry about-enter", to: Route::ComponentShowcase {},
129 style: "--about-delay: 340ms",
130 div { class: "showcase-entry-copy",
131 span { class: "about-index", "04 / CRAFT & DETAILS" }
132 h2 { "界面的枝叶。" }
133 p { "从一枚按钮,到一次温柔的回应。" br {} "看看组成这棵树的那些小细节。" }
134 span { class: "showcase-entry-action", "打开组件图鉴" span { aria_hidden: "true", "→" } }
135 }
136 div { class: "showcase-entry-art", aria_hidden: "true",
137 div { class: "showcase-entry-specimen",
138 span { "YGGDRASIL / UI" }
139 strong { "每个细节,都有回应。" }
140 div { "让想法生根" i { class: "showcase-entry-switch" } }
141 }
142 span { class: "showcase-entry-mark", "✓ 已收藏" }
143 span { class: "showcase-entry-code", "COMPONENT ATLAS · LIVE PREVIEW" }
144 }
145 }
146
147 footer { class: "about-colophon about-enter", style: "--about-delay: 380ms",
148 span { class: "about-colophon-star", aria_hidden: "true", "✳" }
149 p { "生长未完,故事继续。" }
150 span { class: "about-colophon-name", "YGGDRASIL · A PLACE TO REMEMBER" }
151 }
152 }
153 }
154}
155
156#[component]
158fn WorldTree() -> Element {
159 let mut grown = use_signal(|| false);
160 let leaves = [
161 (200, 80, -40),
162 (184, 99, -110),
163 (218, 106, -10),
164 (168, 120, -135),
165 (235, 128, -5),
166 (143, 139, -135),
167 (256, 146, 5),
168 (114, 159, -145),
169 (281, 169, 15),
170 (154, 171, -100),
171 (244, 181, -5),
172 (177, 151, -120),
173 (222, 159, -25),
174 (132, 190, -150),
175 (263, 204, 20),
176 (100, 206, -150),
177 (298, 218, 25),
178 (168, 210, -120),
179 (229, 219, -15),
180 (144, 226, -160),
181 (250, 239, 25),
182 (186, 188, -110),
183 (212, 198, -30),
184 (199, 126, -55),
185 ];
186
187 rsx! {
188 figure { class: "about-tree-figure about-enter", style: "--about-delay: 100ms",
189 button {
190 class: "about-tree",
191 r#type: "button",
192 aria_label: "让记忆生长",
193 aria_pressed: "{grown}",
194 aria_describedby: "about-tree-caption",
195 "data-grown": "{grown}",
196 onclick: move |_| grown.toggle(),
197 span { class: "about-tree-glow", aria_hidden: "true" }
198 svg {
199 class: "about-tree-art",
200 view_box: "0 0 400 440",
201 fill: "none",
202 "aria-hidden": "true",
203 g { class: "about-tree-orbits", stroke: "currentColor", stroke_width: "0.7",
204 circle { cx: "200", cy: "208", r: "154" }
205 circle { cx: "200", cy: "208", r: "137", stroke_dasharray: "2 7" }
206 ellipse { cx: "200", cy: "208", rx: "170", ry: "115", transform: "rotate(-42 200 208)" }
207 path { d: "M200 40V51M200 365V376M32 208H43M357 208H368" }
208 }
209 g { class: "about-tree-stars", fill: "currentColor",
210 path { d: "M307 81L309 88L316 90L309 92L307 99L305 92L298 90L305 88ZM79 274L81 279L86 281L81 283L79 288L77 283L72 281L77 279Z" }
211 circle { cx: "94", cy: "111", r: "2.5" }
212 circle { cx: "330", cy: "247", r: "2" }
213 circle { cx: "263", cy: "62", r: "1.5" }
214 }
215 g { class: "about-tree-roots", stroke: "currentColor", stroke_width: "1.2", stroke_linecap: "round",
216 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" }
217 path { class: "about-tree-ground", d: "M102 286C155 282 243 282 298 286" }
218 }
219 g { class: "about-tree-branches", stroke: "currentColor", stroke_linecap: "round", stroke_linejoin: "round",
220 path { stroke_width: "3", d: "M198 287C202 263 194 244 201 221C207 198 193 182 200 159C205 136 195 111 200 84" }
221 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" }
222 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" }
223 }
224 g { class: "about-tree-leaves",
225 for (index, (x, y, angle)) in leaves.iter().enumerate() {
226 g { key: "{index}", transform: "translate({x} {y}) rotate({angle})",
227 path {
228 class: if index % 3 == 0 { "about-tree-leaf about-tree-new-leaf" } else { "about-tree-leaf" },
229 style: "--leaf-delay: {index % 6 * 45}ms",
230 d: "M0 0C-6-10-4-22 0-27C8-20 10-8 0 0Z",
231 }
232 }
233 }
234 }
235 circle { class: "about-tree-seed", cx: "200", cy: "284", r: "4", fill: "currentColor" }
236 }
237 span { class: "about-tree-touch", aria_hidden: "true", "✳" }
238 }
239 figcaption { id: "about-tree-caption", class: "about-tree-caption", aria_live: "polite",
240 if grown() {
241 "一片新叶,一段被留下的记忆"
242 } else {
243 "轻触这棵树,让记忆生长"
244 }
245 }
246 }
247 }
248}