Implement three-layer button architecture for consistent formatting button styling
- Add button frame isolation layer to prevent site CSS from affecting toolbar appearance - Create style sample container for authentic style previews without layout interference - Update CSS with proper containment boundaries and !important rules for button structure - Preserve all authentic styling (color, weight, transform, decoration) in isolated preview - Fix inconsistent button appearance across different site stylesheets (e.g. .brand class) - Maintain professional toolbar UX while showing accurate style previews
This commit is contained in:
@@ -370,62 +370,59 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
transform: translateY(1px);
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Style preview buttons - new approach using CSS isolation */
|
/* Style preview buttons - three-layer architecture for style isolation */
|
||||||
.insertr-style-btn.insertr-style-preview {
|
.insertr-style-btn.insertr-style-preview {
|
||||||
/* Clean button container - minimal styling */
|
/* Strong button container - prevents content from affecting button structure */
|
||||||
background: var(--insertr-bg-primary);
|
background: var(--insertr-bg-primary) !important;
|
||||||
border: 1px solid var(--insertr-border-color);
|
border: 1px solid var(--insertr-border-color) !important;
|
||||||
border-radius: var(--insertr-border-radius);
|
border-radius: var(--insertr-border-radius) !important;
|
||||||
padding: 0; /* Remove padding - let preview content handle it */
|
padding: 0 !important; /* Let frame handle padding */
|
||||||
font-size: var(--insertr-font-size-sm);
|
font-size: var(--insertr-font-size-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: var(--insertr-transition);
|
transition: var(--insertr-transition);
|
||||||
|
|
||||||
/* Button layout */
|
/* Fixed button dimensions */
|
||||||
min-height: 28px;
|
min-height: 32px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
/* Reset any inherited text styles on the button container only */
|
/* Reset button-level text properties to prevent inheritance */
|
||||||
font-family: var(--insertr-font-family);
|
font-family: var(--insertr-font-family);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
|
color: var(--insertr-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button frame - consistent internal layout immune to content styling */
|
||||||
|
.insertr-button-frame {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 6px 10px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
/* Don't set color here - let the preview content inherit naturally */
|
/* Create style containment boundary */
|
||||||
|
contain: layout style;
|
||||||
/* Ensure content fits */
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preview content container - minimal interference with original styling */
|
/* Style sample - authentic style preview with NO resets */
|
||||||
.insertr-preview-content {
|
.insertr-style-sample {
|
||||||
/* Allow the original classes to style this element completely naturally */
|
/* Authentic style preview - let all styling come through naturally */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
/* Only set essential layout properties */
|
/* Size constraints only */
|
||||||
box-sizing: border-box;
|
max-width: 100px;
|
||||||
|
|
||||||
/* Ensure text fits within button */
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
max-width: 120px;
|
white-space: nowrap;
|
||||||
|
|
||||||
/* Inherit font size from button container */
|
/* All other styling (color, weight, transform, decoration, etc.)
|
||||||
font-size: inherit;
|
comes from applied classes - no interference */
|
||||||
|
|
||||||
/* Remove browser defaults that might interfere - but don't override intentional styling */
|
|
||||||
border: none;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
/* NO background, color, padding defaults - let the classes handle everything */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Minimal fallback styling when no meaningful classes are detected */
|
/* Fallback styling when no meaningful classes are detected */
|
||||||
.insertr-preview-content.insertr-fallback-style {
|
.insertr-style-sample.insertr-fallback-style {
|
||||||
padding: var(--insertr-spacing-xs) var(--insertr-spacing-sm);
|
|
||||||
color: var(--insertr-text-primary);
|
color: var(--insertr-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +447,7 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.3);
|
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-style-btn.insertr-style-active .insertr-preview-content {
|
.insertr-style-btn.insertr-style-active .insertr-style-sample {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +465,7 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
box-shadow: 0 2px 4px rgba(23, 162, 184, 0.3);
|
box-shadow: 0 2px 4px rgba(23, 162, 184, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-style-btn.insertr-default-style.insertr-style-active .insertr-preview-content {
|
.insertr-style-btn.insertr-default-style.insertr-style-active .insertr-style-sample {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -370,62 +370,59 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
transform: translateY(1px);
|
transform: translateY(1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Style preview buttons - new approach using CSS isolation */
|
/* Style preview buttons - three-layer architecture for style isolation */
|
||||||
.insertr-style-btn.insertr-style-preview {
|
.insertr-style-btn.insertr-style-preview {
|
||||||
/* Clean button container - minimal styling */
|
/* Strong button container - prevents content from affecting button structure */
|
||||||
background: var(--insertr-bg-primary);
|
background: var(--insertr-bg-primary) !important;
|
||||||
border: 1px solid var(--insertr-border-color);
|
border: 1px solid var(--insertr-border-color) !important;
|
||||||
border-radius: var(--insertr-border-radius);
|
border-radius: var(--insertr-border-radius) !important;
|
||||||
padding: 0; /* Remove padding - let preview content handle it */
|
padding: 0 !important; /* Let frame handle padding */
|
||||||
font-size: var(--insertr-font-size-sm);
|
font-size: var(--insertr-font-size-sm);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: var(--insertr-transition);
|
transition: var(--insertr-transition);
|
||||||
|
|
||||||
/* Button layout */
|
/* Fixed button dimensions */
|
||||||
min-height: 28px;
|
min-height: 32px;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
/* Reset any inherited text styles on the button container only */
|
/* Reset button-level text properties to prevent inheritance */
|
||||||
font-family: var(--insertr-font-family);
|
font-family: var(--insertr-font-family);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
|
color: var(--insertr-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Button frame - consistent internal layout immune to content styling */
|
||||||
|
.insertr-button-frame {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 6px 10px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
/* Don't set color here - let the preview content inherit naturally */
|
/* Create style containment boundary */
|
||||||
|
contain: layout style;
|
||||||
/* Ensure content fits */
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Preview content container - minimal interference with original styling */
|
/* Style sample - authentic style preview with NO resets */
|
||||||
.insertr-preview-content {
|
.insertr-style-sample {
|
||||||
/* Allow the original classes to style this element completely naturally */
|
/* Authentic style preview - let all styling come through naturally */
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
/* Only set essential layout properties */
|
/* Size constraints only */
|
||||||
box-sizing: border-box;
|
max-width: 100px;
|
||||||
|
|
||||||
/* Ensure text fits within button */
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
max-width: 120px;
|
white-space: nowrap;
|
||||||
|
|
||||||
/* Inherit font size from button container */
|
/* All other styling (color, weight, transform, decoration, etc.)
|
||||||
font-size: inherit;
|
comes from applied classes - no interference */
|
||||||
|
|
||||||
/* Remove browser defaults that might interfere - but don't override intentional styling */
|
|
||||||
border: none;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
/* NO background, color, padding defaults - let the classes handle everything */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Minimal fallback styling when no meaningful classes are detected */
|
/* Fallback styling when no meaningful classes are detected */
|
||||||
.insertr-preview-content.insertr-fallback-style {
|
.insertr-style-sample.insertr-fallback-style {
|
||||||
padding: var(--insertr-spacing-xs) var(--insertr-spacing-sm);
|
|
||||||
color: var(--insertr-text-primary);
|
color: var(--insertr-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +447,7 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.3);
|
box-shadow: 0 2px 4px rgba(0, 123, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-style-btn.insertr-style-active .insertr-preview-content {
|
.insertr-style-btn.insertr-style-active .insertr-style-sample {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,7 +465,7 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
|
|||||||
box-shadow: 0 2px 4px rgba(23, 162, 184, 0.3);
|
box-shadow: 0 2px 4px rgba(23, 162, 184, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.insertr-style-btn.insertr-default-style.insertr-style-active .insertr-preview-content {
|
.insertr-style-btn.insertr-default-style.insertr-style-active .insertr-style-sample {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -597,27 +597,32 @@ export class StyleAwareEditor {
|
|||||||
button.dataset.styleId = styleId;
|
button.dataset.styleId = styleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create preview content container
|
// Create three-layer structure for style isolation
|
||||||
const previewContent = document.createElement('span');
|
const buttonFrame = document.createElement('span');
|
||||||
previewContent.className = 'insertr-preview-content';
|
buttonFrame.className = 'insertr-button-frame';
|
||||||
previewContent.textContent = text;
|
|
||||||
|
const styleSample = document.createElement('span');
|
||||||
|
styleSample.className = 'insertr-style-sample';
|
||||||
|
styleSample.textContent = text;
|
||||||
|
|
||||||
// Apply type-specific styling
|
// Apply type-specific styling
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'style':
|
case 'style':
|
||||||
this.applyStyleButtonStyling(button, previewContent, styleInfo);
|
this.applyStyleButtonStyling(button, styleSample, styleInfo);
|
||||||
break;
|
break;
|
||||||
case 'link':
|
case 'link':
|
||||||
this.applyLinkButtonStyling(button, previewContent);
|
this.applyLinkButtonStyling(button, styleSample);
|
||||||
break;
|
break;
|
||||||
case 'action':
|
case 'action':
|
||||||
default:
|
default:
|
||||||
// Default action button styling
|
// Default action button styling - add fallback class
|
||||||
|
styleSample.classList.add('insertr-fallback-style');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the preview content to the button
|
// Build three-layer structure: button → frame → sample
|
||||||
button.appendChild(previewContent);
|
buttonFrame.appendChild(styleSample);
|
||||||
|
button.appendChild(buttonFrame);
|
||||||
|
|
||||||
// Add click handler
|
// Add click handler
|
||||||
button.addEventListener('click', (e) => {
|
button.addEventListener('click', (e) => {
|
||||||
@@ -631,48 +636,51 @@ export class StyleAwareEditor {
|
|||||||
/**
|
/**
|
||||||
* Apply styling for style buttons
|
* Apply styling for style buttons
|
||||||
*/
|
*/
|
||||||
applyStyleButtonStyling(button, previewContent, styleInfo) {
|
applyStyleButtonStyling(button, styleSample, styleInfo) {
|
||||||
if (!styleInfo) return;
|
if (!styleInfo) return;
|
||||||
|
|
||||||
// Apply styling based on whether this is a detected style or default
|
// Apply styling based on whether this is a detected style or default
|
||||||
if (styleInfo.isDefault) {
|
if (styleInfo.isDefault) {
|
||||||
// Default style - apply semantic styling
|
// Default style - apply semantic styling
|
||||||
button.classList.add('insertr-default-style');
|
button.classList.add('insertr-default-style');
|
||||||
previewContent.classList.add('insertr-default-preview');
|
|
||||||
|
|
||||||
// Add semantic styling for default elements
|
// Add semantic styling for default elements
|
||||||
if (styleInfo.tagName === 'strong') {
|
if (styleInfo.tagName === 'strong') {
|
||||||
previewContent.style.fontWeight = 'bold';
|
styleSample.style.fontWeight = 'bold';
|
||||||
} else if (styleInfo.tagName === 'em') {
|
} else if (styleInfo.tagName === 'em') {
|
||||||
previewContent.style.fontStyle = 'italic';
|
styleSample.style.fontStyle = 'italic';
|
||||||
} else if (styleInfo.tagName === 'a') {
|
} else if (styleInfo.tagName === 'a') {
|
||||||
previewContent.style.textDecoration = 'underline';
|
styleSample.style.textDecoration = 'underline';
|
||||||
previewContent.style.color = '#0066cc';
|
styleSample.style.color = '#0066cc';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add helpful description to title
|
// Add helpful description to title
|
||||||
button.title = `${styleInfo.name}: ${styleInfo.description || 'Default formatting option'}`;
|
button.title = `${styleInfo.name}: ${styleInfo.description || 'Default formatting option'}`;
|
||||||
} else if (styleInfo.element && styleInfo.classes && styleInfo.classes.length > 0) {
|
} else if (styleInfo.element && styleInfo.classes && styleInfo.classes.length > 0) {
|
||||||
// Detected style - apply original classes to preview
|
// Detected style - apply original classes to style sample
|
||||||
button.classList.add('insertr-style-preview');
|
button.classList.add('insertr-style-preview');
|
||||||
|
|
||||||
// Add the detected classes to the preview content
|
// Add the detected classes to the style sample (isolated preview)
|
||||||
styleInfo.classes.forEach(className => {
|
styleInfo.classes.forEach(className => {
|
||||||
previewContent.classList.add(className);
|
styleSample.classList.add(className);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
button.title = `Apply ${styleInfo.classes.join(' ')} styling`;
|
||||||
} else {
|
} else {
|
||||||
// No meaningful styles detected - use fallback
|
// No meaningful styles detected - use fallback
|
||||||
previewContent.classList.add('insertr-fallback-style');
|
button.classList.add('insertr-style-preview');
|
||||||
|
styleSample.classList.add('insertr-fallback-style');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply styling for link buttons
|
* Apply styling for link buttons
|
||||||
*/
|
*/
|
||||||
applyLinkButtonStyling(button, previewContent) {
|
applyLinkButtonStyling(button, styleSample) {
|
||||||
// Add link-specific styling
|
// Add link-specific styling to the isolated sample
|
||||||
previewContent.style.textDecoration = 'underline';
|
styleSample.style.textDecoration = 'underline';
|
||||||
previewContent.style.color = '#0066cc';
|
styleSample.style.color = '#0066cc';
|
||||||
|
button.title = 'Create hyperlink';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user