Bootstrap 5
Chatbot
List
Bootstrap 5 Design
Template
Html
Integration List
Ai
Chatbot Bootstrap 5 optimisées pour la visualisation et l'interaction. Composants modernes et responsive.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="MEZGANI Said" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Snippet Chatboot Bootstrap 5 2026 23040041 | AngularForAll</title>
<!-- Bootstrap 5 + Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<style>
body {
background: #f4f7fc;
min-height: 100vh;
font-family: 'Segoe UI', system-ui, sans-serif;
}
/* ----- CHATBOT WIDGET (flottant) ----- */
.chatbot-widget {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 1055;
display: flex;
flex-direction: column;
align-items: flex-end;
}
/* fenêtre de chat */
.chatbot-window {
width: 340px;
max-width: calc(100vw - 32px);
background: white;
border-radius: 24px;
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12), 0 4px 12px rgba(0, 0, 0, 0.08);
overflow: hidden;
margin-bottom: 16px;
transition: opacity 0.2s, transform 0.2s;
border: 1px solid rgba(0, 0, 0, 0.05);
}
.chatbot-window.d-none {
display: none !important;
}
/* en-tête */
.chatbot-header {
background: linear-gradient(145deg, #0d6efd, #0b5ed7);
color: white;
padding: 16px 18px;
display: flex;
align-items: center;
justify-content: space-between;
}
.chatbot-header-left {
display: flex;
align-items: center;
gap: 10px;
}
.chatbot-avatar {
width: 40px;
height: 40px;
background: white;
border-radius: 40px;
display: flex;
align-items: center;
justify-content: center;
color: #0d6efd;
font-weight: bold;
font-size: 20px;
box-shadow: 0 2px 6px rgba(0,0,0,0.15);
}
.chatbot-title h6 {
margin: 0;
font-weight: 600;
letter-spacing: -0.2px;
}
.chatbot-title small {
opacity: 0.85;
font-size: 12px;
}
.btn-close-chat {
background: rgba(255,255,255,0.2);
border: none;
color: white;
width: 32px;
height: 32px;
border-radius: 32px;
display: flex;
align-items: center;
justify-content: center;
transition: 0.15s;
}
.btn-close-chat:hover {
background: rgba(255,255,255,0.3);
}
/* corps / messages */
.chatbot-body {
height: 360px;
overflow-y: auto;
padding: 18px 16px;
background: #f9fafc;
display: flex;
flex-direction: column;
gap: 12px;
}
.message {
display: flex;
max-width: 85%;
}
.message.bot {
align-self: flex-start;
}
.message.user {
align-self: flex-end;
}
.message-content {
padding: 12px 16px;
border-radius: 20px;
font-size: 14px;
line-height: 1.45;
word-break: break-word;
}
.bot .message-content {
background: white;
border: 1px solid #e9ecef;
border-bottom-left-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.02);
}
.user .message-content {
background: #0d6efd;
color: white;
border-bottom-right-radius: 6px;
}
.typing-indicator {
display: flex;
gap: 5px;
padding: 8px 14px;
background: white;
border-radius: 20px;
border-bottom-left-radius: 6px;
width: fit-content;
border: 1px solid #e9ecef;
}
.typing-dot {
width: 8px;
height: 8px;
background: #adb5bd;
border-radius: 50%;
animation: typingPulse 1.2s infinite ease-in-out;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingPulse {
0%, 60%, 100% { transform: translateY(0); opacity: 0.5; }
30% { transform: translateY(-6px); opacity: 1; }
}
/* zone de saisie */
.chatbot-footer {
background: white;
padding: 12px 16px;
border-top: 1px solid #eef2f6;
display: flex;
align-items: center;
gap: 10px;
}
.chatbot-footer .form-control {
border-radius: 40px;
background: #f2f5f9;
border: 1px solid #e0e7ef;
padding: 10px 16px;
font-size: 14px;
}
.chatbot-footer .form-control:focus {
background: white;
box-shadow: 0 0 0 3px rgba(13,110,253,0.15);
border-color: #0d6efd;
}
.btn-send {
background: #0d6efd;
color: white;
border-radius: 40px;
width: 44px;
height: 44px;
display: flex;
align-items: center;
justify-content: center;
border: none;
transition: 0.15s;
}
.btn-send:hover {
background: #0b5ed7;
transform: scale(1.02);
}
.btn-send i {
font-size: 18px;
}
/* bouton toggle principal (flottant) */
.chatbot-toggle-btn {
width: 60px;
height: 60px;
border-radius: 60px;
background: #0d6efd;
color: white;
border: none;
box-shadow: 0 8px 16px rgba(13, 110, 253, 0.25);
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
transition: all 0.2s;
border: 2px solid rgba(255,255,255,0.3);
}
.chatbot-toggle-btn:hover {
background: #0b5ed7;
transform: scale(1.05);
box-shadow: 0 10px 20px rgba(13, 110, 253, 0.35);
}
.chatbot-toggle-btn i {
transition: transform 0.2s;
}
/* petites animations */
.message {
animation: fadeInUp 0.25s ease;
}
@keyframes fadeInUp {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
/* scroll personnalisé */
.chatbot-body::-webkit-scrollbar { width: 5px; }
.chatbot-body::-webkit-scrollbar-track { background: transparent; }
.chatbot-body::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 10px; }
/* petit badge non lu (optionnel) */
.unread-badge {
position: absolute;
top: -4px;
right: -4px;
background: #dc3545;
color: white;
border-radius: 30px;
padding: 2px 6px;
font-size: 11px;
font-weight: bold;
border: 2px solid white;
}
/* responsive */
@media (max-width: 480px) {
.chatbot-window { width: calc(100vw - 32px); }
}
</style>
</head>
<body>
<!-- Contenu de démonstration (optionnel) -->
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8 text-center">
<h1 class="display-5 fw-semibold mb-3">🤖 Assistant Virtuel</h1>
<p class="lead text-secondary">Cliquez sur l'icône en bas à droite pour discuter avec notre chatbot Bootstrap 5.</p>
<div class="mt-5 p-4 bg-white rounded-4 shadow-sm">
<i class="bi bi-chat-dots fs-1 text-primary"></i>
<p class="mt-3">Posez une question sur nos services, les tarifs ou le support.</p>
</div>
</div>
</div>
</div>
<!-- ========== WIDGET CHATBOT ========== -->
<div class="chatbot-widget">
<!-- Fenêtre de chat (cachée par défaut) -->
<div class="chatbot-window d-none" id="chatWindow">
<div class="chatbot-header">
<div class="chatbot-header-left">
<div class="chatbot-avatar">
<i class="bi bi-robot"></i>
</div>
<div class="chatbot-title">
<h6>SupportBot</h6>
<small><i class="bi bi-circle-fill text-success me-1" style="font-size: 8px;"></i>En ligne · répond en ~1min</small>
</div>
</div>
<button class="btn-close-chat" id="closeChatBtn" aria-label="Fermer">
<i class="bi bi-x-lg"></i>
</button>
</div>
<!-- Zone de messages -->
<div class="chatbot-body" id="chatBody">
<!-- Message initial du bot -->
<div class="message bot">
<div class="message-content">
👋 Bonjour ! Je suis l'assistant virtuel. Comment puis-je vous aider aujourd'hui ?
</div>
</div>
<!-- les autres messages seront injectés ici -->
</div>
<!-- Pied avec input -->
<div class="chatbot-footer">
<input type="text" class="form-control" id="chatInput" placeholder="Écrivez votre message..." autocomplete="off">
<button class="btn-send" id="sendMessageBtn">
<i class="bi bi-send-fill"></i>
</button>
</div>
</div>
<!-- Bouton toggle (ouvrir/fermer) -->
<button class="chatbot-toggle-btn" id="toggleChatBtn">
<i class="bi bi-chat-dots-fill"></i>
</button>
</div>
<!-- Bootstrap JS + Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
(function() {
'use strict';
// ---------- ÉLÉMENTS DOM ----------
const chatWindow = document.getElementById('chatWindow');
const toggleBtn = document.getElementById('toggleChatBtn');
const closeBtn = document.getElementById('closeChatBtn');
const chatBody = document.getElementById('chatBody');
const chatInput = document.getElementById('chatInput');
const sendBtn = document.getElementById('sendMessageBtn');
// Icône du bouton toggle
const toggleIcon = toggleBtn.querySelector('i');
// ---------- FONCTIONS UTILITAIRES ----------
// Ouvre la fenêtre de chat
function openChat() {
chatWindow.classList.remove('d-none');
toggleIcon.classList.remove('bi-chat-dots-fill');
toggleIcon.classList.add('bi-x-lg');
// focus sur l'input
setTimeout(() => chatInput.focus(), 50);
}
// Ferme la fenêtre
function closeChat() {
chatWindow.classList.add('d-none');
toggleIcon.classList.remove('bi-x-lg');
toggleIcon.classList.add('bi-chat-dots-fill');
}
// Bascule ouverture/fermeture
function toggleChat() {
if (chatWindow.classList.contains('d-none')) {
openChat();
} else {
closeChat();
}
}
// Scroll automatique vers le bas
function scrollToBottom() {
chatBody.scrollTop = chatBody.scrollHeight;
}
// Crée un message utilisateur
function addUserMessage(text) {
const messageDiv = document.createElement('div');
messageDiv.className = 'message user';
messageDiv.innerHTML = `<div class="message-content">${escapeHtml(text)}</div>`;
chatBody.appendChild(messageDiv);
scrollToBottom();
}
// Crée un message bot (texte simple)
function addBotMessage(text) {
const messageDiv = document.createElement('div');
messageDiv.className = 'message bot';
messageDiv.innerHTML = `<div class="message-content">${escapeHtml(text)}</div>`;
chatBody.appendChild(messageDiv);
scrollToBottom();
}
// Ajoute l'indicateur "typing..." et retourne l'élément pour le supprimer plus tard
function addTypingIndicator() {
const typingDiv = document.createElement('div');
typingDiv.className = 'message bot';
typingDiv.id = 'typingIndicator';
typingDiv.innerHTML = `
<div class="typing-indicator">
<span class="typing-dot"></span>
<span class="typing-dot"></span>
<span class="typing-dot"></span>
</div>
`;
chatBody.appendChild(typingDiv);
scrollToBottom();
return typingDiv;
}
function removeTypingIndicator() {
const indicator = document.getElementById('typingIndicator');
if (indicator) indicator.remove();
}
// Échappement basique pour éviter injection HTML
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// ---------- SIMULATION DE RÉPONSE BOT (logique simple) ----------
function getBotResponse(userMessage) {
const msg = userMessage.toLowerCase().trim();
// Réponses prédéfinies basiques
if (msg.includes('bonjour') || msg.includes('salut') || msg.includes('hello')) {
return "Bonjour ! 😊 Comment puis-je vous aider ?";
} else if (msg.includes('prix') || msg.includes('tarif') || msg.includes('coût')) {
return "Nos tarifs varient selon les services. Le forfait de base commence à 29€/mois. Souhaitez-vous plus de détails ?";
} else if (msg.includes('horaire') || msg.includes('ouverture')) {
return "Notre équipe est disponible du lundi au vendredi, de 9h à 18h. Le support par chat est ouvert 24/7.";
} else if (msg.includes('contact') || msg.includes('téléphone') || msg.includes('email')) {
return "📞 Vous pouvez nous joindre au +33 1 23 45 67 89 ou par email à support@exemple.fr";
} else if (msg.includes('merci')) {
return "Avec plaisir ! N'hésitez pas si vous avez d'autres questions. 🌟";
} else if (msg.includes('aide') || msg.includes('help')) {
return "Je peux vous renseigner sur : tarifs, horaires, contact, ou assistance technique. Dites-moi ce dont vous avez besoin.";
} else if (msg.includes('tech') || msg.includes('bug') || msg.includes('problème')) {
return "Je suis désolé que vous rencontriez un souci. Pouvez-vous décrire le problème plus précisément ? Je vais vous guider.";
} else {
return "Intéressant ! Je suis un chatbot de démonstration. Pour le moment, je peux répondre à des questions sur les tarifs, horaires, contact ou assistance. Dites-m'en plus 😊";
}
}
// Simulation asynchrone : réponse après un délai
function simulateBotReply(userText) {
// Afficher l'indicateur de saisie
const typingEl = addTypingIndicator();
// Délai aléatoire réaliste
const delay = Math.floor(Math.random() * 900) + 800; // 800-1700ms
setTimeout(() => {
removeTypingIndicator();
const response = getBotResponse(userText);
addBotMessage(response);
}, delay);
}
// ---------- GESTION ENVOI MESSAGE ----------
function handleSendMessage() {
const text = chatInput.value.trim();
if (text === '') return;
// Ajouter le message utilisateur
addUserMessage(text);
// Effacer l'input
chatInput.value = '';
// Simuler la réponse du bot
simulateBotReply(text);
}
// ---------- ÉVÉNEMENTS ----------
toggleBtn.addEventListener('click', toggleChat);
closeBtn.addEventListener('click', closeChat);
sendBtn.addEventListener('click', handleSendMessage);
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
handleSendMessage();
}
});
// Option : clic extérieur pour fermer ? (non, on garde simple)
// Empêche la fermeture involontaire, mais on peut ajouter échap
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && !chatWindow.classList.contains('d-none')) {
closeChat();
}
});
// Si on veut un petit "ping" de notification (badge non lu) après premier message?
// Mais non nécessaire ici. On garde la version épurée.
// Petit bonus : si l'utilisateur ouvre le chat, on scroll en bas
const observer = new MutationObserver(() => {
if (!chatWindow.classList.contains('d-none')) {
scrollToBottom();
}
});
observer.observe(chatWindow, { attributes: true, attributeFilter: ['class'] });
})();
</script>
<!-- petite note : la démo utilise Bootstrap Icons, tout est inclus -->
</body>
</html>
Ouvrir cet aperçu dans un nouvel onglet du navigateur
🔗 Ouvrir dans le navigateur