diff --git a/.changeset/nine-actors-occur.md b/.changeset/nine-actors-occur.md
new file mode 100644
index 000000000..6c410fd84
--- /dev/null
+++ b/.changeset/nine-actors-occur.md
@@ -0,0 +1,6 @@
+---
+'@lion/overlays': minor
+'@lion/tooltip': minor
+---
+
+Abstracted the tooltip arrow related logic to a mixin, so it can be used in other overlays. Also created some demos to show this.
diff --git a/packages/overlays/README.md b/packages/overlays/README.md
index 7832cc2ce..5d71b2360 100644
--- a/packages/overlays/README.md
+++ b/packages/overlays/README.md
@@ -111,7 +111,6 @@ class MyOverlayComponent extends LitElement {
render() {
return html`
-
diff --git a/packages/overlays/docs/20-index.md b/packages/overlays/docs/20-index.md
index 79361bd61..c082dbae2 100644
--- a/packages/overlays/docs/20-index.md
+++ b/packages/overlays/docs/20-index.md
@@ -4,7 +4,9 @@
```js script
import { html } from 'lit-html';
+import { render, LitElement } from '@lion/core';
import {
+ ArrowMixin,
OverlayMixin,
withBottomSheetConfig,
withDropdownConfig,
@@ -94,8 +96,8 @@ or in your Web Component with `OverlayMixin`, make sure you override these metho
- Handle the tearing down of those event listeners
- Define a template which includes:
- invoker slot for your user to provide the invoker node (the element that invokes the overlay content)
- - content slot for your user to provide the content that shows when the overlay is opened
- - \_overlay-shadow-outlet, this slot is currently necessary under the hood for acting as a wrapper element for placement purposes, but is not something your end user should be concerned with, unless they are extending your component.
+ - content slot for your user to provide the content that shows when the overlay is opened,
+ make sure to put it inside a div with id `overlay-content-node-wrapper` which is necessary for positioning logic to work properly.
```js
_defineOverlayConfig() {
@@ -126,7 +128,6 @@ _teardownOpenCloseListeners() {
render() {
return html`
-
@@ -356,7 +357,7 @@ Under the hood, the `OverlayMixin` will instantiate an OverlayController with th
By default, there are only a few `OverlayMixin` methods you need to override to create a working Web Component using an overlay:
-- `render`, the template needs to include a ``, `` and ``.
+- `render`, the template needs to include a `` and `` inside a div with id `overlay-content-node-wrapper` (for positioning).
- `_defineOverlayConfig`, in this protected method, return an object that contains the default configuration for your Web Component's overlay. See configuration section of OverlayController.
- `_setupOpenCloseListeners`, use this lifecycle hook to setup the open and close event listeners on your `_overlayInvokerNode`.
- `_teardownOpenCloseListeners`, use this lifecycle hook to ensure that the listeners are removed when the OverlayController is tearing down. For example when the Web Component is disconnected from the DOM.
@@ -397,7 +398,6 @@ class MyOverlayWC extends OverlayMixin(LitElement) {
render() {
return html`
-
@@ -568,3 +568,57 @@ export const nestedOverlays = () => {
`;
};
```
+
+## Local overlay with an arrow
+
+To add an arrow to the localOverlay you can add `ArrowMixin` to your component.
+And add the `arrowPopperConfig` to the `_defineOverlayConfig`.
+
+```js preview-story
+export const LocalWithArrow = () => {
+ class ArrowExample extends ArrowMixin(OverlayMixin(LitElement)) {
+ // Alternatively, set `this.config = { popperConfig: { placement: 'bottom' } }` on connectedCallback
+ _defineOverlayConfig() {
+ return {
+ ...super._defineOverlayConfig(),
+ popperConfig: {
+ ...super._defineOverlayConfig().popperConfig,
+ placement: 'bottom',
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ this.__toggle = this.__toggle.bind(this);
+ }
+
+ __toggle() {
+ this.opened = !this.opened;
+ }
+
+ _setupOpenCloseListeners() {
+ super._setupOpenCloseListeners();
+ if (this._overlayInvokerNode) {
+ this._overlayInvokerNode.addEventListener('click', this.__toggle);
+ }
+ }
+
+ _teardownOpenCloseListeners() {
+ super._teardownOpenCloseListeners();
+ if (this._overlayInvokerNode) {
+ this._overlayInvokerNode.removeEventListener('click', this.__toggle);
+ }
+ }
+ }
+ if (!customElements.get('arrow-example')) {
+ customElements.define('arrow-example', ArrowExample);
+ }
+ return html`
+
+
+