| 1 | // Package icons is this app's icon set, scaffolded once by |
| 2 | // rastrillo new --icons=lucide --icon-delivery=inline and owned |
| 3 | // by this app from then on. Edit it, add to it, or replace it. |
| 4 | // |
| 5 | // Keys are Lucide slugs whatever the set: that is rastrillo's icon |
| 6 | // vocabulary, so {{icon "search"}} means the same thing in every |
| 7 | // app and the shipped ui/ partials never have to change. |
| 8 | // |
| 9 | // Wire both seams onto your template tree: |
| 10 | // |
| 11 | // tmpl := template.Must(template.New(""). |
| 12 | // Funcs(ui.Funcs(ui.WithIcons(icons.Icon, icons.Assets))). |
| 13 | // ParseFS(ui.Templates(), "*.html")) |
| 14 | // |
| 15 | // Every icon is aria-hidden: it sits beside its own visible text label, |
| 16 | // which is the accessible name. A control that uses an icon as its ONLY |
| 17 | // label needs an explicit aria-label. |
| 18 | package icons |
| 19 | |
| 20 | import "html/template" |
| 21 | |
| 22 | var icons = map[string]template.HTML{ |
| 23 | "alert-triangle": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>`, |
| 24 | "check": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>`, |
| 25 | "check-circle": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>`, |
| 26 | "chevron-down": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><path d="m6 9 6 6 6-6"/></svg>`, |
| 27 | "help-circle": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><path d="M12 17h.01"/></svg>`, |
| 28 | "info": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`, |
| 29 | "kebab": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>`, |
| 30 | "plus": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><path d="M5 12h14"/><path d="M12 5v14"/></svg>`, |
| 31 | "search": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>`, |
| 32 | "x": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`, |
| 33 | "x-circle": `<svg class="icon" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>`, |
| 34 | } |
| 35 | |
| 36 | // Icon renders one icon by its Lucide slug. An unknown slug renders |
| 37 | // nothing rather than panicking a page mid-response — a typo costs a |
| 38 | // missing icon, not a crash. rastrillo generate --check catches it |
| 39 | // before ship. |
| 40 | func Icon(slug string) template.HTML { return icons[slug] } |
| 41 | |
| 42 | // Assets is the markup this delivery mode needs in the document <head>. |
| 43 | // Inline delivery vendors every icon into the binary, so there is |
| 44 | // nothing to load and this returns empty. Call it anyway: switching |
| 45 | // --icon-delivery later then needs no template change. |
| 46 | func Assets() template.HTML { return "" } |
| 47 | |