Skip to content

FTxIcon

A versatile icon component that supports Quasar Material Icons, custom SVG sprites, and inline SVG icons. Optimized for performance with zero build impact when adding new icons.

Features

  • Quasar Material Icons - Full support for all Material Icons
  • SVG Sprites - Optimal performance with sprite-based icons (recommended)
  • Inline SVG - Fallback support for inline SVG icons
  • Multi-Project Support - Library provides common icons, projects manage their own
  • Zero Build Impact - Adding icons doesn't affect build performance
  • Easy Maintenance - Just edit SVG files, no code changes needed

Installation

The component is included in @ftx/ui:

javascript
import { FTxIcon } from '@ftx/ui';

Quick Start

Basic Usage

vue
<template>
  <!-- Quasar Material Icon (explicit with material: prefix) -->
  <FTxIcon name="material:home" size="24px" color="primary" />
  
  <!-- Library icon (ftx: prefix) -->
  <FTxIcon name="ftx:column" svg-size="24px" />
  
  <!-- Project icon (no prefix) -->
  <FTxIcon name="dashboard" svg-size="24px" />
</template>

<script setup>
import { FTxIcon } from '@ftx/ui';
</script>

Props

PropTypeDefaultDescription
nameStringrequiredIcon name. Can be: Quasar Material Icon with material: prefix (e.g., material:home), library icon with ftx: prefix (e.g., ftx:column), or project icon with no prefix (e.g., dashboard)
sizeStringundefinedSize for Quasar Material Icons
colorStringundefinedColor for Quasar Material Icons
svgSizeString'24px'Size for custom SVG icons
svgColorString'currentColor'Color for custom SVG icons
iconClassString''Additional CSS classes
useSpriteBooleantrueUse SVG sprite (recommended for performance)
spritePathStringnullOverride sprite path (optional)

Icon Naming Conventions

The component uses naming conventions to determine which icon system to use:

PrefixTypeExampleDescription
material:Quasar Material Iconmaterial:home, material:font_downloadONLY way to use Quasar Material Icons (wraps QIcon with all Quasar features)
ftx:Library Iconftx:columnCommon icons provided by the library (maps to ftx-column in registry)
No prefixProject Icondashboard, reportsProject-specific icons (must be registered via registerIcon() or sprite file)

Important Notes:

  • Material icons (material:): ONLY way to use Quasar Material Icons. The component wraps QIcon with all Quasar features. The prefix is stripped and the icon name is passed to QIcon. No fallback - must use material: prefix.
  • Library icons (ftx:): Always use custom SVG from the library's sprite file. Example: ftx:column maps to ftx-column in the registry
  • Project icons (no prefix): Use custom SVG if registered/in sprite. No fallback - icons must be explicitly registered via registerIcon(), registerIcons(), or added to a sprite file

Icon Types

The component supports three types of icons based on the naming convention:

1. Quasar Material Icons

Explicit Material Icons (Recommended): Use the material: prefix to explicitly use Quasar Material Icons. This wraps Quasar's QIcon component with all its features:

vue
<FTxIcon name="material:home" size="24px" color="primary" />
<FTxIcon name="material:settings" size="32px" color="secondary" />
<FTxIcon name="material:font_download" size="20px" color="negative" />

The component renders as <q-icon name="icon-name" /> with all QIcon props supported. See Quasar Icon documentation for all available features.

Important: The material: prefix is required to use Quasar Material Icons. There is no fallback - icons without a prefix are treated as project icons only.

vue
<!-- ✅ Correct - Uses Quasar Material Icon -->
<FTxIcon name="material:home" size="24px" color="primary" />

<!-- ❌ Wrong - Will not work, treated as project icon -->
<FTxIcon name="home" size="24px" color="primary" />

2. Library Icons (ftx: prefix)

Common icons provided by the library. These are stored in the common-icons.svg sprite file.

vue
<!-- Library common icon -->
<FTxIcon name="ftx:column" svg-size="24px" />

Note: The ftx:column format maps to ftx-column in the registry. Use the colon format (ftx:) when referencing library icons.

Characteristics:

  • Always start with ftx- prefix
  • Provided by the library
  • Available without any setup
  • Stored in sprite files for optimal performance

3. Project Icons (no prefix)

Project-specific icons that you register in your project. These can be registered via registerIcon(), registerIcons(), or in project sprite files.

vue
<!-- Project icon from sprite -->
<FTxIcon name="dashboard" svg-size="24px" />

<!-- Project icon registered dynamically -->
<FTxIcon name="reports" svg-size="24px" />

Characteristics:

  • No prefix required
  • Registered by your project
  • Must be registered - no fallback to Quasar Material Icons
  • Can be stored in project sprite files or registered dynamically via registerIcon() or registerIcons()

Registering Project Icons:

javascript
import { registerIcon, registerIcons } from '@ftx/ui';

// Register a single icon
registerIcon('dashboard', dashboardSvg);

// Register multiple icons
registerIcons({
  'dashboard': dashboardSvg,
  'reports': reportsSvg,
  'settings': settingsSvg,
});

4. Inline SVG Icons (Fallback)

Icons registered via registerIcon() or registerIcons() are rendered as inline SVG. If a sprite is available and the icon is not in iconMap, the component will use the sprite instead:

vue
<!-- Uses inline SVG from iconMap -->
<FTxIcon name="dashboard" svg-size="24px" />

<!-- Uses sprite if icon not in iconMap -->
<FTxIcon name="settings" svg-size="24px" />

Priority Order:

  1. Icons in iconMap (registered via registerIcon()) → Inline SVG
  2. Icons in sprite files → Sprite reference
  3. Missing icons → Display nothing (like Quasar)

Note: Library icons (ftx: prefix) are always served via sprite files. Project icons can be either in iconMap (inline) or sprite files.

Important: If a project icon is not found (not registered and not in sprite), the component displays nothing (similar to Quasar's behavior). No fallback to Quasar Material Icons - you must use the material: prefix to use Quasar icons.

Available Common Icons

The library provides common icons that are shared across multiple projects. These icons are stored in the common-icons.svg sprite file and are available without any setup:

ftx:column (Library Icon)

A table column icon used for column selection/visibility controls in grid components.

vue
<FTxIcon name="ftx:column" svg-size="24px" />

Note: When using library icons, use the ftx: prefix format. This maps to ftx-column in the internal registry.

Usage in FtxGrid:

The FtxGrid component automatically uses this icon for its column selection button:

vue
<template>
  <FtxGrid :columns="columns" :choose-column="true" />
  <!-- Column icon is automatically displayed in the column selection button -->
</template>

The icon displays a table with columns (vertical lines) inside a rounded rectangle border, making it perfect for column management interfaces.

Internal Usage: The grid component internally uses <FTxIcon name="ftx:column" svg-size="20px" /> to ensure consistency across the library.

Setup for Multi-Project Icon Management

Architecture

Library (Common Icons)
└── common-icons.svg (only shared icons)

Project (Project Icons)
└── svg-icons.svg (all project icons)

Step 1: Create Project Sprite File

Create public/svg-icons.svg in your project:

svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <!-- Project-specific icons -->
    <symbol id="project-dashboard" viewBox="0 0 24 24" fill="none">
      <path d="..." stroke="currentColor" stroke-width="2"/>
    </symbol>
    
    <symbol id="project-reports" viewBox="0 0 24 24" fill="none">
      <path d="..." fill="currentColor"/>
    </symbol>
  </defs>
</svg>

Step 2: Register Sprites

In your main.js or App.vue:

javascript
import { createApp } from 'vue';
import { registerSprite } from '@ftx/ui';
import App from './App.vue';

// Register library common icons sprite (optional)
// Copy common-icons.svg to public/icons/ if needed
registerSprite('/icons/common-icons.svg', {
  prefix: 'ftx-',
  priority: 10
});

// Register your project sprite (no prefix for project icons)
registerSprite('/svg-icons.svg', {
  prefix: '', // No prefix - these are project icons
  priority: 20
});

const app = createApp(App);
app.mount('#app');

Step 3: Use Icons

vue
<template>
  <div>
    <!-- Quasar Material icon (explicit) -->
    <FTxIcon name="material:home" size="24px" />
    
    <!-- Library common icon (ftx: prefix) -->
    <FTxIcon name="ftx:column" svg-size="24px" />
    
    <!-- Project icon (no prefix) -->
    <FTxIcon name="dashboard" svg-size="24px" />
  </div>
</template>

<script setup>
import { FTxIcon } from '@ftx/ui';
</script>

Adding Icons

Adding Project Icons (No Build Needed!)

Method 1: Using Sprite File (Recommended)

  1. Edit your project's sprite file (public/svg-icons.svg)
  2. Add a new <symbol> element (no prefix needed for project icons):
svg
<symbol id="dashboard" viewBox="0 0 24 24" fill="none">
  <path d="..." fill="currentColor"/>
</symbol>
  1. Save the file
  2. Refresh browser - icon is immediately available!
vue
<FTxIcon name="dashboard" svg-size="24px" />

Method 2: Register Dynamically

javascript
import { registerIcon } from '@ftx/ui';
import dashboardIcon from './icons/dashboard.svg?raw';

registerIcon('dashboard', dashboardIcon);

Note: Icons registered via registerIcon() take priority over sprite files. If an icon exists in iconMap, it will use the registered version instead of the sprite.

Adding Common Icons (Library)

Important: Common icons are stored in the common-icons.svg sprite file only. Individual SVG files are not used for common icons.

  1. Edit packages/ui/src/icons/common-icons.svg
  2. Add a new <symbol> element with ftx- prefix:
svg
<symbol id="ftx-new-common-icon" viewBox="0 0 24 24" fill="none">
  <path d="..." stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>

Key points:

  • Use <symbol> element (not <svg>)
  • id attribute must match icon name (e.g., ftx-new-common-icon)
  • Use currentColor for fill/stroke to allow color customization
  • Include viewBox attribute (typically 0 0 24 24)
  1. Rebuild library
  2. The sprite file will be included in the distribution

Note: The icon-registry.js file is primarily for project-specific icons registered dynamically. Common library icons are served via the sprite file for optimal performance.

Multiple Sprite Sources

You can register multiple sprites for different icon sets:

javascript
import { registerSprite } from '@ftx/ui';

// Common icons (highest priority)
registerSprite('/icons/common-icons.svg', {
  prefix: 'ftx-',
  priority: 10
});

// Navigation icons
registerSprite('/icons/nav-icons.svg', {
  prefix: 'nav-',
  priority: 20
});

// Action icons
registerSprite('/icons/action-icons.svg', {
  prefix: 'action-',
  priority: 20
});

// Default project icons
registerSprite('/svg-icons.svg', {
  priority: 30
});

The component searches sprites in priority order.

Examples

Different Sizes

vue
<template>
  <div>
    <FTxIcon name="ftx:column" svg-size="16px" />
    <FTxIcon name="ftx:column" svg-size="24px" />
    <FTxIcon name="ftx:column" svg-size="32px" />
    <FTxIcon name="ftx:column" svg-size="48px" />
  </div>
</template>

Different Colors

vue
<template>
  <div>
    <FTxIcon name="ftx:column" svg-size="24px" svg-color="#1976d2" />
    <FTxIcon name="ftx:column" svg-size="24px" svg-color="#dc004e" />
    <FTxIcon name="ftx:column" svg-size="24px" svg-color="#4caf50" />
  </div>
</template>

With Quasar Components

vue
<template>
  <q-btn>
    <FTxIcon name="ftx:column" svg-size="20px" class="q-mr-sm" />
    Columns
  </q-btn>
</template>

In Grid Component

The FtxGrid component uses the library ftx:column icon for its column selection button:

vue
<template>
  <FtxGrid :columns="columns" :choose-column="true" />
  <!-- The ftx:column icon is automatically displayed in the column selection button -->
</template>

The grid component internally uses <FTxIcon name="ftx:column" svg-size="20px" /> to ensure consistency across the library.

SVG Icon Best Practices

1. Use currentColor

Always use currentColor for fill/stroke to allow color customization:

svg
<symbol id="my-icon" viewBox="0 0 24 24" fill="none">
  <path d="..." fill="currentColor"/>
  <!-- or -->
  <path d="..." stroke="currentColor"/>
</symbol>

2. Include viewBox

Always include a viewBox attribute:

svg
<symbol id="my-icon" viewBox="0 0 24 24">

3. Optimize SVGs

  • Remove unnecessary attributes
  • Remove comments and metadata
  • Optimize paths
  • Use consistent viewBox (e.g., 0 0 24 24)

4. Icon Naming

  • Material icons: Use material: prefix (e.g., material:home) - ONLY way to use Quasar Material Icons (wraps QIcon)
  • Library icons: Use ftx: prefix (e.g., ftx:column) - provided by the library, maps to ftx-column in sprite
  • Project icons: No prefix needed (e.g., dashboard, reports) - registered by your project via registerIcon() or sprite files
  • Use kebab-case: ftx:column, dashboard, nav-settings

Behavior:

  • Missing Material icons → Display nothing (Quasar handles it)
  • Missing sprite icons → Display nothing (browser handles it)
  • Missing registered icons → Display nothing (consistent with Quasar)

API Reference

Sprite Registry Functions

registerSprite(spritePath, options)

Register a sprite source.

javascript
import { registerSprite } from '@ftx/ui';

registerSprite('/svg-icons.svg', {
  prefix: 'project-',  // Optional: icon name prefix
  priority: 20         // Lower = higher priority
});

setDefaultSprite(spritePath)

Set the default sprite path.

javascript
import { setDefaultSprite } from '@ftx/ui';

setDefaultSprite('/svg-icons.svg');

getSpritePath(iconName)

Get sprite path for an icon (used internally).

javascript
import { getSpritePath } from '@ftx/ui';

const path = getSpritePath('ftx-column'); // Internal registry uses ftx-column format
// Returns: '/icons/common-icons.svg'

getSpriteSources()

Get all registered sprite sources.

javascript
import { getSpriteSources } from '@ftx/ui';

const sources = getSpriteSources();
// Returns array of sprite source objects

Performance Benefits

SVG sprites provide significant performance advantages:

ApproachHTTP RequestsBundle SizeBuild TimeCache
Individual SVGsN iconsLargeSlowPoor
Inline SVGs0LargeSlowN/A
SVG Sprites1-2SmallNoneExcellent

Migration Guide

From Individual SVG Files

If you're currently using individual SVG files:

  1. Combine into sprite:

    svg
    <svg xmlns="http://www.w3.org/2000/svg">
      <defs>
        <symbol id="icon1" viewBox="0 0 24 24">...</symbol>
        <symbol id="icon2" viewBox="0 0 24 24">...</symbol>
      </defs>
    </svg>
  2. Register sprite:

    javascript
    setDefaultSprite('/svg-icons.svg');
  3. Update usage:

    vue
    <!-- Old -->
    <img src="/icons/icon1.svg" />
    
    <!-- New -->
    <FTxIcon name="icon1" svg-size="24px" />

From Existing Sprite Component

If you already have a sprite component like SvgIconComponent:

  1. Keep your sprite file (public/svg-icons.svg)
  2. Register it:
    javascript
    setDefaultSprite('/svg-icons.svg');
  3. Replace component:
    vue
    <!-- Old -->
    <SvgIconComponent icon="table-column" />
    
    <!-- New -->
    <FTxIcon name="table-column" svg-size="24px" />

Troubleshooting

Icon Not Showing

  1. Check sprite file is accessible:

    • Open /svg-icons.svg in browser
    • Verify it's in the public folder
  2. Verify symbol ID matches icon name:

    svg
    <symbol id="my-icon" ...>  <!-- Must match name="my-icon" -->
  3. Check sprite is registered:

    javascript
    import { getSpriteSources } from '@ftx/ui';
    console.log(getSpriteSources());
  4. Ensure useSprite={true} (default)

Icon Color Not Changing

  • Use currentColor in SVG fill/stroke
  • Use svg-color prop (not color for custom icons)

Multiple Sprites

  • Check sprite priority order
  • Verify icon name matches symbol ID
  • Use sprite-path prop to force specific sprite

Released under the MIT License.