Componente FAQ Acordeón
Un componente FAQ estilo acordeón clásico con animaciones suaves y secciones expandibles
Diseño Responsivo
Sí
Soporte para Modo Oscuro
No
líneas
—
Compatibilidad del Navegador
No
Componente FAQ Acordeón
Un componente FAQ estilo acordeón clásico con animaciones suaves, secciones expandibles y una interfaz de usuario intuitiva para mostrar preguntas frecuentes.
Características
- Animaciones Suaves: Transiciones CSS para abrir/cerrar secciones
- Expansión Simple/Múltiple: Opción para permitir una o múltiples secciones abiertas
- Navegación por Teclado: Soporte completo de accesibilidad por teclado
- Funcionalidad de Búsqueda: Búsqueda integrada para filtrar preguntas
- Diseño Responsivo: Funciona perfectamente en todos los tamaños de dispositivo
- Indicadores de Iconos: Señales visuales para estados expandidos/colapsados
- Estilo Personalizable: Fácil de tematizar y personalizar
- Auto-desplazamiento: Se desplaza automáticamente a las secciones abiertas
Estructura HTML
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Componente FAQ Acordeón</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="faq-container">
<div class="faq-header">
<h1>Preguntas Frecuentes</h1>
<p>Encuentra respuestas a preguntas comunes sobre nuestros servicios</p>
<div class="search-container">
<input type="text" id="faqSearch" placeholder="Buscar preguntas..." class="search-input">
<svg class="search-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
</div>
<div class="faq-controls">
<button id="expandAll" class="control-btn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="6,9 12,15 18,9"></polyline>
</svg>
Expandir Todo
</button>
<button id="collapseAll" class="control-btn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<polyline points="18,15 12,9 6,15"></polyline>
</svg>
Colapsar Todo
</button>
</div>
</div>
<div class="faq-accordion" id="faqAccordion">
<div class="faq-item" data-category="general">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Cuál es su política de devoluciones?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>Ofrecemos una política de devolución de 30 días para todos los artículos no utilizados en su empaque original. Simplemente contacte a nuestro equipo de servicio al cliente para iniciar una devolución, y le proporcionaremos una etiqueta de envío prepagada.</p>
<ul>
<li>Los artículos deben estar sin usar y en condición original</li>
<li>Se requiere el empaque original</li>
<li>Reembolso procesado dentro de 5-7 días hábiles</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="envio">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Cuánto tiempo toma el envío?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>Los tiempos de envío varían dependiendo de su ubicación y el método de envío seleccionado:</p>
<div class="shipping-table">
<div class="shipping-row">
<span class="shipping-method">Envío Estándar</span>
<span class="shipping-time">5-7 días hábiles</span>
</div>
<div class="shipping-row">
<span class="shipping-method">Envío Express</span>
<span class="shipping-time">2-3 días hábiles</span>
</div>
<div class="shipping-row">
<span class="shipping-method">Envío Nocturno</span>
<span class="shipping-time">1 día hábil</span>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="pago">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Qué métodos de pago aceptan?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>Aceptamos todos los métodos de pago principales para hacer su experiencia de compra conveniente:</p>
<div class="payment-methods">
<div class="payment-item">
<strong>Tarjetas de Crédito:</strong> Visa, MasterCard, American Express, Discover
</div>
<div class="payment-item">
<strong>Billeteras Digitales:</strong> PayPal, Apple Pay, Google Pay
</div>
<div class="payment-item">
<strong>Transferencia Bancaria:</strong> Transferencias ACH y wire aceptadas
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="cuenta">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Cómo creo una cuenta?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>¡Crear una cuenta es rápido y fácil! Siga estos simples pasos:</p>
<ol>
<li>Haga clic en el botón "Registrarse" en la esquina superior derecha</li>
<li>Ingrese su dirección de correo electrónico y cree una contraseña segura</li>
<li>Verifique su dirección de correo electrónico haciendo clic en el enlace que le enviamos</li>
<li>Complete su perfil con su información de envío</li>
<li>¡Comience a comprar con su nueva cuenta!</li>
</ol>
<p><strong>Beneficios de tener una cuenta:</strong></p>
<ul>
<li>Proceso de pago más rápido</li>
<li>Historial de pedidos y seguimiento</li>
<li>Descuentos exclusivos para miembros</li>
<li>Funcionalidad de lista de deseos</li>
</ul>
</div>
</div>
</div>
<div class="faq-item" data-category="soporte">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Cómo puedo contactar al soporte al cliente?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>¡Estamos aquí para ayudar! Puede contactar a nuestro equipo de soporte al cliente a través de múltiples canales:</p>
<div class="contact-methods">
<div class="contact-item">
<div class="contact-icon">📧</div>
<div class="contact-info">
<strong>Soporte por Email</strong>
<p>soporte@ejemplo.com</p>
<span>Respuesta dentro de 24 horas</span>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">📞</div>
<div class="contact-info">
<strong>Soporte Telefónico</strong>
<p>1-800-123-4567</p>
<span>Lun-Vie 9AM-6PM EST</span>
</div>
</div>
<div class="contact-item">
<div class="contact-icon">💬</div>
<div class="contact-info">
<strong>Chat en Vivo</strong>
<p>Disponible en nuestro sitio web</p>
<span>Lun-Vie 9AM-6PM EST</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="faq-item" data-category="general">
<div class="faq-question" tabindex="0" role="button" aria-expanded="false">
<h3>¿Ofrecen envío internacional?</h3>
<div class="faq-icon">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</div>
</div>
<div class="faq-answer">
<div class="faq-content">
<p>¡Sí! Enviamos a más de 50 países en todo el mundo. Las tarifas de envío internacional y los tiempos de entrega varían según el destino.</p>
<div class="international-info">
<div class="info-section">
<h4>Costos de Envío</h4>
<p>Calculados al finalizar la compra basados en peso y destino</p>
</div>
<div class="info-section">
<h4>Tiempo de Entrega</h4>
<p>7-21 días hábiles dependiendo de la ubicación</p>
</div>
<div class="info-section">
<h4>Aduanas y Aranceles</h4>
<p>Responsabilidad del cliente, varía por país</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="no-results" id="noResults" style="display: none;">
<div class="no-results-icon">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor">
<circle cx="11" cy="11" r="8"></circle>
<path d="m21 21-4.35-4.35"></path>
</svg>
</div>
<h3>No se encontraron preguntas</h3>
<p>Intente ajustar sus términos de búsqueda o navegue todas las preguntas arriba.</p>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Estilos CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.faq-container {
max-width: 800px;
margin: 0 auto;
background: white;
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
overflow: hidden;
}.faq-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px 30px;
text-align: center;
}
.faq-header h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 8px;
}
.faq-header p {
font-size: 1.1rem;
opacity: 0.9;
margin-bottom: 30px;
}.search-container {
position: relative;
max-width: 400px;
margin: 0 auto 20px;
}
.search-input {
width: 100%;
padding: 12px 20px 12px 50px;
border: none;
border-radius: 25px;
font-size: 16px;
background: rgba(255, 255, 255, 0.2);
color: white;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.search-input::placeholder {
color: rgba(255, 255, 255, 0.7);
}
.search-input:focus {
outline: none;
background: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.2);
}
.search-icon {
position: absolute;
left: 18px;
top: 50%;
transform: translateY(-50%);
color: rgba(255, 255, 255, 0.7);
}.faq-controls {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.control-btn {
background: rgba(255, 255, 255, 0.2);
border: none;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
gap: 6px;
transition: all 0.3s ease;
backdrop-filter: blur(10px);
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
}.faq-accordion {
padding: 0;
}
.faq-item {
border-bottom: 1px solid #e2e8f0;
transition: all 0.3s ease;
}
.faq-item:last-child {
border-bottom: none;
}
.faq-item.active {
background: #f8fafc;
}
.faq-question {
padding: 24px 30px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
transition: all 0.3s ease;
outline: none;
}
.faq-question:hover {
background: #f8fafc;
}
.faq-question:focus {
background: #f1f5f9;
box-shadow: inset 0 0 0 2px #667eea;
}
.faq-question h3 {
font-size: 1.1rem;
font-weight: 600;
color: #1e293b;
margin: 0;
flex: 1;
text-align: left;
}
.faq-icon {
width: 32px;
height: 32px;
border-radius: 50%;
background: #667eea;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
flex-shrink: 0;
margin-left: 16px;
}
.faq-icon svg {
color: white;
transition: transform 0.3s ease;
}
.faq-item.active .faq-icon {
background: #4f46e5;
transform: rotate(45deg);
}
.faq-answer {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease;
}
.faq-item.active .faq-answer {
max-height: 1000px;
}
.faq-content {
padding: 0 30px 24px;
color: #64748b;
line-height: 1.6;
}
.faq-content p {
margin-bottom: 16px;
}
.faq-content ul,
.faq-content ol {
margin: 16px 0;
padding-left: 20px;
}
.faq-content li {
margin-bottom: 8px;
}.shipping-table {
background: #f8fafc;
border-radius: 8px;
padding: 16px;
margin: 16px 0;
}
.shipping-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 0;
border-bottom: 1px solid #e2e8f0;
}
.shipping-row:last-child {
border-bottom: none;
}
.shipping-method {
font-weight: 500;
color: #374151;
}
.shipping-time {
color: #667eea;
font-weight: 500;
}.payment-methods {
margin: 16px 0;
}
.payment-item {
background: #f8fafc;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 8px;
border-left: 4px solid #667eea;
}
.payment-item strong {
color: #374151;
display: block;
margin-bottom: 4px;
}.contact-methods {
margin: 20px 0;
}
.contact-item {
display: flex;
align-items: flex-start;
gap: 16px;
padding: 16px;
background: #f8fafc;
border-radius: 12px;
margin-bottom: 12px;
}
.contact-icon {
font-size: 24px;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: white;
border-radius: 50%;
flex-shrink: 0;
}
.contact-info strong {
color: #374151;
display: block;
margin-bottom: 4px;
}
.contact-info p {
margin: 0;
color: #667eea;
font-weight: 500;
}
.contact-info span {
font-size: 14px;
color: #64748b;
}.international-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
margin: 20px 0;
}
.info-section {
background: #f8fafc;
padding: 16px;
border-radius: 8px;
border-left: 4px solid #667eea;
}
.info-section h4 {
color: #374151;
margin-bottom: 8px;
font-size: 16px;
}
.info-section p {
margin: 0;
font-size: 14px;
}.no-results {
text-align: center;
padding: 60px 30px;
color: #64748b;
}
.no-results-icon {
margin-bottom: 20px;
opacity: 0.5;
}
.no-results h3 {
font-size: 1.5rem;
margin-bottom: 8px;
color: #374151;
}
.no-results p {
font-size: 1rem;
}@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.faq-item {
animation: fadeIn 0.3s ease;
}@media (max-width: 768px) {
body {
padding: 10px;
}
.faq-container {
border-radius: 12px;
}
.faq-header {
padding: 30px 20px;
}
.faq-header h1 {
font-size: 2rem;
}
.faq-question {
padding: 20px;
}
.faq-content {
padding: 0 20px 20px;
}
.faq-question h3 {
font-size: 1rem;
}
.contact-item {
flex-direction: column;
text-align: center;
}
.international-info {
grid-template-columns: 1fr;
}
}
@media (max-width: 480px) {
.faq-header h1 {
font-size: 1.75rem;
}
.faq-controls {
flex-direction: column;
align-items: center;
}
.control-btn {
width: 100%;
max-width: 200px;
justify-content: center;
}
}
Funcionalidad JavaScript
class AccordionFAQ {
constructor() {
this.accordion = document.getElementById('faqAccordion');
this.searchInput = document.getElementById('faqSearch');
this.expandAllBtn = document.getElementById('expandAll');
this.collapseAllBtn = document.getElementById('collapseAll');
this.noResults = document.getElementById('noResults');
this.faqItems = Array.from(document.querySelectorAll('.faq-item'));
this.init();
}
init() {
this.bindEvents();
this.setupKeyboardNavigation();
}
bindEvents() {
this.accordion.addEventListener('click', (e) => {
const question = e.target.closest('.faq-question');
if (question) {
this.toggleItem(question.parentElement);
}
});
this.searchInput.addEventListener('input', (e) => {
this.filterQuestions(e.target.value);
});
this.expandAllBtn.addEventListener('click', () => this.expandAll());
this.collapseAllBtn.addEventListener('click', () => this.collapseAll());
}
setupKeyboardNavigation() {
this.accordion.addEventListener('keydown', (e) => {
const question = e.target.closest('.faq-question');
if (!question) return;
switch (e.key) {
case 'Enter':
case ' ':
e.preventDefault();
this.toggleItem(question.parentElement);
break;
case 'ArrowDown':
e.preventDefault();
this.focusNext(question);
break;
case 'ArrowUp':
e.preventDefault();
this.focusPrevious(question);
break;
case 'Home':
e.preventDefault();
this.focusFirst();
break;
case 'End':
e.preventDefault();
this.focusLast();
break;
}
});
}
toggleItem(item) {
const isActive = item.classList.contains('active');
const question = item.querySelector('.faq-question');
if (isActive) {
this.closeItem(item);
} else {
this.openItem(item);
}
question.setAttribute('aria-expanded', !isActive);
if (!isActive) {
setTimeout(() => {
item.scrollIntoView({
behavior: 'smooth',
block: 'nearest'
});
}, 150);
}
}
openItem(item) {
item.classList.add('active');
const answer = item.querySelector('.faq-answer');
const content = item.querySelector('.faq-content');
answer.style.maxHeight = content.scrollHeight + 'px';
item.style.animation = 'fadeIn 0.3s ease';
}
closeItem(item) {
item.classList.remove('active');
const answer = item.querySelector('.faq-answer');
answer.style.maxHeight = '0';
}
expandAll() {
const visibleItems = this.faqItems.filter(item =>
item.style.display !== 'none'
);
visibleItems.forEach((item, index) => {
setTimeout(() => {
if (!item.classList.contains('active')) {
this.openItem(item);
const question = item.querySelector('.faq-question');
question.setAttribute('aria-expanded', 'true');
}
}, index * 100);
});
}
collapseAll() {
const activeItems = this.faqItems.filter(item =>
item.classList.contains('active')
);
activeItems.forEach((item, index) => {
setTimeout(() => {
this.closeItem(item);
const question = item.querySelector('.faq-question');
question.setAttribute('aria-expanded', 'false');
}, index * 50);
});
}
filterQuestions(searchTerm) {
const term = searchTerm.toLowerCase().trim();
let visibleCount = 0;
this.faqItems.forEach(item => {
const question = item.querySelector('h3').textContent.toLowerCase();
const answer = item.querySelector('.faq-content').textContent.toLowerCase();
const matches = question.includes(term) || answer.includes(term);
if (matches || term === '') {
item.style.display = 'block';
visibleCount++;
if (term !== '') {
this.highlightSearchTerm(item, term);
} else {
this.removeHighlights(item);
}
} else {
item.style.display = 'none';
if (item.classList.contains('active')) {
this.closeItem(item);
}
}
});
if (visibleCount === 0 && term !== '') {
this.noResults.style.display = 'block';
this.accordion.style.display = 'none';
} else {
this.noResults.style.display = 'none';
this.accordion.style.display = 'block';
}
}
highlightSearchTerm(item, term) {
const question = item.querySelector('h3');
const content = item.querySelector('.faq-content');
const highlightText = (element) => {
const text = element.textContent;
const regex = new RegExp(`(${term})`, 'gi');
const highlightedText = text.replace(regex, '<mark>$1</mark>');
if (text !== highlightedText) {
element.innerHTML = highlightedText;
}
};
highlightText(question);
}
removeHighlights(item) {
const marks = item.querySelectorAll('mark');
marks.forEach(mark => {
mark.outerHTML = mark.textContent;
});
}
focusNext(currentQuestion) {
const questions = Array.from(document.querySelectorAll('.faq-question'));
const visibleQuestions = questions.filter(q =>
q.closest('.faq-item').style.display !== 'none'
);
const currentIndex = visibleQuestions.indexOf(currentQuestion);
const nextIndex = (currentIndex + 1) % visibleQuestions.length;
visibleQuestions[nextIndex].focus();
}
focusPrevious(currentQuestion) {
const questions = Array.from(document.querySelectorAll('.faq-question'));
const visibleQuestions = questions.filter(q =>
q.closest('.faq-item').style.display !== 'none'
);
const currentIndex = visibleQuestions.indexOf(currentQuestion);
const prevIndex = currentIndex === 0 ? visibleQuestions.length - 1 : currentIndex - 1;
visibleQuestions[prevIndex].focus();
}
focusFirst() {
const firstVisible = document.querySelector('.faq-item:not([style*="display: none"]) .faq-question');
if (firstVisible) firstVisible.focus();
}
focusLast() {
const questions = Array.from(document.querySelectorAll('.faq-question'));
const visibleQuestions = questions.filter(q =>
q.closest('.faq-item').style.display !== 'none'
);
const lastVisible = visibleQuestions[visibleQuestions.length - 1];
if (lastVisible) lastVisible.focus();
}
}
document.addEventListener('DOMContentLoaded', () => {
new AccordionFAQ();
document.documentElement.style.scrollBehavior = 'smooth';
const faqItems = document.querySelectorAll('.faq-item');
faqItems.forEach((item, index) => {
item.style.opacity = '0';
item.style.transform = 'translateY(20px)';
setTimeout(() => {
item.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
item.style.opacity = '1';
item.style.transform = 'translateY(0)';
}, index * 100);
});
});
Ejemplos de Uso
Implementación Básica
const faq = new AccordionFAQ();
faq.openItem(document.querySelector('.faq-item[data-category="general"]'));
faq.filterQuestions('envío');
Configuración Personalizada
const faq = new AccordionFAQ({
allowMultiple: true, // Permitir múltiples elementos abiertos
autoClose: false, // No cerrar automáticamente otros elementos
animationDuration: 300, // Duración de animación en ms
scrollOffset: 100, // Desplazamiento al abrir elementos
highlightSearch: true // Resaltar términos de búsqueda
});
Integración con Analytics
class AnalyticsAccordionFAQ extends AccordionFAQ {
toggleItem(item) {
super.toggleItem(item);
const question = item.querySelector('h3').textContent;
const isOpening = item.classList.contains('active');
gtag('event', 'faq_interaction', {
'question': question,
'action': isOpening ? 'open' : 'close'
});
}
}
Compatibilidad del Navegador
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Características Incluidas
✅ Animaciones suaves de acordeón
✅ Funcionalidad de búsqueda con resaltado
✅ Soporte de navegación por teclado
✅ Controles expandir/colapsar todo
✅ Auto-desplazamiento a secciones abiertas
✅ Diseño responsivo
✅ Atributos de accesibilidad ARIA
✅ Opciones de estilo personalizado
✅ Sin dependencias externas
✅ Estructura amigable para SEO
✅ Interfaz táctil amigable
✅ Animaciones de carga
Opciones de Personalización
- Colores: Modificar propiedades personalizadas CSS para tematización
- Velocidad de Animación: Ajustar duraciones de transición
- Diseño: Personalizar espaciado y tipografía
- Iconos: Reemplazar iconos SVG con personalizados
- Búsqueda: Configurar comportamiento de búsqueda y resaltado
- Teclado: Personalizar atajos de teclado
Este componente FAQ acordeón proporciona una forma profesional y amigable para el usuario de mostrar preguntas frecuentes con animaciones suaves y soporte completo de accesibilidad.