RRUI-008 · Link helpers · Icon slot
rui_tel / rui_mailto / rui_sms drop the icon slot blockDocs and Lookbook show with_icon on communication helpers. Standalone rui_link forwards the block and renders the icon. The same block on rui_tel (and mailto/sms) never reaches the Link component — Ruby discards it because the helper neither takes nor forwards &block.
rui_link and support icon slots,” with a rui_tel(…) do |link| link.with_icon(:phone_call) end example. rui_link already does rapidui_component …, &block. The three communication wrappers do not.
| Surface |
ViewHelper#rui_tel, #rui_mailto, #rui_sms
|
|---|---|
| Works today |
rui_link(…) — forwards █ color: / variant: / size: on tel/mailto/sms kwargs (those are **options) |
| Broken today | Icon (and any other) slot set in the helper block — never applied |
| Impact | Phone / email / SMS links cannot show Lucide icons via the documented API |
color: :muted does apply on rui_tel. :muted is a valid ColorBuilderHelper key (defaults to Tailwind gray). With variant: :ghost the link gets the ghost palette, e.g. text-gray-700 hover:bg-gray-100 (and dark counterparts). If muted looks “not muted,” that is the gray-700 / 300 shade table — same steps rui_text(color: :muted) uses — not a dropped kwarg.
<%= rui_tel(
vendor_phone,
vendor_phone,
size: :sm,
variant: :ghost,
color: :muted,
aria: { label: "Call vendor" }
) do |link| %>
<% link.with_icon(:phone) %>
<% end %>
rui_link — leading phone icon, inheriting currentColor from the muted/ghost link.Contrast — this works:
<%= rui_link(vendor_phone, "tel:#{vendor_phone}", size: :sm, variant: :ghost, color: :muted) do |link| %>
<% link.with_icon(:phone) %>
<% end %>
def rui_link(*args, **kwargs, &block)
if block_given? && args.length == 1 && args[0].present?
args = [nil, args[0]]
end
rapidui_component Link::Component, *args, **kwargs, &block
end
def rui_tel(text, number, country_code: nil, **options)
phone = number.to_s
# …country_code normalize…
rapidui_component Link::Component, text, "tel:#{phone}", **options
# ← no &block
end
Same gap on rui_mailto and rui_sms. Ruby silently discards the caller’s block. rapidui_component already accepts &block and passes it to render.
def rui_tel(text, number, country_code: nil, **options, &block)
phone = number.to_s
if country_code.present? && !phone.start_with?("+", "00")
code = country_code.to_s.gsub(/^\+/, "")
phone = "+#{code}#{phone}"
end
rapidui_component Link::Component, text, "tel:#{phone}", **options, &block
end
Same &block forward for rui_mailto and rui_sms.
rui_tel("Call", "+15551212") { |l| l.with_icon(:phone) } asserts SVG (or icon markup) plus href="tel:+15551212".rui_tel(…) { |link| link.with_icon(:phone) } renders the icon.rui_link for slots; kwargs (color:, variant:, size:) stay unchanged.rui_mailto / rui_sms have the same forward + tests.