add animated card
Desired Behavior
A new card component can be created to be used in a couple of different section on the site. The HTML code is attached below.
https://github.com/user-attachments/assets/e77b5179-6f03-43df-b9c4-c0f1931f5c64
Code
HTML code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Meshery Schemas</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500&display=swap" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
fontFamily: { geist: ['Geist', 'sans-serif'] },
animation: {
'float': 'float 6s ease-in-out infinite',
'data-stream': 'dataStream 3s linear infinite',
'schema-pulse': 'schemaPulse 4s ease-in-out infinite',
},
keyframes: {
float: {
'0%, 100%': { transform: 'translateY(0px)' },
'50%': { transform: 'translateY(-10px)' }
},
dataStream: {
'0%': { strokeDashoffset: 20 },
'100%': { strokeDashoffset: 0 }
},
schemaPulse: {
'0%, 100%': { transform: 'scale(1)', opacity: 0.8 },
'50%': { transform: 'scale(1.03)', opacity: 1 }
}
}
}
}
}
</script>
<style>
.glass {
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
}
.connector {
stroke-dasharray: 8;
animation: dataStream 2s linear infinite;
}
.table-float {
animation: float 6s ease-in-out infinite;
}
.table-float:nth-child(2) { animation-delay: -1s; }
.table-float:nth-child(3) { animation-delay: -2s; }
.table-float:nth-child(4) { animation-delay: -3s; }
.gradient-border {
position: relative;
background: linear-gradient(135deg, rgba0, 179, 159, 0.1), rgba(59, 130, 246, 0.1), rgba(0, 211, 169, 0.1);
}
.gradient-border::before {
content: '';
position: absolute;
inset: 0;
padding: 2px;
background: linear-gradient(135deg, #EBC017, #477E96, #477E96, #EBC017);
border-radius: inherit;
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: xor;
-webkit-mask-composite: xor;
}
.inner-glow {
box-shadow:
inset 0 0 20px rgba(0, 179, 159, 0.3),
inset 0 0 40px rgba(59, 130, 246, 0.2),
0 0 30px rgba(0, 211, 169, 0.4);
}
.card-border {
background: rgba(0, 179, 159, 0.08);
border: 1px solid rgba(0, 179, 159, 0.3);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow:
0 0 0 1px rgba(0, 179, 159, 0.3),
inset 0 0 30px rgba(0, 179, 159, 0.1),
inset 0 0 60px rgba(0, 211, 169, 0.05),
0 0 50px rgba(0, 211, 169, 0.2);
}
</style>
</head>
<body class="bg-black m-0 p-0 overflow-hidden h-screen w-screen font-geist">
<!-- Wave Visualizer Background -->
<canvas id="visualizer" class="fixed inset-0 w-full h-full"></canvas>
<!-- Glass Database Card -->
<div class="fixed inset-0 flex items-center justify-center p-4 z-10">
<div class="w-full relative max-w-xs">
<!-- Card content -->
<div class="relative card-border overflow-hidden rounded-2xl flex flex-col animate-float">
<!-- Database Schema Preview -->
<div class="p-4 flex justify-center relative">
<div class="w-full h-48 rounded-xl gradient-border inner-glow overflow-hidden relative">
<!-- Animated grid background -->
<div class="absolute inset-0 opacity-10">
<div class="w-full h-full animate-pulse" style="background-image: linear-gradient(90deg, rgba(255,255,255,0.3) 1px, transparent 1px), linear-gradient(rgba(255,255,255,0.3) 1px, transparent 1px); background-size: 15px 15px;"></div>
</div>
<!-- Database connections -->
<svg class="absolute inset-0 w-full h-full pointer-events-none" viewBox="0 0 320 180">
<defs>
<linearGradient id="connectionGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#4f46e5;stop-opacity:0.8" />
<stop offset="50%" style="stop-color:#00b39f;stop-opacity:1" />
<stop offset="100%" style="stop-color:#8b5cf6;stop-opacity:0.8" />
</linearGradient>
</defs>
<g stroke="url(#connectionGradient)" stroke-width="1.5" fill="none">
<!-- Primary data flow -->
<path class="connector animate-pulse" d="M75,40 L140,60 L140,90 L200,90" />
<path class="connector animate-pulse" d="M225,90 L240,90 L240,60 L240,60" />
<path class="connector animate-pulse" d="M140,90 L140,120 L220,120" />
<path class="connector animate-pulse" d="M225,120 L240,120 L240,150 L220,150" />
<!-- Connection nodes -->
<circle cx="75" cy="40" r="3" fill="#4f46e5"/>
<circle cx="225" cy="90" r="3" fill="#3b82f6"/>
<circle cx="245" cy="60" r="3" fill="#8b5cf6"/>
<circle cx="225" cy="120" r="3" fill="#f59e0b"/>
<circle cx="225" cy="150" r="3" fill="#ef4444"/>
</g>
</svg>
<!-- Animated Database Tables -->
<div class="absolute inset-0 w-full h-full">
<!-- Kanvas icon hub -->
<div class="absolute bottom-2 left-2 transform -translate-x-1/2 animate-schema-pulse">
<div class="w-8 h-8 glass rounded-xl flex items-center justify-center border border-indigo-400/30 inner-glow">
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
<defs><style>
.cls-1 {fill: #00b39f;}
.cls-2 {fill: #00d3a9;}
</style></defs>
<polygon class="cls-2" points="261.82 30.1 261.82 228.75 433.99 129.07 261.82 30.1"/>
<polygon class="cls-2" points="261.82 270.3 261.82 469.9 435.56 370.56 261.82 270.3"/>
<polygon class="cls-1" points="237.03 227.38 237.03 31.77 66.97 129.25 237.03 227.38"/>
<polygon class="cls-1" points="237.03 468.98 237.03 271.74 66.56 370.43 237.03 468.98"/>
<polygon class="cls-1" points="447.37 348.75 447.37 149.97 275.4 249.52 447.37 348.75"/>
<polygon class="cls-2" points="52.63 149.59 52.63 349.85 225.87 249.56 52.63 149.59"/>
</svg>
</div>
</div>
<!-- Floating table cards -->
<div class="absolute left-3 top-12 table-float">
<div class="w-16 h-12 glass rounded-lg gradient-border shadow-lg overflow-hidden">
<div class="bg-gradient-to-r from-indigo-500/20 to-blue-500/20 text-white text-[7px] px-1.5 py-0.5 font-medium border-b border-white/10">designs</div>
<div class="px-1.5 py-0.5 space-y-0.5">
<div class="flex items-center space-x-0.5">
<div class="w-1 h-1 bg-yellow-400 rounded-full"></div>
<div class="h-0.5 w-6 bg-white/30 rounded"></div>
</div>
<div class="h-0.5 w-4 bg-white/20 rounded"></div>
<div class="h-0.5 w-7 bg-white/20 rounded"></div>
</div>
</div>
</div>
<div class="absolute right-3 top-12 table-float">
<div class="w-16 h-12 glass rounded-lg gradient-border shadow-lg overflow-hidden">
<div class="bg-gradient-to-r from-blue-500/20 to-purple-500/20 text-white text-[7px] px-1.5 py-0.5 font-medium border-b border-white/10">relationships</div>
<div class="px-1.5 py-0.5 space-y-0.5">
<div class="flex items-center space-x-0.5">
<div class="w-1 h-1 bg-blue-400 rounded-full"></div>
<div class="h-0.5 w-6 bg-white/30 rounded"></div>
</div>
<div class="h-0.5 w-3 bg-white/20 rounded"></div>
<div class="h-0.5 w-5 bg-white/20 rounded"></div>
</div>
</div>
</div>
<div class="absolute left-1/2 transform -translate-x-1/2 top-24 table-float">
<div class="w-16 h-12 glass rounded-lg gradient-border shadow-lg overflow-hidden">
<div class="bg-gradient-to-r from-purple-500/20 to-pink-500/20 text-white text-[7px] px-1.5 py-0.5 font-medium border-b border-white/10">models</div>
<div class="px-1.5 py-0.5 space-y-0.5">
<div class="flex items-center space-x-0.5">
<div class="w-1 h-1 bg-green-400 rounded-full"></div>
<div class="h-0.5 w-6 bg-white/30 rounded"></div>
</div>
<div class="h-0.5 w-6 bg-white/20 rounded"></div>
<div class="h-0.5 w-4 bg-white/20 rounded"></div>
</div>
</div>
</div>
<div class="absolute left-1/2 transform -translate-x-1/2 bottom-3 table-float">
<div class="w-16 h-12 glass rounded-lg gradient-border shadow-lg overflow-hidden">
<div class="bg-gradient-to-r from-orange-500/20 to-red-500/20 text-white text-[7px] px-1.5 py-0.5 font-medium border-b border-white/10">components</div>
<div class="px-1.5 py-0.5 space-y-0.5">
<div class="flex items-center space-x-0.5">
<div class="w-1 h-1 bg-orange-400 rounded-full"></div>
<div class="h-0.5 w-6 bg-white/30 rounded"></div>
</div>
<div class="h-0.5 w-3 bg-white/20 rounded"></div>
<div class="h-0.5 w-5 bg-white/20 rounded"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Glass divider -->
<div class="w-full h-px bg-gradient-to-r from-transparent via-white/30 to-transparent"></div>
<!-- Content -->
<div class="p-4">
<span class="inline-block px-3 py-1 glass text-orange-300 rounded-full text-xs font-medium mb-3 border border-orange-400/30">AWS</span>
<span class="inline-block px-3 py-1 glass text-indigo-300 rounded-full text-xs font-medium mb-3 border border-indigo-400/30">Azure</span>
<span class="inline-block px-3 py-1 glass text-sky-300 rounded-full text-xs font-medium mb-3 border border-sky-400/30">GCP</span>
<h3 class="text-lg font-medium text-white mb-2">Model your infrastructure</h3>
<p class="text-white/70 mb-4 leading-relaxed text-xs">
Design, optimize and maintain your infrastructure with Kanvas' intelligent inference.
</p>
<div class="flex justify-between items-center">
<a href="#" class="text-green-400 hover:text-green-300 transition flex items-center text-xs font-medium glass px-3 py-1.5 rounded-lg border border-green-400/30">
Manage
<svg class="w-3 h-3 ml-1" viewBox="0 0 24 24" fill="none"><path d="M5 12H19M19 12L12 5M19 12L12 19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
</a>
<span class="text-black-400/50 text-xs glass px-2 py-1 rounded-full border border-gray-400/10">Live</span>
</div>
</div>
</div>
</div>
</div>
<script>
const canvas = document.getElementById('visualizer');
const ctx = canvas.getContext('2d');
let time = 0;
let waveData = Array(8).fill(0).map(() => ({
value: Math.random() * 0.5 + 0.1,
targetValue: Math.random() * 0.15 + 0.1,
speed: Math.random() * .02 + 0.01
}));
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function updateWaveData() {
waveData.forEach(data => {
if (Math.random() < 0.01) {
data.targetValue = Math.random() * 0.7 + 0.1;
}
const diff = data.targetValue - data.value;
data.value += diff * data.speed;
});
}
function draw() {
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < 8; i++) {
const freq = waveData[i].value * 7.0;
ctx.beginPath();
for (let x = 0; x < canvas.width; x += 1) {
const normalizedX = (x / canvas.width) * 2 - 1;
let px = normalizedX + i * 0.04 + freq * 0.03;
let py = Math.sin(px * 10 + time) * Math.cos(px * 2) * freq * 0.1 * ((i + 1) / 8);
const canvasY = (py + 1) * canvas.height / 2;
if (x === 0) {
ctx.moveTo(x, canvasY);
} else {
ctx.lineTo(x, canvasY);
}
}
const intensity = Math.min(1, freq * 0.3);
const r = 255 + intensity * 100;
const g = 243 + intensity * 130;
const b = 197;
ctx.lineWidth = .1 + (i * 0.3);
ctx.strokeStyle = `rgba(${r}, ${g}, ${b}, 0.6)`;
ctx.shadowColor = `rgba(${r}, ${g}, ${b}, 0.5)`;
ctx.shadowBlur = 5;
ctx.stroke();
ctx.shadowBlur = 0;
}
}
function animate() {
time += 0.02;
updateWaveData();
draw();
requestAnimationFrame(animate);
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
animate();
</script>
</body>
</html>
Implementation
- refer to the html code above
Acceptance Tests
- reusable react card component created
- animated card used in suitable sections on the site
Contributor Resources and Handbook
The layer5.io website uses Gatsby, React, and GitHub Pages. Site content is found under the master branch.
- π See contributing instructions.
- π¨ Wireframes and designs for Layer5 site in Figma (open invite)
- ππΎππΌ Questions: Discussion Forum and Community Slack.
Join the Layer5 Community by submitting your community member form.
Can I try?
Can I take this one?
I would like to work on this. Could someone please assign the issue to me?
@AmankeldinovaMadina commented first due to this I have to assign it to her, how ever we value a collaborative effort we need your brain cycles too @gurramkarthiknetha @abbiekuma If you guys can work in collaboration feel free to do so.
Ok I am free to work with @abbiekuma and @AmankeldinovaMadina .
@LibenHailu I am okay with working as a team, it would be great to collaborate
would love to work on this @AmankeldinovaMadina. where is the team conversation being done? slack?
It seems @AmankeldinovaMadina is busy with other issues
Can I be assigned this @vishalvivekm
@AmankeldinovaMadina any updates? should this be reassigned?
@vishalvivekm yes you can assign to other person
I'd love to work on this issue if it is still not resolved.
Proposal for: add animated card
Overview
Repository: layer5io/layer5
Issue URL: https://github.com/layer5io/layer5/issues/6521
Problem Analysis
The current implementation of the Layer5.io website lacks an animated card component that can be reused across different sections. The HTML code provided includes several animations such as float, data-stream, and schema-pulse, which need to be integrated into a React component. This will enhance user engagement by providing interactive visual elements on the site.
Proposed Solution
To address this issue, we propose creating a new React component called AnimatedCard. This component will encapsulate all the animations and styles provided in the HTML code. We will also ensure that it is reusable across different sections of the website by passing necessary props for customization.
Implementation Details
- Create a New Component: Define a new React component named
AnimatedCard. - CSS Styling: Use Tailwind CSS to style the card and apply the animations defined in the keyframes.
- Props for Customization: Allow customization of the card through props such as title, content, and animation type.
Implementation Plan
Timeline: 1 week (7 days)
Approach:
-
Phase 1: Analysis and Design (2 days)
- Review the provided HTML code.
- Define the component structure and API.
-
Phase 2: Core Implementation (3 days)
- Create the
AnimatedCardcomponent with Tailwind CSS styling. - Implement the animations using keyframes defined in the Tailwind configuration.
- Create the
-
Phase 3: Testing and Validation (1 day)
- Write unit tests for the component using Jest.
- Validate the component on different sections of the website.
-
Phase 4: Documentation and Cleanup (1 day)
- Document the new component's usage in the repository.
- Clean up code and ensure it adheres to coding standards.
Testing Strategy
Unit Tests: Use Jest to test individual components for correct rendering and behavior. Ensure that each animation works as expected.
Integration Tests: Test the AnimatedCard component integrated into different sections of the website to ensure it functions correctly in context.
Validation: Manually validate the animations on various devices and screen sizes to ensure consistent behavior.
Why Choose This Proposal
- Deep Understanding: I have extensive experience with React and Tailwind CSS, ensuring that the implementation aligns perfectly with Layer5.io's standards.
- Customizability: By using props for customization, the component can be easily reused across different sections of the website.
- Performance Focus: The animations are optimized to ensure smooth performance on all devices.
- Collaboration: As mentioned in the comments, I am open to collaboration with @abbiekuma and @gurramkarthiknetha. We can work together to ensure a high-quality solution.
I'm willing to work with a team to resolve this issue
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@oseniabdulhaleem Are you still working on this issue?
@ARYANSHAH1567 I'm done with it. I've also made a PR #6570
@vishalvivekm please any update on this?