Card
Stablegrouping related content
Pro plan
Everything in Hobby, plus advanced analytics.
$24
/ month
- · Unlimited projects
- · Advanced analytics
- · Priority support
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/.../card_example.html.erb
<div class="w-full max-w-sm">
<%= render Senren::CardComponent.new do |c| %>
<% c.with_header do %>
<%= render(Senren::TypographyComponent.new(variant: :h4)) { "Pro plan" } %>
<%= render(Senren::TypographyComponent.new(variant: :muted)) { "Everything in Hobby, plus advanced analytics." } %>
<% end %>
<% c.with_body do %>
<div class="flex items-baseline gap-1">
<span class="font-display text-3xl font-semibold tracking-tight">$24</span>
<span class="text-sm text-[hsl(var(--senren-muted-foreground))]">/ month</span>
</div>
<ul class="mt-3 space-y-1.5 text-sm text-[hsl(var(--senren-muted-foreground))]">
<li>· Unlimited projects</li>
<li>· Advanced analytics</li>
<li>· Priority support</li>
</ul>
<% end %>
<% c.with_footer do %>
<%= render(Senren::ButtonComponent.new(variant: :primary, class_name: "w-full")) { "Upgrade" } %>
<% end %>
<% end %>
</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 card
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 card --no-client
At a glance #
Category
Layout
Class name
Senren::CardComponent
Stimulus
—
Variants
default, muted, outline
Depends on
—
Pairs with
button, badge, separator
Source #
app/components/senren/card_component.html.erb
<%= tag.div(**root_attrs("rounded-(--senren-radius) border shadow-sm")) do %>
<% if header? %>
<div class="flex flex-col space-y-1.5 p-6 border-b border-[hsl(var(--senren-border))]"><%= header %></div>
<% end %>
<% if body? %>
<div class="p-6"><%= body %></div>
<% else %>
<div class="p-6"><%= content %></div>
<% end %>
<% if footer? %>
<div class="flex items-center p-6 pt-0 border-t border-[hsl(var(--senren-border))]"><%= footer %></div>
<% end %>
<% end %>
app/components/senren/card_component.rb
# frozen_string_literal: true
module Senren
class CardComponent < BaseComponent
renders_one :header
renders_one :body
renders_one :footer
VARIANTS = {
default: 'bg-[hsl(var(--senren-card))] text-[hsl(var(--senren-card-foreground))] border-[hsl(var(--senren-border))]',
muted: 'bg-[hsl(var(--senren-muted))] text-[hsl(var(--senren-muted-foreground))] border-transparent',
outline: 'bg-transparent text-[hsl(var(--senren-foreground))] border-[hsl(var(--senren-border))]'
}.freeze
SIZES = { md: '' }.freeze
end
end
AI agent rules #
Use for
- +grouping related content
- +dashboard widgets
- +list items
Avoid
- -nesting cards inside cards
Accessibility #
- Use heading inside header slot; landmark roles only when meaningful.