diff --git a/docs/docs/controllers/presence_controller.mdx b/docs/docs/controllers/presence_controller.mdx
new file mode 100644
index 00000000..7ac76132
--- /dev/null
+++ b/docs/docs/controllers/presence_controller.mdx
@@ -0,0 +1,54 @@
+---
+id: PresenceController
+title: PresenceController
+---
+
+import NoActions from "../_partials/no-actions.md";
+import NoTargets from "../_partials/no-targets.md";
+import NoClasses from "../_partials/no-classes.md";
+import NoValues from "../_partials/no-values.md";
+
+## Purpose
+
+A utility controller to wire up other stimulus actions when an element comes into or leaves the document.
+
+
+## [Actions](https://stimulus.hotwire.dev/reference/actions)
+
+
+
+## [Targets](https://stimulus.hotwire.dev/reference/targets)
+
+
+
+
+## [Classes](https://stimulus.hotwire.dev/reference/classes)
+
+
+
+
+## [Values](https://stimulus.hotwire.dev/reference/values)
+
+
+
+
+## Events
+
+| Event | When | Dispatched on | `event.detail` |
+| --- | --- | --- |--- |
+|`presence:added` | When the element enters the DOM | the controller root element | - |
+|`presence:removed` | When the element leaves the DOM | the controller root element | - |
+
+## Side Effects
+
+None
+
+## How to Use
+
+
+
+
diff --git a/docs/sidebars.js b/docs/sidebars.js
index 4126ebb3..403082db 100644
--- a/docs/sidebars.js
+++ b/docs/sidebars.js
@@ -96,6 +96,7 @@ module.exports = {
"controllers/AppearanceController",
"controllers/IntervalController",
"controllers/IntersectionController",
+ "controllers/PresenceController",
"controllers/TimeoutController",
],
},
diff --git a/src/controllers/utility/presence_controller.ts b/src/controllers/utility/presence_controller.ts
new file mode 100644
index 00000000..1f1a4371
--- /dev/null
+++ b/src/controllers/utility/presence_controller.ts
@@ -0,0 +1,13 @@
+import {BaseController} from "../../utilities/base_controller";
+
+export class PresenceController extends BaseController {
+
+ connect() {
+ this.dispatch(this.el, "presence:added");
+ }
+
+ disconnect() {
+ this.dispatch(this.el, "presence:removed");
+ }
+
+}
diff --git a/src/index.ts b/src/index.ts
index 717b5ac5..b642a897 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -36,6 +36,7 @@ export {NavigateFormErrorsController} from "./controllers/forms/navigate_form_er
export {NestedFormController} from "./controllers/forms/nested_form_controller";
export {PasswordConfirmController} from "./controllers/forms/password_confirm_controller";
export {PasswordPeekController} from "./controllers/forms/password_peek_controller";
+export {PresenceController} from "./controllers/utility/presence_controller";
export {RemoteFormController} from "./controllers/forms/remote_form_controller";
export {ResponsiveIframeBodyController, ResponsiveIframeWrapperController} from "./controllers/responsive_iframe_controller";
export {ScrollIntoFocusController} from "./controllers/scroll/scroll_into_focus_controller";