npx skills add ...
npx skills add thinkoodle/rails-skills --skill lucide-icons
Expert guidance for using Lucide icons in Rails applications via the lucide-rails gem. Use when adding icons, choosing icon names, styling SVG icons, making icons accessible, or building icon-based UI patterns (buttons, nav, badges, empty states). Triggers on "lucide", "icon", "lucide-rails", "SVG icon", "icon library", "lucide_icon", "feather icon", "inline SVG", "add an icon", "icon button", "icon name".
npx skills add thinkoodle/rails-skills --skill lucide-icons
Render Lucide icons as inline SVGs via the lucide-rails gem. Icons use currentColor so they inherit text color automatically.
size:. The default 24px is too large for most inline contexts.currentColor. Style the parent, not the SVG.lucide_icon keeps icons consistent, cacheable, and updatable."chevron-right", never "chevronRight" or "ChevronRight".No JavaScript, no import maps, no asset pipeline config. The gem provides a Ruby helper that renders inline SVGs.
Renders:
| Parameter | Default | Description |
|---|---|---|
size | 24 | Width and height in pixels |
class | nil | CSS classes |
stroke_width | 2 | Stroke width (1–3 typical range) |
Any additional HTML attributes are passed through to the <svg> element:
Pick size based on context. Be consistent within each context.
| Context | Size | When |
|---|---|---|
| Badges, inline labels | 12px | Tight spaces, small text |
| Dismiss/close, inline actions | 14px | Body text companion |
| Buttons with text | 16px | Most common for actions |
| Navigation sidebar | 18px | Nav links, menu items |
| Card/list item icons | 20px | Content type indicators |
| Empty states, hero | 32–48px | Large decorative icons |
Icons stroke with currentColor — they inherit the parent's color:
When you need icon-specific colors, use a utility class on the parent or icon wrapper:
Thinner strokes look more refined at larger sizes. Thicker strokes read better small.
Since icons use currentColor, they adapt to dark mode when your text colors do. No extra work needed if your color system uses CSS custom properties.
Icon-only buttons MUST have aria-label.
Decorative — icon accompanies visible text. No extra markup needed:
Meaningful — icon is the only content. MUST add accessible text:
aria-hidden by DefaultThe lucide_icon helper renders SVGs that screen readers skip. This is correct — the accessible name belongs on the interactive parent element, not the icon.
| Icon Name | Use |
|---|---|
home | Home/Dashboard |
layout-dashboard | Dashboard/Overview |
settings | Settings |
users | Team/People |
file-text | Documents/Pages |
log-out | Sign out |
log-in | Sign in |
menu | Hamburger menu |
search | Search |
| Icon Name | Use |
|---|---|
plus | Create/Add |
edit | Edit/Modify |
trash | Delete |
copy | Copy to clipboard |
x | Close/Dismiss |
check | Confirm/Save |
eye | View/Preview |
eye-off | Hide |
download | Download |
upload | Upload |
external-link | Open in new tab |
| Icon Name | Use |
|---|---|
arrow-left | Back |
arrow-right | Forward |
chevron-down | Expand/Dropdown |
chevron-right | Next/Drill-in |
chevron-up | Collapse |
arrow-up-right | External/Outbound |
| Icon Name | Use |
|---|---|
check-circle | Success |
alert-circle | Error |
alert-triangle | Warning |
info | Information |
help-circle | Help |
loader | Loading (animate with CSS) |
lock | Restricted/Private |
unlock | Public/Open |
| Icon Name | Use |
|---|---|
mail | |
bell | Notifications |
message-circle | Chat/Comments |
megaphone | Announcements |
send | Send message |
| Icon Name | Use |
|---|---|
file | Generic file |
file-text | Document |
folder | Folder/Category |
folder-plus | New folder |
image | Image/Photo |
video | Video |
link | Link/URL |
| Icon Name | Use |
|---|---|
github | GitHub |
twitter | Twitter/X |
globe | Website/World |
calendar | Date/Schedule |
clock | Time/History |
star | Favorite |
heart | Like |
filter | Filter |
sort-asc | Sort ascending |
sort-desc | Sort descending |
"chevronRight" → use "chevron-right" (kebab-case always)size: 16<svg> or <img> tags — Always use lucide_icon helpercolor, not the SVG's strokearia-label — Screen readers can't describe itBrowse the full library at lucide.dev/icons.
Search tips:
circle-check not checkmark-in-circlefile, file-text, file-plus, file-xFor detailed patterns, edge cases, and advanced usage, see reference.md.
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="..."></path>
</svg><%= lucide_icon "home", size: 16, class: "text-muted" %>
<%= lucide_icon "home", size: 24, stroke_width: 1.5 %><%= lucide_icon "copy", size: 14, data: { action: "click->clipboard#copy" } %>
<%= lucide_icon "x", size: 18, aria: { label: "Close" } %>.nav-link { color: var(--color-muted); }
.nav-link:hover { color: var(--color-default); }
/* Icon color changes automatically on hover */.text-success { color: var(--color-positive); }
.text-danger { color: var(--color-negative); }
.text-warning { color: var(--color-warning); }
.text-muted { color: var(--color-muted); }<span class="text-success"><%= lucide_icon "check", size: 14 %></span>
<span class="text-danger"><%= lucide_icon "alert-circle", size: 14 %></span><%= lucide_icon "settings", size: 48, stroke_width: 1.5 %> <%# Large, elegant %>
<%= lucide_icon "check", size: 12, stroke_width: 2.5 %> <%# Small, readable %><button class="btn btn-primary">
<%= lucide_icon "plus", size: 16 %>
Create Project
</button>.btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}<button class="btn-icon" aria-label="Close">
<%= lucide_icon "x", size: 18 %>
</button>.btn-icon {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem;
}<%= link_to dashboard_path, class: "nav-link" do %>
<%= lucide_icon "layout-dashboard", size: 18 %>
Dashboard
<% end %><span class="badge">
<%= lucide_icon "lock", size: 12 %>
Restricted
</span>.badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
}<div class="empty-state">
<%= lucide_icon "folder-plus", size: 48, stroke_width: 1.5 %>
<h3>No projects yet</h3>
<p>Create your first project to get started.</p>
</div>.empty-state {
text-align: center;
padding: 3rem 1rem;
}
.empty-state svg {
color: var(--color-muted);
margin-bottom: 1rem;
}<%= link_to edit_post_path(@post), class: "action-link", data: { turbo_frame: "post_form" } do %>
<%= lucide_icon "edit", size: 14 %>
Edit
<% end %><button data-controller="clipboard" data-action="click->clipboard#copy"
data-clipboard-text-value="<%= @invite_url %>">
<%= lucide_icon "copy", size: 14 %>
Copy Link
</button><button>
<%= lucide_icon "plus", size: 16 %> Add Item
</button><%# Option 1: aria-label on the interactive element %>
<button aria-label="Close" class="btn-icon">
<%= lucide_icon "x", size: 18 %>
</button>
<%# Option 2: sr-only span %>
<button class="btn-icon">
<%= lucide_icon "x", size: 18 %>
<span class="sr-only">Close</span>
</button>.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}