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">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/themify-icons@1.0.1/css/themify-icons.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Social Bloom Effect 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: hidden;
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;
}
.social-bloom-card {
width: 200px;
height: 200px;
border-radius: 30px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}
.preview-content {
color: white;
text-align: center;
font-weight: bold;
font-size: var(--text-s);
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
}
.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);
}
.preview-btn svg {
width: 18px;
height: 18px;
stroke: currentColor;
}
.background-selector-wrapper {
position: relative;
display: inline-block;
}
.background-selector-btn {
position: relative;
}
.background-selector-btn:hover {
background-color: rgba(239, 96, 19, 0.2);
border-color: var(--accent);
box-shadow: 0 0 8px rgba(239, 96, 19, 0.3);
}
.hidden-color-input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
z-index: 1;
}
.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;
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: var(--card-bg);
display: flex;
align-items: center;
justify-content: center;
--selected-color: #3b82f6;
}
.color-picker-container:hover {
border-color: var(--accent);
transform: scale(1.05);
box-shadow: 0 0 12px rgba(239, 96, 19, 0.3);
}
.color-picker-container::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--selected-color, #3b82f6);
border-radius: 6px;
transition: var(--transition);
}
input[type="color"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: none;
cursor: pointer;
background: transparent;
opacity: 0;
z-index: 2;
}
.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;
}
select {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border);
border-radius: var(--input-radius);
font-family: var(--font);
font-size: var(--text-xs);
color: var(--text-primary);
background-color: var(--card-bg);
margin-bottom: 0.75rem;
outline: none;
transition: var(--transition);
}
select:focus {
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(239, 96, 19, 0.2);
}
input[type="text"],
input[type="number"] {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border);
border-radius: var(--input-radius);
font-family: var(--font);
font-size: var(--text-xs);
color: var(--text-primary);
background-color: var(--card-bg);
margin-bottom: 0.75rem;
outline: none;
transition: var(--transition);
}
input[type="text"]:focus,
input[type="number"]:focus {
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(239, 96, 19, 0.2);
}
.social-icons-list {
max-height: 200px;
overflow-y: auto;
padding-right: 8px;
}
.social-icon-container {
margin-bottom: 1rem;
}
.icon-input-row {
display: flex;
gap: 8px;
margin-bottom: 12px;
align-items: center;
}
.icon-input-row select {
flex: 1;
margin-bottom: 0;
}
.remove-icon {
background: none;
border: none;
color: var(--text-secondary);
cursor: pointer;
font-size: 16px;
padding: 4px;
transition: var(--transition);
display: flex;
align-items: center;
justify-content: center;
min-width: 32px;
height: 32px;
border-radius: 4px;
}
.remove-icon:hover {
color: #ff4f4f;
background-color: rgba(255, 79, 79, 0.1);
}
.add-icon-btn {
background: none;
border: 1px solid var(--border);
border-radius: var(--input-radius);
color: var(--text-secondary);
cursor: pointer;
transition: var(--transition);
padding: 8px 12px;
font-size: var(--text-xs);
margin-top: 8px;
display: flex;
align-items: center;
gap: 8px;
}
.add-icon-btn:hover {
background-color: rgba(239, 96, 19, 0.1);
border-color: var(--accent);
color: var(--text-primary);
}
.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;
}
@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;
}
.social-bloom-card {
width: 180px;
height: 180px;
}
.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/interaction/" class="breadcrumb-item">Interactions</a>
<span class="breadcrumb-separator">›</span>
<span class="breadcrumb-item active">Social Bloom</span>
</nav>
<div class="action-buttons">
<div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
data-social-bloom
</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">Social Bloom</h1>
<p class="page-subtitle">Interactive social cards 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 social bloom effect 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-social-bloom</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="social-bloom-preview" data-social-bloom="true">
<div class="social-bloom-card" id="bloom-preview" data-social-bloom>
</div>
<div class="preview-controls">
<button class="preview-btn" id="randomize-social-bloom" title="Randomize (R)">🎲</button>
<div class="background-selector-wrapper">
<button class="preview-btn background-selector-btn" id="background-selector">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polygon points="12,2 2,7 12,12 22,7"/>
<polyline points="2,17 12,22 22,17"/>
<polyline points="2,12 12,17 22,12"/>
</svg>
</button>
<input type="color" id="preview-background-picker" class="hidden-color-input" value="#252525" title="Change Preview Background (B)">
</div>
</div>
</div>
</section>
<section class="controls-section">
<div class="card">
<div class="card-heading">
Card Settings
<div class="card-actions">
<button class="card-action-btn" id="reset-card" title="Reset Card Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Card Title</span>
</div>
<input type="text" id="card-title" placeholder="Enter card title" value="Social">
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Gradient Theme
<div class="card-actions">
<button class="card-action-btn" id="reset-gradient" title="Reset Gradient Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Theme</span>
</div>
<select id="gradient-theme">
<option value="monterey">Monterey</option>
<option value="bigsur">Big Sur</option>
<option value="catalyst">Catalyst</option>
<option value="ventura">Ventura</option>
<option value="sonoma">Sonoma</option>
<option value="quantum">Quantum</option>
<option value="aurora">Aurora</option>
<option value="carbon">Carbon</option>
<option value="silver">Silver</option>
<option value="space">Space</option>
<option value="custom">Custom</option>
</select>
</div>
<div id="custom-gradient-controls" style="display: none;">
<div class="control-group">
<div class="control-label">
<span class="label-text">Custom Gradient Colors</span>
</div>
<div class="color-list">
<div class="color-row">
<div class="color-picker-container" style="--selected-color: #A8E48A;">
<input type="color" id="main-color1" value="#A8E48A">
</div>
<div class="color-input-group">
<span class="color-label">HEX</span>
<input type="text" class="color-input hex-input" id="main-color1-hex" value="#A8E48A" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">HSL</span>
<input type="text" class="color-input hsl-input" id="main-color1-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
<div class="color-row">
<div class="color-picker-container" style="--selected-color: #1EB980;">
<input type="color" id="main-color2" value="#1EB980">
</div>
<div class="color-input-group">
<span class="color-label">HEX</span>
<input type="text" class="color-input hex-input" id="main-color2-hex" value="#1EB980" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">HSL</span>
<input type="text" class="color-input hsl-input" id="main-color2-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Social Icons
<div class="card-actions">
<button class="card-action-btn" id="reset-icons" title="Reset Social Icons">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="social-icons-list" id="social-icons-list">
</div>
<button class="add-icon-btn" id="add-icon-btn">
<i class="fas fa-plus"></i> Add Social Icon
</button>
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Typography
<div class="card-actions">
<button class="card-action-btn" id="reset-typography" title="Reset Typography">↺</button>
</div>
</div>
<div class="card-content">
<div class="color-list">
<div class="color-row">
<div class="color-picker-container" style="--selected-color: #ffffff;">
<input type="color" id="title-color" value="#ffffff">
</div>
<div class="color-input-group">
<span class="color-label">TITLE HEX</span>
<input type="text" class="color-input hex-input" id="title-color-hex" value="#ffffff" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">TITLE HSL</span>
<input type="text" class="color-input hsl-input" id="title-color-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
<div class="color-row">
<div class="color-picker-container" style="--selected-color: #ffffff;">
<input type="color" id="icon-color" value="#ffffff">
</div>
<div class="color-input-group">
<span class="color-label">ICON HEX</span>
<input type="text" class="color-input hex-input" id="icon-color-hex" value="#ffffff" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">ICON HSL</span>
<input type="text" class="color-input hsl-input" id="icon-color-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">Font Family</span>
</div>
<select id="font-family">
<option value="system-ui">System UI</option>
<option value="Inter">Inter</option>
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Georgia">Georgia</option>
<option value="Times New Roman">Times New Roman</option>
</select>
</div>
</div>
</div>
</section>
</div>
</div>
<div class="notification" id="notification"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
let bloomConfig = {
title: 'Social',
gradientType: 'monterey',
titleColor: '#ffffff',
iconColor: '#ffffff',
fontFamily: 'system-ui',
socialIcons: [
{ icon: 'ti-facebook', url: 'https://facebook.com' },
{ icon: 'ti-twitter-alt', url: 'https://twitter.com' },
{ icon: 'ti-instagram', url: 'https://instagram.com' }
],
customGradient: {
mainColor1: '#A8E48A',
mainColor2: '#1EB980'
}
};
const defaultConfig = JSON.parse(JSON.stringify(bloomConfig));
let activeBoom = null;
const gradients = {
monterey: {
main: 'linear-gradient(-45deg, #A8E48A 0%, #1EB980 100%)',
slice1: 'linear-gradient(120deg, #34e89e 0%, #0f3443 100%)',
slice2: 'linear-gradient(120deg, #96fbc4 0%, #f9f586 100%)',
slice3: 'linear-gradient(120deg, #38ef7d 0%, #11998e 100%)'
},
bigsur: {
main: 'linear-gradient(-45deg, #00C6FB 0%, #005BEA 100%)',
slice1: 'linear-gradient(120deg, #4facfe 0%, #00f2fe 100%)',
slice2: 'linear-gradient(120deg, #0396FF 0%, #ABDCFF 100%)',
slice3: 'linear-gradient(120deg, #45B649 0%, #DCE35B 100%)'
},
catalyst: {
main: 'linear-gradient(-45deg, #FF6B6B 0%, #FF3366 100%)',
slice1: 'linear-gradient(120deg, #FF0844 0%, #FFB199 100%)',
slice2: 'linear-gradient(120deg, #F6416C 0%, #FFF6B7 100%)',
slice3: 'linear-gradient(120deg, #FF9A9E 0%, #FAD0C4 100%)'
},
ventura: {
main: 'linear-gradient(-45deg, #4158D0 0%, #2563EB 100%)',
slice1: 'linear-gradient(120deg, #0093E9 0%, #80D0C7 100%)',
slice2: 'linear-gradient(120deg, #8EC5FC 0%, #E0C3FC 100%)',
slice3: 'linear-gradient(120deg, #4158D0 0%, #C850C0 100%)'
},
sonoma: {
main: 'linear-gradient(-45deg, #0EA5E9 0%, #2563EB 100%)',
slice1: 'linear-gradient(120deg, #00DBDE 0%, #FC00FF 100%)',
slice2: 'linear-gradient(120deg, #0093E9 0%, #80D0C7 100%)',
slice3: 'linear-gradient(120deg, #48c6ef 0%, #6f86d6 100%)'
},
quantum: {
main: 'linear-gradient(-45deg, #7F00FF 0%, #E100FF 100%)',
slice1: 'linear-gradient(120deg, #FC466B 0%, #3F5EFB 100%)',
slice2: 'linear-gradient(120deg, #3F5EFB 0%, #FC466B 100%)',
slice3: 'linear-gradient(120deg, #8E2DE2 0%, #4A00E0 100%)'
},
aurora: {
main: 'linear-gradient(-45deg, #08AEEA 0%, #2AF598 100%)',
slice1: 'linear-gradient(120deg, #FA8BFF 0%, #2BD2FF 100%)',
slice2: 'linear-gradient(120deg, #2BD2FF 0%, #2BFF88 100%)',
slice3: 'linear-gradient(120deg, #FEE140 0%, #FA709A 100%)'
},
carbon: {
main: 'linear-gradient(-45deg, #1A1A1A 0%, #434343 100%)',
slice1: 'linear-gradient(120deg, #434343 0%, #000000 100%)',
slice2: 'linear-gradient(120deg, #232526 0%, #414345 100%)',
slice3: 'linear-gradient(120deg, #000000 0%, #0f9b0f 100%)'
},
silver: {
main: 'linear-gradient(-45deg, #BDBBBE 0%, #9D9EA3 100%)',
slice1: 'linear-gradient(120deg, #E6DADA 0%, #274046 100%)',
slice2: 'linear-gradient(120deg, #9D9EA3 0%, #E6DADA 100%)',
slice3: 'linear-gradient(120deg, #5D4157 0%, #A8CABA 100%)'
},
space: {
main: 'linear-gradient(-45deg, #000000 0%, #434343 100%)',
slice1: 'linear-gradient(120deg, #09203f 0%, #537895 100%)',
slice2: 'linear-gradient(120deg, #29323c 0%, #485563 100%)',
slice3: 'linear-gradient(120deg, #1e3c72 0%, #2a5298 100%)'
}
};
const socialIcons = [
{ value: 'ti-facebook', label: 'Facebook' },
{ value: 'ti-twitter-alt', label: 'Twitter' },
{ value: 'ti-instagram', label: 'Instagram' },
{ value: 'ti-linkedin', label: 'LinkedIn' },
{ value: 'ti-youtube', label: 'YouTube' },
{ value: 'ti-github', label: 'GitHub' },
{ value: 'ti-email', label: 'Email' },
{ value: 'ti-world', label: 'Website' },
{ value: 'ti-pinterest', label: 'Pinterest' },
{ value: 'ti-vimeo-alt', label: 'Vimeo' },
{ value: 'ti-dribbble', label: 'Dribbble' },
{ value: 'ti-skype', label: 'Skype' },
{ value: 'ti-tumblr-alt', label: 'Tumblr' },
{ value: 'ti-flickr-alt', label: 'Flickr' }
];
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 {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: 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 generateRandomColor() {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}
function generateUniqueId() {
return Math.random().toString(36).substring(2, 8);
}
function generateFullSectionJSON() {
// Generar IDs únicos para todos los elementos
const sectionId = generateUniqueId();
const containerId = generateUniqueId();
const divId = generateUniqueId();
const codeId = generateUniqueId();
const attributeId1 = generateUniqueId();
const attributeId2 = generateUniqueId();
// Obtener el JavaScript actual con la configuración del usuario
const jsCode = generateJavaScriptCode();
// Crear el objeto JSON completo de Bricks Builder
const bricksJSON = {
"content": [
{
"id": sectionId,
"name": "section",
"parent": 0,
"children": [containerId, codeId],
"settings": {
"_justifyContent": "center",
"_height": "500",
"_background": {
"color": {
"hex": "#000000"
}
}
}
},
{
"id": containerId,
"name": "container",
"parent": sectionId,
"children": [divId],
"settings": {
"_alignSelf": "center",
"_justifyContent": "center",
"_alignItems": "center",
"_direction": "row",
"_attributes": [
{
"id": attributeId1,
"name": "data-float-container"
}
]
}
},
{
"id": divId,
"name": "div",
"parent": containerId,
"children": [],
"settings": {
"_zIndex": "99",
"_attributes": [
{
"id": attributeId2,
"name": "data-social-bloom"
}
],
"_width": "280",
"_height": "300",
"_border": {
"radius": {
"top": "15",
"right": "15",
"bottom": "15",
"left": "15"
}
}
},
"label": "Social Bloom Div"
},
{
"id": codeId,
"name": "code",
"parent": sectionId,
"children": [],
"settings": {
"javascriptCode": jsCode,
"executeCode": true,
"_display": "none"
},
"label": "Social Bloom JS"
}
],
"source": "bricksCopiedElements",
"sourceUrl": "https://test.bricksfusion.com",
"version": "2.0.1",
"globalClasses": [],
"globalElements": []
};
return JSON.stringify(bricksJSON, null, 2);
}
function generateJavaScriptCode() {
const customGradientCode = bloomConfig.gradientType === 'custom' ?
`,
custom: {
main: 'linear-gradient(-45deg, ${bloomConfig.customGradient.mainColor1} 0%, ${bloomConfig.customGradient.mainColor2} 100%)',
slice1: 'linear-gradient(120deg, ${bloomConfig.customGradient.mainColor1} 0%, ${bloomConfig.customGradient.mainColor2} 100%)',
slice2: 'linear-gradient(120deg, ${bloomConfig.customGradient.mainColor2} 0%, ${bloomConfig.customGradient.mainColor1} 100%)',
slice3: 'linear-gradient(120deg, ${bloomConfig.customGradient.mainColor1} 50%, ${bloomConfig.customGradient.mainColor2} 100%)'
}` : '';
return `class SocialBloomCard {
constructor() {
this.loadAllIconLibraries();
this.gradients = {
monterey: {
main: 'linear-gradient(-45deg, #A8E48A 0%, #1EB980 100%)',
slice1: 'linear-gradient(120deg, #34e89e 0%, #0f3443 100%)',
slice2: 'linear-gradient(120deg, #96fbc4 0%, #f9f586 100%)',
slice3: 'linear-gradient(120deg, #38ef7d 0%, #11998e 100%)'
},
bigsur: {
main: 'linear-gradient(-45deg, #00C6FB 0%, #005BEA 100%)',
slice1: 'linear-gradient(120deg, #4facfe 0%, #00f2fe 100%)',
slice2: 'linear-gradient(120deg, #0396FF 0%, #ABDCFF 100%)',
slice3: 'linear-gradient(120deg, #45B649 0%, #DCE35B 100%)'
},
catalyst: {
main: 'linear-gradient(-45deg, #FF6B6B 0%, #FF3366 100%)',
slice1: 'linear-gradient(120deg, #FF0844 0%, #FFB199 100%)',
slice2: 'linear-gradient(120deg, #F6416C 0%, #FFF6B7 100%)',
slice3: 'linear-gradient(120deg, #FF9A9E 0%, #FAD0C4 100%)'
},
ventura: {
main: 'linear-gradient(-45deg, #4158D0 0%, #2563EB 100%)',
slice1: 'linear-gradient(120deg, #0093E9 0%, #80D0C7 100%)',
slice2: 'linear-gradient(120deg, #8EC5FC 0%, #E0C3FC 100%)',
slice3: 'linear-gradient(120deg, #4158D0 0%, #C850C0 100%)'
},
sonoma: {
main: 'linear-gradient(-45deg, #0EA5E9 0%, #2563EB 100%)',
slice1: 'linear-gradient(120deg, #00DBDE 0%, #FC00FF 100%)',
slice2: 'linear-gradient(120deg, #0093E9 0%, #80D0C7 100%)',
slice3: 'linear-gradient(120deg, #48c6ef 0%, #6f86d6 100%)'
},
quantum: {
main: 'linear-gradient(-45deg, #7F00FF 0%, #E100FF 100%)',
slice1: 'linear-gradient(120deg, #FC466B 0%, #3F5EFB 100%)',
slice2: 'linear-gradient(120deg, #3F5EFB 0%, #FC466B 100%)',
slice3: 'linear-gradient(120deg, #8E2DE2 0%, #4A00E0 100%)'
},
aurora: {
main: 'linear-gradient(-45deg, #08AEEA 0%, #2AF598 100%)',
slice1: 'linear-gradient(120deg, #FA8BFF 0%, #2BD2FF 100%)',
slice2: 'linear-gradient(120deg, #2BD2FF 0%, #2BFF88 100%)',
slice3: 'linear-gradient(120deg, #FEE140 0%, #FA709A 100%)'
},
carbon: {
main: 'linear-gradient(-45deg, #1A1A1A 0%, #434343 100%)',
slice1: 'linear-gradient(120deg, #434343 0%, #000000 100%)',
slice2: 'linear-gradient(120deg, #232526 0%, #414345 100%)',
slice3: 'linear-gradient(120deg, #000000 0%, #0f9b0f 100%)'
},
silver: {
main: 'linear-gradient(-45deg, #BDBBBE 0%, #9D9EA3 100%)',
slice1: 'linear-gradient(120deg, #E6DADA 0%, #274046 100%)',
slice2: 'linear-gradient(120deg, #9D9EA3 0%, #E6DADA 100%)',
slice3: 'linear-gradient(120deg, #5D4157 0%, #A8CABA 100%)'
},
space: {
main: 'linear-gradient(-45deg, #000000 0%, #434343 100%)',
slice1: 'linear-gradient(120deg, #09203f 0%, #537895 100%)',
slice2: 'linear-gradient(120deg, #29323c 0%, #485563 100%)',
slice3: 'linear-gradient(120deg, #1e3c72 0%, #2a5298 100%)'
}${customGradientCode}
};
this.defaultConfig = {
title: '${bloomConfig.title}',
gradientType: '${bloomConfig.gradientType}',
titleColor: '${bloomConfig.titleColor}',
iconColor: '${bloomConfig.iconColor}',
fontFamily: '${bloomConfig.fontFamily}',
socialIcons: ${JSON.stringify(bloomConfig.socialIcons)},
customGradient: ${JSON.stringify(bloomConfig.customGradient)}
};
this.instances = new Map();
this.init();
}
ensureFontAwesome() {
return new Promise((resolve) => {
const existingFA = document.querySelector('link[href*="font-awesome"]') || document.querySelector('link[href*="fontawesome"]');
if (existingFA) {
setTimeout(resolve, 100);
return;
}
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css';
link.crossOrigin = 'anonymous';
link.onload = () => resolve();
link.onerror = () => {
const altLink = document.createElement('link');
altLink.rel = 'stylesheet';
altLink.href = 'https://use.fontawesome.com/releases/v6.4.0/css/all.css';
altLink.crossOrigin = 'anonymous';
altLink.onload = () => resolve();
altLink.onerror = () => resolve();
document.head.appendChild(altLink);
};
document.head.appendChild(link);
});
}
loadAllIconLibraries() {
this.iconMapping = {
'ti-facebook': 'fab fa-facebook-f',
'ti-twitter-alt': 'fab fa-twitter',
'ti-instagram': 'fab fa-instagram',
'ti-linkedin': 'fab fa-linkedin-in',
'ti-youtube': 'fab fa-youtube',
'ti-github': 'fab fa-github',
'ti-email': 'fas fa-envelope',
'ti-world': 'fas fa-globe',
'ti-pinterest': 'fab fa-pinterest',
'ti-vimeo-alt': 'fab fa-vimeo-v',
'ti-dribbble': 'fab fa-dribbble',
'ti-skype': 'fab fa-skype',
'ti-tumblr-alt': 'fab fa-tumblr',
'ti-flickr-alt': 'fab fa-flickr'
};
}
async init() {
await this.ensureFontAwesome();
setTimeout(() => {
this.checkFontAwesome();
}, 500);
document.querySelectorAll('[data-social-bloom]').forEach(cardWrapper => {
this.setupCard(cardWrapper);
});
}
checkFontAwesome() {
const testIcon = document.createElement('i');
testIcon.className = 'fas fa-home';
testIcon.style.position = 'absolute';
testIcon.style.left = '-9999px';
document.body.appendChild(testIcon);
const computedStyle = window.getComputedStyle(testIcon, ':before');
const content = computedStyle.getPropertyValue('content');
document.body.removeChild(testIcon);
if (!content || content === 'none' || content === '""') {
document.body.classList.add('fa-fallback');
}
}
parseSocialData(data) {
if (!data) return null;
const [icon, url] = data.split('|').map(item => item.trim());
return { icon, url };
}
createSocialButton(socialData, boxClass, index) {
if (!socialData) return \`<div class="box \${boxClass}"></div>\`;
const iconClass = this.iconMapping[socialData.icon] || 'fas fa-link';
const textFallback = {
'ti-facebook': 'f',
'ti-twitter-alt': 't',
'ti-instagram': 'i',
'ti-linkedin': 'l',
'ti-youtube': 'y',
'ti-github': 'g',
'ti-email': '@',
'ti-world': 'w',
'ti-pinterest': 'p',
'ti-vimeo-alt': 'v',
'ti-dribbble': 'd',
'ti-skype': 's',
'ti-tumblr-alt': 'T',
'ti-flickr-alt': 'F'
};
const fallbackText = textFallback[socialData.icon] || '→';
return \`
<div class="box \${boxClass}">
<a href="\${socialData.url}" target="_blank" rel="noopener noreferrer">
<i class="icon \${iconClass}" data-fallback="\${fallbackText}"></i>
</a>
</div>
\`;
}
updateConfig(element, newConfig) {
const instance = this.instances.get(element);
if (!instance) return;
Object.assign(instance.config, newConfig);
element.querySelector('.logo').textContent = instance.config.title;
instance.styleElement.textContent = this.generateStyles(instance.uniqueId, instance.config);
const socialContainer = element.querySelector('.social-container');
if (socialContainer) {
const social1 = instance.config.socialIcons[0] || null;
const social2 = instance.config.socialIcons[1] || null;
const social3 = instance.config.socialIcons[2] || null;
socialContainer.innerHTML = \`
\${this.createSocialButton(social1, 'box1', 1)}
\${this.createSocialButton(social2, 'box2', 2)}
\${this.createSocialButton(social3, 'box3', 3)}
<div class="box box4"></div>
\`;
}
}
generateStyles(uniqueId, config) {
let gradientSet;
if (config.gradientType === 'custom') {
const color1 = config.customGradient.mainColor1;
const color2 = config.customGradient.mainColor2;
gradientSet = {
main: \`linear-gradient(-45deg, \${color1} 0%, \${color2} 100%)\`,
slice1: \`linear-gradient(120deg, \${color1} 0%, \${color2} 100%)\`,
slice2: \`linear-gradient(120deg, \${color2} 0%, \${color1} 100%)\`,
slice3: \`linear-gradient(120deg, \${color1} 50%, \${color2} 100%)\`
};
} else {
gradientSet = this.gradients[config.gradientType] || this.gradients.monterey;
}
return \`
.\${uniqueId} {
position: relative;
width: 100%;
height: 100%;
min-width: 150px;
min-height: 150px;
overflow: hidden;
box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 30px -5px;
transition: all 0.5s ease-in-out;
background: \${gradientSet.main};
font-family: \${config.fontFamily};
}
.\${uniqueId} .social-container {
position: relative;
width: 100%;
height: 100%;
}
.\${uniqueId} .logo {
position: absolute;
right: 50%;
bottom: 50%;
transform: translate(50%, 50%);
transition: all 0.6s ease-in-out;
font-size: 1.3em;
font-weight: 600;
color: \${config.titleColor};
letter-spacing: 3px;
z-index: 2;
}
.\${uniqueId} .box {
position: absolute;
padding: 10px;
text-align: right;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 10% 13% 42% 0%/10% 12% 75% 0%;
transform-origin: bottom left;
transition: all 0.6s ease-in-out;
}
.\${uniqueId} .box::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
opacity: 0;
transition: all 0.5s ease-in-out;
}
.\${uniqueId} .icon {
display: flex;
justify-content: center;
align-items: center;
width: 20px;
height: 20px;
font-size: 20px;
color: \${config.iconColor} !important;
transition: all 0.3s ease-in-out;
opacity: 0.9;
position: relative;
z-index: 2;
}
.\${uniqueId} .icon.fab,
.\${uniqueId} .icon.fas,
.\${uniqueId} .icon.far {
font-family: "Font Awesome 6 Free", "Font Awesome 6 Brands" !important;
font-weight: 900 !important;
font-style: normal !important;
color: \${config.iconColor} !important;
}
.\${uniqueId} .icon:not([class*="fa-"]):before,
.\${uniqueId} .icon.fa:before {
content: attr(data-fallback);
font-family: Arial, sans-serif;
font-weight: bold;
font-style: normal;
}
.\${uniqueId} .box:hover .icon {
opacity: 1;
transform: scale(1.1);
}
.\${uniqueId} .box1 {
width: 70%;
height: 70%;
bottom: -70%;
left: -70%;
}
.\${uniqueId} .box1::before {
background: \${gradientSet.slice1};
}
.\${uniqueId} .box2 {
width: 50%;
height: 50%;
bottom: -50%;
left: -50%;
transition-delay: 0.1s;
}
.\${uniqueId} .box2::before {
background: \${gradientSet.slice2};
}
.\${uniqueId} .box3 {
width: 30%;
height: 30%;
bottom: -30%;
left: -30%;
transition-delay: 0.2s;
}
.\${uniqueId} .box3::before {
background: \${gradientSet.slice3};
}
.\${uniqueId} .box4 {
width: 10%;
height: 10%;
bottom: -10%;
left: -10%;
transition-delay: 0.3s;
}
.\${uniqueId} .box:hover::before {
opacity: 1;
}
.\${uniqueId}:hover, .\${uniqueId}.active {
transform: scale(1.02);
box-shadow: rgba(0, 0, 0, 0.15) 0px 15px 35px -5px;
}
.\${uniqueId}:hover .box, .\${uniqueId} .social-container.active .box {
bottom: -1px;
left: -1px;
}
.\${uniqueId}:hover .logo, .\${uniqueId}.active .logo {
transform: translate(70px, -52px);
letter-spacing: 0px;
}
.\${uniqueId} a {
text-decoration: none;
display: block;
width: 100%;
height: 100%;
}
@media (max-width: 768px) {
.\${uniqueId} {
cursor: pointer;
}
.\${uniqueId} .social-container .box {
pointer-events: none;
padding: 15px;
}
.\${uniqueId} .social-container.active .box {
pointer-events: auto;
}
.\${uniqueId} .box a {
pointer-events: none;
}
.\${uniqueId} .social-container.active .box a {
pointer-events: auto;
}
.\${uniqueId} .logo {
font-size: 1.5em;
font-weight: 700;
}
.\${uniqueId} .icon {
width: 30px;
height: 30px;
font-size: 24px;
}
.\${uniqueId} .box1 {
width: 75%;
height: 75%;
bottom: -75%;
left: -75%;
}
.\${uniqueId} .box2 {
width: 55%;
height: 55%;
bottom: -55%;
left: -55%;
}
.\${uniqueId} .box3 {
width: 35%;
height: 35%;
bottom: -35%;
left: -35%;
}
}
@media (max-width: 480px) {
.\${uniqueId} .logo {
font-size: 1.4em;
}
.\${uniqueId} .icon {
font-size: 22px;
}
}
\`;
}
setupCard(cardWrapper) {
const uniqueId = \`social-card-\${Math.random().toString(36).substr(2, 9)}\`;
cardWrapper.classList.add(uniqueId);
const config = {
title: cardWrapper.getAttribute('data-card-title') || this.defaultConfig.title,
gradientType: cardWrapper.getAttribute('data-card-gradient') || this.defaultConfig.gradientType,
titleColor: cardWrapper.getAttribute('data-title-color') || this.defaultConfig.titleColor,
iconColor: cardWrapper.getAttribute('data-icon-color') || this.defaultConfig.iconColor,
fontFamily: cardWrapper.getAttribute('data-font-family') || this.defaultConfig.fontFamily,
customGradient: this.defaultConfig.customGradient,
socialIcons: []
};
const attr1 = cardWrapper.getAttribute('data-social-1');
const attr2 = cardWrapper.getAttribute('data-social-2');
const attr3 = cardWrapper.getAttribute('data-social-3');
if (attr1 || attr2 || attr3) {
config.socialIcons = [
this.parseSocialData(attr1),
this.parseSocialData(attr2),
this.parseSocialData(attr3)
].filter(Boolean);
} else {
config.socialIcons = this.defaultConfig.socialIcons;
}
const customGradientAttr = cardWrapper.getAttribute('data-custom-gradient');
if (config.gradientType === 'custom' && customGradientAttr) {
const [color1, color2] = customGradientAttr.split(',');
config.customGradient = {
mainColor1: color1,
mainColor2: color2
};
}
const social1 = config.socialIcons[0] || null;
const social2 = config.socialIcons[1] || null;
const social3 = config.socialIcons[2] || null;
cardWrapper.innerHTML = \`
<div class="logo">\${config.title}</div>
<div class="social-container">
\${this.createSocialButton(social1, 'box1', 1)}
\${this.createSocialButton(social2, 'box2', 2)}
\${this.createSocialButton(social3, 'box3', 3)}
<div class="box box4"></div>
</div>
\`;
const styleSheet = document.createElement('style');
styleSheet.setAttribute('data-card-id', uniqueId);
styleSheet.textContent = this.generateStyles(uniqueId, config);
document.head.appendChild(styleSheet);
this.instances.set(cardWrapper, {
uniqueId,
config,
styleElement: styleSheet
});
if (window.matchMedia('(max-width: 768px)').matches) {
const socialContainer = cardWrapper.querySelector('.social-container');
const clickHandler = (e) => {
if (!socialContainer.classList.contains('active')) {
e.preventDefault();
socialContainer.classList.add('active');
}
};
const documentClickHandler = (e) => {
if (!cardWrapper.contains(e.target)) {
socialContainer.classList.remove('active');
}
};
cardWrapper.removeEventListener('click', clickHandler);
document.removeEventListener('click', documentClickHandler);
cardWrapper.addEventListener('click', clickHandler);
document.addEventListener('click', documentClickHandler);
}
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
new SocialBloomCard();
});
} else {
new SocialBloomCard();
}
document.addEventListener('bricks/element_added', () => {
new SocialBloomCard();
});
setTimeout(() => {
new SocialBloomCard();
}, 1000);`;
}
function createSocialBloomCard(cardWrapper) {
const uniqueId = `social-card-${Math.random().toString(36).substr(2, 9)}`;
cardWrapper.classList.add(uniqueId);
const title = bloomConfig.title;
const gradientType = bloomConfig.gradientType;
const titleColor = bloomConfig.titleColor;
const iconColor = bloomConfig.iconColor;
const fontFamily = bloomConfig.fontFamily;
let gradientSet;
if (gradientType === 'custom') {
const color1 = bloomConfig.customGradient.mainColor1;
const color2 = bloomConfig.customGradient.mainColor2;
gradientSet = {
main: `linear-gradient(-45deg, ${color1} 0%, ${color2} 100%)`,
slice1: `linear-gradient(120deg, ${color1} 0%, ${color2} 100%)`,
slice2: `linear-gradient(120deg, ${color2} 0%, ${color1} 100%)`,
slice3: `linear-gradient(120deg, ${color1} 50%, ${color2} 100%)`
};
} else {
gradientSet = gradients[gradientType] || gradients.monterey;
}
const social1 = bloomConfig.socialIcons[0] || null;
const social2 = bloomConfig.socialIcons[1] || null;
const social3 = bloomConfig.socialIcons[2] || null;
cardWrapper.innerHTML = `
<div class="logo">${title}</div>
<div class="social-container">
${createSocialButton(social1, 'box1', 1)}
${createSocialButton(social2, 'box2', 2)}
${createSocialButton(social3, 'box3', 3)}
<div class="box box4"></div>
</div>
`;
const styles = `
.${uniqueId} {
position: relative;
width: 200px;
height: 200px;
border-radius: 30px;
overflow: hidden;
box-shadow: rgba(0, 0, 0, 0.1) 0px 10px 30px -5px;
transition: all 0.5s ease-in-out;
background: ${gradientSet.main};
font-family: ${fontFamily};
}
.${uniqueId} .social-container {
position: relative;
width: 100%;
height: 100%;
}
.${uniqueId} .logo {
position: absolute;
right: 50%;
bottom: 50%;
transform: translate(50%, 50%);
transition: all 0.6s ease-in-out;
font-size: 1.3em;
font-weight: 600;
color: ${titleColor};
letter-spacing: 3px;
z-index: 2;
}
.${uniqueId} .box {
position: absolute;
padding: 10px;
text-align: right;
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 10% 13% 42% 0%/10% 12% 75% 0%;
transform-origin: bottom left;
transition: all 0.6s ease-in-out;
}
.${uniqueId} .box::before {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
opacity: 0;
transition: all 0.5s ease-in-out;
}
.${uniqueId} .icon {
display: flex;
justify-content: center;
align-items: center;
width: 20px;
height: 20px;
font-size: 20px;
color: ${iconColor} !important;
transition: all 0.3s ease-in-out;
opacity: 0.9;
position: relative;
z-index: 2;
}
.${uniqueId} .icon.fab,
.${uniqueId} .icon.fas,
.${uniqueId} .icon.far {
font-family: "Font Awesome 6 Free", "Font Awesome 6 Brands" !important;
font-weight: 900 !important;
font-style: normal !important;
color: ${iconColor} !important;
}
.${uniqueId} .icon:not([class*="fa-"]):before,
.${uniqueId} .icon.fa:before {
content: attr(data-fallback);
font-family: Arial, sans-serif;
font-weight: bold;
font-style: normal;
}
.${uniqueId} .box:hover .icon {
opacity: 1;
transform: scale(1.1);
}
.${uniqueId} .box1 {
width: 70%;
height: 70%;
bottom: -70%;
left: -70%;
}
.${uniqueId} .box1::before {
background: ${gradientSet.slice1};
}
.${uniqueId} .box2 {
width: 50%;
height: 50%;
bottom: -50%;
left: -50%;
transition-delay: 0.1s;
}
.${uniqueId} .box2::before {
background: ${gradientSet.slice2};
}
.${uniqueId} .box3 {
width: 30%;
height: 30%;
bottom: -30%;
left: -30%;
transition-delay: 0.2s;
}
.${uniqueId} .box3::before {
background: ${gradientSet.slice3};
}
.${uniqueId} .box4 {
width: 10%;
height: 10%;
bottom: -10%;
left: -10%;
transition-delay: 0.3s;
}
.${uniqueId} .box:hover::before {
opacity: 1;
}
.${uniqueId}:hover, .${uniqueId}.active {
transform: scale(1.02);
box-shadow: rgba(0, 0, 0, 0.15) 0px 15px 35px -5px;
}
.${uniqueId}:hover .box, .${uniqueId} .social-container.active .box {
bottom: -1px;
left: -1px;
}
.${uniqueId}:hover .logo, .${uniqueId}.active .logo {
transform: translate(70px, -52px);
letter-spacing: 0px;
}
.${uniqueId} a {
text-decoration: none;
display: block;
width: 100%;
height: 100%;
}
@media (max-width: 768px) {
.${uniqueId} {
cursor: pointer;
}
.${uniqueId} .social-container .box {
pointer-events: none;
padding: 15px;
}
.${uniqueId} .social-container.active .box {
pointer-events: auto;
}
.${uniqueId} .box a {
pointer-events: none;
}
.${uniqueId} .social-container.active .box a {
pointer-events: auto;
}
.${uniqueId} .logo {
font-size: 1.5em;
font-weight: 700;
}
.${uniqueId} .icon {
width: 30px;
height: 30px;
font-size: 24px;
}
.${uniqueId} .box1 {
width: 75%;
height: 75%;
bottom: -75%;
left: -75%;
}
.${uniqueId} .box2 {
width: 55%;
height: 55%;
bottom: -55%;
left: -55%;
}
.${uniqueId} .box3 {
width: 35%;
height: 35%;
bottom: -35%;
left: -35%;
}
}
@media (max-width: 480px) {
.${uniqueId} .logo {
font-size: 1.4em;
}
.${uniqueId} .icon {
font-size: 22px;
}
}
`;
const existingStyle = document.querySelector(`style[data-card-id="${uniqueId}"]`);
if (existingStyle) {
existingStyle.remove();
}
const styleSheet = document.createElement('style');
styleSheet.setAttribute('data-card-id', uniqueId);
styleSheet.textContent = styles;
document.head.appendChild(styleSheet);
if (window.matchMedia('(max-width: 768px)').matches) {
const socialContainer = cardWrapper.querySelector('.social-container');
const clickHandler = (e) => {
if (!socialContainer.classList.contains('active')) {
e.preventDefault();
socialContainer.classList.add('active');
}
};
const documentClickHandler = (e) => {
if (!cardWrapper.contains(e.target)) {
socialContainer.classList.remove('active');
}
};
cardWrapper.removeEventListener('click', clickHandler);
document.removeEventListener('click', documentClickHandler);
cardWrapper.addEventListener('click', clickHandler);
document.addEventListener('click', documentClickHandler);
}
return () => {
const styleElement = document.querySelector(`style[data-card-id="${uniqueId}"]`);
if (styleElement) {
styleElement.remove();
}
};
}
function parseSocialData(data) {
if (!data) return null;
const [icon, url] = data.split('|').map(item => item.trim());
return { icon, url };
}
function createSocialButton(socialData, boxClass, index) {
if (!socialData) return `<div class="box ${boxClass}"></div>`;
const iconMapping = {
'ti-facebook': 'fab fa-facebook-f',
'ti-twitter-alt': 'fab fa-twitter',
'ti-instagram': 'fab fa-instagram',
'ti-linkedin': 'fab fa-linkedin-in',
'ti-youtube': 'fab fa-youtube',
'ti-github': 'fab fa-github',
'ti-email': 'fas fa-envelope',
'ti-world': 'fas fa-globe',
'ti-pinterest': 'fab fa-pinterest',
'ti-vimeo-alt': 'fab fa-vimeo-v',
'ti-dribbble': 'fab fa-dribbble',
'ti-skype': 'fab fa-skype',
'ti-tumblr-alt': 'fab fa-tumblr',
'ti-flickr-alt': 'fab fa-flickr'
};
const textFallback = {
'ti-facebook': 'f',
'ti-twitter-alt': 't',
'ti-instagram': 'i',
'ti-linkedin': 'l',
'ti-youtube': 'y',
'ti-github': 'g',
'ti-email': '@',
'ti-world': 'w',
'ti-pinterest': 'p',
'ti-vimeo-alt': 'v',
'ti-dribbble': 'd',
'ti-skype': 's',
'ti-tumblr-alt': 'T',
'ti-flickr-alt': 'F'
};
const iconClass = iconMapping[socialData.icon] || 'fas fa-link';
const fallbackText = textFallback[socialData.icon] || '→';
return `
<div class="box ${boxClass}">
<a href="${socialData.url}" target="_blank" rel="noopener noreferrer">
<i class="icon ${iconClass}" data-fallback="${fallbackText}"></i>
</a>
</div>
`;
}
function updateSocialBloomPreview() {
const preview = document.getElementById('bloom-preview');
if (!preview) return;
if (preview._cleanupSocialBloom) {
preview._cleanupSocialBloom();
}
preview.innerHTML = '';
createSocialBloomCard(preview);
}
function initializeSocialIcons() {
const socialIconsList = document.getElementById('social-icons-list');
socialIconsList.innerHTML = '';
bloomConfig.socialIcons.forEach((socialIcon, index) => {
addSocialIconInput(socialIcon, index);
});
}
function addSocialIconInput(socialIcon, index) {
if (socialIcon === undefined || index === undefined) {
socialIcon = { icon: 'ti-facebook', url: 'https://facebook.com' };
bloomConfig.socialIcons.push(socialIcon);
index = bloomConfig.socialIcons.length - 1;
}
const socialIconsList = document.getElementById('social-icons-list');
const iconContainer = document.createElement('div');
iconContainer.className = 'social-icon-container';
iconContainer.setAttribute('data-index', index);
const iconInputRow = document.createElement('div');
iconInputRow.className = 'icon-input-row';
const iconSelect = document.createElement('select');
iconSelect.id = `social-icon-${index}`;
socialIcons.forEach(icon => {
const option = document.createElement('option');
option.value = icon.value;
option.textContent = icon.label;
if (icon.value === socialIcon.icon) {
option.selected = true;
}
iconSelect.appendChild(option);
});
const urlInput = document.createElement('input');
urlInput.type = 'text';
urlInput.id = `social-url-${index}`;
urlInput.placeholder = 'Enter URL';
urlInput.value = socialIcon.url;
urlInput.style.marginBottom = '8px';
iconSelect.addEventListener('change', function() {
bloomConfig.socialIcons[index].icon = this.value;
updateSocialBloomPreview();
});
urlInput.addEventListener('input', function() {
bloomConfig.socialIcons[index].url = this.value;
updateSocialBloomPreview();
});
iconInputRow.appendChild(iconSelect);
if (bloomConfig.socialIcons.length > 1) {
const removeBtn = document.createElement('button');
removeBtn.className = 'remove-icon';
removeBtn.innerHTML = '<i class="fas fa-times-circle"></i>';
removeBtn.addEventListener('click', function() {
removeSocialIcon(index);
});
iconInputRow.appendChild(removeBtn);
}
iconContainer.appendChild(iconInputRow);
iconContainer.appendChild(urlInput);
socialIconsList.appendChild(iconContainer);
}
function addSocialIcon() {
addSocialIconInput();
updateSocialBloomPreview();
}
function removeSocialIcon(index) {
bloomConfig.socialIcons.splice(index, 1);
initializeSocialIcons();
updateSocialBloomPreview();
}
function toggleCustomGradientControls() {
const gradientTheme = document.getElementById('gradient-theme').value;
const customControls = document.getElementById('custom-gradient-controls');
if (gradientTheme === 'custom') {
customControls.style.display = 'block';
} else {
customControls.style.display = 'none';
}
}
function updateColorInputs() {
const colorFields = [
{ base: 'title-color', value: bloomConfig.titleColor },
{ base: 'icon-color', value: bloomConfig.iconColor },
{ base: 'main-color1', value: bloomConfig.customGradient.mainColor1 },
{ base: 'main-color2', value: bloomConfig.customGradient.mainColor2 }
];
colorFields.forEach(field => {
const colorInput = document.getElementById(field.base);
const hexInput = document.getElementById(`${field.base}-hex`);
const hslInput = document.getElementById(`${field.base}-hsl`);
if (colorInput && hexInput && hslInput) {
colorInput.value = field.value;
hexInput.value = field.value;
const hsl = hexToHsl(field.value);
hslInput.value = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
hexInput.classList.remove('invalid');
hslInput.classList.remove('invalid');
const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
if (colorPickerContainer) {
colorPickerContainer.style.setProperty('--selected-color', field.value);
}
}
});
}
function generateRandomBloom() {
const randomGradients = Object.keys(gradients);
bloomConfig.title = ['Social', 'Connect', 'Follow', 'Links'][Math.floor(Math.random() * 4)];
bloomConfig.gradientType = randomGradients[Math.floor(Math.random() * randomGradients.length)];
bloomConfig.titleColor = generateRandomColor();
bloomConfig.iconColor = generateRandomColor();
bloomConfig.fontFamily = ['system-ui', 'Inter', 'Arial', 'Helvetica'][Math.floor(Math.random() * 4)];
if (Math.random() > 0.7) {
bloomConfig.gradientType = 'custom';
bloomConfig.customGradient.mainColor1 = generateRandomColor();
bloomConfig.customGradient.mainColor2 = generateRandomColor();
}
document.getElementById('card-title').value = bloomConfig.title;
document.getElementById('gradient-theme').value = bloomConfig.gradientType;
document.getElementById('font-family').value = bloomConfig.fontFamily;
toggleCustomGradientControls();
updateColorInputs();
updateSocialBloomPreview();
showNotification('Random social bloom generated!');
}
function setupColorInputs(baseId, configKey) {
const colorInput = document.getElementById(baseId);
const hexInput = document.getElementById(`${baseId}-hex`);
const hslInput = document.getElementById(`${baseId}-hsl`);
if (!colorInput || !hexInput || !hslInput) return;
const updateConfig = (newColor) => {
if (baseId === 'title-color') {
bloomConfig.titleColor = newColor;
} else if (baseId === 'icon-color') {
bloomConfig.iconColor = newColor;
} else if (baseId === 'main-color1') {
bloomConfig.customGradient.mainColor1 = newColor;
} else if (baseId === 'main-color2') {
bloomConfig.customGradient.mainColor2 = newColor;
}
updateSocialBloomPreview();
};
colorInput.addEventListener('input', () => {
const color = colorInput.value;
hexInput.value = color;
const hsl = hexToHsl(color);
hslInput.value = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
hexInput.classList.remove('invalid');
hslInput.classList.remove('invalid');
const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
colorPickerContainer.style.setProperty('--selected-color', color);
updateConfig(color);
});
hexInput.addEventListener('input', (e) => {
let hex = e.target.value;
hex = formatHex(hex);
e.target.value = hex;
if (isValidHex(hex)) {
colorInput.value = hex;
const hsl = hexToHsl(hex);
hslInput.value = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
e.target.classList.remove('invalid');
hslInput.classList.remove('invalid');
const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
colorPickerContainer.style.setProperty('--selected-color', hex);
updateConfig(hex);
} 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;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
const colorPickerContainer = colorInput.closest('.color-row').querySelector('.color-picker-container');
colorPickerContainer.style.setProperty('--selected-color', hex);
updateConfig(hex);
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;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
updateConfig(hex);
return;
}
}
}
if (!isValidHsl(e.target.value)) {
const hsl = hexToHsl(colorInput.value);
e.target.value = `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`;
e.target.classList.remove('invalid');
}
});
}
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');
});
}
function initializeUI() {
updateSocialBloomPreview();
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-social-bloom');
});
document.getElementById('download-config').addEventListener('click', () => {
copyJsToClipboard();
});
document.getElementById('copy-full-section').addEventListener('click', () => {
copyFullSectionToClipboard();
});
document.getElementById('randomize-social-bloom').addEventListener('click', () => {
generateRandomBloom();
});
const backgroundPicker = document.getElementById('preview-background-picker');
const previewContainer = document.getElementById('social-bloom-preview');
backgroundPicker.addEventListener('input', (e) => {
const selectedColor = e.target.value;
previewContainer.style.backgroundColor = selectedColor;
showNotification(`Preview background changed to ${selectedColor}`);
});
previewContainer.style.backgroundColor = '#252525';
document.getElementById('reset-card').addEventListener('click', () => {
bloomConfig.title = defaultConfig.title;
document.getElementById('card-title').value = defaultConfig.title;
updateSocialBloomPreview();
showNotification('Card settings reset');
});
document.getElementById('reset-gradient').addEventListener('click', () => {
bloomConfig.gradientType = defaultConfig.gradientType;
bloomConfig.customGradient = JSON.parse(JSON.stringify(defaultConfig.customGradient));
document.getElementById('gradient-theme').value = defaultConfig.gradientType;
toggleCustomGradientControls();
updateColorInputs();
updateSocialBloomPreview();
showNotification('Gradient settings reset');
});
document.getElementById('reset-icons').addEventListener('click', () => {
bloomConfig.socialIcons = JSON.parse(JSON.stringify(defaultConfig.socialIcons));
initializeSocialIcons();
updateSocialBloomPreview();
showNotification('Social icons reset');
});
document.getElementById('reset-typography').addEventListener('click', () => {
bloomConfig.titleColor = defaultConfig.titleColor;
bloomConfig.iconColor = defaultConfig.iconColor;
bloomConfig.fontFamily = defaultConfig.fontFamily;
document.getElementById('font-family').value = defaultConfig.fontFamily;
updateColorInputs();
updateSocialBloomPreview();
showNotification('Typography reset');
});
document.getElementById('card-title').addEventListener('input', function() {
bloomConfig.title = this.value;
updateSocialBloomPreview();
});
document.getElementById('gradient-theme').addEventListener('change', function() {
bloomConfig.gradientType = this.value;
toggleCustomGradientControls();
updateSocialBloomPreview();
});
document.getElementById('font-family').addEventListener('change', function() {
bloomConfig.fontFamily = this.value;
updateSocialBloomPreview();
});
document.getElementById('add-icon-btn').addEventListener('click', addSocialIcon);
setupColorInputs('title-color', 'titleColor');
setupColorInputs('icon-color', 'iconColor');
setupColorInputs('main-color1', 'customGradient.mainColor1');
setupColorInputs('main-color2', 'customGradient.mainColor2');
initializeSocialIcons();
toggleCustomGradientControls();
updateColorInputs();
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;
}
} else {
switch (e.key.toLowerCase()) {
case 'r':
generateRandomBloom();
break;
case 'b':
document.getElementById('preview-background-picker').click();
break;
}
}
});
function saveConfiguration() {
try {
localStorage.setItem('bricksfusion-social-bloom-config', JSON.stringify(bloomConfig));
} catch (e) {
}
}
function loadConfiguration() {
try {
const saved = localStorage.getItem('bricksfusion-social-bloom-config');
if (saved) {
const savedConfig = JSON.parse(saved);
Object.assign(bloomConfig, savedConfig);
document.getElementById('card-title').value = savedConfig.title;
document.getElementById('gradient-theme').value = savedConfig.gradientType;
document.getElementById('font-family').value = savedConfig.fontFamily;
toggleCustomGradientControls();
updateColorInputs();
initializeSocialIcons();
updateSocialBloomPreview();
}
} catch (e) {
}
}
const originalUpdateSocialBloomPreview = updateSocialBloomPreview;
updateSocialBloomPreview = function() {
originalUpdateSocialBloomPreview();
saveConfiguration();
};
loadConfiguration();
setTimeout(() => {
showNotification('BricksFusion Social Bloom Configurator loaded!');
}, 500);
}
initializeUI();
});
</script>
</body>
</html>
Social Bloom
An animated card that reveals social media links with a beautiful blooming effect on hover. Perfect for team member cards, author bios, and profile sections.
Content
The text that appears on the card before hovering. Keep it short like "SOCIAL", "FOLLOW", or "CONNECT".
Default: Social
Your first social link. Choose a platform from the dropdown and paste your profile URL. This appears as the largest button.
Available platforms: Facebook, Twitter, Instagram, LinkedIn, YouTube, GitHub, Email, Website, Pinterest, Vimeo, Dribbble, Skype, Tumblr, Flickr
Your second social link. Appears as the medium-sized button.
Optional
Your third social link. Appears as the smallest button.
Optional
Colors
Color of the card title text. White works well with most gradients, but you can match it to your brand colors.
Default: White (#ffffff)
Color of the social media icons. Keep it white for clean look, or choose a contrasting color for emphasis.
Default: White (#ffffff)
Gradient Theme
Choose from beautiful pre-made gradient themes. Each has its own personality and color scheme that animates when you hover.
Options: Monterey (green), Big Sur (blue), Catalyst (red), Ventura (purple-blue), Sonoma (cyan-blue), Quantum (purple-pink), Aurora (teal-green), Carbon (dark gray), Silver (gray), Space (dark blue)
Default: Monterey
Want your own colors? Pick two colors to create a custom gradient. The card will blend between them beautifully. Set Gradient Type to "Custom" first.
Format: #color1, #color2 (example: #FF6B6B, #4ECDC4)
Behavior
On mobile devices, the card works differently since there's no hover. Tap once to reveal the social buttons, then tap the buttons to visit links. Tap outside to close.
Automatically adjusts for touch screens
When you hover, social buttons bloom from the bottom-left corner with a smooth cascade effect. Each button has a glassmorphism style with the gradient theme.
Built-in smooth transitions
Performance
This element is lightweight and uses only CSS transforms and transitions. It's perfect for multiple cards on a page without any performance concerns. The glassmorphism effect works best on modern browsers.