Icons
Lucide, Tabler and Simple Icons by name, as nodes you color and animate. Only the icons a scene names end up in its binary.
Loading live preview…
Source of architecture — edit in the playground
//! An architecture diagram with icons: `icon!` names an icon from Lucide,
//! Tabler or Simple Icons, and only those end up in the binary.
use oxframe::prelude::*;
#[oxframe::scene]
pub async fn request(view: View) {
view.add(
Txt::new()
.text("How a request is served")
.h1()
.to_edge(Edge::Top),
);
let flow = view.add(
FlowDiagram::new()
.edge("browser", "edge")
.edge("edge", "api")
.edge("api", "cache")
.edge("api", "database")
.icon("browser", icon!("lucide:globe"))
.icon("edge", icon!("lucide:cloud"))
.icon("api", icon!("lucide:server"))
.icon("cache", icon!("tabler:bolt"))
.icon("database", icon!("lucide:database"))
.opacity(0.0),
);
flow.enter().await;
for _ in 0..flow.len() {
flow.next().await;
}
// A slow query: the database turns red and back.
if let Some(db) = flow.icon("database") {
db.color().to(Danger, 0.3).await;
db.stroke_width().to(3.0, 0.3).await;
wait_for(0.4).await;
all((db.color().to(Text, 0.4), db.stroke_width().to(2.0, 0.4))).await;
}
let logos = view.add(Layout::new().gap(56.0).y(300.0).opacity(0.0));
for name in [
icon!("simple:github"),
icon!("simple:rust"),
icon!("simple:cloudflare"),
] {
logos.add(name.size(56.0).color(Muted));
}
logos.fade_in().await;
wait_for(0.6).await;
}
pub fn project() -> Project {
Project::new("architecture").scene(request())
}An icon by name
Turn on the icons feature of oxframe:
oxframe = { version = "…", features = ["icons"] } let server = view.add(icon!("lucide:server").size(64.0).color(Accent));
view.add(icon!("tabler:heart-filled"));
view.add(icon!("simple:github").color(Muted)); icon! takes the set and the name. The name is the one on the set's site: lucide.dev/icons, tabler.io/icons (add -filled for the filled
variant) and simpleicons.org for brand logos. A name that
does not exist fails to compile and the error lists the closest names, so icon!("lucide:arow-right") suggests arrow-right.
| Prefix | Set | Icons | License |
|---|---|---|---|
lucide: | Lucide, outlines | 2,171 | ISC |
tabler: | Tabler Icons, outlines and -filled | 6,238 | MIT |
simple: | Simple Icons, brand logos | 3,466 | CC0; the brands are trademarks of their owners |
Size, color and line width
An icon is a 24 by 24 grid scaled to .size(), 48 pixels by default. Its color is the
theme's text color unless you set .color() with a color or a theme role. Outline
icons take .stroke_width() on the 24-unit grid, 2 by default; filled icons and logos have
no lines.
The handle, Icon, has color() and stroke_width() as
signals, so a whole icon animates at once. It is a node like any other: fade_in, next_to, scale and layout work on it. Icon::paths gives its
paths one by one, for draw_on, and Icon::style tells an IconStyle::Stroke icon from an IconStyle::Fill one.
server.color().to(Danger, 0.3).await;
server.stroke_width().to(3.0, 0.3).await;
for path in server.paths() {
path.draw_on().await;
} In a flow diagram
FlowDiagram puts an icon at the start of a node's card with .icon(name, icon!(..)). flow.icon(name) returns its handle.
let flow = view.add(
FlowDiagram::new()
.edge("api", "database")
.icon("api", icon!("lucide:server"))
.icon("database", icon!("lucide:database")),
);
flow.enter().await;
if let Some(db) = flow.icon("database") {
db.color().to(Danger, 0.3).await;
} Any other SVG
Icon::from_svg(bytes, IconStyle::Stroke) makes the same node from a 24 by 24 SVG of
your own. For a logo or an illustration at its own size, use the Svg node.
The playground has the feature on, so icon! works in a scene there.