Class: BetterUi::CardComponent

Inherits:
ApplicationComponent show all
Defined in:
app/components/better_ui/card_component.rb

Overview

A flexible card component for displaying content in a styled container.

This component provides a versatile box container with support for multiple color variants, visual styles, sizes, and optional header/footer sections. Perfect for displaying grouped content, information panels, dashboards, and feature highlights.

Examples:

Basic card

<%= render BetterUi::CardComponent.new do %>
  Card content here
<% end %>

Card with header and footer

<%= render BetterUi::CardComponent.new(variant: :primary, style: :outline) do |card| %>
  <% card.with_header { "Card Title" } %>
  <% card.with_body { "Main content goes here" } %>
  <% card.with_footer { "Footer actions" } %>
<% end %>

Transparent card

<%= render BetterUi::CardComponent.new(style: :ghost) do %>
  Transparent card content
<% end %>

Large success card without shadow

<%= render BetterUi::CardComponent.new(variant: :success, size: :lg, shadow: false) do |card| %>
  <% card.with_header { "Success!" } %>
  <% card.with_body { "Operation completed successfully" } %>
<% end %>

Different styles

# Solid (default): Filled colored background
<%= render BetterUi::CardComponent.new(style: :solid) { "Solid card" } %>

# Outline: White background with colored border
<%= render BetterUi::CardComponent.new(style: :outline) { "Outline card" } %>

# Ghost: Transparent background
<%= render BetterUi::CardComponent.new(style: :ghost) { "Ghost card" } %>

# Soft: Light colored background
<%= render BetterUi::CardComponent.new(style: :soft) { "Soft card" } %>

# Bordered: White background with variant-colored border (defaults to :light)
<%= render BetterUi::CardComponent.new(style: :bordered) { "Bordered card" } %>

Constant Summary collapse

SIZES =

Size configurations for padding, text, and border radius

{
  xs: { padding: "p-3", text: "text-xs", radius: "rounded" },
  sm: { padding: "p-4", text: "text-sm", radius: "rounded-md" },
  md: { padding: "p-6", text: "text-base", radius: "rounded-lg" },
  lg: { padding: "p-8", text: "text-lg", radius: "rounded-lg" },
  xl: { padding: "p-10", text: "text-xl", radius: "rounded-xl" }
}.freeze
STYLES =

Available visual styles

%i[solid outline ghost soft bordered].freeze

Constants inherited from ApplicationComponent

ApplicationComponent::SHADOWS, ApplicationComponent::VARIANTS, ApplicationComponent::VARIANT_BODY_DIVIDE, ApplicationComponent::VARIANT_DIVIDE, ApplicationComponent::VARIANT_HEADER_BG, ApplicationComponent::VARIANT_HEADER_TEXT, ApplicationComponent::VARIANT_HIGHLIGHTED, ApplicationComponent::VARIANT_HOVERABLE, ApplicationComponent::VARIANT_RING, ApplicationComponent::VARIANT_SORT_ICON, ApplicationComponent::VARIANT_STRIPED

Instance Method Summary collapse

Constructor Details

#initialize(variant: nil, style: :solid, size: :md, shadow: :sm, header_padding: true, body_padding: true, footer_padding: true, container_classes: nil, header_classes: nil, body_classes: nil, footer_classes: nil, **options) ⇒ CardComponent

Initializes a new card component.

Examples:

With all options

<%= render BetterUi::CardComponent.new(
  variant: :primary,
  style: :outline,
  size: :lg,
  shadow: true,
  container_classes: "mb-4",
  id: "my-card",
  data: { controller: "custom" }
) do |card| %>
  <% card.with_header { "Title" } %>
  <% card.with_body { "Content" } %>
<% end %>

Full-width image with no body padding

<%= render BetterUi::CardComponent.new(body_padding: false) do |card| %>
  <% card.with_header { "Gallery" } %>
  <% card.with_body do %>
    <%= image_tag "photo.jpg", class: "w-full" %>
  <% end %>
<% end %>

Table container with no padding

<%= render BetterUi::CardComponent.new(
  body_padding: false,
  style: :bordered
) do |card| %>
  <% card.with_body do %>
    <table class="w-full">...</table>
  <% end %>
<% end %>

Parameters:

  • variant (Symbol, nil) (defaults to: nil) —

    the color variant (:primary, :secondary, :accent, :success, :danger, :warning, :info, :light, :dark). Defaults to :primary for most styles, :light for :bordered style.

  • style (Symbol) (defaults to: :solid) —

    the visual style (:solid, :outline, :ghost, :soft, :bordered), defaults to :solid

  • size (Symbol) (defaults to: :md) —

    the size variant (:xs, :sm, :md, :lg, :xl), defaults to :md

  • shadow (Boolean) (defaults to: :sm) —

    whether to apply shadow, defaults to true

  • header_padding (Boolean) (defaults to: true) —

    whether to apply padding to header section, defaults to true

  • body_padding (Boolean) (defaults to: true) —

    whether to apply padding to body section, defaults to true

  • footer_padding (Boolean) (defaults to: true) —

    whether to apply padding to footer section, defaults to true

  • container_classes (String, nil) (defaults to: nil) —

    additional CSS classes for the outer wrapper

  • header_classes (String, nil) (defaults to: nil) —

    additional CSS classes for the header section

  • body_classes (String, nil) (defaults to: nil) —

    additional CSS classes for the body section

  • footer_classes (String, nil) (defaults to: nil) —

    additional CSS classes for the footer section

  • options (Hash) —

    additional HTML attributes passed to the card element

Raises:

  • (ArgumentError) —

    if variant is not one of the allowed values

  • (ArgumentError) —

    if style is not one of the allowed values

  • (ArgumentError) —

    if size is not one of the allowed values



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'app/components/better_ui/card_component.rb', line 130

def initialize(
  variant: nil,
  style: :solid,
  size: :md,
  shadow: :sm,
  header_padding: true,
  body_padding: true,
  footer_padding: true,
  container_classes: nil,
  header_classes: nil,
  body_classes: nil,
  footer_classes: nil,
  **options
)
  @style = validate_style(style)
  resolved_variant = variant || default_variant_for_style
  @variant = validate_variant(resolved_variant)
  @size = validate_size(size)
  @shadow = normalize_shadow(shadow)
  @header_padding = header_padding
  @body_padding = body_padding
  @footer_padding = footer_padding
  @container_classes = container_classes
  @header_classes = header_classes
  @body_classes = body_classes
  @footer_classes = footer_classes
  @options = options
end

Instance Method Details

#with_body ⇒ Object

Slot for rendering the main body content of the card. If not provided, the card will render its default content in the body.

Yield Returns:

  • (String) —

    the HTML content for the body



71
# File 'app/components/better_ui/card_component.rb', line 71

renders_one :body

Slot for rendering optional footer content at the bottom of the card. The footer is separated from the body with a divider.

Yield Returns:

  • (String) —

    the HTML content for the footer



77
# File 'app/components/better_ui/card_component.rb', line 77

renders_one :footer

#with_header ⇒ Object

Slot for rendering optional header content at the top of the card. The header is separated from the body with a divider.

Yield Returns:

  • (String) —

    the HTML content for the header



65
# File 'app/components/better_ui/card_component.rb', line 65

renders_one :header