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>CopyPaste Notification 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: 1rem;
text-align: center;
flex-direction: column;
}
.preview-content {
text-align: center;
font-size: 1rem;
color: var(--text-primary);
margin-bottom: 1.5rem;
}
.preview-button {
padding: 12px 24px;
background-color: var(--card-bg);
border: 1px solid var(--border);
border-radius: var(--button-radius);
color: var(--text-primary);
font-family: var(--font);
font-size: var(--text-xs);
font-weight: 500;
cursor: pointer;
transition: var(--transition);
}
.preview-button:hover {
background-color: var(--card-bg-hover);
transform: translateY(-2px);
}
.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;
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: #4CAF50;
}
.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, #4CAF50);
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,
input[type="text"],
input[type="number"],
textarea {
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,
input[type="text"]:focus,
input[type="number"]:focus,
textarea:focus {
border-color: var(--accent);
box-shadow: 0 0 0 2px rgba(239, 96, 19, 0.2);
}
textarea {
min-height: 100px;
resize: vertical;
}
.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;
}
.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); }
}
.clipboard-notification {
position: fixed;
background-color: #4CAF50;
color: #fff;
padding: 16px;
font-family: 'Inter', sans-serif;
font-size: 16px;
font-weight: 500;
text-align: center;
opacity: 0;
transform: translateY(100%);
transition: opacity 0.3s ease-in-out, transform 0.3s ease-in-out;
z-index: 9999;
bottom: 0;
left: 0;
right: 0;
}
.clipboard-notification.apple-style {
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: 0 auto;
border-radius: 14px !important;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.clipboard-notification.material-style {
display: flex;
align-items: center;
justify-content: flex-start;
text-align: left;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
max-width: 380px;
border-radius: 4px !important;
margin: 0 auto;
padding-left: 16px !important;
}
.clipboard-notification.material-style::before {
content: "✓";
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-right: 12px;
background-color: white;
color: #4285F4;
border-radius: 50%;
font-size: 14px;
font-weight: bold;
}
.clipboard-notification.badge-style {
width: auto !important;
max-width: 300px;
border-radius: 50px !important;
display: inline-flex;
align-items: center;
margin: 0 auto;
padding: 6px 20px !important;
font-weight: 600;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
left: 50%;
transform: translateX(-50%) translateY(100%);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
}
.clipboard-notification.badge-style.show {
transform: translateX(-50%) translateY(0) !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.clipboard-notification.minimal-style {
width: auto !important;
padding: 8px 14px !important;
border-radius: 4px !important;
right: 20px;
left: auto;
bottom: 20px;
max-width: 300px;
font-weight: 500;
border: 1px solid rgba(0, 0, 0, 0.08);
}
.clipboard-notification.glassmorphism-style {
background: rgba(24, 24, 24, 0.7) !important;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
border-radius: 16px !important;
max-width: 400px;
width: auto !important;
left: auto;
right: 20px;
bottom: 20px;
display: flex;
align-items: center;
padding: 16px 20px !important;
}
.clipboard-notification.glassmorphism-style::before {
content: "📋";
margin-right: 12px;
font-size: 20px;
}
.clipboard-notification.show {
opacity: 1;
transform: translateY(0);
}
</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">CopyPaste Notification</span>
</nav>
<div class="action-buttons">
<div class="data-attribute-display" id="quick-attribute" title="Click to copy data attribute">
data-clipboard-text
</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">CopyPaste Notification</h1>
<p class="page-subtitle">Interactive clipboard notifications 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 clipboard notification 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 element: go to <strong>Section → Style → Attributes</strong>, add <code>data-clipboard-text</code> as attribute name with your content as value</li>
</ol>
</div>
</div>
</div>
</div>
</div>
<div class="content">
<section class="preview-section">
<div class="preview-container" id="copypaste-preview">
<div class="preview-content">Click the button below to test the notification effect</div>
<button class="preview-button" id="preview-button" data-clipboard-text="This is sample text">Copy Sample Text</button>
<div class="preview-controls">
</div>
</div>
</section>
<section class="controls-section">
<div class="card">
<div class="card-heading">
Preview Content Settings
<div class="card-actions">
<button class="card-action-btn" id="reset-content" title="Reset Content Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Content Type</span>
</div>
<select id="content-type">
<option value="text">Simple Text</option>
<option value="json">JSON</option>
</select>
</div>
<div class="control-group" id="text-content-group">
<div class="control-label">
<span class="label-text">Text to Copy</span>
</div>
<input type="text" id="preview-text-content" value="This is a sample text" placeholder="Enter text to copy...">
</div>
<div class="control-group" id="json-content-group" style="display: none;">
<div class="control-label">
<span class="label-text">JSON to Copy</span>
</div>
<textarea id="preview-json-content" rows="5" placeholder="Enter JSON to copy...">{
"example": "This is a sample JSON",
"number": 42,
"array": [1, 2, 3],
"nested": {
"key": "value"
}
}</textarea>
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Notification Settings
<div class="card-actions">
<button class="card-action-btn" id="reset-notification" title="Reset Notification Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Default Message</span>
</div>
<input type="text" id="default-message" value="Copied to clipboard!" placeholder="Enter notification message...">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Display Duration
<span class="help-tooltip" title="How long the notification stays visible">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="duration-value">2000</span>ms</span>
<button class="reset-btn" onclick="resetParameter('duration', 2000)">↺</button>
</div>
</div>
<input type="range" id="duration" min="500" max="5000" step="100" value="2000">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">Position</span>
</div>
<select id="position">
<option value="bottom">Bottom</option>
<option value="top">Top</option>
<option value="left">Left</option>
<option value="right">Right</option>
</select>
</div>
</div>
</div>
<div class="card">
<div class="card-heading">
Style Settings
<div class="card-actions">
<button class="card-action-btn" id="reset-style" title="Reset Style Settings">↺</button>
</div>
</div>
<div class="card-content">
<div class="control-group">
<div class="control-label">
<span class="label-text">Quick Style Presets</span>
</div>
<select id="preset-selector">
<option value="" selected>Choose a preset style...</option>
<option value="apple">Apple Style</option>
<option value="material">Material Design Plus</option>
<option value="badge">Premium Badge Style</option>
<option value="minimal">Elegant Minimal</option>
<option value="glassmorphism">Glassmorphism 3D</option>
</select>
</div>
<div class="color-list">
<div class="color-row">
<div class="color-picker-container">
<input type="color" id="bg-color" value="#4CAF50">
</div>
<div class="color-input-group">
<span class="color-label">Background HEX</span>
<input type="text" class="color-input hex-input" id="bg-color-hex" value="#4CAF50" placeholder="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">Background HSL</span>
<input type="text" class="color-input hsl-input" id="bg-color-hsl" placeholder="hsl(0, 100%, 50%)">
</div>
</div>
<div class="color-row">
<div class="color-picker-container">
<input type="color" id="text-color" value="#FFFFFF">
</div>
<div class="color-input-group">
<span class="color-label">Text HEX</span>
<input type="text" class="color-input hex-input" id="text-color-hex" value="#FFFFFF" placeholder="#000000">
</div>
<div class="color-input-group">
<span class="color-label">Text HSL</span>
<input type="text" class="color-input hsl-input" id="text-color-hsl" placeholder="hsl(0, 0%, 100%)">
</div>
</div>
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Font Size
<span class="help-tooltip" title="Size of the notification text">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="font-size-value">16</span>px</span>
<button class="reset-btn" onclick="resetParameter('font-size', 16)">↺</button>
</div>
</div>
<input type="range" id="font-size" min="12" max="24" step="1" value="16">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Animation Speed
<span class="help-tooltip" title="Speed of the notification animation">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="animation-speed-value">0.3</span>s</span>
<button class="reset-btn" onclick="resetParameter('animation-speed', 0.3)">↺</button>
</div>
</div>
<input type="range" id="animation-speed" min="0.1" max="1" step="0.1" value="0.3">
</div>
<div class="control-group">
<div class="control-label">
<span class="label-text">
Padding
<span class="help-tooltip" title="Internal spacing of the notification">ℹ</span>
</span>
<div class="value-display">
<span class="value-text"><span id="padding-value">16</span>px</span>
<button class="reset-btn" onclick="resetParameter('padding', 16)">↺</button>
</div>
</div>
<input type="range" id="padding" min="8" max="32" step="1" value="16">
</div>
</div>
</div>
</section>
</div>
</div>
<div class="notification" id="notification"></div>
<script>
document.addEventListener('DOMContentLoaded', function() {
let clipboardConfig = {
defaultMessage: 'Copied to clipboard!',
duration: 2000,
position: 'bottom',
customClass: '',
styles: {
backgroundColor: '#4CAF50',
textColor: '#FFFFFF',
fontSize: 16,
animationSpeed: 0.3,
padding: 16,
roundedCorners: true
},
previewContent: {
type: 'text',
text: 'This is a sample text',
json: {
example: "This is a sample JSON",
number: 42,
array: [1, 2, 3],
nested: {
key: "value"
}
}
}
};
const defaultConfig = JSON.parse(JSON.stringify(clipboardConfig));
let activeNotification = null;
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 showPreviewNotification() {
if (activeNotification) {
activeNotification.classList.remove('show');
setTimeout(() => {
if (activeNotification && activeNotification.parentNode) {
activeNotification.parentNode.removeChild(activeNotification);
}
activeNotification = null;
}, 300);
}
const notification = document.createElement('div');
notification.className = 'clipboard-notification';
if (clipboardConfig.customClass) {
notification.classList.add(clipboardConfig.customClass);
}
notification.textContent = clipboardConfig.defaultMessage;
notification.style.position = 'fixed';
Object.assign(notification.style, {
backgroundColor: clipboardConfig.styles.backgroundColor,
color: clipboardConfig.styles.textColor,
fontSize: `${clipboardConfig.styles.fontSize}px`,
padding: `${clipboardConfig.styles.padding}px`,
transition: `opacity ${clipboardConfig.styles.animationSpeed}s ease-in-out, transform ${clipboardConfig.styles.animationSpeed}s ease-in-out`,
borderRadius: clipboardConfig.styles.roundedCorners ? `${clipboardConfig.styles.padding / 2}px` : '0',
opacity: '0'
});
const position = clipboardConfig.position;
if (clipboardConfig.customClass === 'badge-style') {
Object.assign(notification.style, {
top: 'auto',
left: '50%',
right: 'auto',
bottom: '20px',
opacity: '1',
transform: 'translateX(-50%) translateY(100%)'
});
} else {
switch (position) {
case 'top':
Object.assign(notification.style, {
top: '20px',
left: '0',
right: '0',
bottom: 'auto',
transform: 'translateY(-100%)'
});
break;
case 'left':
Object.assign(notification.style, {
top: '0',
left: '0',
right: 'auto',
bottom: '0',
width: '200px',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: 'translateX(-100%)'
});
break;
case 'right':
Object.assign(notification.style, {
top: '0',
left: 'auto',
right: '0',
bottom: '0',
width: '200px',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: 'translateX(100%)'
});
break;
default:
Object.assign(notification.style, {
top: 'auto',
left: '0',
right: '0',
bottom: '0',
transform: 'translateY(100%)'
});
}
}
document.body.appendChild(notification);
activeNotification = notification;
void notification.offsetWidth;
if (clipboardConfig.customClass === 'badge-style') {
notification.classList.add('show');
} else {
notification.style.opacity = '1';
notification.style.transform = 'translate(0)';
}
setTimeout(() => {
if (clipboardConfig.customClass === 'badge-style') {
notification.classList.remove('show');
} else {
notification.style.opacity = '0';
if (position.includes('top')) {
notification.style.transform = 'translateY(-100%)';
} else if (position.includes('bottom')) {
notification.style.transform = 'translateY(100%)';
} else if (position.includes('left')) {
notification.style.transform = 'translateX(-100%)';
} else if (position.includes('right')) {
notification.style.transform = 'translateX(100%)';
}
}
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
if (activeNotification === notification) {
activeNotification = null;
}
}, clipboardConfig.styles.animationSpeed * 1000);
}, clipboardConfig.duration);
}
function applyPreset(presetName) {
switch(presetName) {
case 'apple':
clipboardConfig.styles.backgroundColor = 'rgba(40, 40, 40, 0.9)';
clipboardConfig.styles.textColor = '#FFFFFF';
clipboardConfig.styles.fontSize = 15;
clipboardConfig.styles.padding = 18;
clipboardConfig.styles.roundedCorners = true;
clipboardConfig.styles.animationSpeed = 0.4;
clipboardConfig.defaultMessage = 'Copied to clipboard';
clipboardConfig.position = 'top';
clipboardConfig.customClass = 'apple-style';
break;
case 'material':
clipboardConfig.styles.backgroundColor = '#4285F4';
clipboardConfig.styles.textColor = '#FFFFFF';
clipboardConfig.styles.fontSize = 15;
clipboardConfig.styles.padding = 18;
clipboardConfig.styles.roundedCorners = false;
clipboardConfig.styles.animationSpeed = 0.3;
clipboardConfig.defaultMessage = 'Content copied';
clipboardConfig.position = 'bottom';
clipboardConfig.customClass = 'material-style';
break;
case 'badge':
clipboardConfig.styles.backgroundColor = '#111111';
clipboardConfig.styles.textColor = '#FFFFFF';
clipboardConfig.styles.fontSize = 14;
clipboardConfig.styles.padding = 16;
clipboardConfig.styles.roundedCorners = true;
clipboardConfig.styles.animationSpeed = 0.25;
clipboardConfig.defaultMessage = '✓ Copied!';
clipboardConfig.position = 'bottom';
clipboardConfig.customClass = 'badge-style';
break;
case 'minimal':
clipboardConfig.styles.backgroundColor = '#F8F8F8';
clipboardConfig.styles.textColor = '#333333';
clipboardConfig.styles.fontSize = 14;
clipboardConfig.styles.padding = 12;
clipboardConfig.styles.roundedCorners = true;
clipboardConfig.styles.animationSpeed = 0.2;
clipboardConfig.defaultMessage = 'Copied';
clipboardConfig.position = 'bottom-right';
clipboardConfig.customClass = 'minimal-style';
break;
case 'glassmorphism':
clipboardConfig.styles.backgroundColor = 'rgba(24, 24, 24, 0.7)';
clipboardConfig.styles.textColor = '#FFFFFF';
clipboardConfig.styles.fontSize = 16;
clipboardConfig.styles.padding = 18;
clipboardConfig.styles.roundedCorners = true;
clipboardConfig.styles.animationSpeed = 0.4;
clipboardConfig.defaultMessage = 'Copied to clipboard';
clipboardConfig.position = 'bottom-right';
clipboardConfig.customClass = 'glassmorphism-style';
break;
}
updateAllControls();
setTimeout(() => {
showPreviewNotification();
}, 300);
}
function updateAllControls() {
document.getElementById('bg-color').value = clipboardConfig.styles.backgroundColor;
document.getElementById('bg-color-hex').value = clipboardConfig.styles.backgroundColor;
updateColorPicker('bg-color', clipboardConfig.styles.backgroundColor);
document.getElementById('text-color').value = clipboardConfig.styles.textColor;
document.getElementById('text-color-hex').value = clipboardConfig.styles.textColor;
updateColorPicker('text-color', clipboardConfig.styles.textColor);
document.getElementById('font-size').value = clipboardConfig.styles.fontSize;
document.getElementById('font-size-value').textContent = clipboardConfig.styles.fontSize;
document.getElementById('animation-speed').value = clipboardConfig.styles.animationSpeed;
document.getElementById('animation-speed-value').textContent = clipboardConfig.styles.animationSpeed;
document.getElementById('padding').value = clipboardConfig.styles.padding;
document.getElementById('padding-value').textContent = clipboardConfig.styles.padding;
document.getElementById('default-message').value = clipboardConfig.defaultMessage;
document.getElementById('position').value = clipboardConfig.position.split('-')[0];
updateColorInputs();
}
function updateColorPicker(id, color) {
const container = document.getElementById(`${id}`).closest('.color-row').querySelector('.color-picker-container');
container.style.setProperty('--selected-color', color);
}
function updateColorInputs() {
const bgColor = clipboardConfig.styles.backgroundColor;
const textColor = clipboardConfig.styles.textColor;
document.getElementById('bg-color-hex').value = bgColor;
document.getElementById('bg-color-hsl').value = `hsl(${hexToHsl(bgColor).h}, ${hexToHsl(bgColor).s}%, ${hexToHsl(bgColor).l}%)`;
document.getElementById('text-color-hex').value = textColor;
document.getElementById('text-color-hsl').value = `hsl(${hexToHsl(textColor).h}, ${hexToHsl(textColor).s}%, ${hexToHsl(textColor).l}%)`;
updateColorPicker('bg-color', bgColor);
updateColorPicker('text-color', textColor);
}
function generateRandomColor() {
return '#' + Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');
}
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 generateJavaScriptCode() {
const jsonString = JSON.stringify(clipboardConfig.previewContent.json);
const escapedJson = jsonString.replace(/`/g, '\\`').replace(/'/g, "\\'");
const escapedText = clipboardConfig.previewContent.text.replace(/'/g, "\\'").replace(/`/g, '\\`');
return `document.addEventListener('DOMContentLoaded', function() {
const config = {
defaultMessage: '${clipboardConfig.defaultMessage}',
duration: ${clipboardConfig.duration},
position: '${clipboardConfig.position}',
customClass: '${clipboardConfig.customClass || ''}',
styles: {
backgroundColor: '${clipboardConfig.styles.backgroundColor}',
textColor: '${clipboardConfig.styles.textColor}',
fontSize: ${clipboardConfig.styles.fontSize},
animationSpeed: ${clipboardConfig.styles.animationSpeed},
padding: ${clipboardConfig.styles.padding},
roundedCorners: ${clipboardConfig.styles.roundedCorners}
},
sampleContent: {
type: '${clipboardConfig.previewContent.type}',
text: '${escapedText}',
json: ${escapedJson}
}
};
const style = document.createElement('style');
style.textContent = \`
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
.clipboard-notification {
position: fixed;
background-color: \${config.styles.backgroundColor};
color: \${config.styles.textColor};
padding: \${config.styles.padding}px;
font-family: 'Inter', sans-serif;
font-size: \${config.styles.fontSize}px;
font-weight: 500;
text-align: center;
z-index: 9999;
opacity: 0;
transition: opacity \${config.styles.animationSpeed}s ease-in-out, transform \${config.styles.animationSpeed}s ease-in-out;
${clipboardConfig.styles.roundedCorners ? `border-radius: ${clipboardConfig.styles.padding / 2}px;` : 'border-radius: 0;'}
}
.clipboard-notification.apple-style {
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
max-width: 400px;
margin: 0 auto;
border-radius: 14px !important;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.clipboard-notification.material-style {
display: flex;
align-items: center;
justify-content: flex-start;
text-align: left;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
max-width: 380px;
border-radius: 4px !important;
margin: 0 auto;
padding-left: 16px !important;
}
.clipboard-notification.material-style::before {
content: "✓";
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
margin-right: 12px;
background-color: white;
color: #4285F4;
border-radius: 50%;
font-size: 14px;
font-weight: bold;
}
.clipboard-notification.badge-style {
width: auto !important;
max-width: 300px;
border-radius: 50px !important;
display: inline-flex;
align-items: center;
margin: 0 auto;
padding: 6px 20px !important;
font-weight: 600;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
left: 50%;
transform: translateX(-50%) translateY(100%);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
}
.clipboard-notification.badge-style.show {
transform: translateX(-50%) translateY(0) !important;
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.clipboard-notification.minimal-style {
width: auto !important;
padding: 8px 14px !important;
border-radius: 4px !important;
right: 20px;
left: auto;
bottom: 20px;
max-width: 300px;
font-weight: 500;
border: 1px solid rgba(0, 0, 0, 0.08);
}
.clipboard-notification.glassmorphism-style {
background: rgba(24, 24, 24, 0.7) !important;
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
border-radius: 16px !important;
max-width: 400px;
width: auto !important;
left: auto;
right: 20px;
bottom: 20px;
display: flex;
align-items: center;
padding: 16px 20px !important;
}
.clipboard-notification.glassmorphism-style::before {
content: "📋";
margin-right: 12px;
font-size: 20px;
}
\`;
document.head.appendChild(style);
let activeNotification = null;
function showNotification(message) {
if (activeNotification) {
if (activeNotification.classList.contains('badge-style')) {
activeNotification.classList.remove('show');
} else {
activeNotification.style.opacity = '0';
if (config.position.includes('top')) {
activeNotification.style.transform = 'translateY(-100%)';
} else if (config.position.includes('bottom')) {
activeNotification.style.transform = 'translateY(100%)';
} else if (config.position.includes('left')) {
activeNotification.style.transform = 'translateX(-100%)';
} else if (config.position.includes('right')) {
activeNotification.style.transform = 'translateX(100%)';
}
}
setTimeout(() => {
if (activeNotification && activeNotification.parentNode) {
activeNotification.parentNode.removeChild(activeNotification);
}
activeNotification = null;
}, config.styles.animationSpeed * 1000);
}
const notification = document.createElement('div');
notification.className = 'clipboard-notification';
if (config.customClass) {
notification.classList.add(config.customClass);
}
notification.textContent = message;
const position = config.position;
if (config.customClass === 'badge-style') {
Object.assign(notification.style, {
top: 'auto',
left: '50%',
right: 'auto',
bottom: '20px',
opacity: '1',
transform: 'translateX(-50%) translateY(100%)'
});
} else {
switch(position) {
case 'top':
Object.assign(notification.style, {
top: '20px',
left: '0',
right: '0',
bottom: 'auto',
transform: 'translateY(-100%)'
});
break;
case 'left':
Object.assign(notification.style, {
top: '0',
left: '0',
right: 'auto',
bottom: '0',
width: '200px',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: 'translateX(-100%)'
});
break;
case 'right':
Object.assign(notification.style, {
top: '0',
left: 'auto',
right: '0',
bottom: '0',
width: '200px',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
transform: 'translateX(100%)'
});
break;
case 'bottom':
default:
Object.assign(notification.style, {
top: 'auto',
left: '0',
right: '0',
bottom: '0',
transform: 'translateY(100%)'
});
break;
}
}
document.body.appendChild(notification);
activeNotification = notification;
void notification.offsetWidth;
if (config.customClass === 'badge-style') {
notification.classList.add('show');
} else {
notification.style.opacity = '1';
notification.style.transform = 'translate(0)';
}
setTimeout(() => {
if (!notification.parentNode) return;
if (config.customClass === 'badge-style') {
notification.classList.remove('show');
} else {
notification.style.opacity = '0';
if (position.includes('top')) {
notification.style.transform = 'translateY(-100%)';
} else if (position.includes('bottom')) {
notification.style.transform = 'translateY(100%)';
} else if (position.includes('left')) {
notification.style.transform = 'translateX(-100%)';
} else if (position.includes('right')) {
notification.style.transform = 'translateX(100%)';
}
}
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
if (activeNotification === notification) {
activeNotification = null;
}
}, config.styles.animationSpeed * 1000);
}, config.duration);
}
function handleCopyClick(e) {
if (e) {
e.preventDefault();
e.stopPropagation();
}
const element = this;
const message = element.getAttribute('data-clipboard-message') || config.defaultMessage;
let content = '';
if (element.hasAttribute('data-clipboard-text')) {
content = element.getAttribute('data-clipboard-text');
} else if (element.hasAttribute('data-clipboard-json')) {
try {
const jsonStr = element.getAttribute('data-clipboard-json');
content = JSON.stringify(JSON.parse(jsonStr), null, 2);
} catch (err) {
showNotification('Error: Invalid JSON format');
return;
}
}
if (!content || content.trim() === '') {
if (config.sampleContent.type === 'text') {
content = config.sampleContent.text;
} else {
content = JSON.stringify(config.sampleContent.json, null, 2);
}
}
if (!content || content.trim() === '') {
showNotification('Error: Nothing to copy');
return;
}
copyTextToClipboard(content, message);
}
function initClipboardButtons() {
const elementsToInit = document.querySelectorAll('[data-clipboard-text], [data-clipboard-json]');
elementsToInit.forEach((element) => {
if (element.getAttribute('data-clipboard-initialized') === 'true') return;
element.setAttribute('data-clipboard-initialized', 'true');
element.style.cursor = 'pointer';
element.addEventListener('click', handleCopyClick);
});
setTimeout(() => {
const newElements = document.querySelectorAll('[data-clipboard-text]:not([data-clipboard-initialized]), [data-clipboard-json]:not([data-clipboard-initialized])');
if (newElements.length > 0) {
newElements.forEach((element) => {
element.setAttribute('data-clipboard-initialized', 'true');
element.style.cursor = 'pointer';
element.addEventListener('click', handleCopyClick);
});
}
}, 1000);
if (elementsToInit.length === 0) {
const sampleButton = document.createElement('button');
sampleButton.className = 'clipboard-sample-button';
sampleButton.style.cssText = 'padding: 10px 16px; background-color: #333; color: white; border: none; border-radius: 4px; cursor: pointer; margin: 20px auto; display: block;';
sampleButton.textContent = 'Copy Sample ' + (config.sampleContent.type === 'text' ? 'Text' : 'JSON');
if (config.sampleContent.type === 'text') {
sampleButton.setAttribute('data-clipboard-text', config.sampleContent.text);
} else {
sampleButton.setAttribute('data-clipboard-json', JSON.stringify(config.sampleContent.json));
}
const container = document.querySelector('.brxe-container') || document.querySelector('.container') || document.body;
container.appendChild(sampleButton);
sampleButton.setAttribute('data-clipboard-initialized', 'true');
sampleButton.addEventListener('click', handleCopyClick);
}
}
function copyTextToClipboard(text, message) {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text)
.then(() => {
showNotification(message);
})
.catch((err) => {
fallbackCopyToClipboard(text, message);
});
} else {
fallbackCopyToClipboard(text, message);
}
}
function fallbackCopyToClipboard(text, message) {
const textArea = document.createElement('textarea');
textArea.value = text;
textArea.style.position = 'fixed';
textArea.style.top = '0';
textArea.style.left = '0';
textArea.style.width = '2em';
textArea.style.height = '2em';
textArea.style.padding = '0';
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
textArea.style.background = 'transparent';
textArea.style.opacity = '0';
textArea.setAttribute('readonly', '');
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
textArea.setSelectionRange(0, 99999);
let success = false;
try {
success = document.execCommand('copy');
if (success) {
showNotification(message);
} else {
showNotification('Copy failed. Please try again.');
}
} catch (err) {
showNotification('Copy failed. Please try again.');
}
document.body.removeChild(textArea);
}
initClipboardButtons();
setTimeout(() => {
const elements = document.querySelectorAll('[data-clipboard-text], [data-clipboard-json]');
elements.forEach((el) => {
if (!el.getAttribute('data-clipboard-initialized')) {
el.setAttribute('data-clipboard-initialized', 'true');
el.style.cursor = 'pointer';
el.addEventListener('click', handleCopyClick);
}
});
}, 2000);
if (window.MutationObserver) {
const observer = new MutationObserver((mutations) => {
let shouldInit = false;
mutations.forEach((mutation) => {
if (mutation.addedNodes.length > 0) {
shouldInit = true;
}
});
if (shouldInit) {
initClipboardButtons();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
window.ClipboardNotification = {
show: showNotification,
copy: function(text, message) {
copyTextToClipboard(text, message || config.defaultMessage);
},
init: initClipboardButtons,
getSampleContent: function() {
return config.sampleContent;
}
};
window.copyPasteContent = function() {
let content;
if (config.sampleContent.type === 'text') {
content = config.sampleContent.text;
} else {
content = JSON.stringify(config.sampleContent.json, null, 2);
}
copyTextToClipboard(content, config.defaultMessage);
return 'Copied: ' + content;
};
});`;
}
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 buttonId = generateUniqueId();
const codeId = 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"
}
},
{
"id": containerId,
"name": "container",
"parent": sectionId,
"children": [divId],
"settings": {
"_alignSelf": "center",
"_justifyContent": "center",
"_alignItems": "center",
"_direction": "row"
}
},
{
"id": divId,
"name": "div",
"parent": containerId,
"children": [buttonId],
"settings": {
"_display": "flex",
"_alignSelf": "center",
"_justifyContent": "center",
"_alignItems": "center",
"_width": "100%",
"_height": "200",
"_columnGap": "10"
}
},
{
"id": buttonId,
"name": "button",
"parent": divId,
"children": [],
"settings": {
"text": "Copy",
"_background": {
"color": {
"hex": "#c5ffb8"
}
},
"_border": {
"radius": {
"top": "15",
"right": "15",
"bottom": "15",
"left": "15"
}
},
"_attributes": [
{
"id": "khyppb",
"name": "data-clipboard-text"
}
]
},
"label": "Copy Button"
},
{
"id": codeId,
"name": "code",
"parent": sectionId,
"children": [],
"settings": {
"javascriptCode": jsCode,
"executeCode": true,
"_display": "none"
},
"label": "Copy JS"
}
],
"source": "bricksCopiedElements",
"sourceUrl": "https://test.bricksfusion.com",
"version": "2.0.1",
"globalClasses": [],
"globalElements": []
};
return JSON.stringify(bricksJSON, null, 2);
}
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}-value`);
if (valueElement) {
valueElement.textContent = defaultValue;
}
switch (parameterId) {
case 'duration':
clipboardConfig.duration = defaultValue;
break;
case 'font-size':
clipboardConfig.styles.fontSize = defaultValue;
break;
case 'animation-speed':
clipboardConfig.styles.animationSpeed = defaultValue;
break;
case 'padding':
clipboardConfig.styles.padding = defaultValue;
break;
}
showNotification(`${parameterId.replace(/-/g, ' ')} reset to default`);
}
};
function initializeUI() {
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-clipboard-text');
});
document.getElementById('download-config').addEventListener('click', () => {
copyJsToClipboard();
});
document.getElementById('copy-full-section').addEventListener('click', () => {
copyFullSectionToClipboard();
});
document.getElementById('reset-content').addEventListener('click', () => {
clipboardConfig.previewContent = { ...defaultConfig.previewContent };
document.getElementById('content-type').value = 'text';
document.getElementById('preview-text-content').value = 'This is a sample text';
document.getElementById('preview-json-content').value = JSON.stringify(defaultConfig.previewContent.json, null, 2);
document.getElementById('text-content-group').style.display = 'block';
document.getElementById('json-content-group').style.display = 'none';
updatePreviewButton();
showNotification('Content settings reset');
});
document.getElementById('reset-notification').addEventListener('click', () => {
clipboardConfig.defaultMessage = defaultConfig.defaultMessage;
clipboardConfig.duration = defaultConfig.duration;
clipboardConfig.position = defaultConfig.position;
document.getElementById('default-message').value = defaultConfig.defaultMessage;
document.getElementById('duration').value = defaultConfig.duration;
document.getElementById('duration-value').textContent = defaultConfig.duration;
document.getElementById('position').value = defaultConfig.position;
showNotification('Notification settings reset');
});
document.getElementById('reset-style').addEventListener('click', () => {
clipboardConfig.styles = { ...defaultConfig.styles };
clipboardConfig.customClass = '';
document.getElementById('preset-selector').value = '';
updateAllControls();
showNotification('Style settings reset');
});
const colorInputs = [
{ color: 'bg-color', config: 'backgroundColor' },
{ color: 'text-color', config: 'textColor' }
];
colorInputs.forEach(({ color, config }) => {
const colorInput = document.getElementById(color);
const hexInput = document.getElementById(`${color}-hex`);
const hslInput = document.getElementById(`${color}-hsl`);
const currentColor = clipboardConfig.styles[config];
hslInput.value = `hsl(${hexToHsl(currentColor).h}, ${hexToHsl(currentColor).s}%, ${hexToHsl(currentColor).l}%)`;
updateColorPicker(color, currentColor);
colorInput.addEventListener('input', () => {
const selectedColor = colorInput.value;
hexInput.value = selectedColor;
hslInput.value = `hsl(${hexToHsl(selectedColor).h}, ${hexToHsl(selectedColor).s}%, ${hexToHsl(selectedColor).l}%)`;
hexInput.classList.remove('invalid');
hslInput.classList.remove('invalid');
clipboardConfig.styles[config] = selectedColor;
updateColorPicker(color, selectedColor);
});
hexInput.addEventListener('input', (e) => {
let hex = e.target.value;
hex = formatHex(hex);
e.target.value = hex;
if (isValidHex(hex)) {
colorInput.value = hex;
hslInput.value = `hsl(${hexToHsl(hex).h}, ${hexToHsl(hex).s}%, ${hexToHsl(hex).l}%)`;
clipboardConfig.styles[config] = hex;
e.target.classList.remove('invalid');
hslInput.classList.remove('invalid');
updateColorPicker(color, 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;
clipboardConfig.styles[config] = hex;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
updateColorPicker(color, 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;
clipboardConfig.styles[config] = hex;
e.target.classList.remove('invalid');
hexInput.classList.remove('invalid');
updateColorPicker(color, hex);
return;
}
}
}
if (!isValidHsl(e.target.value)) {
e.target.value = `hsl(${hexToHsl(colorInput.value).h}, ${hexToHsl(colorInput.value).s}%, ${hexToHsl(colorInput.value).l}%)`;
e.target.classList.remove('invalid');
}
});
});
document.getElementById('default-message').addEventListener('input', function() {
clipboardConfig.defaultMessage = this.value;
updatePreviewButton();
});
document.getElementById('duration').addEventListener('input', function() {
clipboardConfig.duration = parseInt(this.value, 10);
document.getElementById('duration-value').textContent = this.value;
});
document.getElementById('position').addEventListener('change', function() {
clipboardConfig.position = this.value;
});
document.getElementById('font-size').addEventListener('input', function() {
clipboardConfig.styles.fontSize = parseInt(this.value, 10);
document.getElementById('font-size-value').textContent = this.value;
});
document.getElementById('animation-speed').addEventListener('input', function() {
clipboardConfig.styles.animationSpeed = parseFloat(this.value);
document.getElementById('animation-speed-value').textContent = this.value;
});
document.getElementById('padding').addEventListener('input', function() {
clipboardConfig.styles.padding = parseInt(this.value, 10);
document.getElementById('padding-value').textContent = this.value;
});
document.getElementById('content-type').addEventListener('change', function() {
clipboardConfig.previewContent.type = this.value;
document.getElementById('text-content-group').style.display = this.value === 'text' ? 'block' : 'none';
document.getElementById('json-content-group').style.display = this.value === 'json' ? 'block' : 'none';
updatePreviewButton();
});
document.getElementById('preview-text-content').addEventListener('input', function() {
clipboardConfig.previewContent.text = this.value;
updatePreviewButton();
});
document.getElementById('preview-json-content').addEventListener('input', function() {
try {
clipboardConfig.previewContent.json = JSON.parse(this.value);
this.style.borderColor = 'var(--border)';
updatePreviewButton();
} catch (e) {
this.style.borderColor = '#ff4444';
}
});
document.getElementById('preview-button').addEventListener('click', function(e) {
e.preventDefault();
showPreviewNotification();
});
document.getElementById('preset-selector').addEventListener('change', function() {
const presetName = this.value;
if (presetName) {
applyPreset(presetName);
}
});
function updatePreviewButton() {
const previewButton = document.getElementById('preview-button');
if (clipboardConfig.previewContent.type === 'text') {
previewButton.setAttribute('data-clipboard-text', clipboardConfig.previewContent.text);
previewButton.removeAttribute('data-clipboard-json');
} else {
previewButton.setAttribute('data-clipboard-json', JSON.stringify(clipboardConfig.previewContent.json));
previewButton.removeAttribute('data-clipboard-text');
}
previewButton.setAttribute('data-clipboard-message', clipboardConfig.defaultMessage);
previewButton.textContent = `Copy Sample ${clipboardConfig.previewContent.type === 'text' ? 'Text' : 'JSON'}`;
}
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();
}
break;
case 's':
e.preventDefault();
const fullSectionBtn = document.getElementById('copy-full-section');
if (fullSectionBtn && fullSectionBtn.hasAttribute('data-protection-animation')) {
fullSectionBtn.click();
}
break;
}
}
});
updateColorInputs();
updatePreviewButton();
setTimeout(() => {
showNotification('BricksFusion CopyPaste Notification Configurator loaded!');
}, 500);
}
initializeUI();
});
</script>
</body>
</html>
Copy Paste
Adds one-click copy functionality to any button with beautiful notification styles. Perfect for code snippets, API keys, links, or any text you want users to copy easily.
Content
Type of content to copy. Text copies plain text, JSON formats and copies JSON data with proper indentation.
Default: Text
The text to copy when clicked. Can be anything: URLs, code, messages, API keys, email addresses.
Default: Empty
JSON data to copy when Content Type is JSON. Will be automatically formatted with proper indentation.
Default: Empty object
Notification
Success message shown after copying. Keep it short and clear.
Default: Copied to clipboard!
How long the notification stays visible in milliseconds. 2000ms (2 seconds) is usually perfect.
Default: 2000
Where the notification appears. Options: top-left, top-center, top-right, center-left, center, center-right, bottom-left, bottom-center, bottom-right.
Default: Bottom center
Visual style of notification. Modern card is sleek dark, apple glass is iOS-style, neon glow is vibrant, neumorphic is soft 3D, gradient flow is animated rainbow, floating bubble is light and airy, elegant minimal is simple, material 3 is modern with icon.
Default: Modern card
Appearance
Color of the notification text. Make sure it contrasts well with your background.
Default: White
Background color for modern card and neon glow styles. Only affects specific notification styles.
Default: Black
Size of the notification text. 14-16px is readable and not too large.
Default: 14
Internal spacing of the notification. More padding makes it larger and more prominent.
Default: 16
Speed of the fade in/out animation. Lower is faster, higher is slower and smoother.
Default: 0.4
Performance
This element uses the native Clipboard API for modern browsers with a fallback for older ones. It's lightweight with no dependencies and works on all devices. The notification animations use CSS transitions for smooth performance.