5.4 KiB
SVG Usage Analysis Report
Summary
This analysis examines SVG usage patterns in the Svelte 5 codebase to identify optimization opportunities, inconsistencies, and unused assets.
Key Findings
1. Inline SVGs vs. Imported SVGs
Inline SVGs Found:
-
Close/X buttons: Found in 7+ components with identical SVG code
admin/Modal.svelteadmin/UnifiedMediaModal.svelteadmin/MediaInput.svelteadmin/AlbumSelectorModal.svelteadmin/GalleryManager.svelteadmin/MediaDetailsModal.svelteLightbox.svelte
-
Loading spinners: Found in 2+ components
admin/Button.svelteadmin/ImageUploader.svelteadmin/GalleryUploader.svelte
-
Navigation arrows: Found in
PhotoLightbox.svelte -
Lock icon: Found in
LabCard.svelte -
External link icon: Found in
LabCard.svelte
2. SVG Import Patterns
Consistent patterns using aliases:
// Good - using $icons alias
import ArrowLeft from '$icons/arrow-left.svg'
import ChevronDownIcon from '$icons/chevron-down.svg'
// Component imports with ?component
import PhotosIcon from '$icons/photos.svg?component'
import ViewSingleIcon from '$icons/view-single.svg?component'
// Raw imports
import ChevronDownIcon from '$icons/chevron-down.svg?raw'
3. Unused SVG Files
Unused icons in /src/assets/icons/:
dashboard.svgmetadata.svg
Unused illustrations in /src/assets/illos/:
jedmund-blink.svgjedmund-headphones.svgjedmund-listening-downbeat.svgjedmund-listening.svgjedmund-open.svgjedmund-signing-downbeat.svgjedmund-singing.svglogo-figma.svglogo-maitsu.svglogo-pinterest.svglogo-slack.svg
4. Duplicate SVG Definitions
Close/X Button SVG (appears 7+ times):
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
Loading Spinner SVG (appears 3+ times):
<svg class="spinner" width="24" height="24" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none" stroke-dasharray="25" stroke-dashoffset="25" stroke-linecap="round">
<animateTransform attributeName="transform" type="rotate" from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/>
</circle>
</svg>
5. SVGs That Could Be Componentized
- Close Button: Used across multiple modals and components
- Loading Spinner: Used in buttons and upload components
- Navigation Arrows: Used in lightbox and potentially other navigation
- Status Icons: Lock, external link, eye icons in LabCard
Recommendations
1. Create Reusable Icon Components
Option A: Create individual icon components
<!-- $lib/components/icons/CloseIcon.svelte -->
<script>
let { size = 24, class: className = '' } = $props()
</script>
<svg width={size} height={size} viewBox="0 0 24 24" fill="none" class={className}>
<path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
</svg>
Option B: Create an Icon component with name prop
<!-- $lib/components/Icon.svelte -->
<script>
import CloseIcon from '$icons/close.svg'
import LoadingIcon from '$icons/loading.svg'
// ... other imports
let { name, size = 24, class: className = '' } = $props()
const icons = {
close: CloseIcon,
loading: LoadingIcon,
// ... other icons
}
const IconComponent = $derived(icons[name])
</script>
{#if IconComponent}
<IconComponent {size} class={className} />
{/if}
2. Extract Inline SVGs to Files
Create new SVG files for commonly used inline SVGs:
/src/assets/icons/close.svg/src/assets/icons/loading.svg/src/assets/icons/external-link.svg/src/assets/icons/lock.svg/src/assets/icons/eye-off.svg
3. Clean Up Unused Assets
Remove the following unused files to reduce bundle size:
- All unused illustration files (11 files)
- Unused icon files (2 files)
4. Standardize Import Methods
Establish a consistent pattern:
- Use
?componentfor SVGs used as Svelte components - Use direct imports for SVGs used as images
- Avoid
?rawimports unless necessary
5. Create a Loading Component
<!-- $lib/components/LoadingSpinner.svelte -->
<script>
let { size = 24, class: className = '' } = $props()
</script>
<svg class="loading-spinner {className}" width={size} height={size} viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2" fill="none"
stroke-dasharray="25" stroke-dashoffset="25" stroke-linecap="round">
<animateTransform attributeName="transform" type="rotate"
from="0 12 12" to="360 12 12" dur="1s" repeatCount="indefinite"/>
</circle>
</svg>
<style>
.loading-spinner {
color: currentColor;
}
</style>
Benefits of These Changes
- Reduced code duplication: Eliminate 20+ duplicate SVG definitions
- Smaller bundle size: Remove 13 unused SVG files
- Better maintainability: Centralized icon management
- Consistent styling: Easier to apply consistent styles to all icons
- Type safety: With proper component props
- Performance: Less inline SVG parsing, better caching
Implementation Priority
- High Priority: Extract and componentize duplicate inline SVGs (close button, loading spinner)
- Medium Priority: Remove unused SVG files
- Low Priority: Standardize all import patterns and create comprehensive icon system