Class: Shadcn::Toaster::Component

Inherits:
ApplicationViewComponent show all
Defined in:
app/components/shadcn/toaster/component.rb

Overview

Ours, not a port — and the distinction matters more here than anywhere else in this gem.

sonner.tsx is forty lines and emits no data-slot at all: a theme, five icons and four custom properties handed to the sonner package, which supplies every element and every rule — 1,601 lines of TypeScript and 729 of CSS. There is no upstream markup here to be 1:1 with, so parity_spec has nothing to check and this component's shape is this port's own.

What is kept from upstream is what can be: sonner's measurements, read from its stylesheet — 356px wide, 14px between, 24px from the edge, four seconds of life — and the four colours sonner.tsx itself chooses, which are the popover's.

And the way in is Rails': a toast is a component, so the server can raise one. Three routes, in order of how much an app will use them —

flash            `Toaster::Component.new(flash:)` turns each into a toast
turbo_stream     `turbo_stream.append "shadcn-toasts", …` onto this list
javascript       `document.dispatchEvent(new CustomEvent("shadcn--toast", …))`

— where sonner has only the third. See features/toaster.md.

Constant Summary collapse

POSITIONS =
{
  "top-left" => "top-6 left-6 items-start",
  "top-center" => "top-6 left-1/2 -translate-x-1/2 items-center",
  "top-right" => "top-6 right-6 items-end",
  "bottom-left" => "bottom-6 left-6 items-start",
  "bottom-center" => "bottom-6 left-1/2 -translate-x-1/2 items-center",
  "bottom-right" => "bottom-6 right-6 items-end"
}.freeze
DEFAULT_DURATION =

sonner's own, so a caller who has read its docs is not surprised.

4000

Constants inherited from ApplicationViewComponent

ApplicationViewComponent::CONTENTS_STYLE, ApplicationViewComponent::VOID_TAGS

Instance Attribute Summary collapse

Attributes inherited from ApplicationViewComponent

#attributes

Instance Method Summary collapse

Methods inherited from ApplicationViewComponent

#css_classes, default_tag, #merged_style, #render_element, #shadcn_t, slot_name, #style_variants, #tag_name

Constructor Details

#initialize(position: "bottom-right", duration: DEFAULT_DURATION, list_id: "shadcn-toasts", flash: nil, **attributes) ⇒ Component

Returns a new instance of Component.



50
51
52
53
54
55
56
57
# File 'app/components/shadcn/toaster/component.rb', line 50

def initialize(position: "bottom-right", duration: DEFAULT_DURATION,
               list_id: "shadcn-toasts", flash: nil, **attributes)
  @position = POSITIONS.key?(position.to_s) ? position.to_s : "bottom-right"
  @duration = duration
  @list_id = list_id
  @flash = flash
  super(**attributes)
end

Instance Attribute Details

#durationObject (readonly)

Returns the value of attribute duration.



48
49
50
# File 'app/components/shadcn/toaster/component.rb', line 48

def duration
  @duration
end

#flashObject (readonly)

Returns the value of attribute flash.



48
49
50
# File 'app/components/shadcn/toaster/component.rb', line 48

def flash
  @flash
end

#list_idObject (readonly)

Returns the value of attribute list_id.



48
49
50
# File 'app/components/shadcn/toaster/component.rb', line 48

def list_id
  @list_id
end

#positionObject (readonly)

Returns the value of attribute position.



48
49
50
# File 'app/components/shadcn/toaster/component.rb', line 48

def position
  @position
end

Instance Method Details

#callObject



75
76
77
# File 'app/components/shadcn/toaster/component.rb', line 75

def call
  render_element(body: safe_join([ list, template ]))
end

#element_attributes(**defaults) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'app/components/shadcn/toaster/component.rb', line 59

def element_attributes(**defaults)
  super(**{
    class: "group/toaster pointer-events-none fixed z-[100] flex " \
           "#{POSITIONS.fetch(position)}",
    "aria-live" => "polite",
    # sonner's own (index.tsx:792): each toast is read on its own, not as
    # a re-reading of the whole stack every time one arrives.
    "aria-atomic" => "false",
    "aria-label" => shadcn_t("toaster.label"),
    "data-position" => position,
    "data-controller" => "shadcn--toaster",
    "data-shadcn--toaster-duration-value" => duration,
    "data-action" => "shadcn--toast@document->shadcn--toaster#raise"
  }.merge(defaults))
end