Table
Stabletabular data display
| Project | Status | Owner |
|---|---|---|
| Docs site | Active | Mai |
| Billing | Queued | An |
| Search | Review | Linh |
Usage example #
Copy this ERB into a Rails view after installing the component. The snippet below is the same code used by the live preview above.
app/views/.../table_example.html.erb
<div class="w-full">
<%= render Senren::TableComponent.new(
caption: "Project status",
columns: [
{ key: :project, label: "Project" },
{ key: :status, label: "Status" },
{ key: :owner, label: "Owner" }
],
rows: [
{ project: "Docs site", status: "Active", owner: "Mai" },
{ project: "Billing", status: "Queued", owner: "An" },
{ project: "Search", status: "Review", owner: "Linh" }
]
) %>
</div>
Install this component #
Copy the official component into your app
Use this when you want the Senren-maintained implementation copied into app/components/senren.
Terminal
bin/rails senren:add table
Create a custom component with the same conventions
Use this when you need an app-specific static component that follows Senren's ViewComponent structure.
Terminal
bin/rails generate senren:component table --no-client
At a glance #
Category
Data
Class name
Senren::TableComponent
Stimulus
—
Variants
default, compact
Depends on
—
Pairs with
pagination, dropdown_menu, badge
Source #
app/components/senren/table_component.html.erb
<div <%= tag.attributes(**root_attrs("w-full overflow-hidden rounded-(--senren-radius) border border-[hsl(var(--senren-border))]")) %>>
<table class="w-full border-collapse text-left text-sm <%= self.class::VARIANTS[variant] %>">
<% if caption.present? %>
<caption class="sr-only"><%= caption %></caption>
<% end %>
<thead class="bg-[hsl(var(--senren-muted)/0.6)] text-[hsl(var(--senren-muted-foreground))]">
<tr>
<% columns.each do |column| %>
<th scope="col" class="px-4 py-3 font-medium"><%= column_label(column) %></th>
<% end %>
</tr>
</thead>
<tbody class="divide-y divide-[hsl(var(--senren-border))] bg-[hsl(var(--senren-background))] text-[hsl(var(--senren-foreground))]">
<% rows.each do |row| %>
<tr class="transition-colors hover:bg-[hsl(var(--senren-muted)/0.4)]">
<% columns.each do |column| %>
<td class="px-4 py-3"><%= cell_value(row, column) %></td>
<% end %>
</tr>
<% end %>
<% if rows.empty? && content? %>
<tr><td class="px-4 py-6" colspan="<%= columns.size.nonzero? || 1 %>"><%= content %></td></tr>
<% end %>
</tbody>
</table>
</div>
app/components/senren/table_component.rb
# frozen_string_literal: true
module Senren
class TableComponent < BaseComponent
VARIANTS = {
default: '',
compact: 'text-xs'
}.freeze
SIZES = { md: '' }.freeze
def initialize(columns: [], rows: [], caption: nil, variant: :default, class_name: nil, **html)
super(variant: variant, size: :md, class_name: class_name, **html)
@columns = Array(columns)
@rows = Array(rows)
@caption = caption
end
attr_reader :columns, :rows, :caption
def cell_value(row, column)
key = column_key(column)
row.is_a?(Hash) ? (row[key] || row[key.to_s]) : row[key.to_i]
end
def column_label(column)
column.is_a?(Hash) ? (column[:label] || column['label']) : column.to_s.titleize
end
private
def column_key(column)
column.is_a?(Hash) ? (column[:key] || column['key']) : column
end
end
end
AI agent rules #
Use for
- +tabular data display
Avoid
- -layout - use grid/flex
Accessibility #
- Use real th/scope; caption for table summary.