Focusable div

I implemented a focusable div to hide the div, if the user clicks outside of it. I’m not sure if this is a valid approach.
The event listeners for blur and focus are not triggered …
What do you think?

FocusableDiv focusableCompanyInfoContent = new FocusableDiv();
focusableCompanyInfoContent.addBlurListener(event -> {
	log.info("BlurListener: " + event.toString());
});
focusableCompanyInfoContent.addFocusListener(event -> {
	log.info("FocusListener: " + event.toString());
});
@Tag("Div")
public class FocusableDiv extends Div implements Focusable<Div> {

    private Div focusableDiv;

    @Override
    public Element getElement() {
        if(focusableDiv == null) {
            focusableDiv = new Div();
        }
        return focusableDiv.getElement();
    }

    @Override
    public void focus() {
        this.setVisible(true);
    }

    @Override
    public void blur() {
        this.setVisible(false);
    }

    public Div getFocusableDiv() {
        return focusableDiv;
    }

    public void setFocusableDiv(Div focusableDiv) {
        this.focusableDiv = focusableDiv;
    }
}

Regards
Hans

A <div> by itself is not focusable. You’ll need a tabindex at the least. See here: https://allyjs.io/data-tables/focusable.html

Thank you! The focusing and blur works now.
But I ran into a new problem. The element which triggers the focus is also responsible for hiding the div, if clicked again.
The click listener on this element is triggered after the blur listener on the focused div. So it’s not possible to hide the div via that element (because it’s always closed by blur and then opened by the click listener again).
I guess there is no way around that …

Is it possible to detect the clicked element inside the blur listener?

companyInfoToggleContainer.addClickListener(event -> {
	if(!focusableCompanyInfoContent.isVisible()) {
		focusableCompanyInfoContent.setVisible(true);
		focusableCompanyInfoContent.focus();
	} else {
		focusableCompanyInfoContent.setVisible(false);
	}
});
FocusableDiv focusableCompanyInfoContent = new FocusableDiv();
focusableCompanyInfoContent.setTabIndex(0);
focusableCompanyInfoContent.addBlurListener(event -> {
	focusableCompanyInfoContent.setVisible(false);
});

If you’re using the Element API (instead of the built in event listeners like addClickListener), you can use addEventData to add arbitrary information from the event or the element. See more here: https://vaadin.com/docs/v14/flow/element-api/tutorial-event-listener.html#accessing-data-from-events

However, without knowing your exact use case, it somehow feels to me like there could be some simpler solution to what you’re trying to achieve…