trying to port web app starter from PHP
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$title = $prop['title'] ?? 'Trusted by Leading Companies';
|
||||
$logos = $prop['logos'] ?? [
|
||||
['name' => 'TechCorp', 'url' => 'img/cat01.jpg'],
|
||||
['name' => 'StartupX', 'url' => 'img/cat01.jpg'],
|
||||
['name' => 'DevStudio', 'url' => 'img/cat01.jpg'],
|
||||
['name' => 'WebFlow', 'url' => 'img/cat01.jpg'],
|
||||
['name' => 'CodeLab', 'url' => 'img/cat01.jpg'],
|
||||
['name' => 'AppCraft', 'url' => 'img/cat01.jpg']
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="brands-section">
|
||||
<div class="brands-container">
|
||||
<h3 class="brands-title"><?= safe($title) ?></h3>
|
||||
<div class="brands-grid">
|
||||
<?php foreach($logos as $index => $logo): ?>
|
||||
<div class="brand-item" style="animation-delay: <?= $index * 0.1 ?>s">
|
||||
<img src="<?= safe($logo['url']) ?>" alt="<?= safe($logo['name']) ?>" />
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.brands-section {
|
||||
padding: 3rem 0;
|
||||
background: var(--surface);
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.brands-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.brands-title {
|
||||
font-size: 1.125rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 2rem;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.brands-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||
gap: 2rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.brand-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 1rem;
|
||||
border-radius: var(--radius);
|
||||
transition: all 0.3s ease;
|
||||
animation: fadeInScale 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.brand-item:hover {
|
||||
transform: scale(1.05);
|
||||
background: var(--surface-hover);
|
||||
}
|
||||
|
||||
.brand-item img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.3s ease;
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
.brand-item:hover img {
|
||||
opacity: 1;
|
||||
filter: grayscale(0%);
|
||||
}
|
||||
|
||||
@keyframes fadeInScale {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.brands-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.brands-section {
|
||||
padding: 2rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
},
|
||||
|
||||
'about' => 'A brand/logo showcase section with hover effects and animations'
|
||||
]; ?>
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$title = $prop['title'] ?? 'Ready to Get Started?';
|
||||
$subtitle = $prop['subtitle'] ?? 'Join thousands of developers building amazing applications with our framework.';
|
||||
$cta_text = $prop['cta_text'] ?? 'Start Building Now';
|
||||
$cta_link = $prop['cta_link'] ?? '#';
|
||||
$secondary_text = $prop['secondary_text'] ?? 'View Documentation';
|
||||
$secondary_link = $prop['secondary_link'] ?? '#';
|
||||
|
||||
?>
|
||||
<div class="cta-section">
|
||||
<div class="cta-container">
|
||||
<div class="cta-content">
|
||||
<h2 class="cta-title"><?= safe($title) ?></h2>
|
||||
<p class="cta-subtitle"><?= safe($subtitle) ?></p>
|
||||
<div class="cta-actions">
|
||||
<a href="<?= safe($cta_link) ?>" class="btn btn-large cta-primary"><?= safe($cta_text) ?></a>
|
||||
<a href="<?= safe($secondary_link) ?>" class="btn btn-outline btn-large cta-secondary"><?= safe($secondary_text) ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cta-visual">
|
||||
<div class="floating-shapes">
|
||||
<div class="shape shape-1"></div>
|
||||
<div class="shape shape-2"></div>
|
||||
<div class="shape shape-3"></div>
|
||||
<div class="shape shape-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.cta-section {
|
||||
background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
|
||||
color: white;
|
||||
padding: 5rem 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cta-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="hexagons" width="28" height="24" patternUnits="userSpaceOnUse"><polygon points="14,2 26,8 26,20 14,26 2,20 2,8" fill="none" stroke="white" stroke-width="0.5" opacity="0.1"/></pattern></defs><rect width="100%" height="100%" fill="url(%23hexagons)"/></svg>');
|
||||
}
|
||||
|
||||
.cta-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.cta-content {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 3rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.cta-subtitle {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 2.5rem;
|
||||
opacity: 0.9;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.cta-actions {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cta-primary {
|
||||
background: white;
|
||||
color: var(--primary);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.cta-primary:hover {
|
||||
background: transparent;
|
||||
color: white;
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
.cta-secondary {
|
||||
border-color: rgba(255, 255, 255, 0.5);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.cta-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
.cta-visual {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.floating-shapes {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.shape {
|
||||
position: absolute;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(5px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
.shape-1 {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 20px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
animation: float 6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.shape-2 {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
top: 20px;
|
||||
right: 0;
|
||||
animation: float 8s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
.shape-3 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border-radius: 20px;
|
||||
bottom: 40px;
|
||||
left: 20px;
|
||||
animation: float 7s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.shape-4 {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 10px;
|
||||
bottom: 0;
|
||||
right: 30px;
|
||||
animation: float 5s ease-in-out infinite reverse;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% {
|
||||
transform: translateY(0px) rotate(0deg);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-15px) rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 968px) {
|
||||
.cta-container {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.cta-content {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.cta-visual {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.floating-shapes {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.cta-section {
|
||||
padding: 3rem 0;
|
||||
}
|
||||
|
||||
.cta-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.cta-subtitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.cta-actions {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
},
|
||||
|
||||
'about' => 'A compelling call-to-action section with animated floating shapes and gradient background'
|
||||
]; ?>
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$features = $prop['features'] ?? [
|
||||
[
|
||||
'icon' => '⚡',
|
||||
'title' => 'Lightning Fast',
|
||||
'description' => 'Optimized for speed and performance with modern web technologies.'
|
||||
],
|
||||
[
|
||||
'icon' => '🎨',
|
||||
'title' => 'Beautiful Design',
|
||||
'description' => 'Carefully crafted components with attention to detail and user experience.'
|
||||
],
|
||||
[
|
||||
'icon' => '📱',
|
||||
'title' => 'Mobile First',
|
||||
'description' => 'Fully responsive design that works perfectly on all devices.'
|
||||
],
|
||||
[
|
||||
'icon' => '🔧',
|
||||
'title' => 'Easy to Use',
|
||||
'description' => 'Simple and intuitive component system for rapid development.'
|
||||
],
|
||||
[
|
||||
'icon' => '🛡️',
|
||||
'title' => 'Secure',
|
||||
'description' => 'Built with security best practices and modern PHP standards.'
|
||||
],
|
||||
[
|
||||
'icon' => '🚀',
|
||||
'title' => 'Scalable',
|
||||
'description' => 'Architecture designed to grow with your application needs.'
|
||||
]
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="features-section" id="features">
|
||||
<div class="features-header">
|
||||
<h2>Why Choose Our Framework?</h2>
|
||||
<p>Discover the powerful features that make development a breeze</p>
|
||||
</div>
|
||||
<div class="features-grid">
|
||||
<?php foreach($features as $index => $feature): ?>
|
||||
<div class="feature-card" style="animation-delay: <?= $index * 0.1 ?>s">
|
||||
<div class="feature-icon">
|
||||
<?= $feature['icon'] ?>
|
||||
</div>
|
||||
<h3 class="feature-title"><?= safe($feature['title']) ?></h3>
|
||||
<p class="feature-description"><?= safe($feature['description']) ?></p>
|
||||
<div class="feature-overlay"></div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.features-section {
|
||||
padding: 4rem 0;
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
.features-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.features-header h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.features-header p {
|
||||
font-size: 1.25rem;
|
||||
color: var(--text-secondary);
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background: var(--surface);
|
||||
padding: 2.5rem 2rem;
|
||||
border-radius: var(--radius-xl);
|
||||
text-align: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border: 1px solid var(--border);
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation: fadeInUp 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-xl);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.feature-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover::before {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 1.5rem;
|
||||
display: inline-block;
|
||||
padding: 1rem;
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
border-radius: 50%;
|
||||
color: white;
|
||||
box-shadow: var(--shadow-lg);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover .feature-icon {
|
||||
transform: scale(1.1) rotate(5deg);
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.feature-description {
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.feature-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover .feature-overlay {
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.features-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
padding: 0 0.5rem;
|
||||
}
|
||||
|
||||
.features-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 2.5rem;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
},
|
||||
|
||||
'about' => 'A modern features grid with hover animations and gradient effects'
|
||||
]; ?>
|
||||
@@ -0,0 +1,264 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$title = $prop['title'] ?? 'Welcome to the Present';
|
||||
$subtitle = $prop['subtitle'] ?? 'Experience no-quite-modern web development with our cutting-edge framework';
|
||||
$cta_text = $prop['cta_text'] ?? 'Get Started';
|
||||
$cta_link = $prop['cta_link'] ?? '#';
|
||||
|
||||
?>
|
||||
<div class="hero-section">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title"><?= safe($title) ?></h1>
|
||||
<p class="hero-subtitle"><?= safe($subtitle) ?></p>
|
||||
<div class="hero-actions">
|
||||
<a href="<?= safe($cta_link) ?>" class="btn btn-large hero-cta"><?= safe($cta_text) ?></a>
|
||||
<a href="#features" class="btn btn-outline btn-large">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-visual">
|
||||
<div class="floating-card">
|
||||
<div class="card-header"></div>
|
||||
<div class="card-content">
|
||||
<div class="line"></div>
|
||||
<div class="line short"></div>
|
||||
<div class="line"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="floating-elements">
|
||||
<div class="element element-1"></div>
|
||||
<div class="element element-2"></div>
|
||||
<div class="element element-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.hero-section {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 4rem;
|
||||
align-items: center;
|
||||
min-height: 70vh;
|
||||
padding: 4rem 2rem;
|
||||
background: var(--bg-gradient);
|
||||
color: var(--text-primary);
|
||||
border-radius: var(--radius-xl);
|
||||
margin-bottom: 4rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hero-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="white" opacity="0.1"/><circle cx="75" cy="75" r="1" fill="white" opacity="0.1"/><circle cx="50" cy="10" r="0.5" fill="white" opacity="0.1"/><circle cx="10" cy="90" r="0.5" fill="white" opacity="0.1"/></pattern></defs><rect width="100%" height="100%" fill="url(%23grain)"/></svg>');
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 3.5rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 1.5rem;
|
||||
line-height: 1.1;
|
||||
background: none;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.hero-title::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 2rem;
|
||||
opacity: 0.9;
|
||||
line-height: 1.6;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hero-cta {
|
||||
background: var(--surface);
|
||||
color: var(--primary);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.hero-cta:hover {
|
||||
background: var(--surface-hover);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.hero-visual {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.floating-card {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
width: 280px;
|
||||
animation: float 6s ease-in-out infinite;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card-header {
|
||||
height: 60px;
|
||||
background: linear-gradient(90deg, rgba(255,255,255,0.3), rgba(255,255,255,0.1));
|
||||
border-radius: 8px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.card-content .line {
|
||||
height: 12px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.card-content .line.short {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.floating-elements {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.element {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.element-1 {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
top: 20%;
|
||||
left: 10%;
|
||||
animation: float 4s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.element-2 {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
top: 60%;
|
||||
right: 15%;
|
||||
animation: float 5s ease-in-out infinite reverse;
|
||||
}
|
||||
|
||||
.element-3 {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
bottom: 20%;
|
||||
left: 20%;
|
||||
animation: float 7s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0%, 100% { transform: translateY(0px) rotate(0deg); }
|
||||
50% { transform: translateY(-20px) rotate(10deg); }
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.hero-section {
|
||||
grid-template-columns: 1fr;
|
||||
text-align: center;
|
||||
padding: 3rem 1rem;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.hero-title {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.hero-subtitle {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.hero-visual {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.floating-card {
|
||||
width: 240px;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$.ready(() => {
|
||||
const heroTitle = document.querySelector('.hero-title');
|
||||
if (heroTitle) {
|
||||
const text = heroTitle.textContent;
|
||||
heroTitle.textContent = '';
|
||||
|
||||
let i = 0;
|
||||
const typeWriter = () => {
|
||||
if (i < text.length) {
|
||||
heroTitle.textContent += text.charAt(i);
|
||||
i++;
|
||||
setTimeout(typeWriter, 50);
|
||||
}
|
||||
};
|
||||
|
||||
// Start typing animation after a short delay
|
||||
setTimeout(typeWriter, 500);
|
||||
}
|
||||
const heroSection = document.querySelector('.hero-section');
|
||||
if (heroSection) {
|
||||
createFloatingParticles(heroSection);
|
||||
}
|
||||
function createFloatingParticles(container) {
|
||||
const particleCount = 20;
|
||||
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
const particle = document.createElement('div');
|
||||
particle.className = 'particle';
|
||||
|
||||
Object.assign(particle.style, {
|
||||
position: 'absolute',
|
||||
width: Math.random() * 4 + 1 + 'px',
|
||||
height: Math.random() * 4 + 1 + 'px',
|
||||
background: 'rgba(255, 255, 255, 0.3)',
|
||||
borderRadius: '50%',
|
||||
left: Math.random() * 100 + '%',
|
||||
top: Math.random() * 100 + '%',
|
||||
animation: `float ${Math.random() * 3 + 2}s ease-in-out infinite`,
|
||||
animationDelay: Math.random() * 2 + 's'
|
||||
});
|
||||
|
||||
container.appendChild(particle);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
|
||||
},
|
||||
|
||||
'about' => 'A modern hero section with animated floating elements and gradient background'
|
||||
]; ?>
|
||||
@@ -0,0 +1,310 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$plans = $prop['plans'] ?? [
|
||||
[
|
||||
'name' => 'Starter',
|
||||
'price' => 'Free',
|
||||
'period' => '',
|
||||
'description' => 'Perfect for small projects and learning',
|
||||
'features' => [
|
||||
'Up to 3 projects',
|
||||
'Community support',
|
||||
'Core components',
|
||||
'Basic documentation'
|
||||
],
|
||||
'cta' => 'Get Started',
|
||||
'popular' => false
|
||||
],
|
||||
[
|
||||
'name' => 'Professional',
|
||||
'price' => '$29',
|
||||
'period' => '/month',
|
||||
'description' => 'Ideal for growing businesses and teams',
|
||||
'features' => [
|
||||
'Unlimited projects',
|
||||
'Advanced components',
|
||||
'Priority support',
|
||||
'Team collaboration',
|
||||
'Custom themes',
|
||||
'Analytics dashboard'
|
||||
],
|
||||
'cta' => 'Start Free Trial',
|
||||
'popular' => true
|
||||
],
|
||||
[
|
||||
'name' => 'Enterprise',
|
||||
'price' => '$99',
|
||||
'period' => '/month',
|
||||
'description' => 'For large organizations with advanced needs',
|
||||
'features' => [
|
||||
'Everything in Professional',
|
||||
'Custom integrations',
|
||||
'Dedicated support',
|
||||
'SLA guarantee',
|
||||
'Advanced security',
|
||||
'White-label options'
|
||||
],
|
||||
'cta' => 'Contact Sales',
|
||||
'popular' => false
|
||||
]
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="pricing-section">
|
||||
<div class="pricing-container">
|
||||
<div class="pricing-header">
|
||||
<h2>Choose Your Plan</h2>
|
||||
<p>Start building great applications today with our flexible pricing options</p>
|
||||
</div>
|
||||
<div class="pricing-grid">
|
||||
<?php foreach($plans as $index => $plan): ?>
|
||||
<div class="pricing-card <?= $plan['popular'] ? 'popular' : '' ?>" style="animation-delay: <?= $index * 0.2 ?>s">
|
||||
<?php if($plan['popular']): ?>
|
||||
<div class="popular-badge">Most Popular</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="plan-header">
|
||||
<h3 class="plan-name"><?= safe($plan['name']) ?></h3>
|
||||
<div class="plan-price">
|
||||
<span class="price"><?= safe($plan['price']) ?></span>
|
||||
<?php if($plan['period']): ?>
|
||||
<span class="period"><?= safe($plan['period']) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<p class="plan-description"><?= safe($plan['description']) ?></p>
|
||||
</div>
|
||||
|
||||
<div class="plan-features">
|
||||
<ul>
|
||||
<?php foreach($plan['features'] as $feature): ?>
|
||||
<li>
|
||||
<span class="check-icon">✓</span>
|
||||
<?= safe($feature) ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="plan-footer">
|
||||
<button class="btn <?= $plan['popular'] ? 'btn-primary' : 'btn-outline' ?> btn-large plan-cta">
|
||||
<?= safe($plan['cta']) ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="pricing-footer">
|
||||
<p>All plans include a 30-day money-back guarantee. No setup fees.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.pricing-section {
|
||||
padding: 5rem 0;
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
.pricing-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.pricing-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.pricing-header h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.pricing-header p {
|
||||
font-size: 1.25rem;
|
||||
color: var(--text-secondary);
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.pricing-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.pricing-card {
|
||||
background: var(--surface);
|
||||
border: 2px solid var(--border);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: 2.5rem 2rem;
|
||||
position: relative;
|
||||
transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation: fadeInUp 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
.pricing-card:hover {
|
||||
transform: translateY(-8px) scale(1.02);
|
||||
box-shadow: var(--shadow-xl);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.pricing-card.popular {
|
||||
border-color: var(--primary);
|
||||
box-shadow: var(--shadow-lg);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.pricing-card.popular:hover {
|
||||
transform: translateY(-8px) scale(1.07);
|
||||
}
|
||||
|
||||
.popular-badge {
|
||||
position: absolute;
|
||||
top: -1rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
color: white;
|
||||
padding: 0.5rem 1.5rem;
|
||||
border-radius: 50px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.plan-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.plan-name {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.plan-price {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 3rem;
|
||||
font-weight: 800;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.period {
|
||||
font-size: 1.125rem;
|
||||
color: var(--text-secondary);
|
||||
margin-left: 0.25rem;
|
||||
}
|
||||
|
||||
.plan-description {
|
||||
color: var(--text-secondary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.plan-features {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.plan-features ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.plan-features li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 0;
|
||||
color: var(--text-primary);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.plan-features li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
margin-right: 0.75rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.plan-footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.plan-cta {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.pricing-footer {
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pricing-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.pricing-card {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.pricing-card.popular {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.pricing-card.popular:hover {
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
.pricing-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
},
|
||||
|
||||
'about' => 'A modern pricing table with popular plan highlighting and smooth animations'
|
||||
]; ?>
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$stats = $prop['stats'] ?? [
|
||||
['number' => '99.9%', 'label' => 'Uptime'],
|
||||
['number' => '500ms', 'label' => 'Average Response'],
|
||||
['number' => '50K+', 'label' => 'Active Users'],
|
||||
['number' => '24/7', 'label' => 'Support']
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="stats-section">
|
||||
<div class="stats-container">
|
||||
<div class="stats-header">
|
||||
<h2>Trusted by Developers Worldwide</h2>
|
||||
<p>Join thousands of developers who have chosen our framework</p>
|
||||
</div>
|
||||
<div class="stats-grid">
|
||||
<?php foreach($stats as $index => $stat): ?>
|
||||
<div class="stat-item" style="animation-delay: <?= $index * 0.2 ?>s">
|
||||
<div class="stat-number" data-target="<?= safe($stat['number']) ?>"><?= safe($stat['number']) ?></div>
|
||||
<div class="stat-label"><?= safe($stat['label']) ?></div>
|
||||
<div class="stat-bar">
|
||||
<div class="stat-fill" style="animation-delay: <?= ($index * 0.2) + 0.5 ?>s"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.stats-section {
|
||||
background: linear-gradient(135deg, var(--surface) 0%, var(--surface-elevated) 100%);
|
||||
color: var(--text-primary);
|
||||
padding: 4rem 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid var(--border);
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.stats-section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="currentColor" opacity="0.1"/></pattern></defs><rect width="100%" height="100%" fill="url(%23dots)"/></svg>');
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.stats-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.stats-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.stats-header h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.stats-header p {
|
||||
font-size: 1.25rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 3rem;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid var(--glass-border);
|
||||
border-radius: var(--radius-xl);
|
||||
transition: all 0.3s ease;
|
||||
animation: fadeInScale 0.8s ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
|
||||
.stat-item:hover {
|
||||
transform: scale(1.05);
|
||||
background: var(--surface-hover);
|
||||
border-color: var(--border-hover);
|
||||
box-shadow: var(--shadow-lg);
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 3rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(135deg, var(--primary), var(--accent));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 1.1rem;
|
||||
color: var(--text-secondary);
|
||||
margin-bottom: 1rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.stat-bar {
|
||||
height: 4px;
|
||||
background: var(--border);
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.stat-fill {
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, var(--primary), var(--accent));
|
||||
border-radius: 2px;
|
||||
width: 0;
|
||||
animation: fillBar 1.5s ease-out forwards;
|
||||
}
|
||||
|
||||
@keyframes fadeInScale {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fillBar {
|
||||
to {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
.stat-number {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.stats-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
},
|
||||
|
||||
'about' => 'An animated statistics section with gradient backgrounds and progress bars'
|
||||
]; ?>
|
||||
@@ -0,0 +1,214 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$testimonials = $prop['testimonials'] ?? [
|
||||
[
|
||||
'name' => 'Sarah Johnson',
|
||||
'role' => 'Senior Developer at TechCorp',
|
||||
'avatar' => 'img/cat01.jpg',
|
||||
'content' => 'This framework has revolutionized our development process. The component system is intuitive and the performance is outstanding.',
|
||||
'rating' => 5
|
||||
],
|
||||
[
|
||||
'name' => 'Michael Chen',
|
||||
'role' => 'CTO at StartupX',
|
||||
'avatar' => 'img/cat01.jpg',
|
||||
'content' => 'We switched from our legacy system to this framework and saw immediate improvements in both development speed and code quality.',
|
||||
'rating' => 5
|
||||
],
|
||||
[
|
||||
'name' => 'Emily Rodriguez',
|
||||
'role' => 'Full Stack Developer',
|
||||
'avatar' => 'img/cat01.jpg',
|
||||
'content' => 'The documentation is excellent and the learning curve is gentle. Perfect for both beginners and experienced developers.',
|
||||
'rating' => 5
|
||||
]
|
||||
];
|
||||
|
||||
?>
|
||||
<div class="testimonials-section">
|
||||
<div class="testimonials-container">
|
||||
<div class="testimonials-header">
|
||||
<h2>What Developers Say</h2>
|
||||
<p>Don't just take our word for it - hear from the community</p>
|
||||
</div>
|
||||
<div class="testimonials-grid">
|
||||
<?php foreach($testimonials as $index => $testimonial): ?>
|
||||
<div class="testimonial-card" style="animation-delay: <?= $index * 0.2 ?>s">
|
||||
<div class="testimonial-content">
|
||||
<div class="quote-icon">"</div>
|
||||
<p><?= safe($testimonial['content']) ?></p>
|
||||
<div class="stars">
|
||||
<?php for($i = 0; $i < $testimonial['rating']; $i++): ?>
|
||||
<span class="star">★</span>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testimonial-author">
|
||||
<img src="<?= safe($testimonial['avatar']) ?>" alt="<?= safe($testimonial['name']) ?>" class="avatar">
|
||||
<div class="author-info">
|
||||
<div class="author-name"><?= safe($testimonial['name']) ?></div>
|
||||
<div class="author-role"><?= safe($testimonial['role']) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.testimonials-section {
|
||||
padding: 4rem 0;
|
||||
background: var(--bg-color);
|
||||
}
|
||||
|
||||
.testimonials-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.testimonials-header {
|
||||
text-align: center;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
.testimonials-header h2 {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 1rem;
|
||||
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
.testimonials-header p {
|
||||
font-size: 1.25rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.testimonials-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
.testimonial-card {
|
||||
background: var(--surface);
|
||||
border-radius: var(--radius-xl);
|
||||
padding: 2.5rem 2rem;
|
||||
border: 1px solid var(--border);
|
||||
box-shadow: var(--shadow-md);
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: fadeInUp 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
|
||||
.testimonial-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: var(--shadow-xl);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
|
||||
.testimonial-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, var(--primary), var(--secondary));
|
||||
}
|
||||
|
||||
.testimonial-content {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.quote-icon {
|
||||
font-size: 4rem;
|
||||
color: var(--primary);
|
||||
opacity: 0.3;
|
||||
line-height: 1;
|
||||
margin-bottom: 1rem;
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.testimonial-content p {
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.7;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.stars {
|
||||
display: flex;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.star {
|
||||
color: #fbbf24;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.testimonial-author {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
border: 3px solid var(--border);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.testimonial-card:hover .avatar {
|
||||
border-color: var(--primary);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.author-name {
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.author-role {
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.testimonials-grid {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.testimonial-card {
|
||||
padding: 2rem 1.5rem;
|
||||
}
|
||||
|
||||
.testimonials-header h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
|
||||
},
|
||||
|
||||
'about' => 'A testimonials section with user photos, ratings, and smooth animations'
|
||||
]; ?>
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php return [
|
||||
'render' => function($prop) {
|
||||
$themes = cfg('theme/options');
|
||||
$currentTheme = (string)cfg('theme/key');
|
||||
$currentLabel = (string)first(cfg('theme/label'), $themes[$currentTheme]['label'] ?? $currentTheme);
|
||||
$routePath = (string)(URL::$route['l-path'] ?? '');
|
||||
$buildThemeLink = function($themeKey) use($routePath) {
|
||||
return URL::Link($routePath, ['theme' => $themeKey]);
|
||||
};
|
||||
?>
|
||||
<div id="theme-switcher" style="position: fixed; right: 1.5rem; bottom: 1.5rem; z-index: 9999; font-family: inherit;">
|
||||
<style>
|
||||
#theme-switcher .theme-launcher {
|
||||
min-width: 56px;
|
||||
height: 56px;
|
||||
padding: 0 1rem;
|
||||
border-radius: 999px;
|
||||
background: var(--surface, #fff);
|
||||
border: 1px solid var(--border, rgba(0,0,0,0.15));
|
||||
box-shadow: var(--shadow-lg, 0 14px 32px rgba(0,0,0,0.18));
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease, background 0.2s ease;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.65rem;
|
||||
color: var(--text-primary, #111827);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
font: inherit;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
#theme-switcher .theme-launcher:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-xl, 0 22px 42px rgba(0,0,0,0.22));
|
||||
border-color: var(--primary, #2563eb);
|
||||
background: var(--surface-elevated, var(--surface, #fff));
|
||||
}
|
||||
#theme-switcher .theme-launcher-label {
|
||||
display: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#theme-switcher .theme-menu {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 68px;
|
||||
width: min(280px, calc(100vw - 2rem));
|
||||
padding: 0.6rem;
|
||||
border-radius: 14px;
|
||||
border: 1px solid var(--border, rgba(0,0,0,0.15));
|
||||
background: color-mix(in srgb, var(--surface, #fff) 92%, transparent 8%);
|
||||
box-shadow: var(--shadow-xl, 0 22px 42px rgba(0,0,0,0.22));
|
||||
}
|
||||
#theme-switcher .theme-menu[hidden] {
|
||||
display: none;
|
||||
}
|
||||
#theme-switcher .theme-menu-title {
|
||||
margin: 0 0 0.45rem;
|
||||
padding: 0.1rem 0.25rem 0.35rem;
|
||||
color: var(--text-secondary, #6b7280);
|
||||
font-size: 0.74rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
#theme-switcher .theme-menu-list {
|
||||
display: grid;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
#theme-switcher .theme-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
padding: 0.7rem 0.8rem;
|
||||
border-radius: 10px;
|
||||
border: 1px solid transparent;
|
||||
color: var(--text-primary, #111827);
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
#theme-switcher .theme-option:hover {
|
||||
background: color-mix(in srgb, var(--primary, #2563eb) 10%, transparent 90%);
|
||||
border-color: color-mix(in srgb, var(--primary, #2563eb) 22%, transparent 78%);
|
||||
text-decoration: none;
|
||||
}
|
||||
#theme-switcher .theme-option.is-active {
|
||||
background: color-mix(in srgb, var(--primary, #2563eb) 16%, transparent 84%);
|
||||
border-color: color-mix(in srgb, var(--primary, #2563eb) 28%, transparent 72%);
|
||||
}
|
||||
#theme-switcher .theme-option small {
|
||||
color: var(--text-secondary, #6b7280);
|
||||
font-size: 0.76rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
@media (min-width: 860px) {
|
||||
#theme-switcher .theme-launcher-label {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<button id="theme-toggle" class="theme-launcher" aria-haspopup="true" aria-expanded="false" aria-label="Switch theme" title="Switch Theme" type="button">
|
||||
<i class="fas fa-palette" aria-hidden="true"></i>
|
||||
<span class="theme-launcher-label"><?= safe($currentLabel) ?></span>
|
||||
</button>
|
||||
<div id="theme-menu" class="theme-menu" hidden>
|
||||
<div class="theme-menu-title">Available Themes</div>
|
||||
<div class="theme-menu-list">
|
||||
<?php foreach($themes as $themeKey => $themeInfo): ?>
|
||||
<a class="theme-option<?= $themeKey === $currentTheme ? ' is-active' : '' ?>" href="<?= asafe($buildThemeLink($themeKey)) ?>">
|
||||
<span><?= safe((string)$themeInfo['label']) ?></span>
|
||||
<?php if($themeKey === $currentTheme): ?><small>Active</small><?php endif; ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const themeMenu = document.getElementById('theme-menu');
|
||||
|
||||
if (!themeToggle || !themeMenu) return;
|
||||
|
||||
themeToggle.addEventListener('click', function() {
|
||||
const isOpen = !themeMenu.hasAttribute('hidden');
|
||||
themeMenu.toggleAttribute('hidden', isOpen);
|
||||
themeToggle.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
||||
});
|
||||
|
||||
document.addEventListener('click', function(event) {
|
||||
if (!themeMenu.hasAttribute('hidden') && !document.getElementById('theme-switcher').contains(event.target)) {
|
||||
themeMenu.setAttribute('hidden', 'hidden');
|
||||
themeToggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Escape' && !themeMenu.hasAttribute('hidden')) {
|
||||
themeMenu.setAttribute('hidden', 'hidden');
|
||||
themeToggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
},
|
||||
|
||||
'about' => 'A floating theme picker that switches between all configured starter theme families'
|
||||
];
|
||||
Reference in New Issue
Block a user