OXYGENHUB
# a9f1c0bf403a oxygenhub / crates / hub / src / web / icons.rs
3.8 KiB · Rust · last changed feat(web): About counts in its header, wider cards, one-line Diffusion rows, blue primaries, card sidebars (refs #159, #160, #161, #162, #163) 23 days ago source blame history raw
1
//! Small inline icons (oxygenhub#152): 16-unit SVGs drawn in
2
//! `currentColor`, so they take the colour of the text around them.
3
4
/// The opening tag every icon shares.
5
macro_rules! open {
6
    () => {
7
        r#"<svg class="ic" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">"#
8
    };
9
}
10
11
/// The icon by name, as markup; empty for a name it does not know.
12
pub fn svg(name: &str) -> &'static str {
13
    match name {
14
        "home" => concat!(open!(), r#"<path d="M2.5 7.5 8 3l5.5 4.5V13a.5.5 0 0 1-.5.5H9.5V10h-3v3.5H3a.5.5 0 0 1-.5-.5z"/></svg>"#),
15
        "explore" => concat!(open!(), r#"<circle cx="8" cy="8" r="6"/><path d="m10.6 5.4-1.6 3.6-3.6 1.6 1.6-3.6z"/></svg>"#),
16
        "help" => concat!(
17
            open!(),
18
            r#"<circle cx="8" cy="8" r="6"/><path d="M6.3 6.4a1.8 1.8 0 1 1 2.5 1.6c-.5.2-.8.6-.8 1.1v.4"/><circle cx="8" cy="11.4" r=".5" fill="currentColor" stroke="none"/></svg>"#
19
        ),
20
        "projects" => concat!(open!(), r#"<rect x="2" y="2.5" width="12" height="11" rx="1.5"/><path d="M6 2.5v11M10 2.5v7"/></svg>"#),
21
        "bell" => concat!(open!(), r#"<path d="M4 11V7a4 4 0 0 1 8 0v4l1.2 1.5H2.8z"/><path d="M6.6 14a1.5 1.5 0 0 0 2.8 0"/></svg>"#),
22
        "settings" => concat!(
23
            open!(),
24
            r#"<path d="M2 4.5h7M12.5 4.5H14M2 11.5h1.5M7 11.5h7"/><circle cx="10.75" cy="4.5" r="1.75"/><circle cx="5.25" cy="11.5" r="1.75"/></svg>"#
25
        ),
26
        "admin" => concat!(open!(), r#"<path d="M8 1.8 13 3.8v3.7c0 3-2.1 5.6-5 6.7-2.9-1.1-5-3.7-5-6.7V3.8z"/></svg>"#),
27
        "dir" => concat!(
28
            open!(),
29
            r#"<path d="M1.75 3h4.1l1.6 1.6h6.8c.4 0 .75.35.75.75v7.15c0 .4-.35.75-.75.75H1.75c-.4 0-.75-.35-.75-.75V3.75c0-.4.35-.75.75-.75z" fill="currentColor" stroke="none"/></svg>"#
30
        ),
31
        "file" => concat!(
32
            open!(),
33
            r#"<path d="M4 1.75h5l3.5 3.5v8.5a.5.5 0 0 1-.5.5H4a.5.5 0 0 1-.5-.5V2.25a.5.5 0 0 1 .5-.5z"/><path d="M9 1.75v3.5h3.5"/></svg>"#
34
        ),
35
        "link" => concat!(
36
            open!(),
37
            r#"<path d="M4 1.75h5l3.5 3.5v8.5a.5.5 0 0 1-.5.5H4a.5.5 0 0 1-.5-.5V2.25a.5.5 0 0 1 .5-.5z"/><path d="M6 11.5 9.5 8M7 8h2.5v2.5"/></svg>"#
38
        ),
39
        "subrepo" => concat!(open!(), r#"<path d="M2.5 5 8 2.5 13.5 5v6L8 13.5 2.5 11z"/><path d="M2.5 5 8 7.5 13.5 5M8 7.5v6"/></svg>"#),
40
        "up" => concat!(open!(), r#"<path d="M6 3.5 3 6.5l3 3"/><path d="M3 6.5h6.5a3 3 0 0 1 3 3v3"/></svg>"#),
41
        "star" => concat!(open!(), r#"<path d="M8 1.9l1.85 3.75 4.15.6-3 2.92.7 4.13L8 11.35 4.3 13.3l.7-4.13-3-2.92 4.15-.6z"/></svg>"#),
42
        "eye" => concat!(
43
            open!(),
44
            r#"<path d="M1.5 8S4 3.5 8 3.5 14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8z"/><circle cx="8" cy="8" r="2"/></svg>"#
45
        ),
46
        "fork" => concat!(
47
            open!(),
48
            r#"<circle cx="4.5" cy="3.5" r="1.5"/><circle cx="11.5" cy="3.5" r="1.5"/><circle cx="8" cy="12.5" r="1.5"/><path d="M4.5 5v1.5c0 1 .8 1.5 1.8 1.5h3.4c1 0 1.8-.5 1.8-1.5V5M8 8v3"/></svg>"#
49
        ),
50
        "history" => concat!(open!(), r#"<circle cx="8" cy="8" r="6"/><path d="M8 4.5V8l2.5 1.5"/></svg>"#),
51
        _ => "",
52
    }
53
}
54
55
#[cfg(test)]
56
mod tests {
57
    #[test]
58
    fn every_named_icon_is_one_closed_svg() {
59
        for name in [
60
            "home", "explore", "help", "projects", "bell", "settings", "admin", "dir", "file", "link", "subrepo", "up", "history", "star",
61
            "eye", "fork",
62
        ] {
63
            let s = super::svg(name);
64
            assert!(s.starts_with("<svg class=\"ic\"") && s.ends_with("</svg>"), "{name}");
65
            assert_eq!(s.matches("<svg").count(), 1, "{name}");
66
        }
67
        assert_eq!(super::svg("nothing"), "");
68
    }
69
}