Componentes prontos, API consistente
A ElementComponent traz 17 componentes Bootstrap 5 embutidos, todos sob ElementComponent::Components. Eles seguem a mesma API do Element que vimos nos posts anteriores da série: DSL de blocos, add_content encadeável e atributos HTML customizados via **attributes. Nesta primeira leva, vamos ver Alert, Badge, Button, ButtonGroup e Card.
Alert
alert = ElementComponent::Components::Alert.new(variant: :success) do |e|
e.add_content("Operation completed!")
end
# => <div class="alert alert-success" role="alert">Operation completed!</div>
Variantes: :primary, :secondary, :success, :danger, :warning, :info, :light, :dark.
Alerts dispensáveis (com botão de fechar), títulos e links usam sub-componentes dedicados:
alert = ElementComponent::Components::Alert.new(variant: :warning, dismissible: true) do |e|
e.add_content(ElementComponent::Components::AlertHeading.new { |h| h.add_content("Warning") })
e.add_content("Please review. ")
e.add_content(ElementComponent::Components::AlertLink.new(href: "/details") { |l| l.add_content("Details") })
end
| Sub-componente | Tag | Classe CSS |
|---|---|---|
AlertHeading |
<h4> |
.alert-heading |
AlertLink |
<a> |
.alert-link |
AlertCloseButton |
<button> (autofechado) |
.btn-close |
Button
btn = ElementComponent::Components::Button.new(variant: :primary) { |b| b.add_content("Click") }
# => <button class="btn btn-primary" type="button">Click</button>
btn = ElementComponent::Components::Button.new(variant: :danger, outline: true) { |b| b.add_content("Delete") }
# => <button class="btn btn-outline-danger" type="button">Delete</button>
btn = ElementComponent::Components::Button.new(variant: :primary, href: "/home") { |b| b.add_content("Home") }
# => <a class="btn btn-primary" href="/home">Home</a>
Um detalhe elegante: quando você passa href, o componente renderiza um <a> em vez de <button> automaticamente — o mesmo objeto Ruby, tag diferente conforme o contexto de uso.
Opções: variant (primary/secondary/success/danger/warning/info/light/dark/link), outline, size (sm/lg), href.
Badge
badge = ElementComponent::Components::Badge.new(variant: :primary) { |b| b.add_content("New") }
# => <span class="badge bg-primary">New</span>
pill = ElementComponent::Components::Badge.new(variant: :danger, pill: true) { |b| b.add_content("99+") }
# => <span class="badge bg-danger rounded-pill">99+</span>
Card
O Card é o primeiro componente composto da lista — combina vários sub-componentes para montar a estrutura clássica de card do Bootstrap:
card = ElementComponent::Components::Card.new do |c|
c.add_content(ElementComponent::Components::CardImage.new(src: "photo.jpg", top: true))
c.add_content(ElementComponent::Components::CardBody.new do |body|
body.add_content(ElementComponent::Components::CardTitle.new { |t| t.add_content("Title") })
body.add_content(ElementComponent::Components::CardText.new { |t| t.add_content("Some text.") })
end)
c.add_content(ElementComponent::Components::CardFooter.new { |f| f.add_content("Footer") })
end
| Sub-componente | Tag | Classe CSS |
|---|---|---|
CardHeader |
<div> |
.card-header |
CardBody |
<div> |
.card-body |
CardFooter |
<div> |
.card-footer |
CardTitle |
<h5> |
.card-title |
CardText |
<p> |
.card-text |
CardImage |
<img> (autofechado) |
.card-img[-top|-bottom] |
ButtonGroup
group = ElementComponent::Components::ButtonGroup.new do |g|
g.add_content(ElementComponent::Components::Button.new(variant: :primary) { |b| b.add_content("Left") })
g.add_content(ElementComponent::Components::Button.new(variant: :primary) { |b| b.add_content("Middle") })
g.add_content(ElementComponent::Components::Button.new(variant: :primary) { |b| b.add_content("Right") })
end
# => <div class="btn-group" role="group">...</div>
Opções: size (sm/lg), vertical.
O padrão que se repete
Um ponto que vale reforçar: componentes compostos (Card, e mais adiante Modal, Navbar, Dropdown) não têm mágica especial — são apenas Elements Bootstrap-aware compostos via add_content, exatamente como qualquer HTML puro montado com a API core. Isso significa que dá pra misturar componentes prontos com Element.new bruto sempre que precisar de algo fora do catálogo.
Próximo post
Na parte 2 da série, seguimos para os componentes de navegação: Nav, Navbar, Breadcrumb e Pagination, além de Progress e Spinner.