feat: Implement dynamic style preview buttons

- Add JavaScript-based style copying from original elements to toolbar buttons
- Use getComputedStyle() to dynamically apply color, font-weight, text-decoration, text-transform
- Preserve button clickability with protected backgrounds and hover states
- Support any CSS framework/custom styles without hardcoded mappings
- Add comprehensive documentation to TODO.md for future enhancements

Examples:
- 'Emphasis' button now shows red bold text (from .emph class)
- 'Highlight' button displays with style preview while remaining clickable
- 'Brand' button demonstrates text-transform and color changes

This provides intuitive visual feedback so users immediately understand
what each formatting button will do to their content.
This commit is contained in:
2025-09-19 20:48:01 +02:00
parent d317e2e1d9
commit 01c8dcca76
4 changed files with 258 additions and 0 deletions

View File

@@ -380,6 +380,56 @@ body:not(.insertr-edit-mode) .insertr-editing-hover::after {
transform: translateY(1px);
}
/* Style preview buttons - styled dynamically via JavaScript */
.insertr-style-btn.insertr-style-preview {
/* Preserve button structure */
background: var(--insertr-bg-primary) !important;
border: 1px solid var(--insertr-border-color) !important;
border-radius: var(--insertr-border-radius) !important;
padding: var(--insertr-spacing-xs) var(--insertr-spacing-sm) !important;
font-size: var(--insertr-font-size-sm) !important;
cursor: pointer !important;
transition: var(--insertr-transition) !important;
/* Button layout */
min-height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
/* Ensure button remains clickable */
position: relative;
/* Styles will be applied dynamically via JavaScript */
}
/* Add subtle background to preview buttons to ensure they remain clickable-looking */
.insertr-style-btn.insertr-style-preview::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: var(--insertr-bg-primary);
opacity: 0.9;
border-radius: inherit;
z-index: -1;
}
/* Hover state for preview buttons */
.insertr-style-btn.insertr-style-preview:hover {
background: var(--insertr-bg-secondary) !important;
border-color: var(--insertr-text-muted) !important;
transform: none !important;
}
/* Active state for preview buttons */
.insertr-style-btn.insertr-style-preview:active {
background: var(--insertr-border-color) !important;
transform: translateY(1px) !important;
}
/* Editor components */
.insertr-simple-editor,
.insertr-rich-editor,

View File

@@ -246,6 +246,42 @@ export class StyleAwareEditor {
button.title = `Apply ${styleInfo.name} style`;
button.dataset.styleId = styleId;
// Apply preview styling by copying computed styles from the original element
if (styleInfo.element && styleInfo.classes && styleInfo.classes.length > 0) {
// Add the detected classes first
styleInfo.classes.forEach(className => {
button.classList.add(className);
});
// Add special button class
button.classList.add('insertr-style-preview');
// Copy specific style properties from the original element to ensure they show
const computedStyle = window.getComputedStyle(styleInfo.element);
// Copy color (most important for visual preview)
if (computedStyle.color && computedStyle.color !== 'rgb(0, 0, 0)') {
button.style.setProperty('color', computedStyle.color, 'important');
}
// Copy font-weight
if (computedStyle.fontWeight && computedStyle.fontWeight !== '400') {
button.style.setProperty('font-weight', computedStyle.fontWeight, 'important');
}
// Copy text-decoration (for underlines, etc.)
if (computedStyle.textDecoration && computedStyle.textDecoration !== 'none') {
button.style.setProperty('text-decoration', computedStyle.textDecoration, 'important');
}
// Copy text-transform (for uppercase, etc.)
if (computedStyle.textTransform && computedStyle.textTransform !== 'none') {
button.style.setProperty('text-transform', computedStyle.textTransform, 'important');
}
// Don't copy background-color to keep button appearance
}
// Add click handler for style application
button.addEventListener('click', (e) => {
e.preventDefault();