Badge
A compact label for status, counts, and metadata.
Installation
bin/rails g wabi:add badgeExample
Primary
Secondary
Destructive
Outline
div(class: "flex items-center gap-2") do
render Components::UI::Badge.new { "Primary" }
render Components::UI::Badge.new(appearance: :secondary) { "Secondary" }
render Components::UI::Badge.new(appearance: :destructive) { "Destructive" }
render Components::UI::Badge.new(appearance: :outline) { "Outline" }
end
Source
app/components/ui/badge.rb
# frozen_string_literal: true
module Components
module UI
class Badge < Wabi::Base
variants do
base "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs " \
"font-semibold transition-colors motion-reduce:transition-none focus-visible:outline-none focus-visible:ring-2 " \
"focus-visible:ring-ring focus-visible:ring-offset-2"
variant :appearance, {
primary: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground"
}, default: :primary
end
def initialize(appearance: nil, **attrs)
@appearance = appearance
@attrs = attrs
end
def view_template(&)
user_class = @attrs.delete(:class)
div(**@attrs, class: merge_class(tokens(appearance: @appearance), user_class), &)
end
end
end
end
Accessibility
- badges are visual decorations by default — screen readers announce their text content as inline text.
- for status indicators (e.g. "3 unread"), wrap in <span role="status"> or add screen-reader-only context.
- color alone is not sufficient signal — pair the visual badge with text or icon meaning.