v2.2
MENU ANIMATIONS
UI SURECART
BUTTONS
<!DOCTYPE html>
<html lang="en">
<head>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prism Border Configurator - BricksFusion</title>
<style>
:root {
--background: #000;
--card-bg: #1e1e1e;
--card-bg-hover: #252525;
--text-primary: #f2f2f7;
--text-secondary: #8e8e93;
--accent: #ef6013;
--accent-hover: #c64c0c;
--border: #2c2c2e;
--shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
--track: #2c2c2e;
--thumb: #ef6013;
--card-radius: 16px;
--input-radius: 8px;
--button-radius: 12px;
--transition: all 0.25s ease;
--font: 'Inter', BlinkMacSystemFont, "San Francisco", "Helvetica Neue", Helvetica, Arial, sans-serif;
--action-bar-height: 70px;
--success: #28a745;
--warning: #ffc107;
--danger: #dc3545;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font);
background-color: var(--background);
color: var(--text-primary);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding-bottom: var(--action-bar-height);
}
.action-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: var(--action-bar-height);
background: linear-gradient(145deg, #1a1a1a, #0f0f0f);
border-top: 1px solid var(--border);
z-index: 1000;
display: flex;
align-items: center;
padding: 0 1.5rem;
gap: 1rem;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.3);
backdrop-filter: blur(10px);
}
.breadcrumb {
display: flex;
align-items: center;
gap: 0.5rem;
flex: 1;
}
.breadcrumb-item {
color: var(--text-secondary);
font-size: var(--text-xs);
font-weight: 500;
text-decoration: none;
transition: var(--transition);
padding: 0.5rem 0.75rem;
border-radius: 6px;
}
.breadcrumb-item:hover {
color: var(--text-primary);
background-color: rgba(255, 255, 255, 0.05);
}
.breadcrumb-item.active {
color: var(--accent);
background-color: rgba(239, 96, 19, 0.1);
}
.breadcrumb-separator {
color: var(--text-secondary);
font-size: var(--text-xs);
opacity: 0.5;
}
.action-buttons {
display: flex;
align-items: center;
gap: 0.75rem;
}
.action-btn {
padding: 0.6rem 1rem;
background-color: var(--card-bg);
color: var(--text-primary);
font-family: var(--font);
font-size: var(--text-xs);
font-weight: 500;
border: 1px solid var(--border);
border-radius: var(--button-radius);
cursor: pointer;
transition: var(--transition);
display: flex;
align-items: center;
gap: 0.5rem;
text-decoration: none;
white-space: nowrap;
}
.action-btn:hover {
background-color: var(--card-bg-hover);
border-color: var(--accent);
transform: translateY(-1px);
}
.action-btn.primary {
background: linear-gradient(90deg, var(--accent), #ff8c51);
border-color: var(--accent);
color: white;
}
.action-btn.primary:hover {
background: linear-gradient(90deg, var(--accent-hover), #e67a3f);
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(239, 96, 19, 0.3);
}
.data-attribute-display {
background-color: rgba(50, 50, 50, 0.8);
border: 1px solid var(--border);
border-radius: 6px;
padding: 0.5rem 0.75rem;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: var(--text-xs);
color: #ff8c51;
cursor: pointer;
transition: var(--transition);
user-select: all;
}
.data-attribute-display:hover {
background-color: rgba(239, 96, 19, 0.2);
border-color: var(--accent);
}
.container {
max-width: 100%;
margin: 0 auto;
padding: 2rem 1.5rem;
}
.page-header {
text-align: center;
margin-bottom: 2rem;
}
.page-title {
font-size: 2.5rem;
font-weight: 700;
color: var(--text-primary);
margin-bottom: 0.5rem;
background: linear-gradient(90deg, var(--accent), #ff8c51);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.page-subtitle {
font-size: var(--text-s);
color: var(--text-secondary);
font-weight: 500;
}
.instructions-toggle {
margin-bottom: 2rem;
}
.instructions-card {
background-color: var(--card-bg);
border: 1px solid var(--border);
border-radius: var(--card-radius);
box-shadow: var(--shadow);
overflow: hidden;
transition: var(--transition);
}
.instructions-header {
padding: 1rem 1.5rem;
cursor: pointer;
transition: var(--transition);
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid transparent;
}
.instructions-header:hover {
background-color: var(--card-bg-hover);
}
.instructions-card.expanded .instructions-header {
border-bottom-color: var(--border);
}
.instructions-title {
font-size: var(--text-s);
font-weight: 600;
}
.toggle-icon {
font-size: 1.2em;
transition: transform 0.3s ease;
}
.toggle-icon.expanded {
transform: rotate(180deg);
}
.instructions-content {
padding: 0 1.5rem;
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease, padding 0.3s ease;
}
.instructions-content.show {
max-height: 500px;
padding: 1.5rem;
}
.instructions-grid {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
}
.how-to-use ol {
padding-left: 1.5rem;
}
.how-to-use li {
margin-bottom: 0.75rem;
font-size: var(--text-xs);
color: var(--text-secondary);
line-height: 1.6;
}
.how-to-use strong {
color: var(--text-primary);
font-weight: 600;
}
.how-to-use code {
background-color: rgba(50, 50, 50, 0.5);
padding: 0.2rem 0.5rem;
border-radius: 4px;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: var(--text-xs);
color: #ff8c51;
}
.content {
display: grid;
grid-template-columns: 1fr 500px;
gap: 2rem;
align-items: start;
}
.preview-section {
position: sticky;
top: 2rem;
}
.controls-section {
max-width: 500px;
}
.card {
background-color: var(--card-bg);
border-radius: var(--card-radius);
box-shadow: var(--shadow);
overflow: hidden;
margin-bottom: 1.5rem;
border: 1px solid var(--border);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.4);
}
.preview-container {
height: 400px;
width: 100%;
position: relative;
overflow: visible;
border-radius: var(--card-radius);
background-color: #252525;
border: 1px solid var(--border);
box-shadow: var(--shadow);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
text-align: center;
perspective: 1000px;
}
.preview-content {
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
z-index: 1;
}
.preview-controls {
position: absolute;
top: 1rem;
right: 1rem;
display: flex;
gap: 0.5rem;
z-index: 10;
}
.preview-btn {
padding: 0.5rem;
background-color: rgba(0, 0, 0, 0.7);
color: white;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 6px;
cursor: pointer;
transition: var(--transition);
font-size: var(--text-xs);
backdrop-filter: blur(5px);
}
.preview-btn:hover {
background-color: var(--accent);
border-color: var(--accent);
}
.card-heading {
padding: 1rem 1.5rem;
font-size: var(--text-s);
font-weight: 600;
border-bottom: 1px solid var(--border);
letter-spacing: 0.3px;
display: flex;
justify-content: space-between;
align-items: center;
}
.card-actions {
display: flex;
gap: 0.5rem;
}
.card-action-btn {
padding: 0.4rem 0.8rem;
background-color: transparent;
color: var(--text-secondary);
border: 1px solid var(--border);
border-radius: 6px;
cursor: pointer;
font-size: var(--text-xs);
transition: var(--transition);
}
.card-action-btn:hover {
color: var(--text-primary);
border-color: var(--accent);
background-color: rgba(239, 96, 19, 0.1);
}
.card-content {
padding: 1.5rem;
}
.control-group {
margin-bottom: 1.5rem;
position: relative;
}
.control-group:last-child {
margin-bottom: 0;
}
.control-label {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
}
.label-text {
font-size: var(--text-xs);
font-weight: 500;
letter-spacing: 0.2px;
display: flex;
align-items: center;
gap: 0.5rem;
}
.help-tooltip {
cursor: help;
opacity: 0.7;
transition: var(--transition);
}
.help-tooltip:hover {
opacity: 1;
color: var(--accent);
}
.value-display {
display: flex;
align-items: center;
gap: 0.5rem;
}
.value-text {
font-size: var(--text-xs);
color: var(--text-secondary);
background-color: rgba(50, 50, 50, 0.5);
padding: 2px 8px;
border-radius: 4px;
min-width: 45px;
text-align: center;
}
.reset-btn {
padding: 0.2rem 0.4rem;
background-color: transparent;
color: var(--text-secondary);
border: 1px solid var(--border);
border-radius: 4px;
cursor: pointer;
font-size: 10px;
transition: var(--transition);
}
.reset-btn:hover {
color: var(--danger);
border-color: var(--danger);
background-color: rgba(220, 53, 69, 0.1);
}
input[type="range"] {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 6px;
background: var(--track);
border-radius: 3px;
outline: none;
margin: 0.8rem 0;
position: relative;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 20px;
height: 20px;
background: var(--thumb);
border-radius: 50%;
cursor: pointer;
transition: var(--transition);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2);
box-shadow: 0 0 10px rgba(239, 96, 19, 0.5);
}
.color-list {
display: flex;
flex-direction: column;
gap: 1rem;
margin-bottom: 1.5rem;
}
.color-row {
display: flex;
align-items: center;
gap: 1.25rem;
padding: 1rem 1.25rem;
background-color: rgba(30, 30, 30, 0.7);
border: 1px solid var(--border);
border-radius: var(--input-radius);
transition: var(--transition);
}
.color-row:hover {
border-color: var(--accent);
box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.1);
}
.color-picker-container {
position: relative;
width: 40px;
height: 40px;
border-radius: 8px;
overflow: hidden;
border: 2px solid var(--border);
cursor: pointer;
transition: var(--transition);
flex-shrink: 0;
background: linear-gradient(45deg, #f0f0f0 25%, transparent 25%),
linear-gradient(-45deg, #f0f0f0 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #f0f0f0 75%),
linear-gradient(-45deg, transparent 75%, #f0f0f0 75%);
background-size: 8px 8px;
background-position: 0 0, 0 4px, 4px -4px, -4px 0px;
}
.color-picker-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--current-color, #ff00ff);
border-radius: 6px;
z-index: 1;
}
.color-picker-container:hover {
border-color: var(--accent);
transform: scale(1.05);
}
input[type="color"] {
position: absolute;
top: -2px;
left: -2px;
width: calc(100% + 4px);
height: calc(100% + 4px);
border: none;
cursor: pointer;
background: transparent;
z-index: 2;
opacity: 0;
}
.color-input-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.color-label {
font-size: 10px;
font-weight: 500;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-left: 0.25rem;
}
.color-input {
padding: 0.5rem 0.75rem;
background-color: rgba(0, 0, 0, 0.3);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-primary);
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: 12px;
transition: var(--transition);
min-width: 0;
}
.color-input:focus {
border-color: var(--accent);
box-shadow: 0 0 0 1px rgba(239, 96, 19, 0.2);
outline: none;
}
.color-input.invalid {
border-color: var(--danger);
box-shadow: 0 0 0 1px rgba(220, 53, 69, 0.2);
}
.hex-input,
.hsl-input {
width: 100%;
}
.color-input-group:nth-child(2) {
flex: 0.3;
}
.color-input-group:nth-child(3) {
flex: 0.7;
}
.notification {
position: fixed;
bottom: calc(var(--action-bar-height) + 1rem);
left: 50%;
background-color: var(--success);
color: white;
padding: 0.75rem 1rem;
border-radius: var(--input-radius);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
z-index: 1001;
transform: translate(-50%, 200px);
opacity: 0;
transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s ease;
font-size: var(--text-xs);
font-weight: 500;
max-width: 320px;
word-wrap: break-word;
line-height: 1.4;
text-align: center;
}
.notification.show {
transform: translate(-50%, 0);
opacity: 1;
}
.gradient-colors-list {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
margin-bottom: 1rem;
}
.gradient-color-item {
display: flex;
align-items: center;
gap: 0.5rem;
position: relative;
margin-bottom: 0.75rem;
width: 100%;
}
.gradient-remove-btn {
width: 28px;
height: 28px;
border-radius: 50%;
background-color: transparent;
border: 1px solid var(--border);
color: var(--text-secondary);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: var(--transition);
}
.gradient-remove-btn:hover {
background-color: rgba(255, 51, 51, 0.2);
border-color: rgba(255, 51, 51, 0.6);
color: #ff6b6b;
}
.gradient-add-btn {
padding: 0.75rem;
background-color: rgba(40, 40, 40, 0.6);
border: 1px dashed var(--border);
color: var(--text-secondary);
border-radius: var(--input-radius);
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
cursor: pointer;
transition: var(--transition);
width: 100%;
margin-top: 0.75rem;
}
.gradient-add-btn:hover {
background-color: rgba(40, 40, 40, 0.8);
border-color: var(--accent);
color: var(--text-primary);
}
@keyframes prismBorderMove {
0% { background-position: 0% 50%; }
25% { background-position: 100% 50%; }
50% { background-position: 200% 50%; }
75% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.prism-preview {
width: 350px;
height: 200px;
background: var(--card-bg);
border-radius: 16px;
position: relative;
overflow: visible;
z-index: 0;
transform: translateZ(0);
-webkit-transform: translateZ(0);
display: flex;
align-items: center;
justify-content: center;
}
.prism-preview-content {
font-size: 20px;
font-weight: 600;
color: var(--text-primary);
z-index: 1;
}
@media (max-width: 1200px) {
.content {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.preview-section {
position: static;
}
.controls-section {
max-width: 100%;
}
}
@media (max-width: 768px) {
.action-bar {
flex-direction: column;
height: auto;
min-height: var(--action-bar-height);
padding: 0.75rem;
}
.breadcrumb {
order: 1;
width: 100%;
}
.action-buttons {
order: 2;
width: 100%;
justify-content: center;
flex-wrap: wrap;
}
body {
padding-bottom: calc(var(--action-bar-height) + 20px);
}
.notification {
bottom: calc(var(--action-bar-height) + 2rem);
max-width: 280px;
transform: translate(-50%, 250px);
}
.notification.show {
transform: translate(-50%, 0);
opacity: 1;
}
.color-row {
flex-direction: column;
align-items: stretch;
gap: 1rem;
padding: 1rem;
}
.color-picker-container {
align-self: center;
margin-bottom: 0.5rem;
}
.color-input-group {
align-items: stretch;
}
.hex-input,
.hsl-input {
width: 100%;
}
.preview-container {
height: 300px;
}
.data-attribute-display {
font-size: 10px;
padding: 0.4rem 0.6rem;
}
.action-btn {
font-size: 11px;
padding: 0.5rem 0.8rem;
}
.page-title {
font-size: 2rem;
}
}
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
button:focus-visible,
input:focus-visible,
.action-btn:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: var(--background);
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--accent);
}
.loading {
opacity: 0.6;
pointer-events: none;
position: relative;
}
.loading::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border: 2px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="action-bar">
<nav class="breadcrumb">
<a href="https://bricksfusion.com" class="breadcrumb-item">Home</a>
<span class="breadcrumb-separator">›</span>
<a href="https://bricksfusion.com/visual-effects/" class="breadcrumb-item">Visual effects</a>
<span class="breadcrumb-separator">›</span>
<span class="breadcrumb-item active">Prism Border</span>
</nav>
<div class="action-buttons">
<div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
data-prism-border
</div>
<button class="action-btn primary" id="download-config" title="Copy JavaScript code (Ctrl+D)" data-protection-animation="true">
<span>📋</span>
Copy JS
</button>
<button class="action-btn" id="copy-full-section" title="Copy complete section JSON for Bricks Builder (Ctrl+S)" data-protection-animation="true">
<span>📦</span>
Copy Full Section
</button>
</div>
</div>
<div class="container">
<div class="page-header">
<h1 class="page-title">Prism Border</h1>
<p class="page-subtitle">Interactive gradient borders for Bricks Builder</p>
</div>
<div class="instructions-toggle">
<div class="instructions-card" id="instructions-card">
<div class="instructions-header" id="instructions-toggle">
<div class="instructions-title">
How to Use & Code Information
</div>
<span class="toggle-icon">▼</span>
</div>
<div class="instructions-content" id="instructions-content">
<div class="instructions-grid">
<div class="how-to-use">
<ol>
<li>Customize your Prism Border using the controls below</li>
<li>Click <strong>Copy JS</strong> to copy the JavaScript code to clipboard</li>
<li>In Bricks Builder, add a <strong>Code</strong> element</li>
<li>Paste the JavaScript code</li>
<li>To add the effect to any section: go to <strong>Section → Style → Attributes</strong>, add <code>data-prism-border</code> as attribute name (leave value empty)</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<div class="content">
<section class="preview-section">
<div class="preview-container" id="prism-border-preview">
<div class="prism-preview" data-prism-border>
<div class="prism-preview-content">
Interactive Prism Border Preview
</div>
</div>
</div>
</section>
<section class="controls-section">
<div class="card">
<div class="card-heading">
Gradient Colors
<div class="card-actions">
<button class="card-action-btn" id="reset-colors" title="Reset Colors">↺</button>
</div>
</div>
<div class="card-content">
<div class="color-list">
<div class="color-row">
<div class="color-picker-container">
<input type="color" id="color1" value="#ff00ff">
</div>
<div class="color-input-group">
<span class="color-label">HEX</span>
<input type="text" class="color-input hex-input" id="color1-hex" value="#ff00ff" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">HSL</span>
<input type="text" class="color-input hsl-input" id="color1-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
<div class="color-row">
<div class="color-picker-container">
<input type="color" id="color2" value="#00ffff">
</div>
<div class="color-input-group">
<span class="color-label">HEX</span>
<input type="text" class="color-input hex-input" id="color2-hex" value="#00ffff" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">HSL</span>
<input type="text" class="color-input hsl-input" id="color2-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
</div>
<div class="gradient-add-btn" id="add-gradient-color">
<span>+</span>
<span>Add Color</span>
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Animation Settings
<div class="card-actions">
<button class="card-action-btn" id="reset-animation" title="Reset Animation Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">
Animation Speed
<span class="help-tooltip" title="Controls the speed of the gradient animation">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="speed-value">15</span>s</span>
<button class="reset-btn" onclick="resetParameter('animation-speed', 15)">↺</button>
</div>
</div>
<input type="range" id="animation-speed" min="1" max="30" step="1" value="15">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Blur Amount
<span class="help-tooltip" title="Controls the blur intensity of the gradient">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="blur-value">5</span>px</span>
<button class="reset-btn" onclick="resetParameter('blur-amount', 5)">↺</button>
</div>
</div>
<input type="range" id="blur-amount" min="0" max="20" step="1" value="5">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Border Width
<span class="help-tooltip" title="Controls the thickness of the border">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="width-value">2</span>px</span>
<button class="reset-btn" onclick="resetParameter('border-width', 2)">↺</button>
</div>
</div>
<input type="range" id="border-width" min="1" max="10" step="1" value="2">
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Advanced Options
<div class="card-actions">
<button class="card-action-btn" id="reset-advanced" title="Reset Advanced Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Z-Index Position</span>
<div class="value-display">
<span class="value-text" id="z-index-value">-1</span>
<button class="reset-btn" onclick="resetParameter('z-index', -1)">↺</button>
</div>
</div>
<input type="range" id="z-index" min="-10" max="10" value="-1" step="1">
</div>
</div>
</div>
</section>
</div>
</div>
<div class="notification" id="notification"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
let prismBorderConfig = {
colors: ['#ff00ff', '#00ffff'],
speed: '15s',
blur: '5px',
width: '2px',
zIndex: -1
};
const defaultConfig = { ...prismBorderConfig };
let activePreview = null;
function generateUniqueId() {
return Math.random().toString(36).substring(2, 8);
}
function initPrismBorder() {
const sections = document.querySelectorAll('[data-prism-border]:not([data-prism-initialized="true"])');
sections.forEach((section) => {
const colors = [];
for (let i = 1; i <= 10; i++) {
const colorAttr = `data-prism-border-color${i}`;
if (section.hasAttribute(colorAttr)) {
colors.push(section.getAttribute(colorAttr));
}
}
const finalColors = colors.length > 0 ? colors : prismBorderConfig.colors;
const speed = section.hasAttribute('data-prism-border-speed')
? section.getAttribute('data-prism-border-speed')
: prismBorderConfig.speed;
const blur = section.hasAttribute('data-prism-border-blur')
? section.getAttribute('data-prism-border-blur')
: prismBorderConfig.blur;
const width = section.hasAttribute('data-prism-border-width')
? section.getAttribute('data-prism-border-width')
: prismBorderConfig.width;
const zIndex = section.hasAttribute('data-prism-border-z-index')
? parseInt(section.getAttribute('data-prism-border-z-index'))
: prismBorderConfig.zIndex;
const options = {
colors: finalColors,
speed,
blur,
width,
zIndex
};
setupPrismBorder(section, options);
section.dataset.prismInitialized = 'true';
if (section.closest('#prism-border-preview')) {
activePreview = { element: section, options };
}
});
}
function setupPrismBorder(element, options) {
cleanupPrismBorder(element);
element.style.position = 'relative';
element.style.zIndex = '0';
element.style.overflow = 'visible';
element.style.transform = 'translateZ(0)';
element.style.webkitTransform = 'translateZ(0)';
const beforeElement = document.createElement('div');
const afterElement = document.createElement('div');
const colorArray = [...options.colors, options.colors[0]];
const gradientBackground = `linear-gradient(90deg, ${colorArray.join(',')})`;
const borderWidth = parseInt(options.width);
beforeElement.style.cssText = `
content: '';
position: absolute;
z-index: ${options.zIndex};
top: -${borderWidth}px;
right: -${borderWidth}px;
bottom: -${borderWidth}px;
left: -${borderWidth}px;
background: ${gradientBackground};
background-size: 200% 100%;
filter: blur(${options.blur});
animation: prismBorderMove ${options.speed} linear infinite;
border-radius: inherit;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
`;
afterElement.style.cssText = `
content: '';
position: absolute;
z-index: ${options.zIndex + 1};
inset: 0;
background: inherit;
border-radius: inherit;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
`;
element.appendChild(beforeElement);
element.appendChild(afterElement);
element._prismElements = [beforeElement, afterElement];
}
function cleanupPrismBorder(element) {
if (element._prismElements) {
element._prismElements.forEach(el => {
if (el.parentNode) {
el.parentNode.removeChild(el);
}
});
element._prismElements = null;
}
}
function updateConfig() {
if (activePreview) {
const newOptions = {
colors: prismBorderConfig.colors,
speed: prismBorderConfig.speed,
blur: prismBorderConfig.blur,
width: prismBorderConfig.width,
zIndex: prismBorderConfig.zIndex
};
setupPrismBorder(activePreview.element, newOptions);
activePreview.options = newOptions;
}
}
function updatePrismBorderPreview() {
const preview = document.querySelector('[data-prism-border]');
if (!preview) return;
preview.removeAttribute('data-prism-initialized');
for (let i = 0; i < prismBorderConfig.colors.length; i++) {
preview.setAttribute(`data-prism-border-color${i+1}`, prismBorderConfig.colors[i]);
}
preview.setAttribute('data-prism-border-speed', prismBorderConfig.speed);
preview.setAttribute('data-prism-border-blur', prismBorderConfig.blur);
preview.setAttribute('data-prism-border-width', prismBorderConfig.width);
preview.setAttribute('data-prism-border-z-index', prismBorderConfig.zIndex);
initPrismBorder();
}
function hexToHsl(hex) {
const r = parseInt(hex.slice(1, 3), 16) / 255;
const g = parseInt(hex.slice(3, 5), 16) / 255;
const b = parseInt(hex.slice(5, 7), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
let h, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`;
}
function hslToHex(hsl) {
const match = hsl.match(/hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/);
if (!match) return null;
let h = parseInt(match[1]) / 360;
let s = parseInt(match[2]) / 100;
let l = parseInt(match[3]) / 100;
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
const toHex = (c) => {
const hex = Math.round(c * 255).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
function isValidHex(hex) {
return /^#[0-9A-F]{6}$/i.test(hex);
}
function isValidHsl(hsl) {
return /^hsl\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*\)$/i.test(hsl);
}
function formatHex(value) {
let hex = value.replace(/[^0-9A-Fa-f#]/g, '');
if (!hex.startsWith('#')) {
hex = '#' + hex;
}
if (hex.length > 7) {
hex = hex.substring(0, 7);
}
return hex.toUpperCase();
}
function formatHsl(value) {
const cleanValue = value.replace(/[^\d,\s]/g, '');
const numbers = cleanValue.match(/\d+/g);
if (!numbers || numbers.length < 3) {
const partialMatch = value.match(/(\d+)/g);
if (partialMatch && partialMatch.length >= 1) {
const h = Math.min(360, Math.max(0, parseInt(partialMatch[0]) || 0));
const s = Math.min(100, Math.max(0, parseInt(partialMatch[1]) || 50));
const l = Math.min(100, Math.max(0, parseInt(partialMatch[2]) || 50));
return `hsl(${h}, ${s}%, ${l}%)`;
}
return value;
}
let h = Math.min(360, Math.max(0, parseInt(numbers[0])));
let s = Math.min(100, Math.max(0, parseInt(numbers[1])));
let l = Math.min(100, Math.max(0, parseInt(numbers[2])));
return `hsl(${h}, ${s}%, ${l}%)`;
}
function showNotification(message, type = 'success') {
const notification = document.getElementById('notification');
notification.textContent = message;
notification.className = `notification ${type}`;
notification.offsetHeight;
notification.style.visibility = 'visible';
notification.classList.add('show');
setTimeout(() => {
notification.classList.remove('show');
setTimeout(() => {
if (!notification.classList.contains('show')) {
notification.style.visibility = 'hidden';
}
}, 400);
}, 3000);
}
function generateFullSectionJSON() {
const sectionId = generateUniqueId();
const containerId = generateUniqueId();
const divId = generateUniqueId();
const textId = generateUniqueId();
const codeId = generateUniqueId();
const attributeId = generateUniqueId();
const jsCode = generateJavaScriptCode();
const bricksJSON = {
"content": [
{
"id": sectionId,
"name": "section",
"parent": 0,
"children": [containerId, codeId],
"settings": {
"_justifyContent": "center",
"_background": {
"color": {
"hex": "#000000"
}
}
}
},
{
"id": containerId,
"name": "container",
"parent": sectionId,
"children": [divId],
"settings": {
"_direction": "row",
"_justifyContent": "center"
}
},
{
"id": divId,
"name": "div",
"parent": containerId,
"children": [textId],
"settings": {
"_attributes": [
{
"id": attributeId,
"name": "data-prism-border"
}
],
"_height": "200",
"_width": "200",
"_border": {
"radius": {
"top": "15",
"right": "15",
"bottom": "15",
"left": "15"
}
},
"_display": "flex",
"_alignItems": "center",
"_justifyContent": "center",
"_background": {
"color": {
"hex": "#000000"
}
}
},
"label": "Prism Border Div"
},
{
"id": textId,
"name": "text-basic",
"parent": divId,
"children": [],
"settings": {
"text": "Prism Border",
"tag": "p",
"_typography": {
"color": {
"hex": "#ffffff"
},
"font-weight": "400"
},
"_zIndex": "1"
}
},
{
"id": codeId,
"name": "code",
"parent": sectionId,
"children": [],
"settings": {
"javascriptCode": jsCode,
"executeCode": true,
"_display": "none"
},
"label": "Prism Border JS"
}
],
"source": "bricksCopiedElements",
"sourceUrl": "https://test.bricksfusion.com",
"version": "2.0.1",
"globalClasses": [],
"globalElements": []
};
return JSON.stringify(bricksJSON, null, 2);
}
function generateJavaScriptCode() {
const colors = prismBorderConfig.colors;
const speed = prismBorderConfig.speed;
const blur = prismBorderConfig.blur;
const width = prismBorderConfig.width;
const zIndex = prismBorderConfig.zIndex;
return `(function() {
const config = {
colors: ${JSON.stringify(colors)},
speed: '${speed}',
blur: '${blur}',
width: '${width}',
zIndex: ${zIndex}
};
const styleSheet = document.createElement('style');
styleSheet.textContent = \`
@keyframes prismBorderMove {
0% { background-position: 0% 50%; }
25% { background-position: 100% 50%; }
50% { background-position: 200% 50%; }
75% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
\`;
document.head.appendChild(styleSheet);
const createdElements = new WeakMap();
function syncBorderRadius(element, beforeElement, afterElement) {
const computedStyle = window.getComputedStyle(element);
const borderRadius = computedStyle.borderRadius;
if (borderRadius && borderRadius !== '0px') {
beforeElement.style.borderRadius = borderRadius;
afterElement.style.borderRadius = borderRadius;
}
}
function cleanupElement(element) {
const elements = createdElements.get(element);
if (elements) {
elements.forEach(el => el.remove());
createdElements.delete(element);
}
}
function initPrismBorder() {
const elements = document.querySelectorAll('[data-prism-border]');
elements.forEach(element => {
cleanupElement(element);
element.style.position = 'relative';
element.style.zIndex = '0';
element.style.overflow = 'visible';
element.style.transform = 'translateZ(0)';
element.style.webkitTransform = 'translateZ(0)';
const beforeElement = document.createElement('div');
const afterElement = document.createElement('div');
createdElements.set(element, [beforeElement, afterElement]);
let colors = [];
for (let i = 1; i <= 10; i++) {
const colorAttr = \`data-prism-border-color\${i}\`;
if (element.hasAttribute(colorAttr)) {
colors.push(element.getAttribute(colorAttr));
}
}
if (colors.length === 0) {
colors = config.colors;
}
const speed = element.hasAttribute('data-prism-border-speed')
? element.getAttribute('data-prism-border-speed')
: config.speed;
const blur = element.hasAttribute('data-prism-border-blur')
? element.getAttribute('data-prism-border-blur')
: config.blur;
const width = element.hasAttribute('data-prism-border-width')
? element.getAttribute('data-prism-border-width')
: config.width;
const zIndex = element.hasAttribute('data-prism-border-z-index')
? parseInt(element.getAttribute('data-prism-border-z-index'))
: config.zIndex;
const colorArray = [...colors, colors[0]];
const gradientBackground = \`linear-gradient(90deg, \${colorArray.join(',')})\`;
const borderWidth = parseInt(width);
beforeElement.style.cssText = \`
content: '';
position: absolute;
z-index: \${zIndex};
top: -\${borderWidth}px;
right: -\${borderWidth}px;
bottom: -\${borderWidth}px;
left: -\${borderWidth}px;
background: \${gradientBackground};
background-size: 200% 100%;
filter: blur(\${blur});
animation: prismBorderMove \${speed} linear infinite;
will-change: border-radius;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
\`;
afterElement.style.cssText = \`
content: '';
position: absolute;
z-index: \${zIndex + 1};
inset: 0;
background: inherit;
will-change: border-radius;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
\`;
syncBorderRadius(element, beforeElement, afterElement);
element.appendChild(beforeElement);
element.appendChild(afterElement);
const resizeObserver = new ResizeObserver(() => {
syncBorderRadius(element, beforeElement, afterElement);
});
resizeObserver.observe(element);
});
}
function cleanup() {
const elements = document.querySelectorAll('[data-prism-border]');
elements.forEach(cleanupElement);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initPrismBorder);
} else {
initPrismBorder();
}
document.addEventListener('bricks-frontend-updated', () => {
cleanup();
initPrismBorder();
});
const observer = new MutationObserver((mutations) => {
let shouldReinit = false;
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' &&
(mutation.attributeName === 'style' || mutation.attributeName === 'class')) {
shouldReinit = true;
}
});
if (shouldReinit) {
initPrismBorder();
}
});
document.addEventListener('DOMContentLoaded', () => {
observer.observe(document.body, {
attributes: true,
subtree: true,
attributeFilter: ['style', 'class']
});
});
window.cleanupPrismBorders = cleanup;
})();`;
}
function copyJsToClipboard() {
const jsCode = generateJavaScriptCode();
navigator.clipboard.writeText(jsCode)
.then(() => {
showNotification('JavaScript code copied to clipboard!');
})
.catch(err => {
try {
const textArea = document.createElement('textarea');
textArea.value = jsCode;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showNotification('JavaScript code copied to clipboard!');
} catch (fallbackErr) {
showNotification('Failed to copy to clipboard. Please try again.', 'error');
}
});
}
function copyFullSectionToClipboard() {
const sectionJSON = generateFullSectionJSON();
navigator.clipboard.writeText(sectionJSON)
.then(() => {
showNotification('Full section JSON copied to clipboard!');
})
.catch(err => {
try {
const textArea = document.createElement('textarea');
textArea.value = sectionJSON;
textArea.style.position = 'fixed';
textArea.style.opacity = '0';
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
showNotification('Full section JSON copied to clipboard!');
} catch (fallbackErr) {
showNotification('Failed to copy to clipboard. Please try again.', 'error');
}
});
}
function copyToClipboard(text) {
navigator.clipboard.writeText(text)
.then(() => {
showNotification('Copied to clipboard!');
})
.catch(err => {
showNotification('Failed to copy to clipboard', 'error');
});
}
window.resetParameter = function(parameterId, defaultValue) {
const element = document.getElementById(parameterId);
if (element) {
element.value = defaultValue;
const valueElement = document.getElementById(`${parameterId.replace('animation-', '').replace('-amount', '').replace('-', '-')}-value`);
if (valueElement) {
valueElement.textContent = defaultValue;
}
switch (parameterId) {
case 'animation-speed':
prismBorderConfig.speed = defaultValue + 's';
break;
case 'blur-amount':
prismBorderConfig.blur = defaultValue + 'px';
break;
case 'border-width':
prismBorderConfig.width = defaultValue + 'px';
break;
case 'z-index':
prismBorderConfig.zIndex = defaultValue;
break;
}
updateConfig();
showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
}
};
function updateColorInputs() {
prismBorderConfig.colors.forEach((color, index) => {
const colorInput = document.getElementById(`color${index + 1}`);
const hexInput = document.getElementById(`color${index + 1}-hex`);
const hslInput = document.getElementById(`color${index + 1}-hsl`);
if (colorInput && hexInput && hslInput) {
colorInput.value = color;
hexInput.value = color;
hslInput.value = hexToHsl(color);
const container = colorInput.closest('.color-picker-container');
if (container) {
container.style.setProperty('--current-color', color);
}
hexInput.classList.remove('invalid');
hslInput.classList.remove('invalid');
}
});
}
function updateGradientColors() {
const container = document.getElementById('gradient-colors-list') || document.querySelector('.color-list');
if (!container) return;
container.innerHTML = '';
prismBorderConfig.colors.forEach((color, index) => {
const colorRow = createColorRow(color, index);
container.appendChild(colorRow);
});
}
function createColorRow(color, index) {
const colorRow = document.createElement('div');
colorRow.className = 'color-row';
colorRow.innerHTML = `
<div class="color-picker-container" style="--current-color: ${color}">
<input type="color" id="color${index + 1}" value="${color}">
</div>
<div class="color-input-group">
<span class="color-label">HEX</span>
<input type="text" class="color-input hex-input" id="color${index + 1}-hex" value="${color}" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">HSL</span>
<input type="text" class="color-input hsl-input" id="color${index + 1}-hsl" value="${hexToHsl(color)}" placeholder="hsl(0, 100%, 50%)">
</div>
${prismBorderConfig.colors.length > 2 ? `<button class="gradient-remove-btn" onclick="removeColor(${index})">×</button>` : ''}
`;
setupColorRowEvents(colorRow, index);
return colorRow;
}
function setupColorRowEvents(colorRow, index) {
const colorInput = colorRow.querySelector(`#color${index + 1}`);
const hexInput = colorRow.querySelector(`#color${index + 1}-hex`);
const hslInput = colorRow.querySelector(`#color${index + 1}-hsl`);
const container = colorRow.querySelector('.color-picker-container');
colorInput.addEventListener('input', () => {
const color = colorInput.value;
hexInput.value = color;
hslInput.value = hexToHsl(color);
hexInput.classList.remove('invalid');
hslInput.classList.remove('invalid');
container.style.setProperty('--current-color', color);
prismBorderConfig.colors[index] = color;
updateConfig();
});
hexInput.addEventListener('input', (e) => {
let hex = formatHex(e.target.value);
e.target.value = hex;
if (isValidHex(hex)) {
colorInput.value = hex;
hslInput.value = hexToHsl(hex);
container.style.setProperty('--current-color', hex);
prismBorderConfig.colors[index] = hex;
e.target.classList.remove('invalid');
hslInput.classList.remove('invalid');
updateConfig();
} else {
e.target.classList.add('invalid');
}
});
hexInput.addEventListener('blur', (e) => {
if (!isValidHex(e.target.value)) {
e.target.value = colorInput.value;
e.target.classList.remove('invalid');
}
});
hslInput.addEventListener('input', (e) => {
let hsl = e.target.value;
if (isValidHsl(hsl)) {
const hex = hslToHex(hsl);
if (hex) {
colorInput.value = hex;
hexInput.value = hex;
container.style.setProperty('--current-color', hex);
prismBorderConfig.colors[index] = hex;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
updateConfig();
return;
}
}
e.target.classList.add('invalid');
});
hslInput.addEventListener('blur', (e) => {
let hsl = e.target.value;
if (!isValidHsl(hsl) && hsl.trim()) {
const formatted = formatHsl(hsl);
if (isValidHsl(formatted)) {
e.target.value = formatted;
const hex = hslToHex(formatted);
if (hex) {
colorInput.value = hex;
hexInput.value = hex;
container.style.setProperty('--current-color', hex);
prismBorderConfig.colors[index] = hex;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
updateConfig();
return;
}
}
}
if (!isValidHsl(e.target.value)) {
e.target.value = hexToHsl(colorInput.value);
e.target.classList.remove('invalid');
}
});
}
window.removeColor = function(index) {
if (prismBorderConfig.colors.length > 2) {
prismBorderConfig.colors.splice(index, 1);
updateGradientColors();
updateConfig();
showNotification('Color removed');
}
};
function addGradientColor() {
const lastColor = prismBorderConfig.colors[prismBorderConfig.colors.length - 1];
const hue = (parseInt(lastColor.slice(1, 3), 16) + 30) % 256;
const newColor = `#${hue.toString(16).padStart(2, '0')}ffff`;
prismBorderConfig.colors.push(newColor);
updateGradientColors();
updateConfig();
showNotification('Color added');
}
function initializeUI() {
initPrismBorder();
const instructionsToggle = document.getElementById('instructions-toggle');
const instructionsContent = document.getElementById('instructions-content');
const instructionsCard = document.getElementById('instructions-card');
const toggleIcon = instructionsToggle.querySelector('.toggle-icon');
instructionsToggle.addEventListener('click', () => {
const isVisible = instructionsContent.classList.contains('show');
if (isVisible) {
instructionsContent.classList.remove('show');
instructionsCard.classList.remove('expanded');
toggleIcon.classList.remove('expanded');
} else {
instructionsContent.classList.add('show');
instructionsCard.classList.add('expanded');
toggleIcon.classList.add('expanded');
}
});
document.getElementById('quick-attribute').addEventListener('click', () => {
copyToClipboard('data-prism-border');
});
document.getElementById('download-config').addEventListener('click', () => {
copyJsToClipboard();
});
document.getElementById('copy-full-section').addEventListener('click', () => {
copyFullSectionToClipboard();
});
document.getElementById('reset-colors').addEventListener('click', () => {
prismBorderConfig.colors = [...defaultConfig.colors];
updateGradientColors();
updateConfig();
showNotification('Colors reset to default');
});
document.getElementById('reset-animation').addEventListener('click', () => {
prismBorderConfig.speed = defaultConfig.speed;
prismBorderConfig.blur = defaultConfig.blur;
prismBorderConfig.width = defaultConfig.width;
document.getElementById('animation-speed').value = parseInt(defaultConfig.speed);
document.getElementById('blur-amount').value = parseInt(defaultConfig.blur);
document.getElementById('border-width').value = parseInt(defaultConfig.width);
document.getElementById('speed-value').textContent = parseInt(defaultConfig.speed);
document.getElementById('blur-value').textContent = parseInt(defaultConfig.blur);
document.getElementById('width-value').textContent = parseInt(defaultConfig.width);
updateConfig();
showNotification('Animation settings reset');
});
document.getElementById('reset-advanced').addEventListener('click', () => {
prismBorderConfig.zIndex = defaultConfig.zIndex;
document.getElementById('z-index').value = defaultConfig.zIndex;
document.getElementById('z-index-value').textContent = defaultConfig.zIndex;
updateConfig();
showNotification('Advanced settings reset');
});
document.getElementById('add-gradient-color').addEventListener('click', addGradientColor);
const rangeInputs = document.querySelectorAll('input[type="range"]');
rangeInputs.forEach(input => {
let valueElement;
switch (input.id) {
case 'animation-speed':
valueElement = document.getElementById('speed-value');
break;
case 'blur-amount':
valueElement = document.getElementById('blur-value');
break;
case 'border-width':
valueElement = document.getElementById('width-value');
break;
case 'z-index':
valueElement = document.getElementById('z-index-value');
break;
}
if (valueElement) {
valueElement.textContent = input.value;
}
input.addEventListener('input', () => {
if (valueElement) {
valueElement.textContent = input.value;
}
switch (input.id) {
case 'animation-speed':
prismBorderConfig.speed = input.value + 's';
break;
case 'blur-amount':
prismBorderConfig.blur = input.value + 'px';
break;
case 'border-width':
prismBorderConfig.width = input.value + 'px';
break;
case 'z-index':
prismBorderConfig.zIndex = parseInt(input.value);
break;
}
updateConfig();
});
});
document.addEventListener('keydown', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
return;
}
if (e.ctrlKey || e.metaKey) {
switch (e.key.toLowerCase()) {
case 'd':
e.preventDefault();
const downloadBtn = document.getElementById('download-config');
if (downloadBtn && downloadBtn.hasAttribute('data-protection-animation')) {
downloadBtn.click();
} else {
copyJsToClipboard();
}
break;
case 's':
e.preventDefault();
const fullSectionBtn = document.getElementById('copy-full-section');
if (fullSectionBtn && fullSectionBtn.hasAttribute('data-protection-animation')) {
fullSectionBtn.click();
} else {
copyFullSectionToClipboard();
}
break;
}
}
});
updateGradientColors();
setTimeout(() => {
showNotification('BricksFusion Prism Border Configurator loaded!');
}, 500);
function saveConfiguration() {
try {
localStorage.setItem('bricksfusion-prism-border-config', JSON.stringify(prismBorderConfig));
} catch (e) {
}
}
function loadConfiguration() {
try {
const saved = localStorage.getItem('bricksfusion-prism-border-config');
if (saved) {
const savedConfig = JSON.parse(saved);
Object.assign(prismBorderConfig, savedConfig);
document.getElementById('animation-speed').value = parseInt(savedConfig.speed);
document.getElementById('blur-amount').value = parseInt(savedConfig.blur);
document.getElementById('border-width').value = parseInt(savedConfig.width);
document.getElementById('z-index').value = savedConfig.zIndex;
document.getElementById('speed-value').textContent = parseInt(savedConfig.speed);
document.getElementById('blur-value').textContent = parseInt(savedConfig.blur);
document.getElementById('width-value').textContent = parseInt(savedConfig.width);
document.getElementById('z-index-value').textContent = savedConfig.zIndex;
updateGradientColors();
updateConfig();
}
} catch (e) {
}
}
const originalUpdateConfig = updateConfig;
updateConfig = function() {
originalUpdateConfig();
saveConfiguration();
};
loadConfiguration();
}
initializeUI();
});
</script>
</body>
</html>
Prism Border
Creates animated gradient borders that flow smoothly around elements. Features customizable color stops that cycle through your chosen palette. Add soft blur for glowing effects or keep sharp for clean lines. Automatically adapts to element's border radius. Perfect for cards, buttons, or highlighting important content with eye-catching animated borders.
Prism Border
Animated gradient border flowing around the box.
Colors
Choose between 2 and 10 colors for your animated gradient. The border will smoothly transition through all selected colors in sequence, creating a flowing rainbow effect.
Default: Magenta and Cyan
Animation
How quickly the gradient flows around the border. Lower values create slow, elegant movement. Higher values produce fast, energetic flow.
Default: Moderate (15s)
Style
Softness of the border edges. Lower keeps borders crisp and defined. Higher creates a glowing, diffused effect.
Default: Soft (5px)
Thickness of the animated border. Lower creates delicate outlines. Higher produces bold, prominent borders.
Default: Thin (2px)
Layout
Controls whether the border appears behind or in front of your content. Negative values push it behind, positive brings it forward.
Default: Behind content (-1)
Performance
This element uses CSS animations with linear gradients and blur filters. Creates pseudo-elements for the border effect using CSS transforms. Features automatic border-radius inheritance from parent element. Uses ResizeObserver for responsive border-radius updates. Very lightweight - suitable for all devices with unlimited instances per page and smooth 60fps performance.