Defines the widgets that display the distribution of each node on hover
        and the members of each nodes
    
    Parameters
    ----------
    kmgraph: the kepler-mapper graph dict returned by `get_mapper_graph()``
    graph_fw: the FigureWidget representing the graph
    ctooltips: boolean; if True/False the node["custom_tooltips"]/"member_ids"
    are passed to member_textbox

    width, height, top refer to the figure
    size and position of the hovered node distribution

    Returns
    -------
    a box containing the graph figure, the figure of the hovered node
    distribution, and the textboxes displaying the cluster size and  member_ids
    or custom tooltips for hovered node members

def hovering_widgets(
    kmgraph,
    graph_fw,
    ctooltips=False,
    width=400,
    height=300,
    top=100,
    left=50,
    bgcolor="rgb(240,240,240)",
    y_gridcolor="white",
    member_textbox_width=200,
):
    """Defines the widgets that display the distribution of each node on hover
        and the members of each nodes
    
    Parameters
    ----------
    kmgraph: the kepler-mapper graph dict returned by `get_mapper_graph()``
    graph_fw: the FigureWidget representing the graph
    ctooltips: boolean; if True/False the node["custom_tooltips"]/"member_ids"
    are passed to member_textbox

    width, height, top refer to the figure
    size and position of the hovered node distribution

    Returns
    -------
    a box containing the graph figure, the figure of the hovered node
    distribution, and the textboxes displaying the cluster size and  member_ids
    or custom tooltips for hovered node members
    """
    fnode = kmgraph["nodes"][0]
    fwc = node_hist_fig(
        fnode["distribution"],
        title="Cluster Member Distribution",
        width=width,
        height=height,
        top=top,
        left=left,
        bgcolor=bgcolor,
        y_gridcolor=y_gridcolor,
    )
    clust_textbox = ipw.Text(
        value="{:d}".format(fnode["cluster"]["size"]),
        description="Cluster size:",
        disabled=False,
        continuous_update=True,
    )

    clust_textbox.layout = dict(margin="10px 10px 10px 10px", width="200px")

    member_textbox = ipw.Textarea(
        value=", ".join(str(x) for x in fnode["member_ids"])
        if not ctooltips
        else ", ".join(str(x) for x in fnode["custom_tooltips"]),
        description="Members:",
        disabled=False,
        continuous_update=True,
    )

    member_textbox.layout = dict(
        margin="5px 5px 5px 10px", width=str(member_textbox_width) + "px"
    )

    def do_on_hover(trace, points, state):
        if not points.point_inds:
            return
        ind = points.point_inds[0]  # get the index of the hovered node
        node = kmgraph["nodes"][ind]
        # on hover do:
        with fwc.batch_update():  # update data in the cluster member histogr
            fwc.data[0].text = [
                "{:.1f}%".format(d["perc"]) for d in node["distribution"]
            ]
            fwc.data[0].y = [d["height"] for d in node["distribution"]]
            fwc.data[0].marker.color = [d["color"] for d in node["distribution"]]

        clust_textbox.value = "{:d}".format(node["cluster"]["size"])
        member_textbox.value = (
            ", ".join(str(x) for x in node["member_ids"])
            if not ctooltips
            else ", ".join(str(x) for x in node["custom_tooltips"])
        )

    trace = graph_fw.data[1]
    trace.on_hover(do_on_hover)
    return ipw.VBox([ipw.HBox([graph_fw, fwc]), clust_textbox, member_textbox])