erb

ruby
class PostsController < ApplicationController
  def new
    @post = Post.new
  end

  def create

Inline markdown preview using Turbo Frames

rails hotwire turbo
by codesnips 4 tabs
erb
<%= form_with url: autosave_draft_path,
              method: :post,
              local: false,
              data: {
                controller: "autosave",
                autosave_target: "form",

Autosave drafts with Stimulus + Turbo (lightweight)

rails hotwire stimulus
by codesnips 3 tabs
ruby
class Recipe < ApplicationRecord
  has_many :ingredients, inverse_of: :recipe, dependent: :destroy

  accepts_nested_attributes_for :ingredients,
    allow_destroy: true,
    reject_if: :all_blank

Add/remove nested fields with Stimulus (no cocoon)

rails hotwire stimulus
by codesnips 4 tabs
erb
<!DOCTYPE html>
<html>
  <head>
    <title>Contacts</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

Turbo Frames modal: load, submit, then close via stream

rails turbo hotwire
by codesnips 4 tabs
erb
<div id="toasts" class="fixed right-4 top-4 z-50 space-y-2"></div>

Toast notifications delivered with Turbo Streams

rails hotwire turbo
by Henry Kim 2 tabs
erb
<%# Append is also broadcast from the model; this response scrolls the author's view %>
<%= turbo_stream.append "messages" do %>
  <%= render partial: "messages/message", locals: { message: @message } %>
<% end %>

<turbo-stream action="scroll_to" target="<%= dom_id(@message) %>" behavior="smooth" block="end">

Scroll into view after append using a custom Turbo Stream action

rails hotwire turbo
by codesnips 4 tabs
ruby
class SupportMailbox < ApplicationMailbox
  def process
    ticket = Ticket.find_or_create_by!(message_id: mail.message_id) do |t|
      t.subject = mail.subject
      t.from_email = mail.from&.first
      t.body = mail.decoded

Action Mailbox: broadcast incoming emails into a feed

rails hotwire turbo
by Henry Kim 3 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["container", "dialog"]

  connect() {

Accessible modal dialogs with Stimulus and ARIA

stimulus accessibility ux
by Jordan Lee 2 tabs
erb
<%= turbo_frame_tag 'quick_view' do %>
  <div class="text-gray-500">Select a post…</div>
<% end %>

<% @posts.each do |post| %>
  <%= link_to post.title, post_path(post), data: { turbo_frame: 'quick_view' }, class: 'block py-1 hover:underline' %>

Frame-powered inline “quick view” that falls back to full page

rails hotwire turbo
by Henry Kim 2 tabs
erb
<div class="post">
  <h1><%= @post.title %></h1>

  <%= turbo_frame_tag "post_#{@post.id}" do %>
    <div class="post-content">
      <%= simple_format @post.body %>

Turbo Frame for inline editing without page reloads

hotwire turbo turbo-frames
by Jordan Lee 2 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["count", "button"]
  static values = {
    url: String,

Optimistic UI updates with Turbo Streams

hotwire turbo stimulus
by Jordan Lee 3 tabs
javascript
import { Controller } from "@hotwired/stimulus"
import consumer from "../channels/consumer"

export default class extends Controller {
  static values = { roomId: Number }

Typing indicator via ActionCable + Turbo Streams

rails hotwire turbo
by Henry Kim 3 tabs