Navegação, listas e indicadores
Seguindo a série sobre a ElementComponent, esta parte cobre os componentes ligados a navegação e apresentação de dados: Nav, Navbar, Breadcrumb, ListGroup, Pagination, Progress, Spinner e Table.
Nav
nav = ElementComponent::Components::Nav.new(type: :tabs) do |n|
n.add_content(ElementComponent::Components::NavItem.new do |item|
item.add_content(ElementComponent::Components::NavLink.new(href: "/", active: true) { |l| l.add_content("Home") })
end)
n.add_content(ElementComponent::Components::NavItem.new do |item|
item.add_content(ElementComponent::Components::NavLink.new(href: "/profile") { |l| l.add_content("Profile") })
end)
end
# => <ul class="nav nav-tabs">...</ul>
Opções: type (tabs/pills/underline), fill, justified, vertical.
Navbar
O Navbar é o componente de navegação mais completo, combinando marca, toggler responsivo e um menu colapsável:
navbar = ElementComponent::Components::Navbar.new(theme: :dark, background: :dark) do |n|
n.add_content(ElementComponent::Components::NavbarBrand.new(href: "/") { |b| b.add_content("Brand") })
n.add_content(ElementComponent::Components::NavbarToggler.new(target: "nav"))
n.add_content(ElementComponent::Components::NavbarCollapse.new(id: "nav") do |collapse|
collapse.add_content(ElementComponent::Components::NavbarNav.new do |nav|
nav.add_content(ElementComponent::Components::NavItem.new do |item|
item.add_content(ElementComponent::Components::NavLink.new(href: "/", active: true) { |l| l.add_content("Home") })
end)
nav.add_content(ElementComponent::Components::NavItem.new do |item|
item.add_content(ElementComponent::Components::NavLink.new(href: "/about") { |l| l.add_content("About") })
end)
end)
end)
end
Opções: expand (sm/md/lg/xl/xxl), theme (light/dark), background, fixed (top/bottom), sticky (top/bottom), container.
| Sub-componente | Tag | Classe CSS |
|---|---|---|
NavbarBrand |
<a> |
.navbar-brand |
NavbarToggler |
<button> (autofechado) |
.navbar-toggler |
NavbarCollapse |
<div> |
.collapse .navbar-collapse |
NavbarNav |
<ul> |
.navbar-nav |
Repare que Navbar reutiliza NavItem e NavLink do componente Nav — a gem evita duplicar conceitos que já existem, compondo componentes maiores a partir dos menores.
Breadcrumb
crumb = ElementComponent::Components::Breadcrumb.new do |b|
b.add_content(ElementComponent::Components::BreadcrumbItem.new(href: "/") { |i| i.add_content("Home") })
b.add_content(ElementComponent::Components::BreadcrumbItem.new(href: "/section") { |i| i.add_content("Section") })
b.add_content(ElementComponent::Components::BreadcrumbItem.new(active: true) { |i| i.add_content("Current") })
end
# => <nav aria-label="breadcrumb"><ol class="breadcrumb">...</ol></nav>
ListGroup
list = ElementComponent::Components::ListGroup.new(flush: true) do |l|
l.add_content(ElementComponent::Components::ListGroupItem.new { |i| i.add_content("Item 1") })
l.add_content(ElementComponent::Components::ListGroupItem.new(active: true) { |i| i.add_content("Item 2") })
l.add_content(ElementComponent::Components::ListGroupItem.new(href: "/link") { |i| i.add_content("Link") })
end
# => <ul class="list-group list-group-flush">...</ul>
Opções: flush, numbered; ListGroupItem aceita variant, active, disabled, href.
Pagination
nav = ElementComponent::Components::Pagination.new(size: :lg) do |p|
p.add_content(ElementComponent::Components::PageItem.new(active: true) { |i| i.add_content("1") })
p.add_content(ElementComponent::Components::PageItem.new { |i| i.add_content("2") })
end
# => <nav aria-label="Pagination"><ul class="pagination pagination-lg">...</ul></nav>
Progress
progress = ElementComponent::Components::Progress.new do |p|
p.add_content(ElementComponent::Components::ProgressBar.new(value: 75, variant: :success, striped: true) do |bar|
bar.add_content("75%")
end)
end
# => <div class="progress" role="progressbar"><div class="progress-bar bg-success progress-bar-striped" ...>75%</div></div>
Spinner
border = ElementComponent::Components::Spinner.new(type: :border, variant: :primary)
# => <div class="spinner-border text-primary" role="status"></div>
grow = ElementComponent::Components::Spinner.new(type: :grow, variant: :success)
# => <div class="spinner-grow text-success" role="status"></div>
Table
table = ElementComponent::Components::Table.new(striped: true, bordered: true, hover: true) do |t|
t.add_content("<thead><tr><th>Name</th><th>Age</th></tr></thead>")
t.add_content("<tbody><tr><td>John</td><td>30</td></tr></tbody>")
end
# => <table class="table table-striped table-bordered table-hover">...</table>
Opções: striped, bordered, hover, small, variant.
Vale notar que, no exemplo de Table, o conteúdo passado é uma string HTML crua — e por conta do escaping automático coberto na parte 2 da série, strings com <thead>/<tbody> só funcionam como esperado porque o próprio HTML é o conteúdo pretendido. Em casos assim, ou você monta <thead>/<tbody> com Element.new (a forma mais idiomática), ou usa ElementComponent.html_safe() para strings HTML já prontas.
Próximo post
Na parte final da série, fechamos com os componentes interativos mais complexos — Modal, Carousel, Dropdown e CloseButton — e um resumo do fluxo de desenvolvimento e contribuição do projeto.