MishkaCmsCore. Runtime. PageBuilder. Icons. Heroicons
(Mishka CMS Core v0.0.1)
Copy Markdown
View Source
The heroicon set, as a MishkaCmsCore.Runtime.PageBuilder.IconLibrary.
Why this exists
An icon attribute's value is a class name — hero-check, hero-check-solid — resolved by
the Tailwind heroicons plugin at priv/static/temp/js_assets/vendor/heroicons.js, which reads the
SVGs out of deps/heroicons/optimized and emits one hero-* component class per file. Nothing in
the kit bundle carries that list: Chelekom's icon component declares attr :name, :string with
no values and no docs, so the editor's only options were to guess or to make the author type
hero-exclamation-triangle from memory, with a typo producing a silently missing glyph.
So the list is read from the same directory the plugin reads, at compile time: the heroicons
dependency in the deps of the project being built (Mix.Project.deps_path/0) — this library's
own when it is built alone, its host's when it is a dependency. Compile time is the point: deps/
is a build-time artefact and a release does not ship it, while the class names the release renders
are baked into its CSS — reading at runtime would work in dev and return an empty picker in
production.
The four variants
The plugin's own table, which this mirrors exactly:
"" → 24/outline (the default weight)
"-solid" → 24/solid
"-mini" → 20/solid
"-micro" → 16/solidA name is offered in every variant the set actually ships it in — 16/solid carries eight fewer
icons than the others, so a blanket suffix list would advertise glyphs that render as nothing.
When the catalogue is empty
If the directory cannot be found the module compiles to an empty catalogue rather than failing the
build, and available?/0 answers false for this set: every variant lists no names, svg/2 is
nil and css/1 is "". The picker then falls back to a plain text box — a host that does not
use heroicons loses the picker, not the editor.
Summary
Functions
Every icon class the set ships, sorted — hero-academic-cap, hero-academic-cap-micro, …
Whether a catalogue was found at compile time. False means the picker degrades to a text box.
How many icons the query matches in a variant, for the picker's counter.
CSS rules for the named icon classes, mirroring what the Tailwind heroicons plugin emits.
Whether a value names an icon this set actually ships.
The bare names in one variant, without the hero- prefix or the suffix.
The icons matching a query, capped.
One icon as inline SVG, sized to size pixels — nil when the set does not ship it.
The variant suffixes, in the plugin's own order — outline first, because it is the default.
Functions
@spec all() :: [String.t()]
Every icon class the set ships, sorted — hero-academic-cap, hero-academic-cap-micro, …
@spec available?() :: boolean()
Whether a catalogue was found at compile time. False means the picker degrades to a text box.
@spec count(String.t() | nil, String.t()) :: non_neg_integer()
How many icons the query matches in a variant, for the picker's counter.
Counted rather than length(search(...)) because the search is capped — the count is what tells a
reader their query is too broad, and a capped list cannot say so.
CSS rules for the named icon classes, mirroring what the Tailwind heroicons plugin emits.
The editor cannot rely on the site's compiled stylesheet for these. That stylesheet is generated
from the classes the site's own pages RENDER, and a component's default icon appears in no page's
HTML — so chelekom-alert's hero-chat-bubble-bottom-center-text had a 28×28 box on the canvas
with mask-image: none inside it, which reads as "the icon is broken" rather than "this class was
never compiled".
The rule is the plugin's own, restated: the SVG as a data URI mask, currentColor as the paint, and
the plugin's size table (24px, or 20px for -mini, 16px for -micro). Only the classes actually
in front of the reader are emitted — a few per page, not all 1,288.
Whether a value names an icon this set actually ships.
The bare names in one variant, without the hero- prefix or the suffix.
The icons matching a query, capped.
The query is matched against the name with its hero- prefix and variant suffix stripped, so
"arrow" finds hero-arrow-up and hero-arrow-up-solid alike, and a reader who types the whole
class name still finds it. An empty query returns the head of the list rather than nothing: an
empty picker looks broken, and the first page of icons is a reasonable place to start browsing.
@spec svg(String.t(), pos_integer()) :: {:safe, iodata()} | nil
One icon as inline SVG, sized to size pixels — nil when the set does not ship it.
The source file's own <svg> attributes are kept (viewBox, fill, stroke-width), because a 20px
solid icon and a 24px outline icon are drawn differently and a single hardcoded viewBox would
squash half the set.
The variant suffixes, in the plugin's own order — outline first, because it is the default.