Media

Icon

Eighty common icons by name, drawn inline as SVG in the text's colour, in five sizes or any pixel size.

#icon#media#no-js

Demo

Preview
Tuesday 4 November Disk almost full SavedDocs

An unknown name draws the help icon.

Get it

It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.

$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/icon.qwe
main.qwe
import ui/theme.qwe use theme_cssuse ui/icon.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>

Example

The code of the preview above.

demos/icon.qwe
view IconDemo() =    <div.demo-stack>        <div.demo-row id="icon-demo-sizes">            <Icon name="search" size="xs"/>            <Icon name="search" size="sm"/>            <Icon name="search"/>            <Icon name="search" size="lg"/>            <Icon name="search" size="xl"/>            <Icon name="search" px={48} stroke={1.5}/>        </div>        <div.demo-row id="icon-demo-text" style="gap: 18px">            <span><Icon name="calendar"/> Tuesday 4 November</span>            <span style="color: var(--ui-danger)"><Icon name="warning" label="Warning"/> Disk almost full</span>            <span style="color: var(--ui-success)"><Icon name="check-circle"/> Saved</span>            <a href="https://quillolang.org" style="color: var(--ui-accent)">Docs <Icon name="external" size="sm"/></a>        </div>        <div.demo-row id="icon-demo-all" style="gap: 10px; color: var(--ui-muted)">            {for n in icon_names => <Icon name={n} label={n} size="lg"/>}        </div>        <div.demo-row>            <span id="icon-demo-missing"><Icon name="no-such-icon"/></span>            <p.demo-note>An unknown name draws the help icon.</p>        </div>    </div>

Source

ui/icon.qwe
// Icon: one of the kit's icons by name, drawn inline as SVG in the text's colour,// so it sits in a button, a link or a line of text and follows the theme.////   <Icon name="search"/>//   <Icon name="warning" size="lg" label="Warning"/>//   <button><Icon name="trash"/> Delete</button>//// name: one of icon_names (below): search, close, check, plus, minus, menu, more,// user, users, settings, trash, edit, copy, link, external, info, warning, help,// star, heart, mail, phone, calendar, clock, download, upload, share, refresh,// filter, sort, home, bell, lock, unlock, eye, eye-off, image, file, folder, globe,// bookmark, tag, grid, list, map-pin, camera, video, mic, sun, moon, play, pause,// volume, volume-off, maximize, minimize, zoom-in, zoom-out, printer, cart,// credit-card, send, log-out, code, terminal, x-circle, check-circle, alert-circle,// skip-back, skip-forward, arrow-up, arrow-down, arrow-left, arrow-right,// chevron-up, chevron-down, chevron-left, chevron-right. A name it does not know// draws the "help" icon and carries data-missing="true".// size: "xs" (12px), "sm" (16px), "md" (20px, default), "lg" (24px) or "xl" (32px);// px: a size in pixels instead.// label: what screen readers say (role "img"); without one the icon is decoration,// hidden from them, and the text beside it is what they read.// stroke: the line's width (2); 1.5 reads lighter at large sizes.// icon_path(name) gives a name's path data, for drawing one in your own SVG.import ui/theme.qwe use ui_clslet icon_css = css`.ui-icon {  display: inline-block; flex: none; width: 20px; height: 20px; vertical-align: -.22em;  fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round;}.ui-icon-xs { width: 12px; height: 12px; }.ui-icon-sm { width: 16px; height: 16px; }.ui-icon-lg { width: 24px; height: 24px; }.ui-icon-xl { width: 32px; height: 32px; }`let icon_names = [    "search", "close", "check", "plus", "minus", "menu", "more", "user", "users", "settings", "trash", "edit",    "copy", "link", "external", "info", "warning", "help", "star", "heart", "mail", "phone", "calendar", "clock",    "download", "upload", "share", "refresh", "filter", "sort", "home", "bell", "lock", "unlock", "eye", "eye-off",    "image", "file", "folder", "globe", "bookmark", "tag", "grid", "list", "map-pin", "camera", "video", "mic",    "sun", "moon", "play", "pause", "volume", "volume-off", "maximize", "minimize", "zoom-in", "zoom-out",    "printer", "cart", "credit-card", "send", "log-out", "code", "terminal", "x-circle", "check-circle",    "alert-circle", "skip-back", "skip-forward", "arrow-up", "arrow-down", "arrow-left", "arrow-right",    "chevron-up", "chevron-down", "chevron-left", "chevron-right",]// The path data of an icon (24 by 24, a 2px line), or null for a name it does not know.fn icon_path(name: str) -> str? =    match name {        "search" => "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.3-4.3"        "close" => "M18 6 6 18M6 6l12 12"        "check" => "M20 6 9 17l-5-5"        "plus" => "M12 5v14M5 12h14"        "minus" => "M5 12h14"        "menu" => "M4 6h16M4 12h16M4 18h16"        "more" => "M12 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2ZM19 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2ZM5 13a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"        "user" => "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z"        "users" => "M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"        "settings" => "M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6ZM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06A1.65 1.65 0 0 0 4.68 15a1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.68a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06A1.65 1.65 0 0 0 19.4 9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z"        "trash" => "M3 6h18M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M10 11v6M14 11v6"        "edit" => "M12 20h9M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"        "copy" => "M10 8h10a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H10a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2ZM4 16a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2"        "link" => "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"        "external" => "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14 21 3"        "info" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM12 16v-4M12 8h.01"        "warning" => "M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0ZM12 9v4M12 17h.01"        "help" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3M12 17h.01"        "star" => "m12 2 3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2Z"        "heart" => "M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78Z"        "mail" => "M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2ZM22 6l-10 7L2 6"        "phone" => "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92Z"        "calendar" => "M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2ZM16 2v4M8 2v4M3 10h18"        "clock" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM12 6v6l4 2"        "download" => "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"        "upload" => "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12"        "share" => "M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8M16 6l-4-4-4 4M12 2v13"        "refresh" => "M23 4v6h-6M1 20v-6h6M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"        "filter" => "M22 3H2l8 9.46V19l4 2v-8.54L22 3Z"        "sort" => "M3 6h18M6 12h12M9 18h6"        "home" => "m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9ZM9 22V12h6v10"        "bell" => "M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9M13.73 21a2 2 0 0 1-3.46 0"        "lock" => "M5 11h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2ZM7 11V7a5 5 0 0 1 10 0v4"        "unlock" => "M5 11h14a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2ZM7 11V7a5 5 0 0 1 9.9-1"        "eye" => "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8ZM12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"        "eye-off" => "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24M1 1l22 22"        "image" => "M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2ZM8.5 10a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM21 15l-5-5L5 21"        "file" => "M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9l-7-7ZM13 2v7h7"        "folder" => "M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2v11Z"        "globe" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM2 12h20M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10Z"        "bookmark" => "m19 21-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16Z"        "tag" => "M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82ZM7 7h.01"        "grid" => "M3 3h7v7H3zM14 3h7v7h-7zM14 14h7v7h-7zM3 14h7v7H3z"        "list" => "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"        "map-pin" => "M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0ZM12 13a3 3 0 1 0 0-6 3 3 0 0 0 0 6Z"        "camera" => "M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2v11ZM12 17a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z"        "video" => "m23 7-7 5 7 5V7ZM3 5h11a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2Z"        "mic" => "M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3ZM19 10v2a7 7 0 0 1-14 0v-2M12 19v4M8 23h8"        "sun" => "M12 17a5 5 0 1 0 0-10 5 5 0 0 0 0 10ZM12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"        "moon" => "M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79Z"        "play" => "m5 3 14 9-14 9V3Z"        "pause" => "M6 4h4v16H6zM14 4h4v16h-4z"        "volume" => "M11 5 6 9H2v6h4l5 4V5ZM19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07"        "volume-off" => "M11 5 6 9H2v6h4l5 4V5ZM23 9l-6 6M17 9l6 6"        "maximize" => "M8 3H5a2 2 0 0 0-2 2v3M21 8V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3M16 21h3a2 2 0 0 0 2-2v-3"        "minimize" => "M8 3v3a2 2 0 0 1-2 2H3M21 8h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3M16 21v-3a2 2 0 0 1 2-2h3"        "zoom-in" => "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.35-4.35M11 8v6M8 11h6"        "zoom-out" => "M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16ZM21 21l-4.35-4.35M8 11h6"        "printer" => "M6 9V2h12v7M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2M6 14h12v8H6z"        "cart" => "M9 22a1 1 0 1 0 0-2 1 1 0 0 0 0 2ZM20 22a1 1 0 1 0 0-2 1 1 0 0 0 0 2ZM1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"        "credit-card" => "M3 4h18a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2ZM1 10h22"        "send" => "m22 2-7 20-4-9-9-4 20-7ZM22 2 11 13"        "log-out" => "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"        "code" => "m16 18 6-6-6-6M8 6l-6 6 6 6"        "terminal" => "m4 17 6-6-6-6M12 19h8"        "x-circle" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM15 9l-6 6M9 9l6 6"        "check-circle" => "M22 11.08V12a10 10 0 1 1-5.93-9.14M22 4 12 14.01l-3-3"        "alert-circle" => "M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20ZM12 8v4M12 16h.01"        "skip-back" => "M19 20 9 12l10-8v16ZM5 19V5"        "skip-forward" => "m5 4 10 8-10 8V4ZM19 5v14"        "arrow-up" => "M12 19V5M5 12l7-7 7 7"        "arrow-down" => "M12 5v14M19 12l-7 7-7-7"        "arrow-left" => "M19 12H5M12 19l-7-7 7-7"        "arrow-right" => "M5 12h14M12 5l7 7-7 7"        "chevron-up" => "m18 15-6-6-6 6"        "chevron-down" => "m6 9 6 6 6-6"        "chevron-left" => "m15 18-6-6 6-6"        "chevron-right" => "m9 18 6-6-6-6"        _ => null    }view Icon(name: str, size: str = "md", px: int? = null, label: str? = null, stroke: num = 2, class: str? = null) {    style global icon_css    let d = icon_path(name)    <svg class={ui_cls(["ui-icon", px == null && size != "md" && `ui-icon-${size}`, class])}         style={px != null ? `width: ${px}px; height: ${px}px` : null} viewBox="0 0 24 24" stroke-width={stroke}         data-icon={name} data-missing={d == null ? "true" : null}         role={label != null ? "img" : null} aria-label={label} aria-hidden={label == null ? "true" : null}>        <path d={d ?? icon_path("help")}/>    </svg>}
Thread
76Useful? Like it, or add to its thread below.

Thread 0 posts

On Icon: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.