Files
offlineu/templates/_icons.html
T
rmsitzandClaude Sonnet 5 eae6b09ecd Replace all OS-rendered emoji with a consistent SVG icon set
Add a shared Jinja icon macro (templates/_icons.html) with 27 Feather-style
stroke SVGs and import it across every live template - tab bars, buttons,
lesson-type/status icons, folder/course icons, and the lesson player's
footer brand mark all now use currentColor SVGs instead of emoji, matching
the app's vector logo instead of rendering inconsistently per platform.
A few icons built dynamically in JS (thumbnail-load fallbacks, toggled
button states) get a small ICON_SVGS constant per file, since JS template
literals can't call the Jinja macro.

Left pure directional glyphs (expand/collapse chevrons, move up/down
arrows, keyboard-shortcut arrows) as plain Unicode - they already render
as monochrome text, matching the existing collapsible-header chevron
pattern rather than the colorful pictographic emoji this was aimed at.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 21:49:10 -04:00

9 lines
5.0 KiB
HTML

{#
Shared stroke-style SVG icon set (Feather-style, 24x24 viewBox,
currentColor stroke) so every page uses the same hand-picked icons
instead of OS-rendered emoji, which render inconsistently across
platforms and clash with the app's vector logo. Import with
{% import '_icons.html' as icons %} and call icons.icon('name', size).
#}
{% macro icon(name, size=18) %}<svg class="icon" width="{{ size }}" height="{{ size }}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">{% if name == 'home' %}<path d="M3 10.5 12 3l9 7.5"></path><path d="M5 9.5V20a1 1 0 0 0 1 1h4v-6h4v6h4a1 1 0 0 0 1-1V9.5"></path>{% elif name == 'pencil' %}<path d="M12 20h9"></path><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"></path>{% elif name == 'help' %}<circle cx="12" cy="12" r="9"></circle><path d="M9.1 9a2.9 2.9 0 0 1 5.6 1c0 2-2.9 2.5-2.9 4.5"></path><line x1="12" y1="17.5" x2="12" y2="17.51"></line>{% elif name == 'settings' %}<circle cx="12" cy="12" r="3"></circle><path d="M12 2v3M12 19v3M4.2 4.2l2.1 2.1M17.7 17.7l2.1 2.1M2 12h3M19 12h3M4.2 19.8l2.1-2.1M17.7 6.3l2.1-2.1"></path>{% elif name == 'dice' %}<rect x="3" y="3" width="18" height="18" rx="4"></rect><circle cx="8" cy="8" r="1.3" fill="currentColor" stroke="none"></circle><circle cx="16" cy="8" r="1.3" fill="currentColor" stroke="none"></circle><circle cx="8" cy="16" r="1.3" fill="currentColor" stroke="none"></circle><circle cx="16" cy="16" r="1.3" fill="currentColor" stroke="none"></circle><circle cx="12" cy="12" r="1.3" fill="currentColor" stroke="none"></circle>{% elif name == 'folder' %}<path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z"></path>{% elif name == 'graduation-cap' %}<path d="M22 9 12 4 2 9l10 5 10-5Z"></path><path d="M6 11v5c0 1.4 2.7 2.5 6 2.5s6-1.1 6-2.5v-5"></path>{% elif name == 'check' %}<polyline points="20 6 9 17 4 12"></polyline>{% elif name == 'circle' %}<circle cx="12" cy="12" r="9"></circle>{% elif name == 'x' %}<line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line>{% elif name == 'pin' %}<path d="M12 21s7-6.5 7-11.5A7 7 0 0 0 5 9.5C5 14.5 12 21 12 21Z"></path><circle cx="12" cy="9.5" r="2.3"></circle>{% elif name == 'ban' %}<circle cx="12" cy="12" r="9"></circle><line x1="5.6" y1="5.6" x2="18.4" y2="18.4"></line>{% elif name == 'video' %}<rect x="2" y="5" width="14" height="14" rx="2"></rect><path d="M16 10.5 22 7v10l-6-3.5Z"></path>{% elif name == 'music' %}<path d="M9 18V5l11-2v13"></path><circle cx="6.5" cy="18" r="2.5"></circle><circle cx="17.5" cy="16" r="2.5"></circle>{% elif name == 'clipboard' %}<rect x="6" y="4" width="12" height="17" rx="2"></rect><path d="M9 4V3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1"></path><line x1="9" y1="11" x2="15" y2="11"></line><line x1="9" y1="15" x2="13" y2="15"></line>{% elif name == 'package' %}<path d="M21 8 12 3 3 8v8l9 5 9-5Z"></path><path d="M3 8l9 5 9-5M12 13v8"></path>{% elif name == 'file-text' %}<path d="M14 2H7a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8Z"></path><path d="M14 2v6h6"></path><line x1="9" y1="13" x2="15" y2="13"></line><line x1="9" y1="17" x2="15" y2="17"></line>{% elif name == 'trash' %}<path d="M4 7h16"></path><path d="M10 11v6M14 11v6"></path><path d="M6 7l1 12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-12"></path><path d="M9 7V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v3"></path>{% elif name == 'refresh' %}<path d="M21 12a9 9 0 0 1-15.3 6.4"></path><path d="M3 12a9 9 0 0 1 15.3-6.4"></path><polyline points="21 3 21 9 15 9"></polyline><polyline points="3 21 3 15 9 15"></polyline>{% elif name == 'checkbox' %}<path d="M9 11l3 3 7-7"></path><path d="M21 12v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h10"></path>{% elif name == 'list' %}<line x1="4" y1="6" x2="20" y2="6"></line><line x1="4" y1="12" x2="20" y2="12"></line><line x1="4" y1="18" x2="20" y2="18"></line>{% elif name == 'grid' %}<rect x="3" y="3" width="8" height="8" rx="1.5"></rect><rect x="13" y="3" width="8" height="8" rx="1.5"></rect><rect x="3" y="13" width="8" height="8" rx="1.5"></rect><rect x="13" y="13" width="8" height="8" rx="1.5"></rect>{% elif name == 'bar-chart' %}<line x1="6" y1="20" x2="6" y2="14"></line><line x1="12" y1="20" x2="12" y2="8"></line><line x1="18" y1="20" x2="18" y2="11"></line>{% elif name == 'list-dots' %}<line x1="8" y1="6" x2="20" y2="6"></line><line x1="8" y1="12" x2="20" y2="12"></line><line x1="8" y1="18" x2="20" y2="18"></line><circle cx="4" cy="6" r="1"></circle><circle cx="4" cy="12" r="1"></circle><circle cx="4" cy="18" r="1"></circle>{% elif name == 'history' %}<path d="M3 12a9 9 0 1 0 3-6.7"></path><polyline points="3 4 3 9 8 9"></polyline>{% elif name == 'plus-circle' %}<circle cx="12" cy="12" r="9"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line>{% elif name == 'play-circle' %}<circle cx="12" cy="12" r="9"></circle><polygon points="10 8 16 12 10 16 10 8"></polygon>{% elif name == 'play' %}<polygon points="6 3 20 12 6 21 6 3"></polygon>{% endif %}</svg>{% endmacro %}