Class: PhlexKit::SidebarMenuButton

Inherits:
BaseComponent show all
Defined in:
app/components/phlex_kit/sidebar/sidebar_menu_button.rb

Overview

The interactive element of a SidebarMenuItem. as: is :button (default) or :a (pass href:); active: true marks the current page (drives the highlight via data-active — a named kwarg, not an attr, since mix would merge a repeated attribute rather than override; an active link also gets aria-current="page"). tooltip: labels the button while an icon-collapsed rail hides its text (pure-CSS hover bubble) and doubles as the aria-label so the button keeps an accessible name once the text is hidden. Bare block text is wrapped in a automatically so the collapsed rail's > :not(svg) rule can hide it; blocks that emit their own markup (icon + Label) pass through untouched — keep the label in a real element there. Attrs pass through via mix. See sidebar.rb.

Constant Summary collapse

AS_TAGS =

as: is dispatched dynamically (send) — whitelist so it can't reach arbitrary (including private) methods; to_sym so a String "a" still earns aria-current when active.

%i[button a].freeze

Instance Method Summary collapse

Methods inherited from BaseComponent

#on

Constructor Details

#initialize(as: :button, active: false, tooltip: nil, **attrs) ⇒ SidebarMenuButton

Returns a new instance of SidebarMenuButton.



19
20
21
22
23
24
25
26
27
# File 'app/components/phlex_kit/sidebar/sidebar_menu_button.rb', line 19

def initialize(as: :button, active: false, tooltip: nil, **attrs)
  @as = as.to_sym
  unless AS_TAGS.include?(@as)
    raise ArgumentError, "unknown SidebarMenuButton as: #{@as.inspect} (use one of #{AS_TAGS.join(", ")})"
  end
  @active = active
  @tooltip = tooltip
  @attrs = attrs
end

Instance Method Details

#view_template(&block) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/components/phlex_kit/sidebar/sidebar_menu_button.rb', line 29

def view_template(&block)
  base = { class: "pk-sidebar-menu-button", "data-active": (@active ? "true" : "false") }
  base["aria-current"] = "page" if @active && @as == :a
  if @tooltip
    base["data-tooltip"] = @tooltip
    base["aria-label"] = @tooltip
  end
  send(@as, **mix(base, @attrs)) do
    # capture renders the block once; pure text (no markup) gets the span
    # wrapper the icon-collapsed CSS needs. The captured output is
    # already-escaped HTML, so re-emit it via raw(safe(...)).
    content = capture(&block)
    if content.include?("<") || content.empty?
      raw safe(content)
    else
      span { raw safe(content) }
    end
  end
end