web-components
web-components copied to clipboard
[notification] Does not consider opened state changes during the animation
If the opened
state of a Notification
changes multiple times after each other, you may end up with a situation where the notification is opened in React, but still not visible in the browser.
Use case: You perform a server call, which fails and sets the error flag. You then choose to retry the operation, which resets the error flag (notification is hidden) and then immediately fails again and sets the error flag again. At this time, the notification should show up again but it sometimes does and sometimes doesn't.
You can simulate this behaviour with the following code:
const [visible, setVisible] = useState(false);
return (<>
<Checkbox label={"Show notification"} checked={visible}
onCheckedChanged={event => setVisible(event.detail.value)}/>
<Button onClick={() => {
setVisible(true);
setTimeout(() => setVisible(false), 500);
setTimeout(() => setVisible(true), 600);
}}>Toggle</Button>
<Notification opened={visible} duration={0}>Hello World</Notification>
</>);
This seems to be a bug in the <vaadin-notification>
web component. In this state the component's opened
value is true
, while there's no notification overlay visible.
Adapted the repro as a plain web component example:
<script type="module">
import '@vaadin/notification';
import '@vaadin/button';
import '@vaadin/checkbox';
const checkbox = document.querySelector('vaadin-checkbox');
const notification = document.querySelector('vaadin-notification');
const button = document.querySelector('vaadin-button');
notification.renderer = (root) => root.textContent = 'Hello World';
checkbox.addEventListener('checked-changed', (event) => notification.opened = event.detail.value);
button.addEventListener('click', () => {
notification.opened = true;
setTimeout(() => notification.opened = false, 500);
setTimeout(() => notification.opened = true, 600);
});
</script>
<vaadin-checkbox label="Show notification"></vaadin-checkbox>
<vaadin-button>Toggle</vaadin-button>
<vaadin-notification duration="0"></vaadin-notification>
The issue is related to the opening and closing animation. When the animation finishes, the notification component simply add or removes <vaadin-notification-card />
from the DOM without considering opened state changes that could occur during the animation.