Introducing Hanami Icons
Most of what can be read here is around and for Ruby on Rails. My main apps still are powered by it. But monopolies are never good. Hanami is the one I get most excited about.
It is why I extracted the core features (pulling SVGs from remote repository, transforming filenames, etc.) of Rails Icons into a Ruby gem, called Icons, so other frameworks can have all the icons in their apps as well.
Hanami Icons is the next wrapper of the Icons gem for… drumroll… Hanami! It gives you the same interface as Rails Icons too, whether that is Heroicons, Lucide, Tabler or even a folder of your own SVGs.
<%== icon "check", class: "text-gray-500" %>
<%== icon "apple", library: "simple_icons", class: "text-black" %>
if you have seen Rails icons, you know Hanami Icons.
One interface, all the libraries
The work is done in Icons. If you do not know it: it syncs SVGs from their source repositories, normalizes names, handles variants and builds sprite markup. Hanami Icons just adds the Hanami-specific parts: a provider, view helpers and CLI generators.
Hanami Icons supports twelve first-party libraries: from good-old Feather to Heroicons to Lucide and Phosphor. That ranges from 49 icons in SidekickIcons to more than 9,000 in Phosphor. You can also add your own library (more on that below).
Install and generate
Hanami loads CLI extensions from the :cli Bundler group, while the view helpers need the gem at runtime. Add it to both:
gem "hanami_icons", group: [:default, :cli]
Then run:
bundle install
hanami generate icons --library=lucide
The generator writes config/providers/icons.rb, registers the icons provider, adds the helpers to app/views/helpers.rb and syncs the library. You can pick several libraries or only the variants you need:
hanami generate icons --libraries=heroicons lucide
hanami generate icons --library=heroicons --variants solid outline
The Hanami configuration can be used to set a default library and variant there:
HanamiIcons.configure do |config|
config.default_library = "heroicons"
config.default_variant = "outline"
end
Icons and sprites
The main helper takes the icon name and any attributes you want on the SVG:
icon "check"
icon "check", variant: "solid"
icon "check", library: "heroicons"
icon "check", class: "icon icon-small"
icon "check", aria: { label: "Save" }
icon "check", stroke_width: 2
A page with many icons repeats the same paths over and over. Sprites fix that. Generate one:
hanami generate icons:sprite
Then reference symbols instead of inlining every path:
<%== sprite_icon "check" %>
<%== sprite_icon "search", class: "icon icon-small fill-blue-500" %>
Point config.default_sprite_location at the generated file or at a CDN. Set it to nil to inline the sprite in your layout with icons_sprite. Check the README for more details on sprites. They give you the best of customisability and rendering optimisation.
Custom libraries and syncing
Any directory under app/assets/svg/icons is a “library”. Add a SVG and use it:
app/assets/svg/icons/simple_icons/apple.svg
icon "apple", library: "simple_icons"
Libraries with variants use a variant directory, like heroicons/outline/check.svg. If you want a starting point, hanami generate icons --library=simple_icons creates the folder and adds config.custom_library :simple_icons to the provider.
You can also sync a library from a git repository:
HanamiIcons.configure do |config|
config.custom_library :my_icons, source: {
url: "https://github.com/user/icons.git",
variants: { default: "." }
}
end
The icons:sync command runs before the app boots, so it does not load providers. It only sees the first-party libraries. Sync a custom library inside the app context instead:
bundle exec hanami run 'Icons::Sync.new(:my_icons).now'
For first-party libraries, syncing is a single command:
hanami generate icons:sync
hanami generate icons:sync --library=heroicons
hanami generate icons:sync --libraries=heroicons lucide
Run it whenever an upstream library adds icons you want. No bundle update hanami_icons needed.
Hanami Icons is at 0.6.0. It is still early. The generators and helpers have tests, but I want to hear from people using it in real apps before calling it 1.0. If something feels awkward, open an issue or send a pull request.
If Hanami Icons saves you an afternoon, a star helps other Hanami developers find it. ⭐
Want to read me more?
-
Introducing Icons: Add any icon library to your Ruby app
Icons is a new gem to add any icon library to your Ruby apps. -
Free Icon Libraries for Rails Apps
A list of the most popular, free icon libraries you can use in your Ruby on Rails app. -
Rails Icons 1.0.0 is here
You don't need JavaScript for many modern UI components. The accordion is a classic example. Let's explore how it's done.
Over to you…
What did you like about this article? Learned something knew? Found something is missing or even broken? 🫣 Let me (and others) know!
Comments are powered by Chirp Form
{{comment}}