feat(ui): add glowing border effect and improve card hover interactions
- implemented glowing border effect on cards when cursor is near - multiple cards can glow simultaneously within proximity - smooth fade-out without flicker on mouse leave - improved hover animation for better user experience
This commit is contained in:
48
src/app.jsx
48
src/app.jsx
@@ -473,53 +473,7 @@
|
||||
]),
|
||||
|
||||
|
||||
React.createElement('div', {
|
||||
key: 'security-features',
|
||||
className: "grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8"
|
||||
}, [
|
||||
React.createElement('div', { key: 'feature1', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-key accent-green' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDH P-384 Key Exchange"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Military-grade elliptic curve key exchange")
|
||||
]),
|
||||
React.createElement('div', { key: 'feature2', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-user-shield accent-purple' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "MITM Protection"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Out-of-band verification against attacks")
|
||||
]),
|
||||
React.createElement('div', { key: 'feature3', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-lock accent-orange' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "AES-GCM 256 Encryption"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Authenticated encryption standard")
|
||||
]),
|
||||
React.createElement('div', { key: 'feature4', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-sync-alt accent-cyan' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "Perfect Forward Secrecy"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Automatic key rotation every 5 minutes")
|
||||
]),
|
||||
React.createElement('div', { key: 'feature5', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-signature accent-blue' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "ECDSA P-384 Signatures"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Digital signatures for message integrity")
|
||||
]),
|
||||
React.createElement('div', { key: 'feature6', className: "text-center p-3 sm:p-4" }, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 rounded-lg flex items-center justify-center mx-auto mb-2 sm:mb-3" }, [
|
||||
React.createElement('i', { className: 'fas fa-shield-alt accent-red' })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1" }, "SAS Security"),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight" }, "Revolutionary key exchange & MITM protection")
|
||||
]),
|
||||
]),
|
||||
React.createElement(SecurityFeatures, { key: 'security-features' }),
|
||||
|
||||
React.createElement(UniqueFeatureSlider, { key: 'unique-features-slider' }),
|
||||
|
||||
|
||||
59
src/components/ui/SecurityFeatures.jsx
Normal file
59
src/components/ui/SecurityFeatures.jsx
Normal file
@@ -0,0 +1,59 @@
|
||||
const SecurityFeatures = () => {
|
||||
const features = [
|
||||
{ id: 'feature1', color: '#00ff88', icon: 'fas fa-key accent-green', title: 'ECDH P-384 Key Exchange', desc: 'Military-grade elliptic curve key exchange' },
|
||||
{ id: 'feature2', color: '#bb00ff', icon: 'fas fa-user-shield accent-purple', title: 'MITM Protection', desc: 'Out-of-band verification against attacks' },
|
||||
{ id: 'feature3', color: '#ff8800', icon: 'fas fa-lock accent-orange', title: 'AES-GCM 256 Encryption', desc: 'Authenticated encryption standard' },
|
||||
{ id: 'feature4', color: '#00ffff', icon: 'fas fa-sync-alt accent-cyan', title: 'Perfect Forward Secrecy', desc: 'Automatic key rotation every 5 minutes' },
|
||||
{ id: 'feature5', color: '#0088ff', icon: 'fas fa-signature accent-blue', title: 'ECDSA P-384 Signatures', desc: 'Digital signatures for message integrity' },
|
||||
{ id: 'feature6', color: '#ff0044', icon: 'fas fa-shield-alt accent-red', title: 'SAS Security', desc: 'Revolutionary key exchange & MITM protection' }
|
||||
];
|
||||
|
||||
React.useEffect(() => {
|
||||
const cards = document.querySelectorAll(".card");
|
||||
const radius = 200;
|
||||
|
||||
const handleMove = (e) => {
|
||||
cards.forEach((card) => {
|
||||
const rect = card.getBoundingClientRect();
|
||||
const cx = rect.left + rect.width / 2;
|
||||
const cy = rect.top + rect.height / 2;
|
||||
|
||||
const dx = e.clientX - cx;
|
||||
const dy = e.clientY - cy;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (dist < radius) {
|
||||
const x = e.clientX - rect.left;
|
||||
const y = e.clientY - rect.top;
|
||||
card.style.setProperty("--x", `${x}px`);
|
||||
card.style.setProperty("--y", `${y}px`);
|
||||
card.classList.add("active-glow");
|
||||
} else {
|
||||
card.classList.remove("active-glow");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("mousemove", handleMove);
|
||||
return () => window.removeEventListener("mousemove", handleMove);
|
||||
}, []);
|
||||
|
||||
const renderFeature = (f) =>
|
||||
React.createElement('div', {
|
||||
key: f.id,
|
||||
className: "card p-3 sm:p-4 text-center",
|
||||
style: { "--color": f.color }
|
||||
}, [
|
||||
React.createElement('div', { key: 'icon', className: "w-10 h-10 sm:w-12 sm:h-12 flex items-center justify-center mx-auto mb-2 sm:mb-3 relative z-10" }, [
|
||||
React.createElement('i', { className: f.icon })
|
||||
]),
|
||||
React.createElement('h4', { key: 'title', className: "text-xs sm:text-sm font-medium text-primary mb-1 relative z-10" }, f.title),
|
||||
React.createElement('p', { key: 'desc', className: "text-xs text-muted leading-tight relative z-10" }, f.desc)
|
||||
]);
|
||||
|
||||
return React.createElement('div', {
|
||||
className: "grid grid-cols-2 md:grid-cols-2 lg:grid-cols-3 gap-3 sm:gap-4 max-w-6xl mx-auto mt-8"
|
||||
}, features.map(renderFeature));
|
||||
};
|
||||
|
||||
window.SecurityFeatures = SecurityFeatures;
|
||||
@@ -7,6 +7,7 @@ import '../components/ui/SessionTimer.jsx';
|
||||
import '../components/ui/Header.jsx';
|
||||
import '../components/ui/DownloadApps.jsx';
|
||||
import '../components/ui/UniqueFeatureSlider.jsx';
|
||||
import '../components/ui/SecurityFeatures.jsx';
|
||||
import '../components/ui/ComparisonTable.jsx';
|
||||
import '../components/ui/Roadmap.jsx';
|
||||
import '../components/ui/FileTransfer.jsx';
|
||||
|
||||
1
src/scripts/bootstrap-modules.js
vendored
1
src/scripts/bootstrap-modules.js
vendored
@@ -36,6 +36,7 @@
|
||||
loadReactComponent('../components/ui/DownloadApps.jsx'),
|
||||
loadReactComponent('../components/ui/ComparisonTable.jsx'),
|
||||
loadReactComponent('../components/ui/UniqueFeatureSlider.jsx'),
|
||||
loadReactComponent('../components/ui/SecurityFeatures.jsx'),
|
||||
loadReactComponent('../components/ui/Roadmap.jsx'),
|
||||
loadReactComponent('../components/ui/FileTransfer.jsx'),
|
||||
]);
|
||||
|
||||
@@ -127,3 +127,43 @@ tr.bg-black-table {
|
||||
padding-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
.card::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 12px;
|
||||
padding: 2px;
|
||||
background: radial-gradient(
|
||||
circle at var(--x, 50%) var(--y, 50%),
|
||||
var(--color),
|
||||
transparent 80%
|
||||
);
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s;
|
||||
-webkit-mask:
|
||||
linear-gradient(#fff 0 0) content-box,
|
||||
linear-gradient(#fff 0 0);
|
||||
-webkit-mask-composite: xor;
|
||||
mask-composite: exclude;
|
||||
}
|
||||
|
||||
.card.active-glow::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.card::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 3px;
|
||||
border-radius: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user