[Feature] Add Message component#446
Merged
Merged
Conversation
Port the shadcn Bubble component: a chat bubble surface with 7 variants (default, secondary, muted, tinted, outline, ghost, destructive), start/end alignment, grouping, and edge-anchored reactions. - Translates shadcn's cn-bubble-* CSS layer to real Tailwind v4 utilities and RubyUI theme tokens (no custom CSS shipped). - BubbleContent is polymorphic via as: (:div/:a/:button) for link/button bubbles — the idiomatic Phlex equivalent of shadcn's asChild. - No JS. Composes with Tooltip/Popover (docs examples included). Docs page, route, controller, menu entry and site_files updated.
9e0d56b to
75db4cf
Compare
Collapse the duplicated [&_button]/[&_a] pairs into [&:is(button,a)] selectors targeting the content element itself (the polymorphic as: :button/:a case), matching the variant hover selectors. Halves the class string with identical behavior.
75db4cf to
8173b90
Compare
Port the shadcn Message component: the higher-level chat layout that pairs an avatar with bubbles, headers, and footers. Built on top of Bubble (#445). - 6 parts: Message (align start/end), MessageGroup, MessageAvatar, MessageContent, MessageHeader, MessageFooter. - Reuses the existing Avatar and the new Bubble components — no new primitives. Bubble alignment inside a message is driven by Message via group-data-[align=end]/message; Bubble itself is unchanged. - Translates shadcn's cn-message-* CSS layer to Tailwind v4 utilities. - dependencies.yml: message depends on Avatar + Bubble. Closes #444. Docs page, route, controller, menu entry and site_files updated.
8173b90 to
c9dd5e7
Compare
cirdes
approved these changes
Jun 30, 2026
djalmaaraujo
added a commit
that referenced
this pull request
Jun 30, 2026
Port the shadcn Message Scroller: a chat transcript scroller that follows the live edge, anchors new turns near the top, and jumps to the latest message. Built on top of Message (#446) and Bubble (#445). shadcn delegates to a closed React primitive (@shadcn/react); this is a from-scratch Stimulus controller (ruby-ui--message-scroller) — our own code, no external lib: - autoScroll follow-edge: pins to the bottom while the reader is there, releases on wheel/touch/keyboard/scrollbar away, re-engages on jump. - scrollAnchor: settles an appended turn near the top keeping a peek of the previous item (previous_item_peek). - defaultPosition: open at end / start / last-anchor. - preserveOnPrepend: hold the visible row when history loads in above. - Public API for streaming/ActionCable: scrollToEnd/scrollToStart/ scrollToMessage; new rows are picked up via MutationObserver. - rAF-based smooth scrolling (native smooth is unreliable on a contained viewport), honors prefers-reduced-motion. - a11y: content role=log + aria-relevant, button sr-only label, button removed from tab order while inert. Parts: MessageScrollerProvider, MessageScroller, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem, MessageScrollerButton. dependencies.yml: message_scroller depends on Message + Bubble. MCP registry, docs page, route, controller, menu and site_files updated.
djalmaaraujo
added a commit
that referenced
this pull request
Jun 30, 2026
Port the shadcn Message Scroller: a chat transcript scroller that follows the live edge, anchors new turns near the top, and jumps to the latest message. Built on top of Message (#446) and Bubble (#445). shadcn delegates to a closed React primitive (@shadcn/react); this is a from-scratch Stimulus controller (ruby-ui--message-scroller) — our own code, no external lib: - autoScroll follow-edge: pins to the bottom while the reader is there, releases on wheel/touch/keyboard/scrollbar away, re-engages on jump. - scrollAnchor: settles an appended turn near the top keeping a peek of the previous item (previous_item_peek). - defaultPosition: open at end / start / last-anchor. - preserveOnPrepend: hold the visible row when history loads in above. - Public API for streaming/ActionCable: scrollToEnd/scrollToStart/ scrollToMessage; new rows are picked up via MutationObserver. - rAF-based smooth scrolling (native smooth is unreliable on a contained viewport), honors prefers-reduced-motion. - a11y: content role=log + aria-relevant, button sr-only label, button removed from tab order while inert. Parts: MessageScrollerProvider, MessageScroller, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem, MessageScrollerButton. dependencies.yml: message_scroller depends on Message + Bubble. MCP registry, docs page, route, controller, menu and site_files updated.
cirdes
pushed a commit
that referenced
this pull request
Jun 30, 2026
* [Feature] Add Empty component Port the shadcn Empty component: a centered empty-state surface for when there is no data or content. Parts: Empty, EmptyHeader, EmptyMedia (default/icon variants), EmptyTitle, EmptyDescription, EmptyContent. Translates shadcn's cn-empty-* CSS layer to Tailwind v4 utilities. No JS. Docs page, route, controller, menu, site_files and MCP registry updated. * [Feature] Add Message Scroller component Port the shadcn Message Scroller: a chat transcript scroller that follows the live edge, anchors new turns near the top, and jumps to the latest message. Built on top of Message (#446) and Bubble (#445). shadcn delegates to a closed React primitive (@shadcn/react); this is a from-scratch Stimulus controller (ruby-ui--message-scroller) — our own code, no external lib: - autoScroll follow-edge: pins to the bottom while the reader is there, releases on wheel/touch/keyboard/scrollbar away, re-engages on jump. - scrollAnchor: settles an appended turn near the top keeping a peek of the previous item (previous_item_peek). - defaultPosition: open at end / start / last-anchor. - preserveOnPrepend: hold the visible row when history loads in above. - Public API for streaming/ActionCable: scrollToEnd/scrollToStart/ scrollToMessage; new rows are picked up via MutationObserver. - rAF-based smooth scrolling (native smooth is unreliable on a contained viewport), honors prefers-reduced-motion. - a11y: content role=log + aria-relevant, button sr-only label, button removed from tab order while inert. Parts: MessageScrollerProvider, MessageScroller, MessageScrollerViewport, MessageScrollerContent, MessageScrollerItem, MessageScrollerButton. dependencies.yml: message_scroller depends on Message + Bubble. MCP registry, docs page, route, controller, menu and site_files updated. * [Bug Fix] Message Scroller: address review feedback - Gate anchored-turn scrolling behind autoScroll/following, so a new turn never yanks a reader who scrolled up to older content (P1). - Scroll button honors data-direction: a start-direction button now jumps to the start instead of the end (renamed action jumpToEnd → jump) (P2). - Guard last-anchor opening position with hasContentTarget; the Stimulus target getter throws rather than returning undefined (P2). - Include the flex row gap in prepend preservation so the visible row no longer drifts down by one gap per history insertion (P2). - Only treat direct content children as transcript rows; markup mutated inside a message (subtree) is handled as streaming, not history (P2). Rebuilt MCP registry. * [Documentation] Message Scroller: faithful chat-window demo with Empty state Add the shadcn-style chat window as the hero example: a Card with an Empty state until the first message, then a scrolling transcript that follows the live edge, plus an input footer. A docs-only Stimulus demo harness (message-scroller-chat) clones server-rendered user/assistant templates on send so the scroller's autoscroll/anchoring is demonstrated live — standing in for a real ActionCable/streaming source. Uses the new Empty component. * [Bug Fix] Message Scroller: direction-aware scroll button visibility updateButton now derives each button's active state from its own data-direction — an end button activates when away from the bottom, a start button when away from the top — and iterates all button targets. Previously a start-direction button used end logic, so it was inert at the live edge and showed at the wrong end. (cubic P2)
djalmaaraujo
added a commit
that referenced
this pull request
Jul 1, 2026
Bump RubyUI to 1.5.0 (minor: new components since v1.4.0). - gem/lib/ruby_ui.rb → 1.5.0; regenerate gem/ and docs/ Gemfile.lock - docs home hero badge → headline features (Bubble, Message, Empty) - rebuild mcp/data/registry.json Highlights since v1.4.0: - New components: Bubble (#445), Message (#446), Message Scroller (#447), Empty (#448) - Port hover_card & context_menu to Floating UI, drop Popper.js (#438) - Bug fixes: Dialog closed-state + docs controller (#458), DropdownMenu z-index (#440)
djalmaaraujo
added a commit
that referenced
this pull request
Jul 1, 2026
Bump RubyUI to 1.5.0 (minor: new components since v1.4.0). - gem/lib/ruby_ui.rb → 1.5.0; regenerate gem/ and docs/ Gemfile.lock - docs home hero badge → headline features (Bubble, Message, Empty) - rebuild mcp/data/registry.json Highlights since v1.4.0: - New components: Bubble (#445), Message (#446), Message Scroller (#447), Empty (#448) - Port hover_card & context_menu to Floating UI, drop Popper.js (#438) - Bug fixes: Dialog closed-state + docs controller (#458), DropdownMenu z-index (#440)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Ports the shadcn Message component to RubyUI — the higher-level chat layout that pairs an avatar with bubbles, headers, and footers.
Reference:
apps/v4/registry/bases/radix/ui/message.tsxCloses #444.
What's included
Message— row container,align:(start/end); flips avatar/content viaflex-row-reverseMessageGroup— stacks messagesMessageAvatar— wraps the existingAvatar; anchors to the row bottom and lifts when a footer is presentMessageContent— column holding bubbles; drives bubble alignment viagroup-data-[align=end]/messageMessageHeader/MessageFooter— muted meta lines (name, timestamp, "Delivered")Reuse — no new primitives
MessageAvatarMessageContentBubble alignment inside a message is handled entirely by Message — Bubble is unchanged.
dependencies.yml:messagedepends onAvatar+Bubble.Notes
cn-message-*CSS layer; this port translates every rule to Tailwind v4 utilities. No custom CSS, no JS.Marker(the "is typing…" indicator) is a separate shadcn component, out of scope here; the demo uses plain footer text instead.Testing
cd gem && bundle exec rake→ tests + StandardRB green./docs/message: conversation, header/footer, alignment, and group all verified visually against the shadcn demo.Screenshots
Add before/after screenshots of
/docs/message.Summary by cubic
Add a chat
Messagelayout that pairs an avatar with bubbles, headers, and footers to build aligned, grouped conversations. Ships with Tailwind v4 utilities and a docs page; no custom CSS or JS.New Features
Messagewithalign: :start|:end; controls bubble alignment and flips rows.MessageGroup,MessageAvatar,MessageContent,MessageHeader,MessageFooter./docs/messagewith examples; routes, controller, nav, sitemap, and LLM docs maps updated.Messagefiles, metadata, and examples.Dependencies
dependencies.yml:messagedepends onAvatarandBubble;Bubbleis unchanged.Written for commit c9dd5e7. Summary will update on new commits.