x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div data-controller="disappearing-alert">
<button type="button"
class="btn btn-primary position-absolute top-50 start-50 translate-middle"
data-action="click->disappearing-alert#liveAlert">
Show live alert
</button>
<template data-disappearing-alert-target="alertTemplate">
<div class="alert alert-info alert-dismissible fade show mx-3" role="alert"
data-controller='disappearing-alert'
data-action='animationend->disappearing-alert#dismissAlert'>
Disappearing Live Alert
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div data-controller="disappearing-alert">
<button type="button"
class="btn btn-primary position-absolute top-50 start-50 translate-middle"
data-action="click->disappearing-alert#liveAlert">
Show live alert
</button>
<template data-disappearing-alert-target="alertTemplate">
<div class="alert alert-info alert-dismissible fade show mx-3" role="alert"
data-controller='disappearing-alert'
data-action='animationend->disappearing-alert#dismissAlert'>
Disappearing Live Alert
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
</template>
</div>

_disappearing_alert.scss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$alert-color: rgb(0 0 0 / 3%);
@keyframes progress {
from {
inset: 0 100% 0 0;
}
to {
inset: 0;
}
}
.alert.fade {
overflow: hidden;
&::before {
animation: progress 5s ease-in-out forwards;
background-color: $alert-color;
content: '';
position: absolute;
}
&:hover::before {
animation-play-state: paused;
}
}

disappearing_alert_controller.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['alert', 'alertTemplate'];
connect() {
this.bsAlert = bootstrap.Alert.getOrCreateInstance(this.element);
}
liveAlert() {
const template = this.alertTemplateTarget;
const clone = template.content.cloneNode(true);
document.body.appendChild(clone);
}
dismissAlert() {
this.bsAlert.close();
}
}