Bulma Components Built with Phlex
This gem provides a set of ready-to-use Phlex components for common Bulma components and elements, making it easy to build beautiful, responsive interfaces with a clean, Ruby-focused API.
Table of Contents
- Installation
- Usage
- Card
- Dropdown
- Level
- NavigationBar
- Pagination
- Table
- Tabs
- Development
- Contributing
- License
- Credits
Installation
Add this line to your application's Gemfile:
gem "bulma-phlex"
And then execute:
bundle install
Or install it yourself as:
gem install bulma-phlex
Dependencies
This gem requires:
- Ruby 3.4 or higher
- Phlex 2.0.2 or higher
- Bulma CSS (which you'll need to include in your application)
Required Setup
-
Include Bulma CSS in your application. You can add it via npm/yarn, CDN, or the bulma-rails gem.
-
Require the gem in your code:
require "bulma-phlex"
Usage
Use the Phlex components in your Rails views or any Ruby application that supports Phlex components.
Card
Cards are flexible containers that can display various types of content including headers and content sections.
Bulma::Card() do |card|
card.head("Card Title")
card.content do
"This is some card content"
end
end
Rails Feature: Turbo Frame Content
When the turbo-rails
and phlex-rails
gems are installed, the Card component also provides method turbo_frame_content
, which allows the content to be deferred to a turbo frame. The method accepts the same parameters as the Turbo Rails helper method turbo_frame_tag
, with the addition of the following two attributes:
- pending_message (default: "Loading...")
- pending_icon (default: "fas fa-spinner fa-pulse")
Bulma::Card() do |card|
card.head("Product Info")
card.turbo_frame_content("product", src: product_path(@product), pending_message: "Loading product...")
end
Dropdown
The Dropdown component provides a flexible dropdown menu for navigation or actions. It supports both click-to-toggle (default, requires a Stimulus controller) and hoverable modes, as well as alignment and icon customization.
Bulma::Dropdown("Next Actions...") do |dropdown|
dropdown.link "View Profile", "/profile"
dropdown.link "Go to Settings", "/settings"
dropdown.divider
dropdown.item("This is just a text item")
dropdown.item do
div(class: "has-text-weight-bold") { "This is a bold item" }
end
end
Options:
-
label
(required): The dropdown button label. -
click
: Stimulus controller name for click-to-toggle (default:"bulma--dropdown"
). Set tofalse
for hoverable. -
alignment
::left
(default),:right
, or:up
. -
icon
: Icon class for the dropdown arrow (default:"fas fa-angle-down"
).
Dropdown methods:
-
link(label, path)
: Adds a link item. -
item(content = nil, &block)
: Adds a custom item (string or block). -
divider
: Adds a divider line.
Level
The Level component provides a flexible horizontal layout system with left and right alignment.
Bulma::Level() do |level|
level.left do
button(class: "button") { "Left" }
end
level.right do
button(class: "button") { "Right" }
end
level.right do
button(class: "button") { "Right 2" }
end
end
NavigationBar
The NavigationBar component provides a responsive navigation header with support for branding, navigation links, and dropdown menus.
Bulma::NavigationBar() do |navbar|
navbar.brand_item "My App", "/"
navbar.left do |menu|
menu.item "Home", "/"
menu.item "Products", "/products"
end
navbar.right do |menu|
menu.item "About", "/about"
menu.dropdown "Account" do |dropdown|
dropdown.header "User"
dropdown.item "Profile", "/profile"
dropdown.item "Settings", "/settings"
dropdown.divider
dropdown.item "Sign Out", "/logout"
end
end
end
Pagination
The Pagination component provides navigation controls for paginated content, including previous/next links, page number links, and a summary of items being displayed.
# In a controller action:
@products = Product.page(params[:page]).per(20)
# In the view:
Bulma::Pagination(@products, ->(page) { products_path(page: page) })
Table
The Table component provides a way to display data in rows and columns with customizable headers and formatting options.
users = User.all
Bulma::Table(users, fullwidth: true, hoverable: true) do |table|
table.column "Name" do |user|
user.full_name
end
# use the symbol-to-proc shortcut!
table.column "Email", &:email
table.column "Actions" do |user|
link_to "Edit", edit_user_path(user), class: "button is-small"
end
end
Constructor Keyword Arguments:
-
rows
: the data for the table as an enumerable (anything that responds toeach
) -
id
: the Id for the table element (defaults to "table") -
bordered
: adds theis-bordered
class (boolean, defaults to false) -
striped
: adds theis-striped
class (boolean, defaults to false) -
narrow
: adds theis-narrow
class (boolean, defaults to false) -
hoverable
: adds theis-hoverable
class (boolean, defaults to false) -
fullwidth
: adds theis-fullwidth
class (boolean, defaults to false)
Arguments for column
Method:
The column
method takes the column name and any html attributes to be assigned to the table cell element. The block will be called with the row as the parameter.
Additional Column Types
Instead of calling column
, you can also invoke the following methods to add amount, date, and icon columns:
Arguments for amount_column
(Rails only):
- name: content for the
th
element -
currency
(keyword): options that will be passed to [Rails helper number_to_currency](https://api.rubyonrails.org/classes/ActiveSupport/NumberHelper.html#method-i-number_to_currency, uses Rails defaults)
table.amount_column("Payment Amount") { |row| row.payment_amount }
table.amount_column("Total", currency: { unit: "€" }, class: "is-bold", &:total)
Arguments for date_column
:
- name: content for the
th
element -
format
(keyword): the formatting options (will be passed tostrftime
, defaults to "%Y-%m-%d")
table.date_column("Due Date", format: "%B %d, %Y") { |row| row.due_date }
Arguments for conditional_icon
:
The icon column is intended to show a boolean flag: a yes / no or an on / off. When the value is true the icon shows and when the value is false it does not.
- name: content for the
th
element -
icon_class
(keyword): the icon to show (defaults to the Font Awesome check mark: "fas fa-check")
table.conditional_icon("Completed?", &:complete)
table.conditional_icon("Approved?", icon_class: "fas fa-thumbs-up") { |row| row.status == "Approved" }
Pagination
If the table should be paginated, invoke method paginate
with a block that will return a path given a page number.
table.paginate do |page_number|
products_path(page: { number: page_number })
end
In order to support pagination, the rows
argument passed into the constructor must repond with integers to the following:
- current_page
- total_pages
- per_page
- total_count
- previous_page (can be nil)
- next_page (can be nil)
This generates the Bulma pagination component, providing navigation controls for paginated content.
Tabs
The Tabs component provides a way to toggle between different content sections using tabbed navigation, with support for icons and active state management.
Behavior of the tabs can be driven by the data attributes, which are assigned by the object passed in as the data_attributes_builder
. By default, this will use the StimulusDataAttributes
class with the controller name bulma--tabs
. The controller is not provided by this library, but you can create your own Stimulus controller to handle the tab switching logic. Here is an implementation of a Stimulus controller for Bulma tabs.
Bulma::Tabs(tabs_class: "is-boxed", contents_class: "ml-4") do |tabs|
tabs.tab(id: "profile", title: "Profile", active: true) do
"Profile content goes here"
end
tabs.tab(id: "settings", title: "Settings", icon: "fas fa-cog") do
"Settings content goes here"
end
tabs.tab(id: "notifications", title: "Notifications", icon: "fas fa-bell") do
"Notifications content goes here"
end
end
Constructor Keyword Arguments:
-
tabs_class
: Classes to be added to the tabs div, such asis-boxed
,is-medium
,is-centered
, oris-toggle
. -
contents_class
: Classes added to the div that wraps the content (no Bulma related tabs functionality here, just a hook). -
data_attributes_builder
: Builder object that responds tofor_container
,for_tab
, andfor_content
(with the latter two receiving the tabid
). See the defaultStimulusDataAttributes
for an example.
Keyword Arguments for tab
Method:
-
id
: The id to be assigned to the content. The tab will be assigned the same id with the suffix-tab
. -
title
: The name on the tab. -
active
: Adds theis-active
class to the tab and shows the related content. Non-active content is assigned theis-hidden
class. Defaults tofalse
. -
icon
: Specify an optional icon class.
Development
After checking out the repo, run bundle install
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and the created tag, and push the .gem
file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/RockSolt/bulma-phlex.
License
The gem is available as open source under the terms of the MIT License.
Credits
This leverages the Bulma CSS library and Phlex but is not endorsed or certified by either. We are fans of the both and this makes using them together easier.