Icons
An icon in Tela is a tela.Icon
(the text of an SVG document) shown with
h.Icon. Tela draws it as
vectors at the device scale, in the text color of its element, so one icon
serves every size, color and display scale. This page covers using icons, the
Lucide set, making your own set from SVG files, and what icons cost in a binary.
Using an icon
Section titled “Using an icon”import ( "github.com/kuronosu/tela/icons/lucide" . "github.com/kuronosu/tela/h")
Button(Class("inline-flex items-center gap-2 rounded-md bg-primary px-3 py-2 text-sm text-primary-foreground"), Icon(lucide.Check, Class("size-4")), Text("Save"))
Icon(lucide.Search, Class("size-5 text-muted-foreground"), AriaLabel("Search"))- An icon is 1em by 1em, so it follows the font size;
size-*,w-*andh-*change it. It is a block (Class("inline")puts it on a line of text). currentColoris the text color:text-*classes, theme tokens and transitions recolor it without parsing the SVG again.fill-*,stroke-*andstroke-[1.5], on the icon or on an ancestor such as the button, override the document’s own paints.- Icons are decorative (hidden from accessibility).
AriaLabelorAriaLabelledBymakes one an image with that name. - Your own icon is any SVG:
var Logo = tela.Icon{SVG: "<svg ...>"}, ortela.MustSVG(data)for an embedded file.tela.ParseSVGreturns the parse error instead of panicking. The text is parsed once and cached by the text.
Lucide
Section titled “Lucide”Lucide lives in its own module in this repository, so programs that do not use it do not download it:
go get github.com/kuronosu/tela/icons/lucideIt has one exported variable per icon, named after Lucide’s file name
(arrow-up-right is lucide.ArrowUpRight; Lucide’s deprecated aliases such as
lucide.AlertCircle are there too) and no table of icons by name. The module’s
version is Lucide’s: the tag icons/lucide/v1.61.0 has the icons of Lucide
1.61.0 (lucide.Version). The set needs a Tela release with tela.Icon.
Inside a clone of the repository the module is tested from its own directory
(cd icons/lucide && CGO_ENABLED=0 go test ./...): the root module does not
import it and go test ./... at the root skips it. The module’s README says
how to regenerate it for a new Lucide release.
Generating your own set
Section titled “Generating your own set”tela icons gen turns a directory of SVG files into one Go file:
tela icons gen -pkg icons -o ./icons ./svg(Install the command once with
CGO_ENABLED=0 go install github.com/kuronosu/tela/cmd/tela@latest; see
CLI. Without it, go run github.com/kuronosu/tela/cmd/tela icons gen ...
does the same.)
// ArrowUp is the icon "arrow-up".var ArrowUp = tela.Icon{SVG: `<svg xmlns="http://www.w3.org/2000/svg" ...>...</svg>`}| Flag | Meaning |
|---|---|
-pkg name |
Package name of the generated file (required) |
-o dir |
Output directory (default .); the file is icons_gen.go |
-r |
Read the subdirectories too (solid/arrow-up.svg is SolidArrowUp) |
-prefix text, -suffix text |
Added around every name (-prefix Icon: IconArrowUp); a prefix starts with a capital |
-skip-invalid |
Leave out files that cannot be parsed, with a warning (without it, they stop the command) |
-minify=false |
Keep the SVG files as they are (only trimmed) |
-source text, -license name, -license-file file |
Where the icons come from and their license, written in the file header and the package documentation (the license file’s text is copied in) |
How it works:
- Validation. Every file is parsed with the parser Tela draws with; the error is reported with the file’s path. Two files that make the same name are an error, and no file is written when anything fails.
- Minifying. The XML declaration, comments, DOCTYPE,
metadata,titleanddesc, editor namespaces (Inkscape, Illustrator),version,classand unreferencedidattributes (when the file has no<style>), emptydefsand white space between elements go. The generator checks that the minified document draws the same display lists as the original, in several boxes, colors and with the SVG paint classes, and fails otherwise (-minify=falseis the escape hatch). A file that declares entities is kept as written. - Names. File names are split at every character that is not a letter or a
digit and each piece is capitalized:
arrow-upisArrowUp,volume_2isVolume2. A name that does not start with a capital getsIconin front (3d-rotateisIcon3dRotate). Digits that were apart stay apart with an underscore (arrow-down-0-1isArrowDown0_1,arrow-down-01isArrowDown01). - Output. One gofmt’d file sorted by name, so the output is the same on every
run, with a
// Code generated by tela icons gen; DO NOT EDIT.header, a package documentation and a doc comment per icon.
A //go:generate line keeps the set reproducible (the Lucide module does
this). It uses go run, which needs nothing installed and uses the version
of Tela your go.mod requires:
//go:generate go run github.com/kuronosu/tela/cmd/tela icons gen -pkg icons -o . ./svgBinary size
Section titled “Binary size”There is one variable of static data per icon and no map by name on purpose.
The linker drops the variables a program does not use, so an unused icon costs
nothing; a map would reference all of them (about 0.9 MB for 1,600 icons). A
small Tela program (a Div and a Text, stripped, Linux amd64) is 19,873,952
bytes with no Lucide icon and with one, and 19,902,624 bytes (+28 KiB) with 50
of them. If you need to find an icon by a name known at run time, build a map
of the icons you use.