1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum Status {
28 Confirmed,
30 Emerging,
32 Retired,
34}
35
36pub struct DataAttr {
38 pub name: &'static str,
40 pub values: &'static [&'static str],
42 pub default: &'static str,
44 pub description: &'static str,
46}
47
48pub struct ComponentEntry {
50 pub class: &'static str,
52 pub kind: &'static str,
54 pub parent: &'static str,
56 pub data_attrs: &'static [DataAttr],
58 pub example_html: &'static str,
60 pub example_markdown: &'static str,
62 pub status: Status,
64 pub since: &'static str,
66 pub description: &'static str,
68}
69
70pub const COMPONENTS: &[ComponentEntry] = &[
75 ComponentEntry {
76 class: "moss-cards",
77 kind: "container",
78 parent: "",
79 data_attrs: &[
80 DataAttr {
81 name: "data-layout",
82 values: &["grid", "list", "minimal"],
83 default: "grid",
84 description: "Card layout density. Grid: 2-3 cols with covers. List: single column with side covers. Minimal: text-only with year groupings.",
85 },
86 DataAttr {
87 name: "data-density",
88 values: &["default", "compact"],
89 default: "default",
90 description: "Vertical spacing density.",
91 },
92 DataAttr {
93 name: "data-list-axis",
94 values: &["date", "weight", "title"],
95 default: "title",
96 description: "Sort axis for the listing (mirrors the folder's `sort:` frontmatter). Drives `--moss-card-min` density tuning and decides whether each `.moss-card-meta` slot is filled (date axis) or omitted (weight/title axes).",
97 },
98 DataAttr {
99 name: "data-list-has-covers",
100 values: &[""],
101 default: "",
102 description: "Boolean presence flag: emitted iff any child card has a cover. Combines with `data-list-axis` to widen `--moss-card-min` for cover-led layouts. Use `[data-list-has-covers]` in CSS to target it.",
103 },
104 ],
105 example_html: r#"<div class="moss-cards-container">
106 <div class="moss-cards" data-layout="grid" data-list-axis="date" data-list-has-covers>
107 <a class="moss-card" href="...">...</a>
108 <a class="moss-card" href="...">...</a>
109 </div>
110</div>"#,
111 example_markdown: "",
112 status: Status::Confirmed,
113 since: "1",
114 description: "Auto-generated listing of child pages. The single canonical container; layout density on `data-layout` (`grid` for cover-led tiles, `list` for cover+excerpt rows, `minimal` for text-only year-grouped indexes). Wrapped in `.moss-cards-container` to scope CSS container queries.",
115 },
116 ComponentEntry {
117 class: "moss-cards-container",
118 kind: "container",
119 parent: "",
120 data_attrs: &[],
121 example_html: r#"<div class="moss-cards-container">
122 <div class="moss-cards" data-layout="grid">...</div>
123</div>"#,
124 example_markdown: "",
125 status: Status::Confirmed,
126 since: "1",
127 description: "Outer wrapper around `.moss-cards` that carries `container-type: inline-size` so the grid can use `@container` queries instead of viewport `@media` queries. Layout-agnostic — wraps any `data-layout` variant.",
128 },
129 ComponentEntry {
130 class: "moss-summary-layout",
131 kind: "container",
132 parent: "moss-cards",
133 data_attrs: &[],
134 example_html: r#"<div class="moss-cards" data-layout="list">...</div>"#,
135 example_markdown: "",
136 status: Status::Retired,
137 since: "1",
138 description: "Retired: the additional co-class on `.moss-cards[data-layout=\"list\"]` had no matching rules in the default CSS once `children_style: summary` collapsed into the list-layout block, and its lingering emission broke themes that hid the class (e.g. SoCiviC's `.moss/theme/style.css` keyed `display: none` on it, erasing folder-embed listings). Theme authors targeting summary listings should use `.moss-cards[data-layout=\"list\"]` directly.",
139 },
140 ComponentEntry {
146 class: "moss-cards-grid",
147 kind: "container",
148 parent: "",
149 data_attrs: &[],
150 example_html: r#"<div class="moss-cards-grid">
151 <a class="moss-card-grid" href="...">...</a>
152</div>"#,
153 example_markdown: "",
154 status: Status::Retired,
155 since: "0",
156 description: "Retired in Phase 1c — collapsed into `.moss-cards[data-layout=grid]`.",
157 },
158 ComponentEntry {
159 class: "moss-cards-list",
160 kind: "container",
161 parent: "",
162 data_attrs: &[],
163 example_html: r#"<div class="moss-cards-list">
164 <a class="moss-card-list" href="...">...</a>
165</div>"#,
166 example_markdown: "",
167 status: Status::Retired,
168 since: "0",
169 description: "Retired in Phase 1c — collapsed into `.moss-cards[data-layout=list]`.",
170 },
171 ComponentEntry {
172 class: "moss-cards-minimal-year-group",
173 kind: "container",
174 parent: "",
175 data_attrs: &[],
176 example_html: r#"<section class="moss-cards-minimal-year-group">
177 <h3>2024</h3>
178 <div class="moss-card-minimal">...</div>
179</section>"#,
180 example_markdown: "",
181 status: Status::Confirmed,
182 since: "0",
183 description: "Year-grouped section in minimal card layout (e.g. blog index). Modifier `--summary` collapses past years.",
184 },
185 ComponentEntry {
186 class: "moss-cards-minimal-year-group--summary",
187 kind: "container",
188 parent: "moss-cards-minimal-year-group",
189 data_attrs: &[],
190 example_html: r#"<section class="moss-cards-minimal-year-group moss-cards-minimal-year-group--summary">...</section>"#,
191 example_markdown: "",
192 status: Status::Confirmed,
193 since: "0",
194 description: "BEM modifier on `.moss-cards-minimal-year-group`. Applied to year groups that should render in collapsed summary form (e.g. past years on a blog index).",
195 },
196 ComponentEntry {
197 class: "moss-card",
198 kind: "instance",
199 parent: "moss-cards",
200 data_attrs: &[
201 DataAttr {
202 name: "data-linkblog",
203 values: &[],
204 default: "",
205 description: "Presence flag: emitted IFF the card's source page has an `external_url:` frontmatter (linkblog pattern). When set, the element is a `<div>` rather than `<a>` so the kicker can host a nested `<a>★</a>` archive link; title, cover, and description carry their own inner anchors to the canonical URL. Absent on ordinary cards (single whole-card `<a>`).",
206 },
207 ],
208 example_html: r#"<a class="moss-card" href="...">...</a>"#,
209 example_markdown: "",
210 status: Status::Confirmed,
211 since: "1",
212 description: "v1 collapsed shape — single canonical instance class inside `.moss-cards`. Layout-specific styling targets `.moss-cards[data-layout=X] .moss-card`. Tag is `<a>` for ordinary cards and `<div>` for linkblog cards (`[data-linkblog]`).",
213 },
214 ComponentEntry {
215 class: "moss-card-cover",
216 kind: "instance",
217 parent: "moss-card",
218 data_attrs: &[],
219 example_html: r#"<div class="moss-card-cover"><img src="..." /></div>"#,
220 example_markdown: "",
221 status: Status::Confirmed,
222 since: "1",
223 description: "Cover media slot inside `.moss-card`. Gets `.moss-card-no-cover` modifier when no image is present.",
224 },
225 ComponentEntry {
226 class: "moss-card-no-cover",
227 kind: "instance",
228 parent: "moss-card",
229 data_attrs: &[],
230 example_html: r#"<div class="moss-card-cover moss-card-no-cover"></div>"#,
231 example_markdown: "",
232 status: Status::Confirmed,
233 since: "1",
234 description: "Modifier applied to `.moss-card-cover` when no cover media is available.",
235 },
236 ComponentEntry {
237 class: "moss-card-content",
238 kind: "instance",
239 parent: "moss-card",
240 data_attrs: &[],
241 example_html: r#"<div class="moss-card-content">...</div>"#,
242 example_markdown: "",
243 status: Status::Confirmed,
244 since: "1",
245 description: "Text content slot inside a grid-layout `.moss-card` (kicker + title + meta).",
246 },
247 ComponentEntry {
248 class: "moss-card-row",
249 kind: "instance",
250 parent: "moss-card",
251 data_attrs: &[],
252 example_html: r#"<div class="moss-card-row">...</div>"#,
253 example_markdown: "",
254 status: Status::Confirmed,
255 since: "1",
256 description: "Row wrapper inside a list-layout `.moss-card` holding body + cover side-by-side.",
257 },
258 ComponentEntry {
259 class: "moss-card-body",
260 kind: "instance",
261 parent: "moss-card",
262 data_attrs: &[],
263 example_html: r#"<div class="moss-card-body">...</div>"#,
264 example_markdown: "",
265 status: Status::Confirmed,
266 since: "1",
267 description: "Text body slot of a list-layout `.moss-card`.",
268 },
269 ComponentEntry {
270 class: "moss-card-head",
271 kind: "instance",
272 parent: "moss-card",
273 data_attrs: &[],
274 example_html: r#"<div class="moss-card-head">...</div>"#,
275 example_markdown: "",
276 status: Status::Confirmed,
277 since: "1",
278 description: "Header row of a `.moss-card-body` (title + kicker + meta).",
279 },
280 ComponentEntry {
281 class: "moss-card-title",
282 kind: "instance",
283 parent: "moss-card",
284 data_attrs: &[],
285 example_html: r#"<h3 class="moss-card-title">Page title</h3>"#,
286 example_markdown: "",
287 status: Status::Confirmed,
288 since: "1",
289 description: "Title inside `.moss-card`.",
290 },
291 ComponentEntry {
292 class: "moss-card-meta",
293 kind: "instance",
294 parent: "moss-card",
295 data_attrs: &[],
296 example_html: r#"<div class="moss-card-meta">2024-01-15</div>"#,
297 example_markdown: "",
298 status: Status::Confirmed,
299 since: "1",
300 description: "Type-aware metadata slot (date for articles, count for folders, domain for links). Renders ABOVE the title in horizontal mode — filling the kicker position when the explicit `kicker` slot is unset, per `docs/design-system/preview-cards.md:22-30`. To the right of the title in vertical CJK mode (the horizontal kicker position transposed). Meta IS the visual kicker, with the same uppercase overline treatment.",
301 },
302 ComponentEntry {
303 class: "moss-card-kicker",
304 kind: "instance",
305 parent: "moss-card",
306 data_attrs: &[],
307 example_html: r#"<span class="moss-card-kicker">Category</span>"#,
308 example_markdown: "",
309 status: Status::Confirmed,
310 since: "1",
311 description: "Eyebrow / overline above the title inside `.moss-card`.",
312 },
313 ComponentEntry {
314 class: "moss-card-permalink",
315 kind: "instance",
316 parent: "moss-card-kicker",
317 data_attrs: &[],
318 example_html: r#"<a class="moss-card-permalink" href="/posts/foo/" title="Permalink to 'Title'">★</a>"#,
319 example_markdown: "",
320 status: Status::Emerging,
321 since: "1",
322 description: "Author's-archive link mark (★, U+2605) emitted INSIDE `.moss-card-kicker` for linkblog cards (those whose child page has `external_url:`). The card title links to the external canonical (publisher); the `★` links to the local archival copy at the page's slug. Reads as part of the kicker line — \"Publisher · Year ★\". Semantically distinct from Daring-Fireball's linkblog ★ (which marks discussion permalink alongside commentary) — here the local copy is the same content preserved for resilience and stable bylines, not added commentary. Putting `<a>★</a>` inside the kicker is valid because linkblog cards emit `<div class=\"moss-card\" data-linkblog>` (not `<a>`) as the outer element — see the `data-linkblog` attribute described on `.moss-card`.",
323 },
324 ComponentEntry {
325 class: "moss-card-title-link",
326 kind: "instance",
327 parent: "moss-card-head",
328 data_attrs: &[],
329 example_html: r#"<a class="moss-card-title-link" href="https://outlet.example/article"><h3 class="moss-card-title">Article Title</h3></a>"#,
330 example_markdown: "",
331 status: Status::Emerging,
332 since: "1",
333 description: "Anchor wrapping the `.moss-card-title` `<h3>` on linkblog cards. Ordinary cards have the whole-card `<a class=\"moss-card\">` as the link target — but linkblog cards switch the outer to `<div>` so the kicker can host a nested `★` anchor, which means the title needs its own anchor to stay clickable. Same canonical-URL target as the other inner anchors (`moss-card-cover-link`, `moss-card-description-link`).",
334 },
335 ComponentEntry {
336 class: "moss-card-cover-link",
337 kind: "instance",
338 parent: "moss-card-row",
339 data_attrs: &[],
340 example_html: r#"<a class="moss-card-cover-link" href="https://outlet.example/article"><div class="moss-card-cover">...</div></a>"#,
341 example_markdown: "",
342 status: Status::Emerging,
343 since: "1",
344 description: "Anchor wrapping the `.moss-card-cover` on linkblog cards — same role as `.moss-card-title-link` but for the cover image / media. Targets the canonical (external) URL.",
345 },
346 ComponentEntry {
347 class: "moss-card-description-link",
348 kind: "instance",
349 parent: "moss-card-body",
350 data_attrs: &[],
351 example_html: r#"<a class="moss-card-description-link" href="https://outlet.example/article"><p class="moss-card-description">…</p></a>"#,
352 example_markdown: "",
353 status: Status::Emerging,
354 since: "1",
355 description: "Anchor wrapping the `.moss-card-description` on linkblog cards — same role as `.moss-card-title-link` but for the description excerpt. Targets the canonical (external) URL.",
356 },
357 ComponentEntry {
358 class: "moss-card-description",
359 kind: "instance",
360 parent: "moss-card",
361 data_attrs: &[],
362 example_html: r#"<p class="moss-card-description">Excerpt...</p>"#,
363 example_markdown: "",
364 status: Status::Confirmed,
365 since: "1",
366 description: "Excerpt / description paragraph inside a `.moss-card` — below the title in both grid- and list-layout cards.",
367 },
368 ComponentEntry {
369 class: "moss-card-count",
370 kind: "instance",
371 parent: "moss-card",
372 data_attrs: &[],
373 example_html: r#"<div class="moss-card-count">4 articles</div>"#,
374 example_markdown: "",
375 status: Status::Confirmed,
376 since: "1",
377 description: "Tertiary subtitle line showing `N articles` for a folder card. Renders only on non-date listings when the folder card has no `description` to display.",
378 },
379 ComponentEntry {
380 class: "moss-card-grid",
381 kind: "instance",
382 parent: "moss-cards-grid",
383 data_attrs: &[],
384 example_html: r#"<a class="moss-card-grid" href="...">...</a>"#,
385 example_markdown: "",
386 status: Status::Retired,
387 since: "0",
388 description: "Retired in Phase 1c — collapsed into `.moss-card` (with parent `.moss-cards[data-layout=grid]`).",
389 },
390 ComponentEntry {
391 class: "moss-card-grid-cover",
392 kind: "instance",
393 parent: "moss-card-grid",
394 data_attrs: &[],
395 example_html: r#"<div class="moss-card-grid-cover"><img src="..." /></div>"#,
396 example_markdown: "",
397 status: Status::Retired,
398 since: "0",
399 description: "Retired in Phase 1c — collapsed into `.moss-card-cover`.",
400 },
401 ComponentEntry {
402 class: "moss-card-grid-no-cover",
403 kind: "instance",
404 parent: "moss-card-grid",
405 data_attrs: &[],
406 example_html: r#"<div class="moss-card-grid-cover moss-card-grid-no-cover"></div>"#,
407 example_markdown: "",
408 status: Status::Retired,
409 since: "0",
410 description: "Retired in Phase 1c — collapsed into `.moss-card-no-cover`.",
411 },
412 ComponentEntry {
413 class: "moss-card-grid-content",
414 kind: "instance",
415 parent: "moss-card-grid",
416 data_attrs: &[],
417 example_html: r#"<div class="moss-card-grid-content">...</div>"#,
418 example_markdown: "",
419 status: Status::Retired,
420 since: "0",
421 description: "Retired in Phase 1c — collapsed into `.moss-card-content`.",
422 },
423 ComponentEntry {
424 class: "moss-card-grid-kicker",
425 kind: "instance",
426 parent: "moss-card-grid",
427 data_attrs: &[],
428 example_html: r#"<span class="moss-card-grid-kicker">Category</span>"#,
429 example_markdown: "",
430 status: Status::Retired,
431 since: "0",
432 description: "Retired in Phase 1c — collapsed into `.moss-card-kicker`.",
433 },
434 ComponentEntry {
435 class: "moss-card-grid-title",
436 kind: "instance",
437 parent: "moss-card-grid",
438 data_attrs: &[],
439 example_html: r#"<h3 class="moss-card-grid-title">Page title</h3>"#,
440 example_markdown: "",
441 status: Status::Retired,
442 since: "0",
443 description: "Retired in Phase 1c — collapsed into `.moss-card-title`.",
444 },
445 ComponentEntry {
446 class: "moss-card-grid-meta",
447 kind: "instance",
448 parent: "moss-card-grid",
449 data_attrs: &[],
450 example_html: r#"<div class="moss-card-grid-meta">2024-01-15</div>"#,
451 example_markdown: "",
452 status: Status::Retired,
453 since: "0",
454 description: "Retired in Phase 1c — collapsed into `.moss-card-meta`.",
455 },
456 ComponentEntry {
457 class: "moss-card-list",
458 kind: "instance",
459 parent: "moss-cards-list",
460 data_attrs: &[],
461 example_html: r#"<a class="moss-card-list" href="...">...</a>"#,
462 example_markdown: "",
463 status: Status::Retired,
464 since: "0",
465 description: "Retired in Phase 1c — collapsed into `.moss-card` (with parent `.moss-cards[data-layout=list]`).",
466 },
467 ComponentEntry {
468 class: "moss-card-list-row",
469 kind: "instance",
470 parent: "moss-card-list",
471 data_attrs: &[],
472 example_html: r#"<div class="moss-card-list-row">...</div>"#,
473 example_markdown: "",
474 status: Status::Retired,
475 since: "0",
476 description: "Retired in Phase 1c — collapsed into `.moss-card-row`.",
477 },
478 ComponentEntry {
479 class: "moss-card-list-cover",
480 kind: "instance",
481 parent: "moss-card-list",
482 data_attrs: &[],
483 example_html: r#"<div class="moss-card-list-cover"><img src="..." /></div>"#,
484 example_markdown: "",
485 status: Status::Retired,
486 since: "0",
487 description: "Retired in Phase 1c — collapsed into `.moss-card-cover`.",
488 },
489 ComponentEntry {
490 class: "moss-card-list-body",
491 kind: "instance",
492 parent: "moss-card-list",
493 data_attrs: &[],
494 example_html: r#"<div class="moss-card-list-body">...</div>"#,
495 example_markdown: "",
496 status: Status::Retired,
497 since: "0",
498 description: "Retired in Phase 1c — collapsed into `.moss-card-body`.",
499 },
500 ComponentEntry {
501 class: "moss-card-list-head",
502 kind: "instance",
503 parent: "moss-card-list",
504 data_attrs: &[],
505 example_html: r#"<div class="moss-card-list-head">...</div>"#,
506 example_markdown: "",
507 status: Status::Retired,
508 since: "0",
509 description: "Retired in Phase 1c — collapsed into `.moss-card-head`.",
510 },
511 ComponentEntry {
512 class: "moss-card-list-kicker",
513 kind: "instance",
514 parent: "moss-card-list",
515 data_attrs: &[],
516 example_html: r#"<span class="moss-card-list-kicker">Category</span>"#,
517 example_markdown: "",
518 status: Status::Retired,
519 since: "0",
520 description: "Retired in Phase 1c — collapsed into `.moss-card-kicker`.",
521 },
522 ComponentEntry {
523 class: "moss-card-list-title",
524 kind: "instance",
525 parent: "moss-card-list",
526 data_attrs: &[],
527 example_html: r#"<h3 class="moss-card-list-title">Page title</h3>"#,
528 example_markdown: "",
529 status: Status::Retired,
530 since: "0",
531 description: "Retired in Phase 1c — collapsed into `.moss-card-title`.",
532 },
533 ComponentEntry {
534 class: "moss-card-list-meta",
535 kind: "instance",
536 parent: "moss-card-list",
537 data_attrs: &[],
538 example_html: r#"<div class="moss-card-list-meta">2024-01-15</div>"#,
539 example_markdown: "",
540 status: Status::Retired,
541 since: "0",
542 description: "Retired in Phase 1c — collapsed into `.moss-card-meta`.",
543 },
544 ComponentEntry {
545 class: "moss-card-list-description",
546 kind: "instance",
547 parent: "moss-card-list",
548 data_attrs: &[],
549 example_html: r#"<p class="moss-card-list-description">Excerpt...</p>"#,
550 example_markdown: "",
551 status: Status::Retired,
552 since: "0",
553 description: "Retired in Phase 1c — collapsed into `.moss-card-description`.",
554 },
555 ComponentEntry {
556 class: "moss-card-minimal",
557 kind: "instance",
558 parent: "moss-cards-minimal-year-group",
559 data_attrs: &[],
560 example_html: r#"<div class="moss-card-minimal">
561 <a class="moss-prefix-link" href="...">...</a>
562</div>"#,
563 example_markdown: "",
564 status: Status::Retired,
565 since: "0",
566 description: "Retired in Phase 1c — collapsed into `.moss-card` (with parent `.moss-cards[data-layout=minimal]`).",
567 },
568 ComponentEntry {
569 class: "moss-folder-item",
570 kind: "instance",
571 parent: "moss-cards-minimal-year-group",
572 data_attrs: &[],
573 example_html: r#"<div class="moss-card-minimal moss-folder-item">
574 <a class="moss-prefix-link moss-folder-link" href="...">...</a>
575 <p class="moss-folder-description">...</p>
576</div>"#,
577 example_markdown: "",
578 status: Status::Confirmed,
579 since: "0",
580 description: "Modifier on `.moss-card-minimal` for folder-type entries in minimal listings.",
581 },
582 ComponentEntry {
583 class: "moss-folder-title",
584 kind: "instance",
585 parent: "moss-folder-item",
586 data_attrs: &[],
587 example_html: r#"<span class="moss-folder-title">Folder name</span>"#,
588 example_markdown: "",
589 status: Status::Confirmed,
590 since: "0",
591 description: "Title text of a folder entry in minimal listings.",
592 },
593 ComponentEntry {
594 class: "moss-folder-description",
595 kind: "instance",
596 parent: "moss-folder-item",
597 data_attrs: &[],
598 example_html: r#"<p class="moss-folder-description">Description...</p>"#,
599 example_markdown: "",
600 status: Status::Confirmed,
601 since: "0",
602 description: "Description paragraph of a folder entry in minimal listings.",
603 },
604 ComponentEntry {
605 class: "moss-folder-link",
606 kind: "instance",
607 parent: "moss-folder-item",
608 data_attrs: &[],
609 example_html: r#"<a class="moss-prefix-link moss-folder-link" href="...">...</a>"#,
610 example_markdown: "",
611 status: Status::Confirmed,
612 since: "0",
613 description: "Modifier on `.moss-prefix-link` for folder-type links in minimal listings.",
614 },
615 ComponentEntry {
619 class: "moss-prefix-link",
620 kind: "instance",
621 parent: "moss-card-minimal",
622 data_attrs: &[],
623 example_html: r#"<a class="moss-prefix-link" href="...">
624 <span class="moss-prefix-link-prefix">2024-01-15</span>
625 <span class="moss-prefix-link-title">Page title</span>
626</a>"#,
627 example_markdown: "",
628 status: Status::Emerging,
629 since: "0",
630 description: "Link with a prefix span (date or icon) and a title span. Used inside minimal cards.",
631 },
632 ComponentEntry {
633 class: "moss-prefix-link-prefix",
634 kind: "instance",
635 parent: "moss-prefix-link",
636 data_attrs: &[],
637 example_html: r#"<span class="moss-prefix-link-prefix">2024-01-15</span>"#,
638 example_markdown: "",
639 status: Status::Emerging,
640 since: "0",
641 description: "Prefix slot of a prefix-link (typically a date).",
642 },
643 ComponentEntry {
644 class: "moss-prefix-link-title",
645 kind: "instance",
646 parent: "moss-prefix-link",
647 data_attrs: &[],
648 example_html: r#"<span class="moss-prefix-link-title">Page title</span>"#,
649 example_markdown: "",
650 status: Status::Emerging,
651 since: "0",
652 description: "Title slot of a prefix-link.",
653 },
654 ComponentEntry {
655 class: "moss-prefix-link-suffix",
656 kind: "instance",
657 parent: "moss-prefix-link",
658 data_attrs: &[],
659 example_html: r#"<span class="moss-prefix-link-suffix">→</span>"#,
660 example_markdown: "",
661 status: Status::Emerging,
662 since: "0",
663 description: "Optional trailing slot of a prefix-link.",
664 },
665 ComponentEntry {
671 class: "moss-callout",
672 kind: "standalone",
673 parent: "",
674 data_attrs: &[],
675 example_html: r#"<div class="moss-callout callout" data-type="note">
676 <div class="callout-title">Note</div>
677 <div class="callout-content">Body...</div>
678</div>"#,
679 example_markdown: "> [!note]\n> Body...",
680 status: Status::Confirmed,
681 since: "0",
682 description: "Obsidian-style callout. The Obsidian-compat `.callout` class is co-emitted; type lives on `data-type` (v1).",
683 },
684 ComponentEntry {
685 class: "callout",
686 kind: "standalone",
687 parent: "",
688 data_attrs: &[
689 DataAttr {
690 name: "data-type",
691 values: &["note", "info", "tip", "warning", "pending"],
692 default: "note",
693 description: "v1 callout type. Theme authors target `.callout[data-type=...]` to style by variant.",
694 },
695 ],
696 example_html: r#"<div class="moss-callout callout" data-type="note">...</div>"#,
697 example_markdown: "",
698 status: Status::Confirmed,
699 since: "0",
700 description: "Obsidian-compat class co-emitted on every callout for theme parity. Type lives on `data-type` (v1).",
701 },
702 ComponentEntry {
703 class: "callout-title",
704 kind: "instance",
705 parent: "moss-callout",
706 data_attrs: &[],
707 example_html: r#"<div class="callout-title">Note</div>"#,
708 example_markdown: "",
709 status: Status::Confirmed,
710 since: "0",
711 description: "Title row of a callout.",
712 },
713 ComponentEntry {
714 class: "callout-content",
715 kind: "instance",
716 parent: "moss-callout",
717 data_attrs: &[],
718 example_html: r#"<div class="callout-content">Body...</div>"#,
719 example_markdown: "",
720 status: Status::Confirmed,
721 since: "0",
722 description: "Body container of a callout.",
723 },
724 ComponentEntry {
725 class: "callout-note",
726 kind: "instance",
727 parent: "moss-callout",
728 data_attrs: &[],
729 example_html: r#"<div class="moss-callout callout callout-note">...</div>"#,
730 example_markdown: "> [!note]\n> Body",
731 status: Status::Retired,
732 since: "0",
733 description: "Retired in Phase 1c — type lives on `.callout[data-type=note]`.",
734 },
735 ComponentEntry {
736 class: "callout-info",
737 kind: "instance",
738 parent: "moss-callout",
739 data_attrs: &[],
740 example_html: r#"<div class="moss-callout callout callout-info">...</div>"#,
741 example_markdown: "> [!info]\n> Body",
742 status: Status::Retired,
743 since: "0",
744 description: "Retired in Phase 1c — type lives on `.callout[data-type=info]`.",
745 },
746 ComponentEntry {
747 class: "callout-tip",
748 kind: "instance",
749 parent: "moss-callout",
750 data_attrs: &[],
751 example_html: r#"<div class="moss-callout callout callout-tip">...</div>"#,
752 example_markdown: "> [!tip]\n> Body",
753 status: Status::Retired,
754 since: "0",
755 description: "Retired in Phase 1c — type lives on `.callout[data-type=tip]`.",
756 },
757 ComponentEntry {
758 class: "callout-warning",
759 kind: "instance",
760 parent: "moss-callout",
761 data_attrs: &[],
762 example_html: r#"<div class="moss-callout callout callout-warning">...</div>"#,
763 example_markdown: "> [!warning]\n> Body",
764 status: Status::Retired,
765 since: "0",
766 description: "Retired in Phase 1c — type lives on `.callout[data-type=warning]`.",
767 },
768 ComponentEntry {
769 class: "callout-pending",
770 kind: "instance",
771 parent: "moss-callout",
772 data_attrs: &[],
773 example_html: r#"<div class="moss-callout callout callout-pending">...</div>"#,
774 example_markdown: "> [!pending]\n> Body",
775 status: Status::Retired,
776 since: "0",
777 description: "Retired in Phase 1c — type lives on `.callout[data-type=pending]`.",
778 },
779 ComponentEntry {
784 class: "moss-embed",
785 kind: "standalone",
786 parent: "",
787 data_attrs: &[
788 DataAttr {
789 name: "data-type",
790 values: &["audio", "video", "pdf", "notebook", "table", "iframe", "3d"],
791 default: "",
792 description: "v1 embed kind. Set on the embed element. Theme authors target `.moss-embed[data-type=...]`.",
793 },
794 DataAttr {
795 name: "data-width",
796 values: &["body", "wide", "page", "screen"],
797 default: "body",
798 description: "Display width — text-column (body), wider than text (wide), page-width (page), or viewport-width (screen). See spec § P9.",
799 },
800 ],
801 example_html: r#"<div class="moss-embed moss-embed-pdf"><iframe src="..."></iframe></div>"#,
802 example_markdown: "![[paper.pdf]]",
803 status: Status::Confirmed,
804 since: "0",
805 description: "Base class on every typed embed. Kind on `data-type` (v1). `.moss-embed-audio` / `-video` / `-pdf` / `-notebook` / `-table` / `-iframe` / `-3d` retired in Phase 1c.",
806 },
807 ComponentEntry {
808 class: "moss-embed-audio",
809 kind: "instance",
810 parent: "moss-embed",
811 data_attrs: &[],
812 example_html: r#"<div class="moss-embed moss-embed-audio"><audio controls src="..."></audio></div>"#,
813 example_markdown: "![[track.mp3]]",
814 status: Status::Retired,
815 since: "0",
816 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=audio]`.",
817 },
818 ComponentEntry {
819 class: "moss-embed-video",
820 kind: "instance",
821 parent: "moss-embed",
822 data_attrs: &[],
823 example_html: r#"<div class="moss-embed moss-embed-video"><video controls src="..."></video></div>"#,
824 example_markdown: "![[clip.mp4]]",
825 status: Status::Retired,
826 since: "0",
827 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=video]`.",
828 },
829 ComponentEntry {
830 class: "moss-embed-pdf",
831 kind: "instance",
832 parent: "moss-embed",
833 data_attrs: &[],
834 example_html: r#"<div class="moss-embed moss-embed-pdf"><iframe src="..."></iframe></div>"#,
835 example_markdown: "![[paper.pdf]]",
836 status: Status::Retired,
837 since: "0",
838 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=pdf]`.",
839 },
840 ComponentEntry {
841 class: "moss-embed-iframe",
842 kind: "instance",
843 parent: "moss-embed",
844 data_attrs: &[],
845 example_html: r#"<div class="moss-embed moss-embed-iframe"><iframe src="..."></iframe></div>"#,
846 example_markdown: "![[page.html]]",
847 status: Status::Retired,
848 since: "0",
849 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=iframe]`.",
850 },
851 ComponentEntry {
852 class: "moss-embed-notebook",
853 kind: "instance",
854 parent: "moss-embed",
855 data_attrs: &[],
856 example_html: r#"<div class="moss-embed moss-embed-notebook">...</div>"#,
857 example_markdown: "![[analysis.ipynb]]",
858 status: Status::Retired,
859 since: "0",
860 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=notebook]`.",
861 },
862 ComponentEntry {
863 class: "moss-embed-ipynb",
864 kind: "instance",
865 parent: "moss-embed",
866 data_attrs: &[],
867 example_html: r#"<div class="moss-embed moss-embed-ipynb">...</div>"#,
868 example_markdown: "",
869 status: Status::Emerging,
870 since: "0",
871 description: "Alias of `.moss-embed-notebook`; consolidation pending.",
872 },
873 ComponentEntry {
874 class: "moss-embed-table",
875 kind: "instance",
876 parent: "moss-embed",
877 data_attrs: &[],
878 example_html: r#"<div class="moss-embed moss-embed-table"><table>...</table></div>"#,
879 example_markdown: "![[data.csv]]",
880 status: Status::Retired,
881 since: "0",
882 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=table]`.",
883 },
884 ComponentEntry {
885 class: "moss-embed-3d",
886 kind: "instance",
887 parent: "moss-embed",
888 data_attrs: &[],
889 example_html: r#"<div class="moss-embed moss-embed-3d">...</div>"#,
890 example_markdown: "![[model.glb]]",
891 status: Status::Retired,
892 since: "0",
893 description: "Retired in Phase 1c — collapsed to `.moss-embed[data-type=3d]`.",
894 },
895 ComponentEntry {
896 class: "moss-embed-error",
897 kind: "instance",
898 parent: "moss-embed",
899 data_attrs: &[],
900 example_html: r#"<div class="moss-embed moss-embed-error">File not found: ...</div>"#,
901 example_markdown: "",
902 status: Status::Confirmed,
903 since: "0",
904 description: "Error state for embeds whose target cannot be resolved.",
905 },
906 ComponentEntry {
907 class: "moss-embed-missing",
908 kind: "instance",
909 parent: "moss-embed",
910 data_attrs: &[],
911 example_html: r#"<div class="moss-embed-missing">Folder not found: journal</div>"#,
912 example_markdown: "",
913 status: Status::Confirmed,
914 since: "1",
915 description: "Fallback rendered when a folder-list embed (`![[journal/]]`) targets a folder that does not exist or cannot be resolved. Distinct from `.moss-embed-error` (file/wikilink resolution failure) — this one is specifically the folder-listing path.",
916 },
917 ComponentEntry {
921 class: "moss-hero",
922 kind: "standalone",
923 parent: "",
924 data_attrs: &[
925 DataAttr {
926 name: "data-width",
927 values: &["body", "wide", "page", "screen"],
928 default: "body",
929 description: "Display width — text-column (body), wider than text (wide), page-width (page), or viewport-width (screen). See spec § P9. Phase 1c will emit this from authoring shortcode (e.g. `:::hero {full}` -> `data-width=\"screen\"`).",
930 },
931 ],
932 example_html: r#"<section class="moss-hero" data-width="page">
933 <div class="moss-hero-content">...</div>
934</section>"#,
935 example_markdown: "",
936 status: Status::Confirmed,
937 since: "0",
938 description: "Hero banner section at the top of a page (cover image + title). v1 adds `data-width` for author-controlled sizing.",
939 },
940 ComponentEntry {
941 class: "moss-hero-content",
942 kind: "instance",
943 parent: "moss-hero",
944 data_attrs: &[],
945 example_html: r#"<div class="moss-hero-content">...</div>"#,
946 example_markdown: "",
947 status: Status::Confirmed,
948 since: "0",
949 description: "Text content slot inside `.moss-hero`.",
950 },
951 ComponentEntry {
952 class: "moss-image",
953 kind: "standalone",
954 parent: "",
955 data_attrs: &[
956 DataAttr {
957 name: "data-aspect",
958 values: &["portrait", "square", "auto"],
959 default: "auto",
960 description: "v1 image aspect-ratio hint. Theme authors target `.moss-image[data-aspect=...]`. Emitter wiring lands in a follow-up.",
961 },
962 DataAttr {
963 name: "data-width",
964 values: &["body", "wide", "page", "screen"],
965 default: "body",
966 description: "Display width — text-column (body), wider than text (wide), page-width (page), or viewport-width (screen). See spec § P9.",
967 },
968 ],
969 example_html: r#"<figure class="moss-image" data-aspect="portrait" data-width="body"><img src="..." alt="..." /></figure>"#,
970 example_markdown: "",
971 status: Status::Confirmed,
972 since: "0",
973 description: "Wrapper around an inline `<img>` for sizing and figure semantics. v1 adds `data-aspect` (collapses `--portrait`/`--square`/`--auto` modifiers) and `data-width` (P9).",
974 },
975 ComponentEntry {
976 class: "moss-align-left",
977 kind: "standalone",
978 parent: "",
979 data_attrs: &[],
980 example_html: r#"<img src="..." alt="..." class="moss-align-left" />"#,
981 example_markdown: "![[photo.jpg|align-left]]",
982 status: Status::Confirmed,
983 since: "0",
984 description: "Floats an image to the left of body text (editorial runaround). Defaults max-width to 50% on desktop, collapses to full-width below 48rem. CSS `:has()` escalates the float to a wrapping `<figure class=\"moss-image\">` or `<picture>` when present. Mirrors WordPress's `alignleft` convention.",
985 },
986 ComponentEntry {
987 class: "moss-align-right",
988 kind: "standalone",
989 parent: "",
990 data_attrs: &[],
991 example_html: r#"<img src="..." alt="..." class="moss-align-right" />"#,
992 example_markdown: "![[photo.jpg|align-right]]",
993 status: Status::Confirmed,
994 since: "0",
995 description: "Floats an image to the right of body text (editorial runaround). Symmetric counterpart to `.moss-align-left`. Mirrors WordPress's `alignright` convention.",
996 },
997 ComponentEntry {
998 class: "moss-visual",
999 kind: "standalone",
1000 parent: "",
1001 data_attrs: &[],
1002 example_html: r#"<div class="moss-visual">...</div>"#,
1003 example_markdown: "",
1004 status: Status::Emerging,
1005 since: "0",
1006 description: "Generic visual block (figure-like surface).",
1007 },
1008 ComponentEntry {
1009 class: "moss-article-title",
1010 kind: "instance",
1011 parent: "",
1012 data_attrs: &[],
1013 example_html: r#"<h1 class="moss-article-title">Title</h1>"#,
1014 example_markdown: "",
1015 status: Status::Emerging,
1016 since: "0",
1017 description: "Article-page H1 title emitted from frontmatter.",
1018 },
1019 ComponentEntry {
1020 class: "moss-heading-anchor",
1021 kind: "instance",
1022 parent: "",
1023 data_attrs: &[],
1024 example_html: r##"<h2 id="setup">Setup<a class="moss-heading-anchor" href="#setup" aria-label="Permalink to this section"><span aria-hidden="true">#</span></a></h2>"##,
1025 example_markdown: "## Setup",
1026 status: Status::Emerging,
1027 since: "1",
1028 description: "Clickable permalink appended inside every author-written body heading that carries a slug id; links to the heading's `#`-fragment. The auto-injected `moss-article-title` H1 is emitted separately and gets no anchor.",
1029 },
1030 ComponentEntry {
1034 class: "moss-grid",
1035 kind: "container",
1036 parent: "",
1037 data_attrs: &[
1038 DataAttr {
1039 name: "data-width",
1040 values: &["body", "wide", "page", "screen"],
1041 default: "body",
1042 description: "Display width — text-column (body), wider than text (wide), page-width (page), or viewport-width (screen). See spec § P9.",
1043 },
1044 ],
1045 example_html: r#"<div class="moss-grid" data-width="wide">
1046 <div class="moss-grid-card">...</div>
1047</div>"#,
1048 example_markdown: "",
1049 status: Status::Confirmed,
1050 since: "0",
1051 description: "Generic grid container (used by profiles, link previews, etc.). Modifier classes: `profiles`, `featured`, `no-cards`. v1 adds `data-width` (P9).",
1052 },
1053 ComponentEntry {
1054 class: "moss-grid-card",
1055 kind: "instance",
1056 parent: "moss-grid",
1057 data_attrs: &[
1058 DataAttr {
1059 name: "data-kind",
1060 values: &["link", "friend", "card"],
1061 default: "card",
1062 description: "v1 grid-card variant. Today expressed via co-emitted classes (`.link-card`, `.friend-card`, `.no-cards`); Phase 1c collapses to this `data-kind` attribute.",
1063 },
1064 ],
1065 example_html: r#"<a class="moss-grid-card" data-kind="link" href="...">...</a>"#,
1066 example_markdown: "",
1067 status: Status::Confirmed,
1068 since: "0",
1069 description: "Card instance inside `.moss-grid`. Today emits sibling classes `link-card` / `friend-card` / `no-cards`; v1 collapses to `data-kind`.",
1070 },
1071 ComponentEntry {
1072 class: "moss-gridxyz",
1073 kind: "container",
1074 parent: "",
1075 data_attrs: &[],
1076 example_html: r#"<div class="moss-gridxyz">...</div>"#,
1077 example_markdown: "",
1078 status: Status::Emerging,
1079 since: "0",
1080 description: "Experimental free-form grid variant. Subject to renaming.",
1081 },
1082 ComponentEntry {
1083 class: "moss-gallery",
1084 kind: "container",
1085 parent: "",
1086 data_attrs: &[
1087 DataAttr {
1088 name: "data-width",
1089 values: &["body", "wide", "page", "screen"],
1090 default: "body",
1091 description: "Display width — text-column (body), wider than text (wide), page-width (page), or viewport-width (screen). See spec § P9.",
1092 },
1093 ],
1094 example_html: r#"<div class="moss-gallery" data-width="page">
1095 <figure class="moss-gallery-item">...</figure>
1096</div>"#,
1097 example_markdown: "",
1098 status: Status::Confirmed,
1099 since: "0",
1100 description: "Image gallery container. v1 adds `data-width` (P9).",
1101 },
1102 ComponentEntry {
1103 class: "moss-gallery-item",
1104 kind: "instance",
1105 parent: "moss-gallery",
1106 data_attrs: &[],
1107 example_html: r#"<figure class="moss-gallery-item"><img src="..." /></figure>"#,
1108 example_markdown: "",
1109 status: Status::Confirmed,
1110 since: "0",
1111 description: "Single image entry inside `.moss-gallery`.",
1112 },
1113 ComponentEntry {
1114 class: "moss-buttons",
1115 kind: "container",
1116 parent: "",
1117 data_attrs: &[
1118 DataAttr {
1119 name: "data-style",
1120 values: &["default", "inverted"],
1121 default: "default",
1122 description: "v1 button-row style. Theme authors target `.moss-buttons[data-style=...]`.",
1123 },
1124 ],
1125 example_html: r#"<div class="moss-buttons" data-style="inverted">
1126 <a class="moss-btn" href="...">Click</a>
1127</div>"#,
1128 example_markdown: "",
1129 status: Status::Confirmed,
1130 since: "0",
1131 description: "Container for a row of `.moss-btn` buttons. v1: the inverted variant is on `data-style=\"inverted\"`.",
1132 },
1133 ComponentEntry {
1137 class: "moss-btn",
1138 kind: "standalone",
1139 parent: "",
1140 data_attrs: &[
1141 DataAttr {
1142 name: "data-role",
1143 values: &["default", "primary", "secondary"],
1144 default: "default",
1145 description: "v1 button role. Theme authors target `.moss-btn[data-role=...]`.",
1146 },
1147 ],
1148 example_html: r#"<button class="moss-btn" data-role="primary">
1149 <span class="moss-btn__label">Submit</span>
1150</button>"#,
1151 example_markdown: "",
1152 status: Status::Confirmed,
1153 since: "0",
1154 description: "Generic button primitive. Role on `data-role` (v1).",
1155 },
1156 ComponentEntry {
1157 class: "moss-btn__label",
1158 kind: "instance",
1159 parent: "moss-btn",
1160 data_attrs: &[],
1161 example_html: r#"<span class="moss-btn__label">Submit</span>"#,
1162 example_markdown: "",
1163 status: Status::Confirmed,
1164 since: "0",
1165 description: "Label span inside `.moss-btn`.",
1166 },
1167 ComponentEntry {
1168 class: "moss-btn__check",
1169 kind: "instance",
1170 parent: "moss-btn",
1171 data_attrs: &[],
1172 example_html: r#"<span class="moss-btn__check">✓</span>"#,
1173 example_markdown: "",
1174 status: Status::Confirmed,
1175 since: "0",
1176 description: "Success checkmark slot inside `.moss-btn`.",
1177 },
1178 ComponentEntry {
1179 class: "moss-btn__spinner",
1180 kind: "instance",
1181 parent: "moss-btn",
1182 data_attrs: &[],
1183 example_html: r#"<span class="moss-btn__spinner"></span>"#,
1184 example_markdown: "",
1185 status: Status::Confirmed,
1186 since: "0",
1187 description: "Loading spinner slot inside `.moss-btn`.",
1188 },
1189 ComponentEntry {
1193 class: "moss-subscribe",
1194 kind: "standalone",
1195 parent: "",
1196 data_attrs: &[],
1197 example_html: r#"<div class="moss-subscribe">
1198 <form class="moss-subscribe-form">...</form>
1199</div>"#,
1200 example_markdown: "",
1201 status: Status::Confirmed,
1202 since: "0",
1203 description: "Newsletter subscribe block (auto-injected into footer when email channel configured).",
1204 },
1205 ComponentEntry {
1206 class: "moss-subscribe-form",
1207 kind: "instance",
1208 parent: "moss-subscribe",
1209 data_attrs: &[],
1210 example_html: r#"<form class="moss-subscribe-form">...</form>"#,
1211 example_markdown: "",
1212 status: Status::Emerging,
1213 since: "0",
1214 description: "Form element inside `.moss-subscribe`.",
1215 },
1216 ComponentEntry {
1217 class: "moss-subscribe-btn-slot",
1218 kind: "instance",
1219 parent: "moss-subscribe",
1220 data_attrs: &[],
1221 example_html: r#"<div class="moss-subscribe-btn-slot"><button class="moss-btn">...</button></div>"#,
1222 example_markdown: "",
1223 status: Status::Emerging,
1224 since: "0",
1225 description: "Slot in the subscribe form that holds the submit button.",
1226 },
1227 ComponentEntry {
1228 class: "moss-subscribe-status",
1229 kind: "instance",
1230 parent: "moss-subscribe",
1231 data_attrs: &[],
1232 example_html: r#"<div class="moss-subscribe-status">
1233 <span class="moss-subscribe-status__icon"></span>
1234 Subscribed!
1235</div>"#,
1236 example_markdown: "",
1237 status: Status::Emerging,
1238 since: "0",
1239 description: "Status message shown after submit (success/error).",
1240 },
1241 ComponentEntry {
1242 class: "moss-subscribe-status__icon",
1243 kind: "instance",
1244 parent: "moss-subscribe-status",
1245 data_attrs: &[],
1246 example_html: r#"<span class="moss-subscribe-status__icon"></span>"#,
1247 example_markdown: "",
1248 status: Status::Emerging,
1249 since: "0",
1250 description: "Icon slot inside `.moss-subscribe-status`.",
1251 },
1252 ComponentEntry {
1253 class: "moss-subscribe-landing",
1254 kind: "standalone",
1255 parent: "",
1256 data_attrs: &[],
1257 example_html: r#"<section class="moss-subscribe-landing">...</section>"#,
1258 example_markdown: "",
1259 status: Status::Emerging,
1260 since: "0",
1261 description: "Standalone subscribe landing page surface (larger variant).",
1262 },
1263 ComponentEntry {
1267 class: "moss-series-nav",
1268 kind: "standalone",
1269 parent: "",
1270 data_attrs: &[],
1271 example_html: r#"<nav class="moss-series-nav">
1272 <div class="moss-series-nav-links">...</div>
1273</nav>"#,
1274 example_markdown: "",
1275 status: Status::Confirmed,
1276 since: "0",
1277 description: "Series navigation bar (prev/next/collection) on series pages.",
1278 },
1279 ComponentEntry {
1280 class: "moss-series-nav-links",
1281 kind: "instance",
1282 parent: "moss-series-nav",
1283 data_attrs: &[],
1284 example_html: r#"<div class="moss-series-nav-links">...</div>"#,
1285 example_markdown: "",
1286 status: Status::Confirmed,
1287 since: "0",
1288 description: "Row holding prev/next links in series nav.",
1289 },
1290 ComponentEntry {
1291 class: "moss-series-nav-link",
1292 kind: "instance",
1293 parent: "moss-series-nav",
1294 data_attrs: &[],
1295 example_html: r#"<a class="moss-series-nav-link moss-series-nav-prev" href="...">...</a>"#,
1296 example_markdown: "",
1297 status: Status::Confirmed,
1298 since: "0",
1299 description: "Individual link inside series nav. Modifiers: `moss-series-nav-prev`, `moss-series-nav-next`, `empty` (placeholder).",
1300 },
1301 ComponentEntry {
1302 class: "moss-series-nav-prev",
1303 kind: "instance",
1304 parent: "moss-series-nav",
1305 data_attrs: &[],
1306 example_html: r#"<a class="moss-series-nav-link moss-series-nav-prev" href="...">...</a>"#,
1307 example_markdown: "",
1308 status: Status::Confirmed,
1309 since: "0",
1310 description: "Previous-page modifier on a series nav link.",
1311 },
1312 ComponentEntry {
1313 class: "moss-series-nav-next",
1314 kind: "instance",
1315 parent: "moss-series-nav",
1316 data_attrs: &[],
1317 example_html: r#"<a class="moss-series-nav-link moss-series-nav-next" href="...">...</a>"#,
1318 example_markdown: "",
1319 status: Status::Confirmed,
1320 since: "0",
1321 description: "Next-page modifier on a series nav link.",
1322 },
1323 ComponentEntry {
1324 class: "moss-series-nav-arrow",
1325 kind: "instance",
1326 parent: "moss-series-nav",
1327 data_attrs: &[],
1328 example_html: r#"<span class="moss-series-nav-arrow">→</span>"#,
1329 example_markdown: "",
1330 status: Status::Confirmed,
1331 since: "0",
1332 description: "Arrow glyph inside a series-nav link.",
1333 },
1334 ComponentEntry {
1335 class: "moss-series-nav-title",
1336 kind: "instance",
1337 parent: "moss-series-nav",
1338 data_attrs: &[],
1339 example_html: r#"<span class="moss-series-nav-title">Next page title</span>"#,
1340 example_markdown: "",
1341 status: Status::Confirmed,
1342 since: "0",
1343 description: "Title text of the destination page in a series-nav link.",
1344 },
1345 ComponentEntry {
1346 class: "moss-series-nav-collection",
1347 kind: "instance",
1348 parent: "moss-series-nav",
1349 data_attrs: &[],
1350 example_html: r#"<div class="moss-series-nav-collection">...</div>"#,
1351 example_markdown: "",
1352 status: Status::Confirmed,
1353 since: "0",
1354 description: "Collection-listing slot in series nav (sibling pages).",
1355 },
1356 ComponentEntry {
1357 class: "moss-series-nav-collection-row",
1358 kind: "instance",
1359 parent: "moss-series-nav-collection",
1360 data_attrs: &[],
1361 example_html: r#"<div class="moss-series-nav-collection-row">...</div>"#,
1362 example_markdown: "",
1363 status: Status::Confirmed,
1364 since: "0",
1365 description: "Row inside the collection listing of series nav.",
1366 },
1367 ComponentEntry {
1371 class: "moss-collection-cover",
1372 kind: "standalone",
1373 parent: "",
1374 data_attrs: &[],
1375 example_html: r#"<section class="moss-collection-cover">
1376 <div class="moss-collection-cover-row">...</div>
1377</section>"#,
1378 example_markdown: "",
1379 status: Status::Emerging,
1380 since: "0",
1381 description: "Header surface on a collection landing page.",
1382 },
1383 ComponentEntry {
1384 class: "moss-collection-cover-row",
1385 kind: "instance",
1386 parent: "moss-collection-cover",
1387 data_attrs: &[],
1388 example_html: r#"<div class="moss-collection-cover-row">...</div>"#,
1389 example_markdown: "",
1390 status: Status::Emerging,
1391 since: "0",
1392 description: "Row inside `.moss-collection-cover`.",
1393 },
1394 ComponentEntry {
1395 class: "moss-collection-cover-body",
1396 kind: "instance",
1397 parent: "moss-collection-cover",
1398 data_attrs: &[],
1399 example_html: r#"<div class="moss-collection-cover-body">...</div>"#,
1400 example_markdown: "",
1401 status: Status::Emerging,
1402 since: "0",
1403 description: "Body content slot inside `.moss-collection-cover`.",
1404 },
1405 ComponentEntry {
1409 class: "moss-input",
1410 kind: "standalone",
1411 parent: "",
1412 data_attrs: &[],
1413 example_html: r#"<input class="moss-input" type="email" />"#,
1414 example_markdown: "",
1415 status: Status::Confirmed,
1416 since: "0",
1417 description: "Generic form input primitive.",
1418 },
1419 ComponentEntry {
1420 class: "moss-field",
1421 kind: "container",
1422 parent: "",
1423 data_attrs: &[],
1424 example_html: r#"<div class="moss-field">
1425 <label class="moss-label">Email</label>
1426 <input class="moss-input" />
1427</div>"#,
1428 example_markdown: "",
1429 status: Status::Confirmed,
1430 since: "0",
1431 description: "Form field group (label + input). Modifier `--inline` for horizontal layout.",
1432 },
1433 ComponentEntry {
1434 class: "moss-label",
1435 kind: "instance",
1436 parent: "moss-field",
1437 data_attrs: &[],
1438 example_html: r#"<label class="moss-label">Email</label>"#,
1439 example_markdown: "",
1440 status: Status::Confirmed,
1441 since: "0",
1442 description: "Label primitive for `.moss-field`. Modifier `--small` for compact form.",
1443 },
1444 ComponentEntry {
1445 class: "moss-link",
1446 kind: "standalone",
1447 parent: "",
1448 data_attrs: &[],
1449 example_html: r#"<a class="moss-link" href="...">Click me</a>"#,
1450 example_markdown: "",
1451 status: Status::Confirmed,
1452 since: "0",
1453 description: "Inline-link primitive (resets `<button>` chrome too). Use `--subtle` for muted variant.",
1454 },
1455 ComponentEntry {
1456 class: "moss-field--inline",
1457 kind: "instance",
1458 parent: "moss-field",
1459 data_attrs: &[],
1460 example_html: r#"<div class="moss-field moss-field--inline">
1461 <label class="moss-label">Email</label>
1462 <input class="moss-input" />
1463</div>"#,
1464 example_markdown: "",
1465 status: Status::Confirmed,
1466 since: "0",
1467 description: "BEM modifier on `.moss-field` for horizontal label+input layout (used by settings UI primitives).",
1468 },
1469 ComponentEntry {
1470 class: "moss-label--small",
1471 kind: "instance",
1472 parent: "moss-label",
1473 data_attrs: &[],
1474 example_html: r#"<label class="moss-label moss-label--small">Compact label</label>"#,
1475 example_markdown: "",
1476 status: Status::Confirmed,
1477 since: "0",
1478 description: "BEM modifier on `.moss-label` for compact form (used by services settings rows).",
1479 },
1480 ComponentEntry {
1481 class: "moss-info-grid",
1482 kind: "container",
1483 parent: "",
1484 data_attrs: &[],
1485 example_html: r#"<div class="moss-info-grid">
1486 <div class="moss-field moss-field--inline">...</div>
1487 <div class="moss-field moss-field--inline">...</div>
1488</div>"#,
1489 example_markdown: "",
1490 status: Status::Emerging,
1491 since: "0",
1492 description: "Two-column aligned label+value rows (CSS grid with `display: contents` children). Used by the deployment settings panel; ships in the default theme so authors can reuse the layout.",
1493 },
1494 ComponentEntry {
1495 class: "moss-row",
1496 kind: "container",
1497 parent: "",
1498 data_attrs: &[],
1499 example_html: r#"<div class="moss-row">
1500 <div class="moss-field">...</div>
1501 <div class="moss-field">...</div>
1502</div>"#,
1503 example_markdown: "",
1504 status: Status::Emerging,
1505 since: "0",
1506 description: "Horizontal flex row of equal-flex `.moss-field` children. Form-row layout helper shipped in the default theme.",
1507 },
1508 ComponentEntry {
1509 class: "moss-input-feedback",
1510 kind: "instance",
1511 parent: "moss-field",
1512 data_attrs: &[],
1513 example_html: r#"<span class="moss-input-feedback">Saving…</span>"#,
1514 example_markdown: "",
1515 status: Status::Emerging,
1516 since: "0",
1517 description: "Auto-save status hint slot under `.moss-field`. Three state modifiers: `--success`, `--error`, `--fade-out`.",
1518 },
1519 ComponentEntry {
1520 class: "moss-input-feedback--success",
1521 kind: "instance",
1522 parent: "moss-input-feedback",
1523 data_attrs: &[],
1524 example_html: r#"<span class="moss-input-feedback moss-input-feedback--success">Saved</span>"#,
1525 example_markdown: "",
1526 status: Status::Emerging,
1527 since: "0",
1528 description: "Success state modifier on `.moss-input-feedback`.",
1529 },
1530 ComponentEntry {
1531 class: "moss-input-feedback--error",
1532 kind: "instance",
1533 parent: "moss-input-feedback",
1534 data_attrs: &[],
1535 example_html: r#"<span class="moss-input-feedback moss-input-feedback--error">Failed to save</span>"#,
1536 example_markdown: "",
1537 status: Status::Emerging,
1538 since: "0",
1539 description: "Error state modifier on `.moss-input-feedback`.",
1540 },
1541 ComponentEntry {
1542 class: "moss-input-feedback--fade-out",
1543 kind: "instance",
1544 parent: "moss-input-feedback",
1545 data_attrs: &[],
1546 example_html: r#"<span class="moss-input-feedback moss-input-feedback--success moss-input-feedback--fade-out">Saved</span>"#,
1547 example_markdown: "",
1548 status: Status::Emerging,
1549 since: "0",
1550 description: "Transient fade-out modifier on `.moss-input-feedback` (applied after a success message to dismiss it).",
1551 },
1552 ComponentEntry {
1556 class: "moss-comments",
1557 kind: "standalone",
1558 parent: "",
1559 data_attrs: &[],
1560 example_html: r#"<section class="moss-comments">...</section>"#,
1561 example_markdown: "",
1562 status: Status::Confirmed,
1563 since: "0",
1564 description: "Comments surface (per-site SQLite backend or Artalk legacy).",
1565 },
1566 ComponentEntry {
1567 class: "moss-service-inactive",
1568 kind: "instance",
1569 parent: "",
1570 data_attrs: &[],
1571 example_html: r#"<section class="moss-comments moss-service-inactive">...</section>"#,
1572 example_markdown: "",
1573 status: Status::Confirmed,
1574 since: "0",
1575 description: "Co-class applied to `.moss-comments` and `.moss-subscribe-form` when the backing service is not configured. Hidden by default in published sites and revealed inside the preview chrome so authors can see the inactive surface during editing.",
1576 },
1577 ComponentEntry {
1581 class: "moss-preview-popup",
1582 kind: "chrome",
1583 parent: "",
1584 data_attrs: &[],
1585 example_html: r#"<div class="moss-preview-popup" role="tooltip" aria-live="polite">
1586 <strong class="moss-preview-title">...</strong>
1587 <p class="moss-preview-desc">...</p>
1588 <p class="moss-preview-text">...</p>
1589</div>"#,
1590 example_markdown: "",
1591 status: Status::Confirmed,
1592 since: "0",
1593 description: "Floating link-preview popover injected at `document.body` level by the runtime `preview.js`. Fetches `/_moss/previews.json` and renders a hover card with title, description, and excerpt for internal links.",
1594 },
1595 ComponentEntry {
1596 class: "moss-preview-title",
1597 kind: "instance",
1598 parent: "moss-preview-popup",
1599 data_attrs: &[],
1600 example_html: r#"<strong class="moss-preview-title">Article title</strong>"#,
1601 example_markdown: "",
1602 status: Status::Confirmed,
1603 since: "0",
1604 description: "Title slot inside `.moss-preview-popup`.",
1605 },
1606 ComponentEntry {
1607 class: "moss-preview-desc",
1608 kind: "instance",
1609 parent: "moss-preview-popup",
1610 data_attrs: &[],
1611 example_html: r#"<p class="moss-preview-desc">Short description</p>"#,
1612 example_markdown: "",
1613 status: Status::Confirmed,
1614 since: "0",
1615 description: "Description slot inside `.moss-preview-popup` (from frontmatter `description`).",
1616 },
1617 ComponentEntry {
1618 class: "moss-preview-text",
1619 kind: "instance",
1620 parent: "moss-preview-popup",
1621 data_attrs: &[],
1622 example_html: r#"<p class="moss-preview-text">Excerpt of the linked article…</p>"#,
1623 example_markdown: "",
1624 status: Status::Confirmed,
1625 since: "0",
1626 description: "Excerpt slot inside `.moss-preview-popup` (auto-extracted from the linked article body).",
1627 },
1628 ComponentEntry {
1629 class: "moss-colophon",
1630 kind: "chrome",
1631 parent: "",
1632 data_attrs: &[],
1633 example_html: r#"<footer class="moss-colophon">
1634 <span class="moss-colophon-icon"></span>
1635 Built with moss
1636</footer>"#,
1637 example_markdown: "",
1638 status: Status::Confirmed,
1639 since: "0",
1640 description: "Footer colophon credit appended by moss.",
1641 },
1642 ComponentEntry {
1643 class: "moss-colophon-icon",
1644 kind: "instance",
1645 parent: "moss-colophon",
1646 data_attrs: &[],
1647 example_html: r#"<span class="moss-colophon-icon"></span>"#,
1648 example_markdown: "",
1649 status: Status::Confirmed,
1650 since: "0",
1651 description: "Icon slot inside `.moss-colophon`.",
1652 },
1653 ComponentEntry {
1654 class: "moss-shell-frame",
1655 kind: "chrome",
1656 parent: "",
1657 data_attrs: &[],
1658 example_html: r#"<div class="moss-shell-frame">...</div>"#,
1659 example_markdown: "",
1660 status: Status::Emerging,
1661 since: "0",
1662 description: "App-shell frame surface (preview chrome).",
1663 },
1664 ComponentEntry {
1665 class: "main-nav",
1666 kind: "chrome",
1667 parent: "",
1668 data_attrs: &[],
1669 example_html: r#"<nav class="main-nav container">...</nav>"#,
1670 example_markdown: "",
1671 status: Status::Confirmed,
1672 since: "0",
1673 description: "Top site navigation bar. Legacy non-`moss-` prefix kept for theme parity.",
1674 },
1675 ComponentEntry {
1676 class: "moss-child-section-divider",
1677 kind: "instance",
1678 parent: "",
1679 data_attrs: &[],
1680 example_html: r#"<hr class="moss-child-section-divider" />"#,
1681 example_markdown: "",
1682 status: Status::Emerging,
1683 since: "0",
1684 description: "Divider rule between auto-generated child sections.",
1685 },
1686 ComponentEntry {
1687 class: "moss-unknown-shortcode",
1688 kind: "standalone",
1689 parent: "",
1690 data_attrs: &[],
1691 example_html: r#"<div class="moss-unknown-shortcode">Unknown shortcode: foo</div>"#,
1692 example_markdown: "{{< foo >}}",
1693 status: Status::Confirmed,
1694 since: "0",
1695 description: "Fallback emitted when a shortcode tag is not recognised by any plugin.",
1696 },
1697 ComponentEntry {
1701 class: "moss-hl-keyword",
1702 kind: "instance",
1703 parent: "",
1704 data_attrs: &[],
1705 example_html: r#"<span class="moss-hl-keyword">if</span>"#,
1706 example_markdown: "",
1707 status: Status::Emerging,
1708 since: "0",
1709 description: "Syntax-highlight token: keyword.",
1710 },
1711 ComponentEntry {
1712 class: "moss-hl-string",
1713 kind: "instance",
1714 parent: "",
1715 data_attrs: &[],
1716 example_html: r#"<span class="moss-hl-string">"hi"</span>"#,
1717 example_markdown: "",
1718 status: Status::Emerging,
1719 since: "0",
1720 description: "Syntax-highlight token: string literal.",
1721 },
1722 ComponentEntry {
1723 class: "moss-hl-comment",
1724 kind: "instance",
1725 parent: "",
1726 data_attrs: &[],
1727 example_html: r#"<span class="moss-hl-comment">// note</span>"#,
1728 example_markdown: "",
1729 status: Status::Emerging,
1730 since: "0",
1731 description: "Syntax-highlight token: comment.",
1732 },
1733 ComponentEntry {
1734 class: "moss-hl-function",
1735 kind: "instance",
1736 parent: "",
1737 data_attrs: &[],
1738 example_html: r#"<span class="moss-hl-function">render</span>"#,
1739 example_markdown: "",
1740 status: Status::Emerging,
1741 since: "0",
1742 description: "Syntax-highlight token: function name.",
1743 },
1744 ComponentEntry {
1745 class: "moss-hl-type",
1746 kind: "instance",
1747 parent: "",
1748 data_attrs: &[],
1749 example_html: r#"<span class="moss-hl-type">String</span>"#,
1750 example_markdown: "",
1751 status: Status::Emerging,
1752 since: "0",
1753 description: "Syntax-highlight token: type name.",
1754 },
1755 ComponentEntry {
1756 class: "moss-hl-number",
1757 kind: "instance",
1758 parent: "",
1759 data_attrs: &[],
1760 example_html: r#"<span class="moss-hl-number">42</span>"#,
1761 example_markdown: "",
1762 status: Status::Emerging,
1763 since: "0",
1764 description: "Syntax-highlight token: numeric literal.",
1765 },
1766 ComponentEntry {
1767 class: "moss-hl-operator",
1768 kind: "instance",
1769 parent: "",
1770 data_attrs: &[],
1771 example_html: r#"<span class="moss-hl-operator">+</span>"#,
1772 example_markdown: "",
1773 status: Status::Emerging,
1774 since: "0",
1775 description: "Syntax-highlight token: operator.",
1776 },
1777 ComponentEntry {
1778 class: "moss-hl-builtin",
1779 kind: "instance",
1780 parent: "",
1781 data_attrs: &[],
1782 example_html: r#"<span class="moss-hl-builtin">print</span>"#,
1783 example_markdown: "",
1784 status: Status::Emerging,
1785 since: "0",
1786 description: "Syntax-highlight token: builtin identifier.",
1787 },
1788 ComponentEntry {
1789 class: "moss-hl-tag",
1790 kind: "instance",
1791 parent: "",
1792 data_attrs: &[],
1793 example_html: r#"<span class="moss-hl-tag">div</span>"#,
1794 example_markdown: "",
1795 status: Status::Emerging,
1796 since: "0",
1797 description: "Syntax-highlight token: markup tag name.",
1798 },
1799 ComponentEntry {
1800 class: "moss-hl-attr",
1801 kind: "instance",
1802 parent: "",
1803 data_attrs: &[],
1804 example_html: r#"<span class="moss-hl-attr">class</span>"#,
1805 example_markdown: "",
1806 status: Status::Emerging,
1807 since: "0",
1808 description: "Syntax-highlight token: attribute name.",
1809 },
1810 ComponentEntry {
1811 class: "moss-hl-meta",
1812 kind: "instance",
1813 parent: "",
1814 data_attrs: &[],
1815 example_html: r#"<span class="moss-hl-meta">@derive</span>"#,
1816 example_markdown: "",
1817 status: Status::Emerging,
1818 since: "0",
1819 description: "Syntax-highlight token: meta/annotation.",
1820 },
1821 ComponentEntry {
1822 class: "moss-hl-addition-bg",
1823 kind: "instance",
1824 parent: "",
1825 data_attrs: &[],
1826 example_html: r#"<span class="moss-hl-addition-bg">+ added line</span>"#,
1827 example_markdown: "",
1828 status: Status::Emerging,
1829 since: "0",
1830 description: "Syntax-highlight diff token: added-line background.",
1831 },
1832 ComponentEntry {
1833 class: "moss-hl-deletion",
1834 kind: "instance",
1835 parent: "",
1836 data_attrs: &[],
1837 example_html: r#"<span class="moss-hl-deletion">- removed line</span>"#,
1838 example_markdown: "",
1839 status: Status::Emerging,
1840 since: "0",
1841 description: "Syntax-highlight diff token: removed-line text.",
1842 },
1843 ComponentEntry {
1844 class: "moss-hl-deletion-bg",
1845 kind: "instance",
1846 parent: "",
1847 data_attrs: &[],
1848 example_html: r#"<span class="moss-hl-deletion-bg">- removed line</span>"#,
1849 example_markdown: "",
1850 status: Status::Emerging,
1851 since: "0",
1852 description: "Syntax-highlight diff token: removed-line background.",
1853 },
1854 ComponentEntry {
1855 class: "moss-recent",
1856 kind: "container",
1857 parent: "",
1858 data_attrs: &[],
1859 example_html: r#"<ul class="moss-recent">
1860 <li><a href="/posts/spring-notes/">Spring notes</a><div class="moss-recent__date">2026-04-12</div><div class="moss-recent__desc">A walk through the garden.</div></li>
1861</ul>"#,
1862 example_markdown: ":::recent count=5 since=2026-01-01\n",
1863 status: Status::Emerging,
1864 since: "0",
1865 description: "Auto-generated list of recent posts emitted by the `:::recent` shortcode. Sorted newest-first; date and description slots are filled per child. No default CSS in the bundled theme — theme authors style it freely.",
1866 },
1867 ComponentEntry {
1868 class: "moss-recent__date",
1869 kind: "instance",
1870 parent: "moss-recent",
1871 data_attrs: &[],
1872 example_html: r#"<div class="moss-recent__date">2026-04-12</div>"#,
1873 example_markdown: "",
1874 status: Status::Emerging,
1875 since: "0",
1876 description: "Per-entry date slot inside `.moss-recent` (BEM child). Format is `YYYY-MM-DD`, derived from frontmatter `date`. Empty string when the post lacks a parseable date.",
1877 },
1878 ComponentEntry {
1879 class: "moss-recent__desc",
1880 kind: "instance",
1881 parent: "moss-recent",
1882 data_attrs: &[],
1883 example_html: r#"<div class="moss-recent__desc">A walk through the garden.</div>"#,
1884 example_markdown: "",
1885 status: Status::Emerging,
1886 since: "0",
1887 description: "Per-entry description slot inside `.moss-recent` (BEM child). Sourced from frontmatter `description`; empty when unset.",
1888 },
1889];
1890
1891pub fn retired_class_names() -> impl Iterator<Item = &'static str> {
1897 COMPONENTS.iter()
1898 .filter(|e| e.status == Status::Retired)
1899 .map(|e| e.class)
1900}