Material
Chatbot
List
Material Design
Template
Html
Integration List
Ai
Chatbot Material 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 Material 2026 23040040 | AngularForAll</title>
<!-- Material Design 3 Web Components -->
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" rel="stylesheet" />
<link rel="stylesheet" href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background: #f5f5f5;
min-height: 100vh;
margin: 0;
padding: 0;
}
/* Variables Material Design 3 */
:root {
--md-sys-color-primary: #6750A4;
--md-sys-color-on-primary: #FFFFFF;
--md-sys-color-primary-container: #EADDFF;
--md-sys-color-on-primary-container: #21005D;
--md-sys-color-surface: #FEF7FF;
--md-sys-color-surface-variant: #E7E0EC;
--md-sys-color-on-surface: #1D1B20;
--md-sys-color-on-surface-variant: #49454F;
--md-sys-color-outline: #79747E;
--md-sys-color-secondary-container: #E8DEF8;
--md-sys-color-on-secondary-container: #1D192B;
--md-elevation-2: 0px 3px 3px -2px rgba(0,0,0,0.2), 0px 3px 4px 0px rgba(0,0,0,0.14), 0px 1px 8px 0px rgba(0,0,0,0.12);
--md-elevation-3: 0px 3px 5px -1px rgba(0,0,0,0.2), 0px 6px 10px 0px rgba(0,0,0,0.14), 0px 1px 18px 0px rgba(0,0,0,0.12);
--md-elevation-4: 0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12);
}
/* Container du widget */
.chatbot-widget {
position: fixed;
bottom: 24px;
right: 24px;
z-index: 1000;
display: flex;
flex-direction: column;
align-items: flex-end;
}
/* Fenêtre de chat */
.chat-window {
width: 360px;
max-width: calc(100vw - 32px);
background: var(--md-sys-color-surface);
border-radius: 28px;
box-shadow: var(--md-elevation-3);
margin-bottom: 16px;
overflow: hidden;
display: none;
flex-direction: column;
border: 1px solid var(--md-sys-color-outline);
animation: slideIn 0.3s cubic-bezier(0.2, 0, 0, 1);
}
.chat-window.active {
display: flex;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(20px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
/* Header Material */
.chat-header {
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
padding: 16px 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.chat-header-left {
display: flex;
align-items: center;
gap: 12px;
}
.chat-avatar {
width: 40px;
height: 40px;
background: var(--md-sys-color-primary-container);
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
color: var(--md-sys-color-on-primary-container);
}
.chat-avatar .material-symbols-outlined {
font-size: 24px;
font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
.chat-title h3 {
font-size: 16px;
font-weight: 500;
margin: 0 0 2px 0;
letter-spacing: 0.15px;
}
.chat-title .status {
font-size: 12px;
opacity: 0.9;
display: flex;
align-items: center;
gap: 4px;
}
.status-dot {
width: 8px;
height: 8px;
background: #4CAF50;
border-radius: 4px;
display: inline-block;
}
.close-btn {
width: 40px;
height: 40px;
border-radius: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background 0.2s;
border: none;
background: transparent;
color: var(--md-sys-color-on-primary);
}
.close-btn:hover {
background: rgba(255, 255, 255, 0.08);
}
.close-btn .material-symbols-outlined {
font-size: 20px;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
/* Body des messages */
.chat-body {
height: 380px;
overflow-y: auto;
padding: 16px;
background: var(--md-sys-color-surface);
display: flex;
flex-direction: column;
gap: 12px;
}
.chat-body::-webkit-scrollbar {
width: 4px;
}
.chat-body::-webkit-scrollbar-track {
background: transparent;
}
.chat-body::-webkit-scrollbar-thumb {
background: var(--md-sys-color-outline);
border-radius: 4px;
}
/* Messages */
.message {
display: flex;
max-width: 85%;
animation: messageAppear 0.3s cubic-bezier(0.2, 0, 0, 1);
}
@keyframes messageAppear {
from {
opacity: 0;
transform: translateY(8px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.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.5;
letter-spacing: 0.25px;
word-break: break-word;
}
.bot .message-content {
background: var(--md-sys-color-surface-variant);
color: var(--md-sys-color-on-surface-variant);
border-bottom-left-radius: 4px;
}
.user .message-content {
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
border-bottom-right-radius: 4px;
}
/* Indicateur de frappe */
.typing-indicator {
display: flex;
gap: 4px;
padding: 12px 16px;
background: var(--md-sys-color-surface-variant);
border-radius: 20px;
border-bottom-left-radius: 4px;
width: fit-content;
}
.typing-dot {
width: 8px;
height: 8px;
background: var(--md-sys-color-on-surface-variant);
border-radius: 4px;
animation: typingBounce 1.4s infinite ease-in-out;
opacity: 0.6;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingBounce {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-6px); }
}
/* Footer avec input */
.chat-footer {
padding: 12px 16px;
background: var(--md-sys-color-surface);
border-top: 1px solid var(--md-sys-color-outline);
display: flex;
align-items: center;
gap: 12px;
}
.chat-input-wrapper {
flex: 1;
position: relative;
}
.chat-input {
width: 100%;
padding: 12px 16px;
border: 1px solid var(--md-sys-color-outline);
border-radius: 24px;
font-size: 14px;
font-family: 'Roboto', sans-serif;
background: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
outline: none;
transition: border-color 0.2s, box-shadow 0.2s;
}
.chat-input:focus {
border-color: var(--md-sys-color-primary);
box-shadow: 0 0 0 2px rgba(103, 80, 164, 0.1);
}
.chat-input::placeholder {
color: var(--md-sys-color-on-surface-variant);
opacity: 0.6;
}
.send-btn {
width: 48px;
height: 48px;
border-radius: 24px;
background: var(--md-sys-color-primary-container);
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.2, 0, 0, 1);
color: var(--md-sys-color-on-primary-container);
}
.send-btn:hover {
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
box-shadow: var(--md-elevation-2);
}
.send-btn .material-symbols-outlined {
font-size: 20px;
font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}
/* FAB - Floating Action Button */
.fab {
width: 56px;
height: 56px;
border-radius: 16px;
background: var(--md-sys-color-primary-container);
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: var(--md-elevation-3);
transition: all 0.2s cubic-bezier(0.2, 0, 0, 1);
color: var(--md-sys-color-on-primary-container);
position: relative;
}
.fab:hover {
box-shadow: var(--md-elevation-4);
background: var(--md-sys-color-primary);
color: var(--md-sys-color-on-primary);
}
.fab .material-symbols-outlined {
font-size: 24px;
font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
transition: transform 0.2s;
}
/* Badge non lu */
.unread-badge {
position: absolute;
top: -4px;
right: -4px;
background: #B3261E;
color: white;
border-radius: 12px;
padding: 2px 6px;
font-size: 11px;
font-weight: 500;
border: 2px solid var(--md-sys-color-surface);
min-width: 18px;
text-align: center;
}
/* Responsive */
@media (max-width: 480px) {
.chat-window {
width: calc(100vw - 32px);
}
.chatbot-widget {
bottom: 16px;
right: 16px;
}
}
/* Contenu démo */
.demo-content {
max-width: 800px;
margin: 60px auto;
padding: 40px 20px;
text-align: center;
}
.demo-content h1 {
font-size: 48px;
font-weight: 400;
color: var(--md-sys-color-on-surface);
margin-bottom: 16px;
}
.demo-content p {
font-size: 18px;
color: var(--md-sys-color-on-surface-variant);
margin-bottom: 40px;
}
.material-card {
background: var(--md-sys-color-surface);
border-radius: 28px;
padding: 40px;
box-shadow: var(--md-elevation-2);
border: 1px solid var(--md-sys-color-outline);
}
.material-card .material-symbols-outlined {
font-size: 64px;
color: var(--md-sys-color-primary);
font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 48;
margin-bottom: 16px;
}
</style>
</head>
<body>
<!-- Contenu de démonstration -->
<div class="demo-content">
<h1>Assistant Virtuel</h1>
<p>Cliquez sur le FAB en bas à droite pour discuter avec notre assistant</p>
<div class="material-card">
<span class="material-symbols-outlined">chat</span>
<h2 style="font-weight: 400; margin-bottom: 12px; color: var(--md-sys-color-on-surface);">Support Material Design</h2>
<p style="color: var(--md-sys-color-on-surface-variant);">Posez une question sur nos services, les tarifs ou le support.</p>
</div>
</div>
<!-- ========== WIDGET CHATBOT MATERIAL DESIGN ========== -->
<div class="chatbot-widget">
<!-- Fenêtre de chat -->
<div class="chat-window" id="chatWindow">
<!-- Header -->
<div class="chat-header">
<div class="chat-header-left">
<div class="chat-avatar">
<span class="material-symbols-outlined">smart_toy</span>
</div>
<div class="chat-title">
<h3>Assistant Material</h3>
<div class="status">
<span class="status-dot"></span>
<span>En ligne</span>
</div>
</div>
</div>
<button class="close-btn" id="closeChatBtn">
<span class="material-symbols-outlined">close</span>
</button>
</div>
<!-- Body (messages) -->
<div class="chat-body" id="chatBody">
<div class="message bot">
<div class="message-content">
👋 Bonjour ! Je suis l'assistant Material. Comment puis-je vous aider aujourd'hui ?
</div>
</div>
</div>
<!-- Footer avec input -->
<div class="chat-footer">
<div class="chat-input-wrapper">
<input type="text" class="chat-input" id="chatInput" placeholder="Votre message..." autocomplete="off">
</div>
<button class="send-btn" id="sendMessageBtn">
<span class="material-symbols-outlined">send</span>
</button>
</div>
</div>
<!-- FAB Toggle -->
<button class="fab" id="toggleChatBtn">
<span class="material-symbols-outlined" id="fabIcon">chat</span>
</button>
</div>
<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');
const fabIcon = document.getElementById('fabIcon');
// Fonctions utilitaires
function openChat() {
chatWindow.classList.add('active');
fabIcon.textContent = 'close';
setTimeout(() => chatInput.focus(), 100);
}
function closeChat() {
chatWindow.classList.remove('active');
fabIcon.textContent = 'chat';
}
function toggleChat() {
chatWindow.classList.contains('active') ? closeChat() : openChat();
}
function scrollToBottom() {
chatBody.scrollTop = chatBody.scrollHeight;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Ajouter message utilisateur
function addUserMessage(text) {
const msgDiv = document.createElement('div');
msgDiv.className = 'message user';
msgDiv.innerHTML = `<div class="message-content">${escapeHtml(text)}</div>`;
chatBody.appendChild(msgDiv);
scrollToBottom();
}
// Ajouter message bot
function addBotMessage(text) {
const msgDiv = document.createElement('div');
msgDiv.className = 'message bot';
msgDiv.innerHTML = `<div class="message-content">${escapeHtml(text)}</div>`;
chatBody.appendChild(msgDiv);
scrollToBottom();
}
// Indicateur de frappe
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 el = document.getElementById('typingIndicator');
if (el) el.remove();
}
// Logique de réponse du bot
function getBotResponse(userMsg) {
const msg = userMsg.toLowerCase().trim();
if (msg.includes('bonjour') || msg.includes('salut') || msg.includes('hello'))
return "Bonjour ! 😊 Comment puis-je vous aider aujourd'hui ?";
if (msg.includes('prix') || msg.includes('tarif') || msg.includes('coût'))
return "Nos tarifs sont compétitifs. Le forfait de base commence à 29€/mois. Souhaitez-vous plus d'informations ?";
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.";
if (msg.includes('contact') || msg.includes('téléphone') || msg.includes('email'))
return "📞 Contactez-nous au +33 1 23 45 67 89 ou par email à support@material-assistant.fr";
if (msg.includes('merci'))
return "Avec plaisir ! 🌟 N'hésitez pas si vous avez d'autres questions.";
if (msg.includes('aide') || msg.includes('help'))
return "Je peux vous aider sur : tarifs, horaires, contact, ou support technique. Que souhaitez-vous savoir ?";
if (msg.includes('tech') || msg.includes('bug') || msg.includes('problème'))
return "Je comprends votre problème technique. Pouvez-vous me donner plus de détails pour que je puisse vous aider efficacement ?";
if (msg.includes('material') || msg.includes('design'))
return "Material Design est un système de design créé par Google. Notre interface suit les principes Material 3 !";
return "Je suis là pour vous aider ! Vous pouvez me parler de tarifs, horaires, support technique ou contact. Que voulez-vous savoir ? 😊";
}
function simulateBotReply(userText) {
const typingEl = addTypingIndicator();
const delay = Math.floor(Math.random() * 900) + 800;
setTimeout(() => {
removeTypingIndicator();
addBotMessage(getBotResponse(userText));
}, delay);
}
function handleSendMessage() {
const text = chatInput.value.trim();
if (!text) return;
addUserMessage(text);
chatInput.value = '';
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();
}
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && chatWindow.classList.contains('active')) {
closeChat();
}
});
// Ripple effect Material Design sur les boutons
function createRipple(event) {
const button = event.currentTarget;
const ripple = document.createElement('span');
const diameter = Math.max(button.clientWidth, button.clientHeight);
const radius = diameter / 2;
ripple.style.width = ripple.style.height = `${diameter}px`;
ripple.style.left = `${event.clientX - button.offsetLeft - radius}px`;
ripple.style.top = `${event.clientY - button.offsetTop - radius}px`;
ripple.classList.add('ripple');
const existingRipple = button.querySelector('.ripple');
if (existingRipple) existingRipple.remove();
button.appendChild(ripple);
}
// Style pour l'effet ripple
const style = document.createElement('style');
style.textContent = `
.fab, .close-btn, .send-btn {
position: relative;
overflow: hidden;
}
.ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.3);
transform: scale(0);
animation: ripple-animation 0.6s ease-out;
pointer-events: none;
}
@keyframes ripple-animation {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(style);
// Ajouter l'effet ripple
[toggleBtn, closeBtn, sendBtn].forEach(btn => {
btn.addEventListener('click', createRipple);
});
})();
</script>
</body>
</html>
Ouvrir cet aperçu dans un nouvel onglet du navigateur
🔗 Ouvrir dans le navigateur