Message
A chat message layout that pairs an avatar with bubbles, headers, and footers. Built on top of Avatar and Bubble.
Usage
Conversation
ME
R
ME
Rdiv(class: "flex flex-col gap-6") do Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble do BubbleContent { "Deploying to prod real quick." } end end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) do BubbleContent { "It's 4:55 PM. On a Friday." } end end end Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble do BubbleContent { "It's a one-line change." } end MessageFooter { "Delivered" } end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do BubbleGroup do Bubble(variant: :muted) do BubbleContent { "It's always a one-line change 😭." } end Bubble(variant: :muted) do BubbleContent { "Alright, let me take a look." } BubbleReactions(role: "img", aria_label: "Reaction: thumbs up") do span { "👍" } end end end end end end
With header
Header and footer
OLMessage do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@oliver") AvatarFallback { "OL" } end end MessageContent do MessageHeader { "Oliver" } Bubble(variant: :muted) do BubbleContent { "Pushed the fix, can you review?" } end MessageFooter { "9:41 AM" } end end
Alignment
Sender and receiver
R
MEdiv(class: "flex flex-col gap-6") do Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "Aligned to the start." } } end end Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble { BubbleContent { "Aligned to the end." } } end end end
Group
Message group
R
RMessageGroup do Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "First message." } } end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "Second, tighter spacing." } } end end end
Installation
Using RubyUI CLI
Run the install command
rails g ruby_ui:component Message
Manual installation
1
Add RubyUI::Message to app/components/ruby_ui/message/message.rb
# frozen_string_literal: true module RubyUI class Message < Base def initialize(align: :start, **attrs) @align = align super(**attrs) end def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message", align: @align}, class: "group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse" } end end end
2
Add RubyUI::MessageAvatar to app/components/ruby_ui/message/message_avatar.rb
# frozen_string_literal: true module RubyUI class MessageAvatar < Base def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message-avatar"}, class: "flex w-fit min-w-8 shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted group-has-data-[slot=message-footer]/message:-translate-y-8" } end end end
3
Add RubyUI::MessageContent to app/components/ruby_ui/message/message_content.rb
# frozen_string_literal: true module RubyUI class MessageContent < Base def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message-content"}, class: "flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:[&>[data-slot]]:self-end" } end end end
4
Add RubyUI::MessageDocs to app/components/ruby_ui/message/message_docs.rb
# frozen_string_literal: true class Views::Docs::Message < Views::Base def view_template component = "Message" div(class: "max-w-2xl mx-auto w-full py-10 space-y-10") do render Docs::Header.new(title: "Message", description: "A chat message layout that pairs an avatar with bubbles, headers, and footers. Built on top of Avatar and Bubble.") Heading(level: 2) { "Usage" } render Docs::VisualCodeExample.new(title: "Conversation", context: self) do <<~RUBY div(class: "flex flex-col gap-6") do Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble do BubbleContent { "Deploying to prod real quick." } end end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) do BubbleContent { "It's 4:55 PM. On a Friday." } end end end Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble do BubbleContent { "It's a one-line change." } end MessageFooter { "Delivered" } end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do BubbleGroup do Bubble(variant: :muted) do BubbleContent { "It's always a one-line change 😭." } end Bubble(variant: :muted) do BubbleContent { "Alright, let me take a look." } BubbleReactions(role: "img", aria_label: "Reaction: thumbs up") do span { "👍" } end end end end end end RUBY end Heading(level: 2) { "With header" } render Docs::VisualCodeExample.new(title: "Header and footer", context: self) do <<~RUBY Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@oliver") AvatarFallback { "OL" } end end MessageContent do MessageHeader { "Oliver" } Bubble(variant: :muted) do BubbleContent { "Pushed the fix, can you review?" } end MessageFooter { "9:41 AM" } end end RUBY end Heading(level: 2) { "Alignment" } render Docs::VisualCodeExample.new(title: "Sender and receiver", context: self) do <<~RUBY div(class: "flex flex-col gap-6") do Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "Aligned to the start." } } end end Message(align: :end) do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/joeldrapper.png", alt: "@me") AvatarFallback { "ME" } end end MessageContent do Bubble { BubbleContent { "Aligned to the end." } } end end end RUBY end Heading(level: 2) { "Group" } render Docs::VisualCodeExample.new(title: "Message group", context: self) do <<~RUBY MessageGroup do Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "First message." } } end end Message do MessageAvatar do Avatar(size: :sm) do AvatarImage(src: "https://github.com/shadcn.png", alt: "@rabbit") AvatarFallback { "R" } end end MessageContent do Bubble(variant: :muted) { BubbleContent { "Second, tighter spacing." } } end end end RUBY end render Components::ComponentSetup::Tabs.new(component_name: component) # components render Docs::ComponentsTable.new(component_files(component)) end end end
5
Add RubyUI::MessageFooter to app/components/ruby_ui/message/message_footer.rb
# frozen_string_literal: true module RubyUI class MessageFooter < Base def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message-footer"}, class: "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-data-[align=end]/message:justify-end group-has-data-[variant=ghost]/message:px-0" } end end end
6
Add RubyUI::MessageGroup to app/components/ruby_ui/message/message_group.rb
# frozen_string_literal: true module RubyUI class MessageGroup < Base def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message-group"}, class: "flex min-w-0 flex-col gap-2" } end end end
7
Add RubyUI::MessageHeader to app/components/ruby_ui/message/message_header.rb
# frozen_string_literal: true module RubyUI class MessageHeader < Base def view_template(&) div(**attrs, &) end private def default_attrs { data: {slot: "message-header"}, class: "flex max-w-full min-w-0 items-center px-3 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0" } end end end
8
Install required components
Component Message relies on the following RubyUI components. Refer to their individual installation guides for setup instructions:
Components
| Component | Built using | Source |
|---|---|---|
Message | Phlex | |
MessageAvatar | Phlex | |
MessageContent | Phlex | |
MessageDocs | Phlex | |
MessageFooter | Phlex | |
MessageGroup | Phlex | |
MessageHeader | Phlex |