Separator
A visual divider with horizontal or vertical orientation.
Installation
bin/rails g wabi:add separatorExample
Above the lineBelow the line
div(class: "flex flex-col gap-2 text-sm") do
span { "Above the line" }
render Components::UI::Separator.new
span { "Below the line" }
end
LeftRight
div(class: "flex items-center gap-2 text-sm") do
span { "Left" }
render Components::UI::Separator.new(orientation: :vertical, class: "h-4")
span { "Right" }
end
Source
app/components/ui/separator.rb
# frozen_string_literal: true
module Components
module UI
class Separator < Wabi::Base
variants do
base "shrink-0 bg-border"
variant :orientation, {
horizontal: "h-[1px] w-full",
vertical: "h-full w-[1px]"
}, default: :horizontal
end
def initialize(orientation: nil, decorative: true, **attrs)
@orientation = orientation
@decorative = decorative
@attrs = attrs
end
def view_template
user_class = @attrs.delete(:class)
aria_orientation = @orientation == :vertical ? "vertical" : "horizontal"
if @decorative
div(
role: "none",
**@attrs,
class: merge_class(tokens(orientation: @orientation), user_class)
)
else
# Use the native <hr> element which carries role=separator implicitly,
# avoiding the need for an explicit role attribute and satisfying WCAG semantics.
# border-0 neutralizes Tailwind preflight's default hr border-top so the
# bg-border line renders identically to the decorative <div> variant.
hr(
"aria-orientation": aria_orientation,
**@attrs,
class: merge_class(tokens(orientation: @orientation), "border-0", user_class)
)
end
end
end
end
end
Accessibility
- role="separator" with aria-orientation reflecting horizontal or vertical — only when decorative: false is passed.
- decorative separators (purely visual) default to decorative: true, which renders role="none" and no aria-orientation.
- semantic separators (between distinct content groups) pass decorative: false to activate role="separator" for screen-reader navigation.