Domma Icons
A comprehensive SVG icon library with 540+ icons across 19 categories, including a Forms set for beside form fields. Click any icon to copy.
0 icons in 0 categories
<p class="text-sm text-muted"><strong id="total-icons">0</strong> icons in <strong id="total-categories">0</strong> categories</p>
<div class="flex flex-wrap items-center gap-3 mb-4 sx-gallery-controls">
<div class="icons-search-wrapper">
<span class="icons-search-icon" data-icon="search" data-icon-size="18"></span>
<input type="text" class="icons-search-input form-input" id="search" placeholder="Search icons..." aria-label="Search icons">
</div>
<div class="icons-size-controls">
<button class="icons-size-btn" data-size="16" type="button">16</button>
<button class="icons-size-btn active" data-size="24" type="button">24</button>
<button class="icons-size-btn" data-size="32" type="button">32</button>
<button class="icons-size-btn" data-size="48" type="button">48</button>
</div>
</div>
<div class="tabs" id="icon-tabs">
<div class="tab-list icons-tab-list" role="tablist" id="tab-list"></div>
<div class="tab-content" id="icon-gallery"></div>
</div>
<div class="icons-no-results" id="no-results" style="display:none">
<div class="icons-no-results-icon" data-icon="search" data-icon-size="64"></div>
<p class="text-2xl font-semibold mb-2">No icons found</p>
<p>Try a different search term</p>
</div>/**
* Domma Icons - from public/showcase/icons.
*/
export function mount(root) {
// Icon size state
let currentSize = 24;
// Category data
const categoryMeta = {
buildings: {name: 'Buildings', description: 'Architecture, structures, landmarks, and facilities'},
code: {name: 'Code', description: 'Code, and code operations'},
commerce: {name: 'Commerce', description: 'Shopping, payments, and e-commerce'},
communication: {name: 'Communication', description: 'Messaging, email, and notification icons'},
devices: {name: 'Devices', description: 'Electronic devices, phones, computers, and hardware'},
emojis: {name: 'Emojis', description: 'Expressive emoji faces and emotional reactions'},
files: {name: 'Files', description: 'Documents, folders, and file operations'},
finance: {name: 'Finance', description: 'Charts, currency, banking, and business icons'},
health: {name: 'Health', description: 'Medical, wellness, pills, and healthcare symbols'},
media: {name: 'Media', description: 'Audio, video, images, and playback controls'},
navigation: {name: 'Navigation', description: 'Arrows, directions, and navigation elements'},
seasonal: {name: 'Seasonal', description: '\'Tis the season to be jolly'},
social: {name: 'Social', description: 'Social media, sharing, and user interactions'},
sport: {name: 'Sport', description: 'Sports, fitness, awards, and athletic equipment'},
status: {name: 'Status', description: 'Indicators, alerts, and state icons'},
transport: {name: 'Transport', description: 'Vehicle icons'},
ui: {name: 'UI', description: 'Core user interface elements - buttons, menus, controls'},
forms: {name: 'Forms', description: 'Input fields, validation, and form controls'},
weather: {name: 'Weather', description: 'Weather conditions, sun, clouds, rain, and meteorology'}
};
// Track tabs instance
let tabsInstance = null;
// Render the icon gallery
function renderGallery(filter = '') {
const gallery = $(root).find('#icon-gallery');
const tabList = $(root).find('#tab-list');
const categories = Domma.icons.listCategories();
const filterLower = filter.toLowerCase();
let totalIcons = 0;
let totalCategories = 0;
let navHtml = '';
let panelsHtml = '';
let firstCategory = true;
Object.entries(categories).forEach(([key, cat]) => {
let icons = cat.icons;
// Filter icons
if (filterLower) {
icons = icons.filter(name => name.toLowerCase().includes(filterLower));
}
if (icons.length === 0) return;
totalCategories++;
totalIcons += icons.length;
const meta = categoryMeta[key] || {name: key, description: ''};
const activeClass = firstCategory ? ' active' : '';
// Tab navigation item
navHtml += `<button type="button" class="tab-item icons-tab-item${activeClass}" role="tab" data-tab="${key}">${meta.name} (${icons.length})</button>`;
// Tab panel content
panelsHtml += `
<div class="tab-panel${activeClass}" data-panel="${key}">
<p class="icons-category-description">${meta.description}</p>
<div class="icons-icon-grid">
`;
icons.forEach(name => {
const iconHtml = Domma.icons.html(name, {size: currentSize});
panelsHtml += `
<div class="icons-icon-card" data-icon-name="${name}" title="Click to copy: ${name}">
${iconHtml}
<span class="icons-icon-name">${name}</span>
</div>
`;
});
panelsHtml += '</div></div>';
firstCategory = false;
});
tabList.html(navHtml, {safe: false});
gallery.html(panelsHtml, {safe: false});
// Update stats
$(root).find('#total-icons').text(totalIcons);
$(root).find('#total-categories').text(totalCategories);
// Show/hide elements based on results
const hasResults = totalIcons > 0;
$(root).find('#no-results').css('display', hasResults ? 'none' : 'block');
$(root).find('#icon-tabs').css('display', hasResults ? 'block' : 'none');
// Initialise tabs component
if (hasResults) {
tabsInstance = E.tabs(root.querySelector('#icon-tabs'), {animation: true});
}
// Attach click handlers
$('.icons-icon-card').on('click', function () {
const name = $(this).attr('data-icon-name');
copyToClipboard(name);
});
}
// Copy icon name to clipboard
function copyToClipboard(name) {
const text = `data-icon="${name}"`;
navigator.clipboard.writeText(text).then(() => {
E.toast(`Copied: ${name}`, {...({
position: 'bottom-center',
duration: 2000
}), type: 'success'});
});
}
// Search handler with debounce
let searchTimeout;
$(root).find('#search').on('input', function () {
clearTimeout(searchTimeout);
searchTimeout = setTimeout(() => {
renderGallery($(this).val());
}, 200);
});
// Size controls
$('.icons-size-btn').on('click', function () {
$('.icons-size-btn').removeClass('active');
$(this).addClass('active');
currentSize = parseInt($(this).attr('data-size'), 10);
renderGallery($(root).find('#search').val());
});
// Initial render
renderGallery();
}Usage
HTML Data Attributes
<!-- Basic usage -->
<span data-icon="check"></span>
<!-- With size -->
<span data-icon="user" data-icon-size="32"></span>
JavaScript API
// Scan and render data-icon attributes
I.scan();
// Create an SVG element
const icon = I.render('heart', {size: 24});
$('#icon-target').append(icon);
// Get an SVG HTML string
const svg = I.html('star', {size: 24, class: 'my-icon'});
// List the available categories
I.listCategories();
<div class="icons-usage-grid">
<div class="icons-usage-card">
<h3>HTML Data Attributes</h3>
<pre><code class="language-html"><!-- Basic usage -->
<span data-icon="check"></span>
<!-- With size -->
<span data-icon="user" data-icon-size="32"></span></code></pre>
</div>
<div class="icons-usage-card">
<h3>JavaScript API</h3>
<pre><code class="language-javascript">// Scan and render data-icon attributes
I.scan();
// Create an SVG element
const icon = I.render('heart', {size: 24});
$('#icon-target').append(icon);
// Get an SVG HTML string
const svg = I.html('star', {size: 24, class: 'my-icon'});
// List the available categories
I.listCategories();</code></pre>
</div>
</div>