
3D Extruded Buildings & Urban Footprints
Real-world 3D building extrusions with dynamic sunlight shadows, terrain DEM elevations, and pitch/bearing camera controls.
iconsuiShowcase + recipe page for the registry’s default icon set (Lucide). Not a runtime component — install the npm package directly. Documented here so consumers can browse names and import recipes.
Also available for React ->$pnpm dlx shadcn-vue@latest add https://uipkge.dev/r/vue/icons.json$npx shadcn-vue@latest add https://uipkge.dev/r/vue/icons.json$yarn dlx shadcn-vue@latest add https://uipkge.dev/r/vue/icons.json$bunx shadcn-vue@latest add https://uipkge.dev/r/vue/icons.jsonnpx shadcn-vue@latest add @uipkge/iconsInstalls to:app/components/ui/icons/| Name | Type / Values | Default | Required |
|---|---|---|---|
sizeSize | 'xs''sm''md''lg''xl''2xl''inherit' | 'md' | optional |
colorColor | string | — | optional |
classCustom class for icon libraries (fa-, mdi-, etc.) | HTMLAttributes['class'] | — | optional |
srcFor img-based icons | string | — | optional |
alt | string | — | optional |
rotationRotation/flip | number | string | — | optional |
flip | 'horizontal''vertical''both' | — | optional |
labelA11y | string | — | optional |
ariaLabel | string | — | optional |
inlineStyle | boolean | true | optional |
<script setup lang="ts">
import { computed } from 'vue'
import type { HTMLAttributes } from 'vue'
import { cn } from '@/lib/utils'
/**
* Universal Icon component supporting multiple icon libraries:
* - Lucide (default, via slot)
* - Font Awesome (via class:fa-* and :class)
* - Material Design Icons (via class:mdi-* and :class)
* - Heroicons (via slot)
* - Custom SVG (via src prop)
*/
const props = withDefaults(
defineProps<{
// Size
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'inherit'
// Color
color?: string
// Custom class for icon libraries (fa-, mdi-, etc.)
class?: HTMLAttributes['class']
// For img-based icons
src?: string
alt?: string
// Rotation/flip
rotation?: number | string
flip?: 'horizontal' | 'vertical' | 'both'
// A11y
label?: string
ariaLabel?: string
// Style
inline?: boolean
}>(),
{
size: 'md',
inline: true,
},
)
const sizeClasses = {
xs: 'size-3',
sm: 'size-4',
md: 'size-5',
lg: 'size-6',
xl: 'size-8',
'2xl': 'size-12',
inherit: 'size-full',
}
const rotationDeg = computed(() => {
if (!props.rotation) return undefined
return typeof props.rotation === 'string' ? parseInt(props.rotation) : props.rotation
})
const flipClasses = computed(() => {
if (!props.flip) return ''
if (props.flip === 'horizontal') return '-scale-x-100'
if (props.flip === 'vertical') return '-scale-y-100'
if (props.flip === 'both') return '-scale-x-100 -scale-y-100'
return ''
})
</script>
<template>
<!-- Image-based icon (Material Design, custom URLs, etc.) -->
<img
v-if="src"
data-uipkge
data-slot="icon"
:src="src"
:alt="alt || label || ''"
:class="
cn(
'shrink-0 object-contain',
inline ? 'inline-block' : 'block',
size !== 'inherit' ? sizeClasses[size] : '',
flipClasses,
props.class,
)
"
:style="{
color: color,
transform: rotationDeg ? `rotate(${rotationDeg}deg)` : undefined,
}"
:aria-label="ariaLabel || label || undefined"
role="img"
/>
<!-- Slot-based icon (Lucide, Heroicons, inline SVG) -->
<span
v-else
data-uipkge
data-slot="icon"
:class="
cn(
'shrink-0 items-center justify-center',
inline ? 'inline-flex' : 'flex',
size !== 'inherit' ? sizeClasses[size] : '',
flipClasses,
props.class,
)
"
:style="{
color: color,
transform: rotationDeg ? `rotate(${rotationDeg}deg)` : undefined,
}"
:aria-label="ariaLabel || label || undefined"
:role="ariaLabel || label ? 'img' : undefined"
:aria-hidden="!(ariaLabel || label) ? 'true' : undefined"
>
<slot />
</span>
</template>
export { default as Icon } from './Icon.vue'
// Icon library class prefixes for reference:
// Font Awesome: 'fa-solid', 'fa-regular', 'fa-brands', 'fa-*'
// Material Design: 'mdi mdi-*'
// Heroicons: already SVG-based, use slot
// Helper function to generate Font Awesome class
export function faClass(iconName: string, style: 'solid' | 'regular' | 'brands' = 'solid'): string {
const prefix = style === 'brands' ? 'fab' : style === 'solid' ? 'fas' : 'far'
return `${prefix} fa-${iconName}`
}
// Helper function to generate Material Design class
export function mdiClass(iconName: string): string {
return `mdi mdi-${iconName}`
}
Raw manifest:https://uipkge.dev/r/vue/icons.json