gg_icon

Package VersionHex Docs

The set-agnostic icon interface for Lustre — the shared contract every gg_icons_* set (lucide, tabler, heroicons, …) is generated against. It holds the size scale, the svg wrapper, and the authoring placeholder. It imports no concrete icon set and ships no Tailwind, keeping it a lean, dual-target (JS + Erlang) foundation.

Part of the gg_ui project. See dev-docs/icons.md for the full icon-system design.

gleam add gg_icon

What's in it

An icon is a Gleam function that emits a Lustre SVG element with its path data baked in — no npm runtime, tree-shakeable per function, identical on both Lustre targets. The concrete sets do that emitting; gg_icon is the interface they all call.

Size + size

A typed size scale. Each maps to a cn-icon-size-* class whose name carries the size- token, so an explicit size defeats a container's [&_svg:not([class*='size-'])] auto-size default (the shadcn idiom). Sizing is orthogonal to set and variant.

import gg_icon/icon
// Default size (whatever the container/CSS decides):
lucide.star([])
// Typed scale → "cn-icon-size-lg":
lucide.star([icon.size(icon.Lg)])
// One-off escape hatch — wins by source order (keep the `size-` token):
lucide.star([attribute.class("size-[18px]")])

svg

The shared wrapper every generated icon calls. It's generic over view_box and per-variant defaults so it serves stroke and fill variants (an outline variant passes fill=none stroke=currentColor; a filled one passes fill=currentColor). Caller attrs are appended last, so overrides win by source order. Everything stays currentColor, so color / text-* drive the colour.

icon.svg(
view_box: "0 0 24 24",
defaults: [#("fill", "none"), #("stroke", "currentColor"), #("stroke-width", "2")],
attrs: attrs,
children: [svg.path([attribute.attribute("d", "m6 9 6 6 6-6")])],
)

placeholder + fallback_box

placeholder is the authoring construct used in registry source — the (future) CLI transformer rewrites each call to a direct <shard>.<icon>(attrs) for the user's chosen set/variant, so it never reaches a shipped bundle. Until then (and in any non-transformed runtime) it renders fallback_box: a neutral rounded square marking where an icon would go.

Consuming a set

You don't usually depend on gg_icon directly — you depend on a set that depends on it, and call the set's generated functions:

import gg_icons_lucide/lucide/c as lucide_c
pub fn view() {
lucide_c.chevron_down([icon.size(icon.Sm)])
}

Licence

MIT