Files
the-collective-hub/.github/instructions/icons.instructions.md
T
KungRaseri b192cd53ba docs(copilot): add Copilot instructions for The Collective Hub
- Add comprehensive project overview and core philosophy
- Document file structure reference for the codebase
- Create key files reference table for task-specific guidance
- Include multi-tenant guidelines and site resolution flow
2026-06-05 23:46:15 -07:00

5.4 KiB


description: "Use when adding icons to components or pages for The Collective Hub. Covers @lucide/svelte usage patterns — import, pass, style, and render icons." applyTo: "src//*.svelte", "src//*.ts"

Icon Usage

Overview

This project uses Lucide Icons for all UI iconography:

Source Package Purpose
Lucide Icons @lucide/svelte General UI icons (arrows, actions, status, social media, etc.)

1. Lucide Icons (@lucide/svelte)

Import Pattern

Import individual icons as named exports from @lucide/svelte — there is no centralized icon barrel/index file:

import { Heart, Menu, X, BookOpen, Video, Star, ThumbsUp } from '@lucide/svelte';

Browse the full icon catalog at lucide.dev/icons.

Note: There is no $lib/components/ui/icons barrel. All icon imports are direct from @lucide/svelte. If a centralized re-export pattern is desired in the future, it should be added to src/lib/icons/ (which does not exist yet) and clearly marked as planned in this document.

Component Props

Each Lucide icon component accepts these props:

Prop Type Default Description
size number 24 Width & height in pixels
class string '' Tailwind CSS classes for styling
strokeWidth number 2 Stroke width of the icon paths

Rendering

Use icons as self-closing components in the template:

<Heart size={20} class="text-cyan-400" />
<X size={18} class="text-slate-500 transition-colors hover:text-slate-300" />
<Video size={16} class="text-cyan-300" />

Sizing Conventions

Context size Example
Inline text / badge 16 <Heart size={16} class="text-rose-400" />
Stat card icons 20 <Star size={20} class="text-cyan-400" />
Decorative / empty state 24 <BookOpen size={24} class="text-slate-600" />

Dynamic Fill (Toggle Icons)

For icons like Hearts that toggle between filled and unfilled, control fill via the fill-current Tailwind utility:

<Heart size={20} class={isActive ? 'fill-current text-rose-400' : 'text-slate-400'} />

The fill-current class tells Tailwind to use the current text color as the fill color.

Passing Icons as Props to Other Components

Components that accept icons expect an icon component constructor, not a string. Use Svelte's Component type:

<script lang="ts">
	import type { Component } from 'svelte';
	import { Heart } from '@lucide/svelte';

	let {
		title,
		value,
		icon = undefined
	} = $props<{
		title: string;
		value: string | number;
		icon?: Component;
	}>();
</script>

{#if icon}
	<svelte:component this={icon} size={20} class="text-cyan-400" />
{/if}

At the call site, pass the component constructor (not an instance):

<script lang="ts">
	import { Heart } from '@lucide/svelte';
</script>

<StatCard title="Likes" value="42" icon={Heart} />

Dynamic Icons from Dictionaries

For dynamic icon selection (e.g., mapping status to icon), use a Record<string, Component>:

import type { Component } from 'svelte';
import { CheckCircle, XCircle, AlertTriangle } from '@lucide/svelte';

const statusIcons: Record<string, Component> = {
	success: CheckCircle,
	failure: XCircle,
	warning: AlertTriangle
};

Then render with <svelte:component>:

<svelte:component this={statusIcons[status]} size={16} class="text-cyan-400" />

2. Brand Icons (Social Media)

For social media / brand logos (Facebook, Instagram, LinkedIn, YouTube, etc.), use Lucide's brand icons or simple-icons package if Lucide doesn't cover them:

<!-- For specific brand logos, use simple-icons -->
<script lang="ts">
	import { siFacebook, siInstagram, siLinkedin, siYoutube } from 'simple-icons';
</script>

<!-- Using Lucide for social icons -->
<Globe size={18} class="text-slate-400" />
<Mail size={18} class="text-slate-400" />

<svg viewBox="0 0 24 24" class="h-5 w-5 fill-current text-slate-400">
	<path d={siFacebook.path} />
</svg>

3. Removed Patterns (What NOT To Do)

These patterns should not be used:

No lucide-svelte package (wrong package name)

// OLD — DO NOT USE
import { Heart } from 'lucide-svelte';

Use @lucide/svelte instead:

// ✅ CORRECT
import { Heart } from '@lucide/svelte';

4. Exceptions

These cases still use {@html} legitimately — they are not icon-related:

  • JSON-LD structured data injection (in <svelte:head>):
    <!-- eslint-disable-next-line svelte/no-at-html-tags -->
    {@html `<script type="application/ld+json">${jsonLd}</script>`}
    

5. Guidelines

  • Prefer @lucide/svelte components for all UI icons
  • Use simple-icons for brand logos not available in Lucide
  • Use size prop matching the text size context (16 for small, 20 for default, 24 for large)
  • Use class for color and styling via Tailwind utilities