Create "Apps" section in documentation and Add interactive c4a-script playground and LLM context builder for Crawl4AI
- Created a new HTML page (`index.html`) for the interactive LLM context builder, allowing users to select and combine different `crawl4ai` context files. - Implemented JavaScript functionality (`llmtxt.js`) to manage component selection, context types, and file downloads. - Added CSS styles (`llmtxt.css`) for a terminal-themed UI. - Introduced a new Markdown file (`build.md`) detailing the requirements and functionality of the context builder. - Updated the navigation in `mkdocs.yml` to include links to the new context builder and demo apps. - Added a new Markdown file (`why.md`) explaining the motivation behind the new context structure and its benefits for AI coding assistants.
This commit is contained in:
604
docs/md_v2/apps/c4a-script/playground/app.js
Normal file
604
docs/md_v2/apps/c4a-script/playground/app.js
Normal file
@@ -0,0 +1,604 @@
|
||||
// Playground App JavaScript
|
||||
class PlaygroundApp {
|
||||
constructor() {
|
||||
this.isLoggedIn = false;
|
||||
this.currentSection = 'home';
|
||||
this.productsLoaded = 0;
|
||||
this.maxProducts = 100;
|
||||
this.tableRowsLoaded = 10;
|
||||
this.inspectorMode = false;
|
||||
this.tooltip = null;
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupCookieBanner();
|
||||
this.setupNewsletterPopup();
|
||||
this.setupNavigation();
|
||||
this.setupAuth();
|
||||
this.setupProductCatalog();
|
||||
this.setupForms();
|
||||
this.setupTabs();
|
||||
this.setupDataTable();
|
||||
this.setupInspector();
|
||||
this.loadInitialData();
|
||||
}
|
||||
|
||||
// Cookie Banner
|
||||
setupCookieBanner() {
|
||||
const banner = document.getElementById('cookie-banner');
|
||||
const acceptBtn = banner.querySelector('.accept');
|
||||
const declineBtn = banner.querySelector('.decline');
|
||||
|
||||
acceptBtn.addEventListener('click', () => {
|
||||
banner.style.display = 'none';
|
||||
console.log('✅ Cookies accepted');
|
||||
});
|
||||
|
||||
declineBtn.addEventListener('click', () => {
|
||||
banner.style.display = 'none';
|
||||
console.log('❌ Cookies declined');
|
||||
});
|
||||
}
|
||||
|
||||
// Newsletter Popup
|
||||
setupNewsletterPopup() {
|
||||
const popup = document.getElementById('newsletter-popup');
|
||||
const closeBtn = popup.querySelector('.close');
|
||||
const subscribeBtn = popup.querySelector('.subscribe');
|
||||
|
||||
// Show popup after 3 seconds
|
||||
setTimeout(() => {
|
||||
popup.style.display = 'flex';
|
||||
}, 3000);
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
popup.style.display = 'none';
|
||||
});
|
||||
|
||||
subscribeBtn.addEventListener('click', () => {
|
||||
const email = popup.querySelector('input').value;
|
||||
if (email) {
|
||||
console.log(`📧 Subscribed: ${email}`);
|
||||
popup.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
// Close on outside click
|
||||
popup.addEventListener('click', (e) => {
|
||||
if (e.target === popup) {
|
||||
popup.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Navigation
|
||||
setupNavigation() {
|
||||
const navLinks = document.querySelectorAll('.nav-link');
|
||||
const sections = document.querySelectorAll('.section');
|
||||
|
||||
navLinks.forEach(link => {
|
||||
link.addEventListener('click', (e) => {
|
||||
e.preventDefault();
|
||||
const targetId = link.getAttribute('href').substring(1);
|
||||
|
||||
// Update active states
|
||||
navLinks.forEach(l => l.classList.remove('active'));
|
||||
link.classList.add('active');
|
||||
|
||||
// Show target section
|
||||
sections.forEach(s => s.classList.remove('active'));
|
||||
const targetSection = document.getElementById(targetId);
|
||||
if (targetSection) {
|
||||
targetSection.classList.add('active');
|
||||
this.currentSection = targetId;
|
||||
|
||||
// Load content for specific sections
|
||||
this.loadSectionContent(targetId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start tutorial button
|
||||
const startBtn = document.getElementById('start-tutorial');
|
||||
if (startBtn) {
|
||||
startBtn.addEventListener('click', () => {
|
||||
console.log('🚀 Tutorial started!');
|
||||
alert('Tutorial started! Check the console for progress.');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Authentication
|
||||
setupAuth() {
|
||||
const loginBtn = document.getElementById('login-btn');
|
||||
const logoutBtn = document.getElementById('logout-btn');
|
||||
const loginModal = document.getElementById('login-modal');
|
||||
const loginForm = document.getElementById('login-form');
|
||||
const closeBtn = loginModal.querySelector('.close');
|
||||
|
||||
loginBtn.addEventListener('click', () => {
|
||||
loginModal.style.display = 'flex';
|
||||
});
|
||||
|
||||
closeBtn.addEventListener('click', () => {
|
||||
loginModal.style.display = 'none';
|
||||
});
|
||||
|
||||
loginForm.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
const rememberMe = document.getElementById('remember-me').checked;
|
||||
const messageEl = document.getElementById('login-message');
|
||||
|
||||
// Simple validation
|
||||
if (email === 'demo@example.com' && password === 'demo123') {
|
||||
this.isLoggedIn = true;
|
||||
messageEl.textContent = '✅ Login successful!';
|
||||
messageEl.className = 'form-message success';
|
||||
|
||||
setTimeout(() => {
|
||||
loginModal.style.display = 'none';
|
||||
document.getElementById('login-btn').style.display = 'none';
|
||||
document.getElementById('user-info').style.display = 'flex';
|
||||
document.getElementById('username-display').textContent = 'Demo User';
|
||||
console.log(`✅ Logged in${rememberMe ? ' (remembered)' : ''}`);
|
||||
}, 1000);
|
||||
} else {
|
||||
messageEl.textContent = '❌ Invalid credentials. Try demo@example.com / demo123';
|
||||
messageEl.className = 'form-message error';
|
||||
}
|
||||
});
|
||||
|
||||
logoutBtn.addEventListener('click', () => {
|
||||
this.isLoggedIn = false;
|
||||
document.getElementById('login-btn').style.display = 'block';
|
||||
document.getElementById('user-info').style.display = 'none';
|
||||
console.log('👋 Logged out');
|
||||
});
|
||||
|
||||
// Close modal on outside click
|
||||
loginModal.addEventListener('click', (e) => {
|
||||
if (e.target === loginModal) {
|
||||
loginModal.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Product Catalog
|
||||
setupProductCatalog() {
|
||||
// View toggle
|
||||
const infiniteBtn = document.getElementById('infinite-scroll-btn');
|
||||
const paginationBtn = document.getElementById('pagination-btn');
|
||||
const infiniteView = document.getElementById('infinite-scroll-view');
|
||||
const paginationView = document.getElementById('pagination-view');
|
||||
|
||||
infiniteBtn.addEventListener('click', () => {
|
||||
infiniteBtn.classList.add('active');
|
||||
paginationBtn.classList.remove('active');
|
||||
infiniteView.style.display = 'block';
|
||||
paginationView.style.display = 'none';
|
||||
this.setupInfiniteScroll();
|
||||
});
|
||||
|
||||
paginationBtn.addEventListener('click', () => {
|
||||
paginationBtn.classList.add('active');
|
||||
infiniteBtn.classList.remove('active');
|
||||
paginationView.style.display = 'block';
|
||||
infiniteView.style.display = 'none';
|
||||
});
|
||||
|
||||
// Load more button
|
||||
const loadMoreBtn = paginationView.querySelector('.load-more');
|
||||
loadMoreBtn.addEventListener('click', () => {
|
||||
this.loadMoreProducts();
|
||||
});
|
||||
|
||||
// Collapsible filters
|
||||
const collapsibles = document.querySelectorAll('.collapsible');
|
||||
collapsibles.forEach(header => {
|
||||
header.addEventListener('click', () => {
|
||||
const content = header.nextElementSibling;
|
||||
const toggle = header.querySelector('.toggle');
|
||||
content.style.display = content.style.display === 'none' ? 'block' : 'none';
|
||||
toggle.textContent = content.style.display === 'none' ? '▶' : '▼';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setupInfiniteScroll() {
|
||||
const container = document.querySelector('.products-container');
|
||||
const loadingIndicator = document.getElementById('loading-indicator');
|
||||
|
||||
container.addEventListener('scroll', () => {
|
||||
if (container.scrollTop + container.clientHeight >= container.scrollHeight - 100) {
|
||||
if (this.productsLoaded < this.maxProducts) {
|
||||
loadingIndicator.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
this.loadMoreProducts();
|
||||
loadingIndicator.style.display = 'none';
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadMoreProducts() {
|
||||
const grid = document.getElementById('product-grid');
|
||||
const batch = 10;
|
||||
|
||||
for (let i = 0; i < batch && this.productsLoaded < this.maxProducts; i++) {
|
||||
const product = this.createProductCard(this.productsLoaded + 1);
|
||||
grid.appendChild(product);
|
||||
this.productsLoaded++;
|
||||
}
|
||||
|
||||
console.log(`📦 Loaded ${batch} more products. Total: ${this.productsLoaded}`);
|
||||
}
|
||||
|
||||
createProductCard(id) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'product-card';
|
||||
card.innerHTML = `
|
||||
<div class="product-image">📦</div>
|
||||
<div class="product-name">Product ${id}</div>
|
||||
<div class="product-price">$${(Math.random() * 100 + 10).toFixed(2)}</div>
|
||||
<button class="btn btn-sm">Quick View</button>
|
||||
`;
|
||||
|
||||
// Quick view functionality
|
||||
const quickViewBtn = card.querySelector('button');
|
||||
quickViewBtn.addEventListener('click', () => {
|
||||
alert(`Quick view for Product ${id}`);
|
||||
});
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
// Forms
|
||||
setupForms() {
|
||||
// Contact Form
|
||||
const contactForm = document.getElementById('contact-form');
|
||||
const subjectSelect = document.getElementById('contact-subject');
|
||||
const departmentGroup = document.getElementById('department-group');
|
||||
const departmentSelect = document.getElementById('department');
|
||||
|
||||
subjectSelect.addEventListener('change', () => {
|
||||
if (subjectSelect.value === 'support') {
|
||||
departmentGroup.style.display = 'block';
|
||||
departmentSelect.innerHTML = `
|
||||
<option value="">Select department</option>
|
||||
<option value="technical">Technical Support</option>
|
||||
<option value="billing">Billing Support</option>
|
||||
<option value="general">General Support</option>
|
||||
`;
|
||||
} else {
|
||||
departmentGroup.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
contactForm.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const messageDisplay = document.getElementById('contact-message-display');
|
||||
messageDisplay.textContent = '✅ Message sent successfully!';
|
||||
messageDisplay.className = 'form-message success';
|
||||
console.log('📧 Contact form submitted');
|
||||
});
|
||||
|
||||
// Multi-step Form
|
||||
const surveyForm = document.getElementById('survey-form');
|
||||
const steps = surveyForm.querySelectorAll('.form-step');
|
||||
const progressFill = document.getElementById('progress-fill');
|
||||
let currentStep = 1;
|
||||
|
||||
surveyForm.addEventListener('click', (e) => {
|
||||
if (e.target.classList.contains('next-step')) {
|
||||
if (currentStep < 3) {
|
||||
steps[currentStep - 1].style.display = 'none';
|
||||
currentStep++;
|
||||
steps[currentStep - 1].style.display = 'block';
|
||||
progressFill.style.width = `${(currentStep / 3) * 100}%`;
|
||||
}
|
||||
} else if (e.target.classList.contains('prev-step')) {
|
||||
if (currentStep > 1) {
|
||||
steps[currentStep - 1].style.display = 'none';
|
||||
currentStep--;
|
||||
steps[currentStep - 1].style.display = 'block';
|
||||
progressFill.style.width = `${(currentStep / 3) * 100}%`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
surveyForm.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
document.getElementById('survey-success').style.display = 'block';
|
||||
console.log('📋 Survey submitted successfully!');
|
||||
});
|
||||
}
|
||||
|
||||
// Tabs
|
||||
setupTabs() {
|
||||
const tabBtns = document.querySelectorAll('.tab-btn');
|
||||
const tabPanes = document.querySelectorAll('.tab-pane');
|
||||
|
||||
tabBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const targetTab = btn.getAttribute('data-tab');
|
||||
|
||||
// Update active states
|
||||
tabBtns.forEach(b => b.classList.remove('active'));
|
||||
btn.classList.add('active');
|
||||
|
||||
// Show target pane
|
||||
tabPanes.forEach(pane => {
|
||||
pane.style.display = pane.id === targetTab ? 'block' : 'none';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Show more functionality
|
||||
const showMoreBtn = document.querySelector('.show-more');
|
||||
const hiddenText = document.querySelector('.hidden-text');
|
||||
|
||||
if (showMoreBtn) {
|
||||
showMoreBtn.addEventListener('click', () => {
|
||||
if (hiddenText.style.display === 'none') {
|
||||
hiddenText.style.display = 'block';
|
||||
showMoreBtn.textContent = 'Show Less';
|
||||
} else {
|
||||
hiddenText.style.display = 'none';
|
||||
showMoreBtn.textContent = 'Show More';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Load comments
|
||||
const loadCommentsBtn = document.querySelector('.load-comments');
|
||||
const commentsSection = document.querySelector('.comments-section');
|
||||
|
||||
if (loadCommentsBtn) {
|
||||
loadCommentsBtn.addEventListener('click', () => {
|
||||
commentsSection.style.display = 'block';
|
||||
commentsSection.innerHTML = `
|
||||
<div class="comment">
|
||||
<div class="comment-author">John Doe</div>
|
||||
<div class="comment-text">Great product! Highly recommended.</div>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<div class="comment-author">Jane Smith</div>
|
||||
<div class="comment-text">Excellent quality and fast shipping.</div>
|
||||
</div>
|
||||
`;
|
||||
loadCommentsBtn.style.display = 'none';
|
||||
console.log('💬 Comments loaded');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Data Table
|
||||
setupDataTable() {
|
||||
const loadMoreBtn = document.querySelector('.load-more-rows');
|
||||
const searchInput = document.querySelector('.search-input');
|
||||
const exportBtn = document.getElementById('export-btn');
|
||||
const sortableHeaders = document.querySelectorAll('.sortable');
|
||||
|
||||
// Load more rows
|
||||
loadMoreBtn.addEventListener('click', () => {
|
||||
this.loadMoreTableRows();
|
||||
});
|
||||
|
||||
// Search functionality
|
||||
searchInput.addEventListener('input', (e) => {
|
||||
const searchTerm = e.target.value.toLowerCase();
|
||||
const rows = document.querySelectorAll('#table-body tr');
|
||||
|
||||
rows.forEach(row => {
|
||||
const text = row.textContent.toLowerCase();
|
||||
row.style.display = text.includes(searchTerm) ? '' : 'none';
|
||||
});
|
||||
});
|
||||
|
||||
// Export functionality
|
||||
exportBtn.addEventListener('click', () => {
|
||||
console.log('📊 Exporting table data...');
|
||||
alert('Table data exported! (Check console)');
|
||||
});
|
||||
|
||||
// Sorting
|
||||
sortableHeaders.forEach(header => {
|
||||
header.addEventListener('click', () => {
|
||||
console.log(`🔄 Sorting by ${header.getAttribute('data-sort')}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
loadMoreTableRows() {
|
||||
const tbody = document.getElementById('table-body');
|
||||
const batch = 10;
|
||||
|
||||
for (let i = 0; i < batch; i++) {
|
||||
const row = document.createElement('tr');
|
||||
const id = this.tableRowsLoaded + i + 1;
|
||||
row.innerHTML = `
|
||||
<td>User ${id}</td>
|
||||
<td>user${id}@example.com</td>
|
||||
<td>${new Date().toLocaleDateString()}</td>
|
||||
<td><button class="btn btn-sm">Edit</button></td>
|
||||
`;
|
||||
tbody.appendChild(row);
|
||||
}
|
||||
|
||||
this.tableRowsLoaded += batch;
|
||||
console.log(`📄 Loaded ${batch} more rows. Total: ${this.tableRowsLoaded}`);
|
||||
}
|
||||
|
||||
// Load initial data
|
||||
loadInitialData() {
|
||||
// Load initial products
|
||||
this.loadMoreProducts();
|
||||
|
||||
// Load initial table rows
|
||||
this.loadMoreTableRows();
|
||||
}
|
||||
|
||||
// Load content when navigating to sections
|
||||
loadSectionContent(sectionId) {
|
||||
switch(sectionId) {
|
||||
case 'catalog':
|
||||
// Ensure products are loaded in catalog
|
||||
if (this.productsLoaded === 0) {
|
||||
this.loadMoreProducts();
|
||||
}
|
||||
break;
|
||||
case 'data-tables':
|
||||
// Ensure table rows are loaded
|
||||
if (this.tableRowsLoaded === 0) {
|
||||
this.loadMoreTableRows();
|
||||
}
|
||||
break;
|
||||
case 'forms':
|
||||
// Forms are already set up
|
||||
break;
|
||||
case 'tabs':
|
||||
// Tabs content is static
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Inspector Mode
|
||||
setupInspector() {
|
||||
const inspectorBtn = document.getElementById('inspector-btn');
|
||||
|
||||
// Create tooltip element
|
||||
this.tooltip = document.createElement('div');
|
||||
this.tooltip.className = 'inspector-tooltip';
|
||||
this.tooltip.style.cssText = `
|
||||
position: fixed;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
color: white;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-family: monospace;
|
||||
pointer-events: none;
|
||||
z-index: 10000;
|
||||
display: none;
|
||||
max-width: 300px;
|
||||
`;
|
||||
document.body.appendChild(this.tooltip);
|
||||
|
||||
inspectorBtn.addEventListener('click', () => {
|
||||
this.toggleInspector();
|
||||
});
|
||||
|
||||
// Add mouse event listeners
|
||||
document.addEventListener('mousemove', this.handleMouseMove.bind(this));
|
||||
document.addEventListener('mouseout', this.handleMouseOut.bind(this));
|
||||
}
|
||||
|
||||
toggleInspector() {
|
||||
this.inspectorMode = !this.inspectorMode;
|
||||
const inspectorBtn = document.getElementById('inspector-btn');
|
||||
|
||||
if (this.inspectorMode) {
|
||||
inspectorBtn.classList.add('active');
|
||||
inspectorBtn.style.background = '#0fbbaa';
|
||||
document.body.style.cursor = 'crosshair';
|
||||
} else {
|
||||
inspectorBtn.classList.remove('active');
|
||||
inspectorBtn.style.background = '';
|
||||
document.body.style.cursor = '';
|
||||
this.tooltip.style.display = 'none';
|
||||
this.removeHighlight();
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseMove(e) {
|
||||
if (!this.inspectorMode) return;
|
||||
|
||||
const element = e.target;
|
||||
if (element === this.tooltip) return;
|
||||
|
||||
// Highlight element
|
||||
this.highlightElement(element);
|
||||
|
||||
// Show tooltip with element info
|
||||
const info = this.getElementInfo(element);
|
||||
this.tooltip.innerHTML = info;
|
||||
this.tooltip.style.display = 'block';
|
||||
|
||||
// Position tooltip
|
||||
const x = e.clientX + 15;
|
||||
const y = e.clientY + 15;
|
||||
|
||||
// Adjust position if tooltip would go off screen
|
||||
const rect = this.tooltip.getBoundingClientRect();
|
||||
const adjustedX = x + rect.width > window.innerWidth ? x - rect.width - 30 : x;
|
||||
const adjustedY = y + rect.height > window.innerHeight ? y - rect.height - 30 : y;
|
||||
|
||||
this.tooltip.style.left = adjustedX + 'px';
|
||||
this.tooltip.style.top = adjustedY + 'px';
|
||||
}
|
||||
|
||||
handleMouseOut(e) {
|
||||
if (!this.inspectorMode) return;
|
||||
if (e.target === document.body) {
|
||||
this.removeHighlight();
|
||||
this.tooltip.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
highlightElement(element) {
|
||||
this.removeHighlight();
|
||||
element.style.outline = '2px solid #0fbbaa';
|
||||
element.style.outlineOffset = '1px';
|
||||
element.setAttribute('data-inspector-highlighted', 'true');
|
||||
}
|
||||
|
||||
removeHighlight() {
|
||||
const highlighted = document.querySelector('[data-inspector-highlighted]');
|
||||
if (highlighted) {
|
||||
highlighted.style.outline = '';
|
||||
highlighted.style.outlineOffset = '';
|
||||
highlighted.removeAttribute('data-inspector-highlighted');
|
||||
}
|
||||
}
|
||||
|
||||
getElementInfo(element) {
|
||||
const tagName = element.tagName.toLowerCase();
|
||||
const id = element.id ? `#${element.id}` : '';
|
||||
const classes = element.className ?
|
||||
`.${element.className.split(' ').filter(c => c).join('.')}` : '';
|
||||
|
||||
let selector = tagName;
|
||||
if (id) {
|
||||
selector = id;
|
||||
} else if (classes) {
|
||||
selector = `${tagName}${classes}`;
|
||||
}
|
||||
|
||||
// Build info HTML
|
||||
let info = `<strong>${selector}</strong>`;
|
||||
|
||||
// Add additional attributes
|
||||
const attrs = [];
|
||||
if (element.name) attrs.push(`name="${element.name}"`);
|
||||
if (element.type) attrs.push(`type="${element.type}"`);
|
||||
if (element.href) attrs.push(`href="${element.href}"`);
|
||||
if (element.value && element.tagName === 'INPUT') attrs.push(`value="${element.value}"`);
|
||||
|
||||
if (attrs.length > 0) {
|
||||
info += `<br><span style="color: #888;">${attrs.join(' ')}</span>`;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize app when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
window.playgroundApp = new PlaygroundApp();
|
||||
console.log('🎮 Playground app initialized!');
|
||||
});
|
||||
328
docs/md_v2/apps/c4a-script/playground/index.html
Normal file
328
docs/md_v2/apps/c4a-script/playground/index.html
Normal file
@@ -0,0 +1,328 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>C4A-Script Playground</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Cookie Banner -->
|
||||
<div class="cookie-banner" id="cookie-banner">
|
||||
<div class="cookie-content">
|
||||
<p>🍪 We use cookies to enhance your experience. By continuing, you agree to our cookie policy.</p>
|
||||
<div class="cookie-actions">
|
||||
<button class="btn accept">Accept All</button>
|
||||
<button class="btn btn-secondary decline">Decline</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Newsletter Popup (appears after 3 seconds) -->
|
||||
<div class="modal" id="newsletter-popup" style="display: none;">
|
||||
<div class="modal-content">
|
||||
<span class="close">×</span>
|
||||
<h2>📬 Subscribe to Our Newsletter</h2>
|
||||
<p>Get the latest updates on web automation!</p>
|
||||
<input type="email" placeholder="Enter your email" class="input">
|
||||
<button class="btn subscribe">Subscribe</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Header -->
|
||||
<header class="site-header">
|
||||
<nav class="nav-menu">
|
||||
<a href="#home" class="nav-link active">Home</a>
|
||||
<a href="#catalog" class="nav-link" id="catalog-link">Products</a>
|
||||
<a href="#forms" class="nav-link">Forms</a>
|
||||
<a href="#data-tables" class="nav-link">Data Tables</a>
|
||||
<div class="dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle">More ▼</a>
|
||||
<div class="dropdown-content">
|
||||
<a href="#tabs">Tabs Demo</a>
|
||||
<a href="#accordion">FAQ</a>
|
||||
<a href="#gallery">Gallery</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="auth-section">
|
||||
<button class="btn btn-sm" id="inspector-btn" title="Toggle Inspector">🔍</button>
|
||||
<button class="btn btn-sm" id="login-btn">Login</button>
|
||||
<div class="user-info" id="user-info" style="display: none;">
|
||||
<span class="user-avatar">👤</span>
|
||||
<span class="welcome-message">Welcome, <span id="username-display">User</span>!</span>
|
||||
<button class="btn btn-sm btn-secondary" id="logout-btn">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="main-content">
|
||||
<!-- Home Section -->
|
||||
<section id="home" class="section active">
|
||||
<h1>Welcome to C4A-Script Playground</h1>
|
||||
<p>This is an interactive demo for testing C4A-Script commands. Each section contains different challenges for web automation.</p>
|
||||
|
||||
<button class="btn btn-primary" id="start-tutorial">Start Tutorial</button>
|
||||
|
||||
<div class="feature-grid">
|
||||
<div class="feature-card">
|
||||
<h3>🔐 Authentication</h3>
|
||||
<p>Test login forms and user sessions</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>📜 Dynamic Content</h3>
|
||||
<p>Infinite scroll and pagination</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>📝 Forms</h3>
|
||||
<p>Complex form interactions</p>
|
||||
</div>
|
||||
<div class="feature-card">
|
||||
<h3>📊 Data Tables</h3>
|
||||
<p>Sortable and filterable data</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Login Modal -->
|
||||
<div class="modal" id="login-modal" style="display: none;">
|
||||
<div class="modal-content login-form">
|
||||
<span class="close">×</span>
|
||||
<h2>Login</h2>
|
||||
<form id="login-form">
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input type="email" id="email" class="input" placeholder="demo@example.com">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password</label>
|
||||
<input type="password" id="password" class="input" placeholder="demo123">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="remember-me">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Login</button>
|
||||
<div class="form-message" id="login-message"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Catalog Section -->
|
||||
<section id="catalog" class="section">
|
||||
<h1>Product Catalog</h1>
|
||||
|
||||
<div class="view-toggle">
|
||||
<button class="btn btn-sm active" id="infinite-scroll-btn">Infinite Scroll</button>
|
||||
<button class="btn btn-sm" id="pagination-btn">Pagination</button>
|
||||
</div>
|
||||
|
||||
<!-- Filters Sidebar -->
|
||||
<div class="catalog-layout">
|
||||
<aside class="filters-sidebar">
|
||||
<h3>Filters</h3>
|
||||
<div class="filter-group">
|
||||
<h4 class="collapsible">Category <span class="toggle">▼</span></h4>
|
||||
<div class="filter-content">
|
||||
<label><input type="checkbox"> Electronics</label>
|
||||
<label><input type="checkbox"> Clothing</label>
|
||||
<label><input type="checkbox"> Books</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<h4 class="collapsible">Price Range <span class="toggle">▼</span></h4>
|
||||
<div class="filter-content">
|
||||
<input type="range" min="0" max="1000" value="500">
|
||||
<span>$0 - $500</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Products Grid -->
|
||||
<div class="products-container">
|
||||
<div class="product-grid" id="product-grid">
|
||||
<!-- Products will be loaded here -->
|
||||
</div>
|
||||
|
||||
<!-- Infinite Scroll View -->
|
||||
<div id="infinite-scroll-view" class="view-mode">
|
||||
<div class="loading-indicator" id="loading-indicator" style="display: none;">
|
||||
<div class="spinner"></div>
|
||||
<p>Loading more products...</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination View -->
|
||||
<div id="pagination-view" class="view-mode" style="display: none;">
|
||||
<button class="btn load-more">Load More</button>
|
||||
<div class="pagination">
|
||||
<button class="page-btn">1</button>
|
||||
<button class="page-btn">2</button>
|
||||
<button class="page-btn">3</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Forms Section -->
|
||||
<section id="forms" class="section">
|
||||
<h1>Form Examples</h1>
|
||||
|
||||
<!-- Contact Form -->
|
||||
<div class="form-card">
|
||||
<h2>Contact Form</h2>
|
||||
<form id="contact-form">
|
||||
<div class="form-group">
|
||||
<label>Name</label>
|
||||
<input type="text" class="input" id="contact-name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input type="email" class="input" id="contact-email">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Subject</label>
|
||||
<select class="input" id="contact-subject">
|
||||
<option value="">Select a subject</option>
|
||||
<option value="support">Support</option>
|
||||
<option value="sales">Sales</option>
|
||||
<option value="feedback">Feedback</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="department-group" style="display: none;">
|
||||
<label>Department</label>
|
||||
<select class="input" id="department">
|
||||
<option value="">Select department</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Message</label>
|
||||
<textarea class="input" id="contact-message" rows="4"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Send Message</button>
|
||||
<div class="form-message" id="contact-message-display"></div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Multi-step Form -->
|
||||
<div class="form-card">
|
||||
<h2>Multi-step Survey</h2>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" id="progress-fill" style="width: 33%"></div>
|
||||
</div>
|
||||
<form id="survey-form">
|
||||
<!-- Step 1 -->
|
||||
<div class="form-step active" data-step="1">
|
||||
<h3>Step 1: Basic Information</h3>
|
||||
<div class="form-group">
|
||||
<label>Full Name</label>
|
||||
<input type="text" class="input" id="full-name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Email</label>
|
||||
<input type="email" class="input" id="survey-email">
|
||||
</div>
|
||||
<button type="button" class="btn next-step">Next</button>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="form-step" data-step="2" style="display: none;">
|
||||
<h3>Step 2: Preferences</h3>
|
||||
<div class="form-group">
|
||||
<label>Interests (select multiple)</label>
|
||||
<select multiple class="input" id="interests">
|
||||
<option value="tech">Technology</option>
|
||||
<option value="sports">Sports</option>
|
||||
<option value="music">Music</option>
|
||||
<option value="travel">Travel</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn prev-step">Previous</button>
|
||||
<button type="button" class="btn next-step">Next</button>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="form-step" data-step="3" style="display: none;">
|
||||
<h3>Step 3: Confirmation</h3>
|
||||
<p>Please review your information and submit.</p>
|
||||
<button type="button" class="btn prev-step">Previous</button>
|
||||
<button type="submit" class="btn btn-primary" id="submit-survey">Submit Survey</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="form-message success-message" id="survey-success" style="display: none;">
|
||||
✅ Survey submitted successfully!
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Tabs Section -->
|
||||
<section id="tabs" class="section">
|
||||
<h1>Tabs Demo</h1>
|
||||
<div class="tabs-container">
|
||||
<div class="tabs-header">
|
||||
<button class="tab-btn active" data-tab="description">Description</button>
|
||||
<button class="tab-btn" data-tab="reviews">Reviews</button>
|
||||
<button class="tab-btn" data-tab="specs">Specifications</button>
|
||||
</div>
|
||||
<div class="tabs-content">
|
||||
<div class="tab-pane active" id="description">
|
||||
<h3>Product Description</h3>
|
||||
<p>This is a detailed description of the product...</p>
|
||||
<div class="expandable-text">
|
||||
<p class="text-preview">Lorem ipsum dolor sit amet, consectetur adipiscing elit...</p>
|
||||
<button class="btn btn-sm show-more">Show More</button>
|
||||
<div class="hidden-text" style="display: none;">
|
||||
<p>This is the hidden text that appears when you click "Show More". It contains additional details about the product that weren't visible initially.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="reviews" style="display: none;">
|
||||
<h3>Customer Reviews</h3>
|
||||
<button class="btn btn-sm load-comments">Load Comments</button>
|
||||
<div class="comments-section" style="display: none;">
|
||||
<!-- Comments will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="specs" style="display: none;">
|
||||
<h3>Technical Specifications</h3>
|
||||
<table class="specs-table">
|
||||
<tr><td>Model</td><td>XYZ-2000</td></tr>
|
||||
<tr><td>Weight</td><td>2.5 kg</td></tr>
|
||||
<tr><td>Dimensions</td><td>30 x 20 x 10 cm</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Data Tables Section -->
|
||||
<section id="data-tables" class="section">
|
||||
<h1>Data Tables</h1>
|
||||
<div class="table-controls">
|
||||
<input type="text" class="input search-input" placeholder="Search...">
|
||||
<button class="btn btn-sm" id="export-btn">Export</button>
|
||||
</div>
|
||||
<table class="data-table" id="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sortable" data-sort="name">Name ↕</th>
|
||||
<th class="sortable" data-sort="email">Email ↕</th>
|
||||
<th class="sortable" data-sort="date">Date ↕</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="table-body">
|
||||
<!-- Table rows will be loaded here -->
|
||||
</tbody>
|
||||
</table>
|
||||
<button class="btn load-more-rows">Load More Rows</button>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
627
docs/md_v2/apps/c4a-script/playground/styles.css
Normal file
627
docs/md_v2/apps/c4a-script/playground/styles.css
Normal file
@@ -0,0 +1,627 @@
|
||||
/* Playground Styles - Modern Web App Theme */
|
||||
:root {
|
||||
--primary-color: #0fbbaa;
|
||||
--secondary-color: #3f3f44;
|
||||
--background-color: #ffffff;
|
||||
--text-color: #333333;
|
||||
--border-color: #e0e0e0;
|
||||
--error-color: #ff3c74;
|
||||
--success-color: #0fbbaa;
|
||||
--warning-color: #ffa500;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-color);
|
||||
background-color: var(--background-color);
|
||||
}
|
||||
|
||||
/* Cookie Banner */
|
||||
.cookie-banner {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #2c3e50;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.cookie-content {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.cookie-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.site-header {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: 1rem 2rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
text-decoration: none;
|
||||
color: var(--text-color);
|
||||
font-weight: 500;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.nav-link:hover,
|
||||
.nav-link.active {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Dropdown */
|
||||
.dropdown {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
min-width: 160px;
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
|
||||
z-index: 1;
|
||||
border-radius: 4px;
|
||||
top: 100%;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.dropdown:hover .dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-content a {
|
||||
color: var(--text-color);
|
||||
padding: 0.75rem 1rem;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-content a:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
/* Auth Section */
|
||||
.auth-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.main-content {
|
||||
padding: 2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.section.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #0aa599;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 0.25rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Feature Grid */
|
||||
.feature-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: #f8f9fa;
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Modal */
|
||||
.modal {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0,0,0,0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: white;
|
||||
padding: 2rem;
|
||||
border-radius: 8px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
position: relative;
|
||||
animation: modalFadeIn 0.3s;
|
||||
}
|
||||
|
||||
@keyframes modalFadeIn {
|
||||
from { opacity: 0; transform: translateY(-20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 1rem;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Forms */
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.input {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.form-message {
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem;
|
||||
border-radius: 4px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-message.error {
|
||||
background-color: #ffe6e6;
|
||||
color: var(--error-color);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.form-message.success {
|
||||
background-color: #e6fff6;
|
||||
color: var(--success-color);
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Product Catalog */
|
||||
.view-toggle {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.catalog-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 250px 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.filters-sidebar {
|
||||
background-color: #f8f9fa;
|
||||
padding: 1rem;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.filter-group {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.collapsible {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.filter-content {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.filter-content label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Product Grid */
|
||||
.product-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.product-card {
|
||||
background-color: white;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
color: var(--primary-color);
|
||||
font-size: 1.2rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Loading Indicator */
|
||||
.loading-indicator {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 3px solid #f3f3f3;
|
||||
border-top: 3px solid var(--primary-color);
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.pagination {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
justify-content: center;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.page-btn {
|
||||
padding: 0.5rem 1rem;
|
||||
border: 1px solid var(--border-color);
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.page-btn:hover,
|
||||
.page-btn.active {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Multi-step Form */
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
background-color: #e0e0e0;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.progress-fill {
|
||||
height: 100%;
|
||||
background-color: var(--primary-color);
|
||||
border-radius: 4px;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
.form-step {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.form-step.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Tabs */
|
||||
.tabs-container {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.tabs-header {
|
||||
display: flex;
|
||||
border-bottom: 2px solid var(--border-color);
|
||||
}
|
||||
|
||||
.tab-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 1rem 2rem;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-color);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tab-btn:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tab-btn.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 2px;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tabs-content {
|
||||
padding: 2rem 0;
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-pane.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Expandable Text */
|
||||
.expandable-text {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.text-preview {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.show-more {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
/* Comments Section */
|
||||
.comments-section {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.comment {
|
||||
background-color: #f8f9fa;
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.comment-author {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Data Table */
|
||||
.table-controls {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.data-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.data-table th,
|
||||
.data-table td {
|
||||
padding: 0.75rem;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.data-table th {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sortable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sortable:hover {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* Form Cards */
|
||||
.form-card {
|
||||
background-color: white;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
padding: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.form-card h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Success Message */
|
||||
.success-message {
|
||||
background-color: #e6fff6;
|
||||
color: var(--success-color);
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Load More Button */
|
||||
.load-more,
|
||||
.load-more-rows {
|
||||
display: block;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {
|
||||
.catalog-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.feature-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.cookie-content {
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inspector Mode */
|
||||
#inspector-btn.active {
|
||||
background: var(--primary-color) !important;
|
||||
color: var(--bg-primary) !important;
|
||||
}
|
||||
|
||||
.inspector-tooltip {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
Reference in New Issue
Block a user