diff --git a/docs/components/mutation-observer.md b/docs/components/mutation-observer.md
index 1eddefcb..258803bc 100644
--- a/docs/components/mutation-observer.md
+++ b/docs/components/mutation-observer.md
@@ -8,7 +8,7 @@ The mutation observer will report changes to the content it wraps through the `s
```html preview
-
+
Click to mutate
@@ -42,6 +42,47 @@ The mutation observer will report changes to the content it wraps through the `s
```
+```jsx react
+import { useState } from 'react';
+import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .resize-observer-overview div {
+ display: flex;
+ border: solid 2px rgb(var(--sl-input-border-color));
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 4rem 2rem;
+ }
+`;
+
+const types = ['primary', 'success', 'neutral', 'warning', 'danger'];
+let clicks = 0;
+
+const App = () => {
+ const [type, setType] = useState('primary');
+
+ function handleClick() {
+ clicks++;
+ setType(types[clicks % types.length]);
+ }
+
+ return (
+ <>
+ console.log(event.detail)}
+ >
+ Click to mutate
+
+
+
+ >
+ );
+};
+```
+
?> When you create a mutation observer, you must indicate what changes it should respond to by including at least one of `attr`, `child-list`, or `char-data`. If you don't specify at least one of these attributes, no mutation events will be emitted.
## Examples
@@ -101,4 +142,55 @@ Use the `child-list` attribute to watch for new child elements that are added or
```
+```jsx react
+import { useState } from 'react';
+import { SlButton, SlMutationObserver } from '@shoelace-style/shoelace/dist/react';
+
+const css = `
+ .mutation-child-list .buttons {
+ display: flex;
+ gap: .25rem;
+ flex-wrap: wrap;
+ margin-bottom: 1rem;
+ }
+`;
+
+let buttonCount = 0;
+
+const App = () => {
+ const [buttonIds, setButtonIds] = useState([]);
+
+ function addButton() {
+ setButtonIds([...buttonIds, ++buttonCount]);
+ }
+
+ function removeButton(id) {
+ setButtonIds(buttonIds.filter(i => i !== id));
+ }
+
+ return (
+ <>
+
+
console.log(event.detail)}
+ >
+
+ Add button
+ {buttonIds.map(id => (
+ removeButton(id)}>
+ {id}
+
+ ))}
+
+
+
+
+ 👆 Add and remove buttons and watch the console
+
+ >
+ );
+};
+```
+
[component-metadata:sl-mutation-observer]
diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md
index b81a8246..88134ad7 100644
--- a/docs/resources/changelog.md
+++ b/docs/resources/changelog.md
@@ -9,6 +9,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
## Next
- Added React examples and CodePen links to all components
+- Changed the `attr` in experimental `` to require `"*"` instead of `""` to target all attributes
- Fixed a bug in `` where the `label` attribute didn't set the label
- Fixed a bug in `` that caused disabled and readonly controls to transition on hover
- The `panel` property of `` is now reflected
diff --git a/src/components/mutation-observer/mutation-observer.ts b/src/components/mutation-observer/mutation-observer.ts
index 685b282a..7f36c465 100644
--- a/src/components/mutation-observer/mutation-observer.ts
+++ b/src/components/mutation-observer/mutation-observer.ts
@@ -19,8 +19,8 @@ export default class SlMutationObserver extends LitElement {
private mutationObserver: MutationObserver;
/**
- * Watches for changes to attributes. If empty, all changes will be reported. To watch only specific attributes,
- * separate them by a space.
+ * Watches for changes to attributes. If set to *, all changes will be reported. To watch only specific attributes,
+ * separate them by a space, e.g. "class id title".
*/
@property({ reflect: true }) attr: string;
@@ -80,12 +80,15 @@ export default class SlMutationObserver extends LitElement {
}
startObserver() {
+ const observeAttributes = typeof this.attr === 'string' && this.attr.length > 0;
+ const attributeFilter = observeAttributes && this.attr !== '*' ? this.attr.split(' ') : undefined;
+
try {
this.mutationObserver.observe(this, {
subtree: true,
childList: this.childList,
- attributes: typeof this.attr === 'string',
- attributeFilter: typeof this.attr === 'string' && this.attr.length > 0 ? this.attr.split(' ') : undefined,
+ attributes: observeAttributes,
+ attributeFilter,
attributeOldValue: this.attrOldValue,
characterData: this.charData,
characterDataOldValue: this.charDataOldValue