Turbo
Boson works with Hotwire Turbo out of the box — no configuration required.
Overview
If your app uses Hotwire Turbo, Boson's built-in lifecycle system takes care of component initialization and cleanup for you. There's nothing to configure — just import Boson and everything works.
This covers Turbo Drive (full-page navigations), Turbo Frames (partial page updates), and Turbo Streams (server-pushed DOM changes).
How It Works
Boson components use data-controller attributes to identify themselves in the DOM. The lifecycle system watches for these elements and manages their JavaScript automatically:
- Standard page loads — components are initialized when the DOM is ready
- Turbo Drive navigation — components are torn down before caching and re-initialized after each visit
- Turbo Frames & Streams — a MutationObserver detects elements as they're added or removed from the DOM and initializes or cleans up their components instantly
Turbo Drive
When Turbo replaces the page body during navigation, Boson listens for two events:
turbo:before-cache— tears down all components, calling theirdestroy()methods to remove event listeners and clean up stateturbo:load— re-initializes all components on the new page
This prevents duplicate event listeners and stale state that would otherwise accumulate across Turbo navigations.
Turbo Frames & Streams
For content injected via Turbo Frames or Streams, Boson uses a MutationObserver that watches the entire document. When new elements with data-controller appear in the DOM, they're initialized automatically. When elements are removed, their components are cleaned up.
This means you can freely use Boson components inside Turbo Frames and they'll work exactly as expected — dropdowns, modals, forms, and everything else.
{{-- A Turbo Frame that loads new content with Boson components --}}
<turbo-frame id="notifications">
{{-- Any Boson components inside here (modals, dropdowns, forms, etc.) --}}
{{-- are automatically initialized when the frame loads --}}
{{-- and cleaned up when the frame is replaced --}}
<x-boson::dropdown>
<x-boson::dropdown.trigger>
<x-boson::button icon="bell">Notifications</x-boson::button>
</x-boson::dropdown.trigger>
<x-boson::dropdown.menu>
<x-boson::dropdown.item>New message</x-boson::dropdown.item>
</x-boson::dropdown.menu>
</x-boson::dropdown>
</turbo-frame>
Setup
There's nothing to configure. If Turbo is present on the page, Boson responds to its events. If Turbo isn't present, Boson simply initializes on DOMContentLoaded. The same import works either way:
// resources/js/app.js
import '../../vendor/davidgut/boson/resources/js/boson.js';
// That's it. Works with or without Turbo.
Turbo Attributes
Several Boson components accept a turbo:* prefix to pass Turbo data attributes. Each prefixed prop maps to a data-turbo-* attribute on the rendered element.
{{-- turbo:frame="main" → data-turbo-frame="main" --}}
<x-boson::link href="/users" turbo:frame="main">Users</x-boson::link>
{{-- turbo:action="replace" → data-turbo-action="replace" --}}
<x-boson::link href="/settings" turbo:action="replace">Settings</x-boson::link>
{{-- Multiple turbo attributes --}}
<x-boson::button turbo:confirm="Are you sure?" turbo:submits-with="Saving...">Save</x-boson::button>
The following components support the turbo:* prefix:
- Button —
turbo:confirm,turbo:submits-with, etc. - Form —
turbo:confirm,turbo:frame,turbo:stream, etc. - Link —
turbo:frame,turbo:action,turbo:prefetch, etc. - Navbar item —
turbo:frame,turbo:action - Navlist item —
turbo:frame,turbo:action - Breadcrumbs item —
turbo:frame,turbo:action
Opting Out
All of the components above default to turbo="true". To disable Turbo on a specific element, set :turbo="false". This outputs data-turbo="false" on the rendered HTML.
{{-- Disable Turbo on a form (use standard browser submission) --}}
<x-boson::form :turbo="false" action="/upload" method="POST">
...
</x-boson::form>
{{-- Disable Turbo on a link --}}
<x-boson::link :turbo="false" href="/download/report.pdf">Download PDF</x-boson::link>
{{-- Disable Turbo on a button rendered as a link --}}
<x-boson::button :turbo="false" as="a" href="/external">External Link</x-boson::button>
Confirmation Dialogs
Use turbo:confirm to show a browser confirmation dialog before Turbo processes the element. Pair with turbo:submits-with on buttons to change the button text while submitting.
{{-- Confirm before submitting --}}
<x-boson::form action="/teams/1" method="DELETE" turbo:confirm="Delete this team?">
<x-boson::button type="submit" variant="danger" turbo:submits-with="Deleting...">
Delete Team
</x-boson::button>
</x-boson::form>
{{-- Confirm on a standalone button --}}
<x-boson::button turbo:confirm="Are you sure?">Archive</x-boson::button>