Lucide React Reference
Lucide is a beautiful and consistent icon library with over 1000 icons. All icons are tree-shakeable, meaning only imported icons are included in the bundle.
Import
import {
Plus,
Trash2,
Check,
Circle,
Search,
Filter,
MoreHorizontal,
} from "lucide-react";
interface Task {
id: string;
text: string;
done: boolean;
}
export default function App() {
const [tasks, setTasks] = React.useState<Task[]>([]);
const [input, setInput] = React.useState("");
const [search, setSearch] = React.useState("");
const addTask = () => {
if (!input.trim()) return;
setTasks(prev => [...prev, { id: crypto.randomUUID(), text: input, done: false }]);
setInput("");
};
const toggleTask = (id: string) => {
setTasks(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t));
};
const deleteTask = (id: string) => {
setTasks(prev => prev.filter(t => t.id !== id));
};
const filtered = tasks.filter(t => t.text.toLowerCase().includes(search.toLowerCase()));
return (
<div>
<div>
<div>
<h3 className="flex items-center gap-2">
<Check className="w-5 h-5" />
Tasks
</h3>
</div>
<div className="space-y-4">
<div className="flex gap-2">
<input
value={input}
onChange={e => setInput(e.target.value)}
placeholder="Add task..."
onKeyDown={e => e.key === "Enter" && addTask()}
/>
<button onClick={addTask} size="icon">
<Plus className="w-4 h-4" />
</button>
</div>
<div className="relative">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
<input
value={search}
onChange={e => setSearch(e.target.value)}
placeholder="Search..."
className="pl-9"
/>
</div>
<div className="space-y-2">
{filtered.map(task => (
<div key={task.id} className="flex items-center gap-3 p-2 rounded-md hover:bg-muted">
<button onClick={() => toggleTask(task.id)}>
{task.done ? (
<Check className="w-5 h-5 text-primary" />
) : (
<Circle className="w-5 h-5 text-muted-foreground" />
)}
</button>
<span className={task.done ? "line-through text-muted-foreground flex-1" : "flex-1"}>
{task.text}
</span>
<button variant="ghost" size="icon" onClick={() => deleteTask(task.id)}>
<Trash2 className="w-4 h-4" />
</button>
</div>
))}
</div>
</div>
</div>
</div>
);
}
Best Practices
- Use consistent sizing -
w-4 h-4for buttons/list items,w-5 h-5for headers - Use
currentColor- Icons inherit text color by default - Use semantic color tokens -
text-primary,text-muted-foreground,text-destructive - Add
mr-2orml-2for spacing between icon and text in buttons - Use
Loader2withanimate-spinfor loading states - Import only the icons you need (do NOT import entire library)