vdelacou/iblis-ui

View on GitHub
src/components/ui_components/helper_button/index.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import { Grid, IconButton, Paper, Popper, Typography, WithTheme, withTheme } from '@material-ui/core';
import { HelpCircle } from 'mdi-material-ui';
import * as React from 'react';
import { style } from './style';

export interface HelperButtonProps {
    /**
     * The text to display in the top of the helper popup
     */
    helperTitle: string;
    /**
     * The component to display in the pop up
     */
    contentComponent: React.ReactNode;
}
class CardTitleState {
    /**
     * on which element show the help menu. if undefined the menu is not show
     */
    readonly anchorEl?: null | HTMLElement | ((element: HTMLElement) => HTMLElement) = null;
    /**
     * open the help menu
     */
    readonly open: boolean = false;
    /**
     * open the help menu on Hober
     */
    readonly openHover: boolean = false;
}
class HelperButtonBase extends React.PureComponent<HelperButtonProps & WithTheme, CardTitleState> {

    readonly state = new CardTitleState();

    toggleHelpMenu = (event: React.MouseEvent<HTMLElement>) => {
        const { currentTarget } = event;
        this.setState((prevState) => {
            if (prevState.open) {
                return ({
                    anchorEl: null,
                    open: false,
                });
            } else {
                return ({
                    anchorEl: currentTarget,
                    open: true,
                });
            }
        });
    }

    openHelpMenuHover = (event: React.MouseEvent<HTMLElement>) => {
        if (!this.state.open) {
            const { currentTarget } = event;
            this.setState(() => ({
                anchorEl: currentTarget,
                openHover: true,
            }));
        }
    }

    closeHelpMenuHover = () => {
        if (!this.state.open) {
            this.setState(() => ({
                anchorEl: null,
                openHover: false,
            }));
        }
    }

    renderMenuHelp = (): React.ReactNode => {
        return (
            <Paper style={style(this.props.theme).helpPaper}>
                <Grid container={true} justify={'center'} style={style(this.props.theme).helpLineContainer} >
                    <Typography variant={'headline'} style={style(this.props.theme).helpTitle} >
                        {this.props.helperTitle}
                    </Typography>
                </Grid>
                <Grid container={true} style={style(this.props.theme).helpContentContainer}>
                    {this.props.contentComponent}
                </Grid>
            </Paper>
        );
    }

    render(): React.ReactNode {

        const { theme } = this.props;
        const id = open ? 'popper-helper' : undefined;

        const popperModifiers = {
            flip: {
                enabled: true,
            },
            preventOverflow: {
                enabled: true,
                boundariesElement: 'scrollParent',
            },
        };

        return (
            <div>
                <IconButton
                    onPointerEnter={(event) => this.openHelpMenuHover(event)}
                    onPointerLeave={() => this.closeHelpMenuHover()}
                    onClick={(event) => this.toggleHelpMenu(event)}
                    style={style(theme).helpButton}
                >
                    <HelpCircle color={this.state.open ? 'primary' : 'default'} style={style(theme).helpIcon} />
                </IconButton>
                <Popper
                    id={id}
                    placement="bottom-end"
                    open={this.state.open || this.state.openHover}
                    anchorEl={this.state.anchorEl}
                    modifiers={popperModifiers}
                >
                    {this.renderMenuHelp()}
                </Popper>
            </div>
        );
    }
}

const HelperButtonWithTheme: React.ComponentType<HelperButtonProps> = withTheme()(HelperButtonBase);

/**
 * Helper Button to display a popup
 */
export const HelperButton: React.ComponentType<HelperButtonProps> = (HelperButtonWithTheme);