UNPKG

styledot

Version:
125 lines (113 loc) 4.31 kB
// This is the layer that executes on the official react-modal component // This is accessed by // - modal-instance.jsx (for React usage) // - modal-init.js (for vanilla usage) // https://style.23andme.com/components/#modals-section for more information import React from 'react'; import PropTypes from 'prop-types'; import ReactModal from 'react-modal'; import { v4 as uuid } from 'uuid'; ReactModal.setAppElement('body'); class Modal extends React.Component { constructor(props) { super(props); this.state = { hasScrolled: false, }; this.handleScroll = this.handleScroll.bind(this); this.closeModal = this.props.closeModal.bind(this); this.ctaPosition = props.ctaPosition ? `dismiss-cta-${props.ctaPosition}` : ''; this.uid = uuid(); } classString() { let defaultClasses = 'sd-modal sd-elevation-2'; if (this.props.alternateModal) { defaultClasses += ` sd-modal-${this.props.alternateModal}`; if (this.props.useWhiteDismissButton) { defaultClasses += ` mod-modal-white-dismiss`; } } return defaultClasses; } overlayClassString() { let overlayDefaultClasses = 'sd-modal-overlay'; if (this.props.alternateModal === 'interstitial') { overlayDefaultClasses += ` mod-overlay-dark`; } return overlayDefaultClasses; } handleScroll() { const wrapper = document.querySelector('.sd-modal-wrapper'); if (wrapper.scrollTop > 0 && !this.state.hasScrolled) { this.setState({ hasScrolled: true }); } else if (wrapper.scrollTop === 0 && this.state.hasScrolled) { this.setState({ hasScrolled: false }); } } render() { return ( <ReactModal isOpen={this.props.isVisible} onRequestClose={this.props.closeModal} className={this.classString()} overlayClassName={this.overlayClassString()} bodyOpenClassName="sd-modal-body" contentLabel={this.props.contentLabel} aria={{ describedby: `modal-contents-${this.uid}` modal: true, }} > <button className={`sd-unbutton sd-modal-dismiss-top ${this.state.hasScrolled ? 'mod-scrolled' : ''}`} onClick={this.props.closeModal} aria-label="Close" /> <div id={`modal-contents-${this.uid}`} className="sd-modal-wrapper" onScroll={this.handleScroll}> {this.props.contents && ( <div // Careful here! dangerouslySetInnerHTML={{ __html: this.props.contents, }} /> )} {this.props.children && this.props.children} {this.props.includeDismissCta && ( <div className={`sd-modal-dismiss-cta-container ${this.ctaPosition}`}> <button className={`sd-button sd-modal-dismiss-cta ${this.props.extraClasses}`} onClick={this.props.closeModal} > {this.props.dismissText} </button> </div> )} </div> </ReactModal> ); } } Modal.defaultProps = { contents: '', dismissText: 'Close', ctaPosition: '', extraClasses: '', includeDismissCta: true, alternateModal: '', useWhiteDismissButton: false, contentLabel: 'Modal', }; Modal.propTypes = { isVisible: PropTypes.bool.isRequired, closeModal: PropTypes.func.isRequired, contents: PropTypes.string, dismissText: PropTypes.string, ctaPosition: PropTypes.string, extraClasses: PropTypes.string, includeDismissCta: PropTypes.bool, alternateModal: PropTypes.string, useWhiteDismissButton: PropTypes.bool, contentLabel: PropTypes.string, }; export default Modal;