These components used to generate a table in Rails 7 app.
rails g component Tables::Table
rails g component Tables::Row
rails g component Tables::Header
rails g component Tables::Cell
rails g component Tables::CheckboxCell
After running generator delete the following files (don't need them).
rm app/components/tables/cell_component.html.erb
rm app/components/tables/header_component.html.erb
# frozen_string_literal: true
class Tables::TableComponent < ApplicationComponent
renders_many :headers, Tables::HeaderComponent
renders_many :rows, Tables::RowComponent
end
<div class="mt-4 flex flex-col">
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<% headers.each do |header| %>
<%= header %>
<% end %>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<% rows.each do |row| %>
<%= row %>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
</div>
# frozen_string_literal: true
class Tables::HeaderComponent < ApplicationComponent
include Tables::CellClasses
attr_reader :title, :align, :small_visible
def initialize(title = nil, align: :left, small_visible: true)
@title = title
@align = align
@small_visible = small_visible
end
def call
tag.th title || content, scope: "col",
class: class_names("px-6 py-3 text-xs font-medium text-gray-500 uppercase tracking-wider", align_class, small_visible_class)
end
end
# frozen_string_literal: true
class Tables::RowComponent < ApplicationComponent
renders_many :cells, Tables::CellComponent
end
<tr>
<% cells.each do |cell| %>
<%= cell %>
<% end %>
</tr>
# frozen_string_literal: true
class Tables::CellComponent < ApplicationComponent
include Tables::CellClasses
private attr_reader :primary, :align, :small_visible
def initialize(primary: false, align: :left, small_visible: true)
@primary = primary
@align = align
@small_visible = small_visible
end
def call
tag.td content, class: class_names("px-6 py-2 whitespace-nowrap text-sm", align_class, small_visible_class, {
"font-medium text-gray-900": primary,
"text-gray-500": !primary
})
end
end
# frozen_string_literal: true
class Tables::CheckboxCellComponent < ApplicationComponent
private attr_reader :checked
def initialize(checked)
@checked = checked
end
def check_state
checked ? "checked" : "unchecked"
end
end
<div class="flex h-5">
<input disabled <%= check_state %> type="checkbox" class="h-4 w-4 rounded border-gray-300 text-indigo-600">
</div>
Put in app/components/tables
# frozen_string_literal: true
module Tables::CellClasses
def small_visible_class
small_visible == true ? "" : "hidden md:table-cell"
end
def align_class
align == :right ? "text-right" : "text-left"
end
end