From 551b3fa30132125ff2e864ae38383bf7ba5b340c Mon Sep 17 00:00:00 2001 From: Joakim Date: Sun, 21 Sep 2025 22:06:35 +0200 Subject: [PATCH] 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 --- internal/content/assets/insertr.css | 69 ++++++++++++++--------------- lib/src/styles/insertr.css | 69 ++++++++++++++--------------- lib/src/ui/style-aware-editor.js | 54 ++++++++++++---------- 3 files changed, 97 insertions(+), 95 deletions(-) diff --git a/internal/content/assets/insertr.css b/internal/content/assets/insertr.css index 2dff1d2..30675ae 100644 --- a/internal/content/assets/insertr.css +++ b/internal/content/assets/insertr.css @@ -370,62 +370,59 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after { 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 { - /* Clean button container - minimal styling */ - background: var(--insertr-bg-primary); - border: 1px solid var(--insertr-border-color); - border-radius: var(--insertr-border-radius); - padding: 0; /* Remove padding - let preview content handle it */ + /* Strong button container - prevents content from affecting button structure */ + background: var(--insertr-bg-primary) !important; + border: 1px solid var(--insertr-border-color) !important; + border-radius: var(--insertr-border-radius) !important; + padding: 0 !important; /* Let frame handle padding */ font-size: var(--insertr-font-size-sm); cursor: pointer; transition: var(--insertr-transition); - /* Button layout */ - min-height: 28px; + /* Fixed button dimensions */ + min-height: 32px; 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); text-decoration: none; font-weight: normal; 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 */ - - /* Ensure content fits */ + /* Create style containment boundary */ + contain: layout style; overflow: hidden; } -/* Preview content container - minimal interference with original styling */ -.insertr-preview-content { - /* Allow the original classes to style this element completely naturally */ +/* Style sample - authentic style preview with NO resets */ +.insertr-style-sample { + /* Authentic style preview - let all styling come through naturally */ display: inline-block; - /* Only set essential layout properties */ - box-sizing: border-box; - - /* Ensure text fits within button */ - white-space: nowrap; + /* Size constraints only */ + max-width: 100px; overflow: hidden; text-overflow: ellipsis; - max-width: 120px; + white-space: nowrap; - /* Inherit font size from button container */ - font-size: inherit; - - /* 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 */ + /* All other styling (color, weight, transform, decoration, etc.) + comes from applied classes - no interference */ } -/* Minimal fallback styling when no meaningful classes are detected */ -.insertr-preview-content.insertr-fallback-style { - padding: var(--insertr-spacing-xs) var(--insertr-spacing-sm); +/* Fallback styling when no meaningful classes are detected */ +.insertr-style-sample.insertr-fallback-style { 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); } -.insertr-style-btn.insertr-style-active .insertr-preview-content { +.insertr-style-btn.insertr-style-active .insertr-style-sample { 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); } -.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; } diff --git a/lib/src/styles/insertr.css b/lib/src/styles/insertr.css index 2dff1d2..30675ae 100644 --- a/lib/src/styles/insertr.css +++ b/lib/src/styles/insertr.css @@ -370,62 +370,59 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after { 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 { - /* Clean button container - minimal styling */ - background: var(--insertr-bg-primary); - border: 1px solid var(--insertr-border-color); - border-radius: var(--insertr-border-radius); - padding: 0; /* Remove padding - let preview content handle it */ + /* Strong button container - prevents content from affecting button structure */ + background: var(--insertr-bg-primary) !important; + border: 1px solid var(--insertr-border-color) !important; + border-radius: var(--insertr-border-radius) !important; + padding: 0 !important; /* Let frame handle padding */ font-size: var(--insertr-font-size-sm); cursor: pointer; transition: var(--insertr-transition); - /* Button layout */ - min-height: 28px; + /* Fixed button dimensions */ + min-height: 32px; 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); text-decoration: none; font-weight: normal; 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 */ - - /* Ensure content fits */ + /* Create style containment boundary */ + contain: layout style; overflow: hidden; } -/* Preview content container - minimal interference with original styling */ -.insertr-preview-content { - /* Allow the original classes to style this element completely naturally */ +/* Style sample - authentic style preview with NO resets */ +.insertr-style-sample { + /* Authentic style preview - let all styling come through naturally */ display: inline-block; - /* Only set essential layout properties */ - box-sizing: border-box; - - /* Ensure text fits within button */ - white-space: nowrap; + /* Size constraints only */ + max-width: 100px; overflow: hidden; text-overflow: ellipsis; - max-width: 120px; + white-space: nowrap; - /* Inherit font size from button container */ - font-size: inherit; - - /* 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 */ + /* All other styling (color, weight, transform, decoration, etc.) + comes from applied classes - no interference */ } -/* Minimal fallback styling when no meaningful classes are detected */ -.insertr-preview-content.insertr-fallback-style { - padding: var(--insertr-spacing-xs) var(--insertr-spacing-sm); +/* Fallback styling when no meaningful classes are detected */ +.insertr-style-sample.insertr-fallback-style { 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); } -.insertr-style-btn.insertr-style-active .insertr-preview-content { +.insertr-style-btn.insertr-style-active .insertr-style-sample { 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); } -.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; } diff --git a/lib/src/ui/style-aware-editor.js b/lib/src/ui/style-aware-editor.js index 2d6b40e..7d91b2f 100644 --- a/lib/src/ui/style-aware-editor.js +++ b/lib/src/ui/style-aware-editor.js @@ -597,27 +597,32 @@ export class StyleAwareEditor { button.dataset.styleId = styleId; } - // Create preview content container - const previewContent = document.createElement('span'); - previewContent.className = 'insertr-preview-content'; - previewContent.textContent = text; + // Create three-layer structure for style isolation + const buttonFrame = document.createElement('span'); + buttonFrame.className = 'insertr-button-frame'; + + const styleSample = document.createElement('span'); + styleSample.className = 'insertr-style-sample'; + styleSample.textContent = text; // Apply type-specific styling switch (type) { case 'style': - this.applyStyleButtonStyling(button, previewContent, styleInfo); + this.applyStyleButtonStyling(button, styleSample, styleInfo); break; case 'link': - this.applyLinkButtonStyling(button, previewContent); + this.applyLinkButtonStyling(button, styleSample); break; case 'action': default: - // Default action button styling + // Default action button styling - add fallback class + styleSample.classList.add('insertr-fallback-style'); break; } - // Add the preview content to the button - button.appendChild(previewContent); + // Build three-layer structure: button → frame → sample + buttonFrame.appendChild(styleSample); + button.appendChild(buttonFrame); // Add click handler button.addEventListener('click', (e) => { @@ -631,48 +636,51 @@ export class StyleAwareEditor { /** * Apply styling for style buttons */ - applyStyleButtonStyling(button, previewContent, styleInfo) { + applyStyleButtonStyling(button, styleSample, styleInfo) { if (!styleInfo) return; // Apply styling based on whether this is a detected style or default if (styleInfo.isDefault) { // Default style - apply semantic styling button.classList.add('insertr-default-style'); - previewContent.classList.add('insertr-default-preview'); // Add semantic styling for default elements if (styleInfo.tagName === 'strong') { - previewContent.style.fontWeight = 'bold'; + styleSample.style.fontWeight = 'bold'; } else if (styleInfo.tagName === 'em') { - previewContent.style.fontStyle = 'italic'; + styleSample.style.fontStyle = 'italic'; } else if (styleInfo.tagName === 'a') { - previewContent.style.textDecoration = 'underline'; - previewContent.style.color = '#0066cc'; + styleSample.style.textDecoration = 'underline'; + styleSample.style.color = '#0066cc'; } // Add helpful description to title button.title = `${styleInfo.name}: ${styleInfo.description || 'Default formatting option'}`; } 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'); - // Add the detected classes to the preview content + // Add the detected classes to the style sample (isolated preview) styleInfo.classes.forEach(className => { - previewContent.classList.add(className); + styleSample.classList.add(className); }); + + button.title = `Apply ${styleInfo.classes.join(' ')} styling`; } else { // 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 */ - applyLinkButtonStyling(button, previewContent) { - // Add link-specific styling - previewContent.style.textDecoration = 'underline'; - previewContent.style.color = '#0066cc'; + applyLinkButtonStyling(button, styleSample) { + // Add link-specific styling to the isolated sample + styleSample.style.textDecoration = 'underline'; + styleSample.style.color = '#0066cc'; + button.title = 'Create hyperlink'; } /**