Guest User

Untitled

a guest
Apr 25th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.18 KB | None | 0 0
  1. import React from 'react'
  2. import { string, object } from 'prop-types'
  3.  
  4. import styles from './AnimatedHeightContainer.css'
  5.  
  6. class AnimatedHeightContainer extends React.Component {
  7.  
  8. static propTypes = {
  9. className: string,
  10. style: object,
  11. }
  12.  
  13. constructor () {
  14. super()
  15. this.el = null
  16. this.manualUpdate = this.manualUpdate.bind(this)
  17. }
  18.  
  19. componentDidMount () {
  20. this.manualUpdate()
  21. window.addEventListener('resize', this.manualUpdate)
  22. }
  23.  
  24. componentWillUnmount () {
  25. window.removeEventListener('resize', this.manualUpdate)
  26. }
  27.  
  28. componentDidUpdate () {
  29. this.manualUpdate()
  30. }
  31.  
  32. async manualUpdate () {
  33.  
  34. const animationFrame = async () => new Promise(res => requestAnimationFrame(() => res()))
  35.  
  36. // Compute the height of the content
  37. const originalHeight = this.el.style.height
  38. this.el.style.height = 'auto'
  39. const computedHeight = this.el.getBoundingClientRect().height
  40. await animationFrame() // [0]
  41. this.el.style.height = originalHeight
  42.  
  43. // Manually set the height to the computed height to force a css transition
  44. // (this is needed since css won't transition to 'auto')
  45. await animationFrame()
  46. this.el.style.height = computedHeight + 'px'
  47.  
  48. // [0] If we have multiple AnimatedHeightContainer's nested, the ancestor's height
  49. // calculation (above) is dependent on all it's decendant's computed heights
  50. // (i.e height: auto) So we need to pause somehow until they've all been
  51. // calculated.
  52. // All the browsers seem to handle this timing stuff differently. setTimeout
  53. // doesn't work half the time on Chrome, but requestAnimationFrame results in
  54. // a 1-frame flash of bad animation on Safari. I've picked the lesser of two
  55. // evils for now.
  56. }
  57.  
  58. render () {
  59. return (
  60. <div
  61. className={`${styles.container} ${this.props.className}`}
  62. style={this.props.style}
  63. ref={el => this.el = el}
  64. >
  65. {this.props.children}
  66. </div>
  67. )
  68. }
  69.  
  70. }
  71.  
  72. export default AnimatedHeightContainer
Add Comment
Please, Sign In to add comment