Cross-framework compatibility utilities and adapters for building Vue components that work seamlessly across Vue 2, Vue 2.7, and Vue 3
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The SVG Icon System provides comprehensive tools for creating SVG icon components with gradient icon support, unique ID generation, and responsive styling integration. It handles cross-framework compatibility and prevents SVG gradient conflicts in complex applications.
Factory function for creating Vue components from SVG icon definitions with theming and responsive support.
/**
* Create SVG icon component with theme and responsive integration
* @param config - SVG icon configuration
* @returns Function that creates Vue component instances
*/
function svg(config: SvgConfig): (propData?: any) => DefineComponent;
interface SvgConfig {
/** Icon component name (without prefix) */
name?: string;
/** SVG component definition */
component: any;
}Usage Examples:
import { svg } from "@opentiny/vue-common";
import IconUser from './icons/IconUser.vue';
// Create icon component
const TinyIconUser = svg({
name: 'IconUser',
component: IconUser
});
// Use in templates or render functions
export default {
components: {
TinyIconUser
},
template: `
<TinyIconUser
:fill="'#1890ff'"
:width="24"
:height="24"
custom-class="user-icon"
/>
`
};Special handling for SVG icons with gradient definitions to prevent ID conflicts when multiple instances are rendered.
/**
* List of icon names that require gradient ID processing
*/
const GRADIENT_ICONS_LIST: string[];
/**
* Generate unique IDs for gradient SVG icons to prevent conflicts
* @param vnode - Virtual node containing SVG element
*/
function generateIcon(vnode: any): void;Gradient Icons:
'IconLoadingShadow' - Loading spinner with gradient shadow'IconNoData' - No data placeholder with gradient stylingUsage Examples:
import { svg, GRADIENT_ICONS_LIST } from "@opentiny/vue-common";
import IconLoadingShadow from './icons/IconLoadingShadow.vue';
// Gradient icons are automatically processed
const LoadingIcon = svg({
name: 'IconLoadingShadow',
component: IconLoadingShadow
});
// Multiple instances won't have ID conflicts
export default {
setup() {
return {
LoadingIcon
};
},
template: `
<div>
<LoadingIcon class="loading-1" />
<LoadingIcon class="loading-2" />
<LoadingIcon class="loading-3" />
</div>
`
};SVG icons automatically adapt to different display modes and include responsive styling classes.
Mobile-First Mode:
tiny-svg data attributeh-4 w-4 inline-blockPC/Mobile Modes:
Usage Examples:
import { svg } from "@opentiny/vue-common";
const ResponsiveIcon = svg({
name: 'ResponsiveIcon',
component: IconComponent
});
// Icon adapts based on tiny_mode context
export default {
props: {
tiny_mode: String // 'pc', 'mobile', 'mobile-first'
},
template: `
<!-- Mobile-first: gets 'h-4 w-4 inline-block' classes -->
<!-- PC/Mobile: uses custom width/height -->
<ResponsiveIcon
:width="32"
:height="32"
custom-class="my-icon"
/>
`
};Icons support comprehensive styling customization through props and CSS custom properties.
Styling Props:
fill - Fill color for the SVGwidth - Icon width (string or number)height - Icon height (string or number)custom-class - Additional CSS classesfirst-color - Primary color for dual-tone iconssecond-color - Secondary color for dual-tone iconsUsage Examples:
import { svg } from "@opentiny/vue-common";
const CustomIcon = svg({
name: 'CustomIcon',
component: IconComponent
});
export default {
setup() {
return {
CustomIcon
};
},
template: `
<CustomIcon
fill="#ff6b6b"
:width="48"
:height="48"
custom-class="rotating-icon shadow-lg"
first-color="#4ecdc4"
second-color="#45b7d1"
/>
`
};Icons use CSS custom properties for advanced theming and dynamic color management.
/* CSS custom properties set by icon system */
.tiny-svg {
--tiny-first-color: /* value from first-color prop */;
--tiny-second-color: /* value from second-color prop */;
}
/* Use in icon SVG definitions */
.icon-path-primary {
fill: var(--tiny-first-color, #1890ff);
}
.icon-path-secondary {
fill: var(--tiny-second-color, #666666);
}Creating a comprehensive icon library with consistent theming.
import { svg } from "@opentiny/vue-common";
// Import all icon components
import * as IconComponents from './icons';
// Create icon library
const IconLibrary = Object.keys(IconComponents).reduce((library, iconName) => {
const componentName = iconName.replace('Icon', '');
library[componentName] = svg({
name: iconName,
component: IconComponents[iconName]
});
return library;
}, {});
// Export individual icons
export const {
User,
Settings,
Search,
LoadingShadow,
NoData
} = IconLibrary;
// Usage in components
export default {
components: {
IconUser: IconLibrary.User,
IconSettings: IconLibrary.Settings
},
template: `
<div class="toolbar">
<IconUser custom-class="user-avatar" />
<IconSettings @click="openSettings" />
</div>
`
};Dynamically rendering icons based on data or user interaction.
import { svg, hooks } from "@opentiny/vue-common";
import * as IconComponents from './icons';
export default {
setup(props) {
// Create dynamic icon library
const iconLibrary = hooks.computed(() => {
return Object.keys(IconComponents).reduce((library, iconName) => {
library[iconName] = svg({
name: iconName,
component: IconComponents[iconName]
});
return library;
}, {});
});
// Dynamic icon component
const dynamicIcon = hooks.computed(() => {
const iconName = props.iconName;
return iconLibrary.value[iconName] || null;
});
return {
dynamicIcon
};
},
props: {
iconName: String,
iconSize: {
type: Number,
default: 24
}
},
template: `
<component
:is="dynamicIcon"
v-if="dynamicIcon"
:width="iconSize"
:height="iconSize"
:fill="iconColor"
/>
`
};Icons that automatically adapt to theme changes.
import { svg, resolveTheme, hooks } from "@opentiny/vue-common";
export default {
setup(props, context) {
const theme = resolveTheme(props, context);
// Theme-based icon colors
const iconColors = hooks.computed(() => {
const colorSchemes = {
tiny: {
primary: '#1890ff',
secondary: '#666666',
success: '#52c41a',
warning: '#faad14',
error: '#ff4d4f'
},
saas: {
primary: '#4f46e5',
secondary: '#6b7280',
success: '#10b981',
warning: '#f59e0b',
error: '#ef4444'
}
};
return colorSchemes[theme] || colorSchemes.tiny;
});
const StatusIcon = svg({
name: 'StatusIcon',
component: IconComponent
});
return {
StatusIcon,
iconColors
};
},
props: {
status: {
type: String,
default: 'primary'
}
},
template: `
<StatusIcon
:fill="iconColors[status]"
:width="20"
:height="20"
/>
`
};Icons with proper accessibility support and semantic meaning.
import { svg } from "@opentiny/vue-common";
const AccessibleIcon = svg({
name: 'AccessibleIcon',
component: IconComponent
});
export default {
components: {
AccessibleIcon
},
props: {
ariaLabel: String,
decorative: {
type: Boolean,
default: false
}
},
template: `
<AccessibleIcon
:aria-label="decorative ? undefined : ariaLabel"
:aria-hidden="decorative"
:role="decorative ? 'presentation' : 'img'"
custom-class="accessible-icon"
/>
`
};The SVG icon system includes several performance optimizations:
markRawInstall with Tessl CLI
npx tessl i tessl/npm-opentiny--vue-common