Glyphs
Phlex icon components for every rails_icons library — plus bundled RuboCop cops that validate icon names at lint time and autocorrect legacy icon helpers.
class ApplicationComponent < Phlex::HTML
include Glyphs
end
LucideIcon(:house, class: "size-4")
PhosphorIcon("lock", variant: :bold)
HeroIcon(:check, class: "size-5 text-success")
Installation
# Gemfile
gem "glyphs"
Glyphs renders the SVG files that rails_icons syncs into your app. If you haven't already:
rails generate rails_icons:install --libraries=lucide heroicons
rails generate rails_icons:sync --libraries=lucide heroicons
Outside Rails, configure the icons gem directly:
Icons.configure do |config|
config.base_path = File.(__dir__)
config.icons_path = "svg/icons"
end
Components
include Glyphs (a Phlex::Kit) into your component base class and call icons as capitalized methods:
| Component | rails_icons library |
|---|---|
LucideIcon |
lucide |
PhosphorIcon |
phosphor |
HeroIcon |
heroicons |
TablerIcon |
tabler |
FeatherIcon |
feather |
BoxIcon |
boxicons |
FlagIcon |
flags |
HugeIcon |
hugeicons |
LinearIcon |
linear |
RadixIcon |
radix |
SidekickIcon |
sidekickicons |
WeatherIcon |
weather |
AnimatedIcon |
animated (bundled spinners: faded-spinner, bouncing-dots, ...) |
Names can be symbols or strings; underscores are dasherized (:circle_check → circle-check.svg).
variant: selects the library variant (default comes from your rails_icons/icons configuration);
every other keyword (class:, data:, stroke_width:, ...) is forwarded onto the <svg> tag.
The generic component requires an explicit library:
Icon(:house, library: :lucide) # flagged by Glyphs/PreferLibraryComponent, prefer LucideIcon(:house)
Custom libraries get first-class components too:
Glyphs.register_library(:brand, component: :BrandIcon)
BrandIcon(:logo)
(The SVG location for a custom library is configured through rails_icons/icons custom-library config.)
Missing-icon policy
# config/initializers/glyphs.rb
Glyphs.configure do |config|
# Re-raise Icons::IconNotFound? Defaults to true in local Rails
# environments (and outside Rails), false otherwise.
config.raise_on_missing = Rails.env.local?
# Optional handler, called before the fallback renders (when not raising).
config.on_missing_icon = lambda do |error, name:, library:, variant:|
Rails.logger.error("Icon missing: #{library}/#{variant}/#{name} (#{error.})")
end
# Rendered instead of the missing icon (per library). nil/absent => re-raise.
config.fallback_icons = {
lucide: "circle-question-mark",
phosphor: "question",
heroicons: "question-mark-circle"
}
# Memoize rendered SVG strings per [library, variant, name, attributes]. Default: true.
# Note: fallback renders are cached under the original name, so on_missing_icon
# fires once per process per missing icon rather than on every render.
config.cache_svgs = true
end
RuboCop cops
Add the plugin (RuboCop >= 1.72):
# .rubocop.yml
plugins:
- glyphs
(Classic require: [glyphs/rubocop] also works, but you must enable the cops yourself.)
Glyphs/LegacyIconHelper
Autocorrects legacy helper calls to Glyphs components:
_lucide(:house, class: "size-4") # => LucideIcon(:house, class: "size-4")
_heroicon(:check) # => HeroIcon(:check)
icon("check", library: "lucide") # => LucideIcon("check")
icon("check") # => HeroIcon("check") (DefaultLibraryComponent)
Glyphs/LegacyIconHelper:
Include:
- app/**/*.rb
DefaultLibraryComponent: HeroIcon
# Mappings replaces the built-in defaults (_lucide/_phosphor/_hero/_heroicon/_tabler):
# Mappings:
# _custom: CustomIcon
Glyphs/IconResolution
Validates statically-known icon names against your synced SVG directories, honors literal
variant: keywords, suggests close matches (with autocorrect for unambiguous typos and the
Lucide v1 renames), and flags raw iconify class strings:
LucideIcon(:alert_triangle) # => corrected to LucideIcon(:triangle_alert)
span(class: "iconify lucide--house size-4") # => corrected to LucideIcon(:house, class: "size-4")
Glyphs/IconResolution:
Include:
- app/**/*.rb
IconsPath: app/assets/svg/icons
# Libraries merges over the built-in defaults (component => Dir/DefaultVariant):
Libraries:
PhosphorIcon: { Dir: phosphor, DefaultVariant: regular }
Glyphs/PreferLibraryComponent
Icon(:house, library: :lucide) # => LucideIcon(:house)
Migrating an app off icon helpers
- Add
gem "glyphs",include Glyphswhere the helpers used to be included. - Add the plugin and cop config above to
.rubocop.yml. - Delete your local icon helper, then run:
bundle exec rubocop -A --only Glyphs/LegacyIconHelper,Glyphs/PreferLibraryComponent
- Wire your old missing-icon logging into
Glyphs.configure(see above).
Development
bundle install
bundle exec rspec
bundle exec rubocop
License
MIT — see LICENSE.txt.