From c64f0551cf0fd67b26fa27e3fa95722e9ed844fa Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 27 Jun 2018 08:52:41 -0600 Subject: [PATCH] add MutationObserver to accordion to trigger setChildContentHeight when children change (#947) * add MutationObserver to accordion to trigger setChildContentHeight when children change * remove requestAnimationFrame around MutationObserver registration and add comment to change log * set up observer in ref creation function * mock MutationObserver --- CHANGELOG.md | 2 +- .../src/views/accordion/accordion_grow.js | 55 +++++++++++-------- src/components/accordion/accordion.js | 16 +++++- src/components/accordion/accordion.test.js | 12 ++++ 4 files changed, 60 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f87f1e7b9c..3afe3253088 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## [`master`](https://github.com/elastic/eui/tree/master) -No public interface changes since `1.0.0`. +- `EuiAccordion` use MutationObserver to re-calculate height when children DOM changes ([#947](https://github.com/elastic/eui/pull/947)) ## [`1.0.0`](https://github.com/elastic/eui/tree/v1.0.0) diff --git a/src-docs/src/views/accordion/accordion_grow.js b/src-docs/src/views/accordion/accordion_grow.js index 89923766a88..a8933dd8bc2 100644 --- a/src-docs/src/views/accordion/accordion_grow.js +++ b/src-docs/src/views/accordion/accordion_grow.js @@ -1,3 +1,6 @@ +/* eslint react/no-multi-comp: 0 */ +/* eslint react/prefer-stateless-function: 0 */ + import React, { Component } from 'react'; import { @@ -7,18 +10,44 @@ import { EuiText, } from '../../../../src/components'; - -class AccordionGrow extends Component { +class Rows extends Component { state = { counter: 1 } + onIncrease() { + this.setState(prevState => ({ + counter: prevState.counter + 1 + })); + } + + onDecrease() { + this.setState(prevState => ({ + counter: Math.max(0, prevState.counter - 1) + })); + } + render() { const rows = []; for (let i = 1; i <= this.state.counter; i++) { rows.push(

Row {i}

); } + return ( + + +

+ this.onIncrease()}>Increase height + {' '} + this.onDecrease()}>Decrease height +

+ { rows } +
+ ); + } +} +class AccordionGrow extends Component { + render() { return ( - - -

- this.onIncrease()}>Increase height - {' '} - this.onDecrease()}>Decrease height -

- { rows } -
+
); } - - onIncrease() { - this.setState(prevState => ({ - counter: prevState.counter + 1 - })); - } - - onDecrease() { - this.setState(prevState => ({ - counter: Math.max(0, prevState.counter - 1) - })); - } } export default AccordionGrow; diff --git a/src/components/accordion/accordion.js b/src/components/accordion/accordion.js index d470b3748cb..9152027493a 100644 --- a/src/components/accordion/accordion.js +++ b/src/components/accordion/accordion.js @@ -56,6 +56,20 @@ export class EuiAccordion extends Component { })); } + setChildContentRef = (node) => { + this.childContent = node; + + if (this.observer) { + this.observer.disconnect(); + this.observer = null; + } + + if (node) { + this.observer = new MutationObserver(this.setChildContentHeight); + this.observer.observe(this.childContent, { childList: true, subtree: true }); + } + } + render() { const { children, @@ -140,7 +154,7 @@ export class EuiAccordion extends Component { ref={node => { this.childWrapper = node; }} id={id} > -
{ this.childContent = node; }}> +
{children}
diff --git a/src/components/accordion/accordion.test.js b/src/components/accordion/accordion.test.js index 2832314e9ba..3d4aa26e2b2 100644 --- a/src/components/accordion/accordion.test.js +++ b/src/components/accordion/accordion.test.js @@ -81,6 +81,18 @@ describe('EuiAccordion', () => { }); describe('behavior', () => { + beforeAll(() => { + global.MutationObserver = class { + constructor() {} + disconnect() {} + observe() {} + }; + }); + + afterAll(() => { + delete global.MutationObserver; + }); + it('opens when clicked once', () => { const component = mount(