Icon
Eighty common icons by name, drawn inline as SVG in the text's colour, in five sizes or any pixel size.
Demo
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.qwemain.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>}Related
FileIconA file's icon by its extension, written on it and coloured by its kind: document, sheet, PDF, image, code and more.6 views · 9 downloadsIconGridEvery icon of the kit with its name in a grid, narrowed as you type, each one a click away from its name.6 views · 7 downloadsAudioPlayerAn audio clip with play, a seek bar that says the time, and a button cycling through playback speeds.6 views · 7 downloadsCameraCaptureTakes a photo with the camera into a hidden input as a data URL, with retake, and says so when there is no camera.6 views · 6 downloadsCoverImageA wide picture with a title, subtitle and actions over a gradient, in three heights.7 views · 7 downloadsEmbedFrameAnother page in a frame that keeps its shape and fills its width, with a title, permissions and a sandbox.5 views · 4 downloads
Thread
Thread 0 posts
On Icon: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.