Skip to main content

fc_dioxus/components/
citation.rs

1//! Inline citation markers and the source list they point to, from citation.css.
2use crate::{
3    core::{assets, attrs::component_attributes},
4    prelude::*,
5    theme::use_stylesheets,
6};
7const CITE: Bem = Bem::new("fc-cite");
8const SOURCES: Bem = Bem::new("fc-sources");
9const SOURCE: Bem = Bem::new("fc-source");
10
11/// A numbered marker in running text, linking to its [`Source`]. Its name reads
12/// "Source n: title", so the number alone is never all a screen reader hears.
13#[component]
14pub fn Cite(index: u32, title: AccessibleName, source: Id) -> Element {
15    rsx! {
16        if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_CITATION_CSS } }
17        a { class: CITE.block(), href: "#{source}", aria_label: "Source {index}: {title}", "{index}" }
18    }
19}
20
21/// The ordered list of [`Source`]s cited above it.
22#[component]
23pub fn Sources(
24    /// Names the list; "Sources" when omitted.
25    #[props(default)]
26    label: Option<AccessibleName>,
27    #[props(default)] class: Option<String>,
28    #[props(extends = GlobalAttributes)] attributes: Vec<Attribute>,
29    children: Element,
30) -> Element {
31    let attributes = component_attributes(
32        attributes,
33        ClassList::new(SOURCES.block()).extend(class.as_deref()),
34        &["aria-label"],
35    );
36    let label = label.map_or_else(|| "Sources".to_owned(), |l| l.to_string());
37    rsx! {
38        if use_stylesheets() { document::Stylesheet { href: assets::COMPONENTS_CITATION_CSS } }
39        ol { aria_label: label, ..attributes, {children} }
40    }
41}
42
43/// One cited source: its number, title, and where it lives.
44#[component]
45pub fn Source(
46    /// The id [`Cite`] markers link to.
47    id: Id,
48    index: u32,
49    href: String,
50    title: Element,
51    #[props(default)] domain: Option<Element>,
52    /// A decorative favicon or glyph.
53    #[props(default)]
54    icon: Option<Element>,
55) -> Element {
56    let link = crate::core::link::use_link(Some(href));
57    rsx! {
58        li { class: SOURCE.block(), id: "{id}",
59            a { class: SOURCE.element("link"), href: link.href.clone(), onclick: move |event| { link.follow(&event); },
60                if let Some(icon) = icon { span { class: SOURCE.element("icon"), aria_hidden: "true", {icon} } }
61                span { class: SOURCE.element("index"), "{index}" }
62                span { class: SOURCE.element("title"), {title} }
63                if let Some(domain) = domain { span { class: SOURCE.element("domain"), {domain} } }
64            }
65        }
66    }
67}