From a643d7aebc6aefa1376b58ca2cf650f212840fb5 Mon Sep 17 00:00:00 2001 From: Sahil Date: Sun, 9 Mar 2025 02:31:12 +0530 Subject: [PATCH] fix: text color detection bug fixed --- apps/studio/.env.example | 2 +- .../src/lib/editor/engine/style/index.ts | 49 +++++++++++++++++-- apps/studio/src/lib/editor/styles/index.ts | 5 ++ .../StylesTab/single/ColorInput/index.tsx | 48 ++++++++++++++++-- packages/utility/src/color.ts | 9 ++++ 5 files changed, 104 insertions(+), 9 deletions(-) diff --git a/apps/studio/.env.example b/apps/studio/.env.example index 11d4b66d5..f1a54cca6 100644 --- a/apps/studio/.env.example +++ b/apps/studio/.env.example @@ -1,7 +1,7 @@ # Only add these if you have valid keys. Otherwise, comment them out. VITE_SUPABASE_API_URL= VITE_SUPABASE_ANON_KEY= -VITE_MIXPANEL_TOKEN= +# VITE_MIXPANEL_TOKEN= # Add your keys here to use Anthropic directly VITE_ANTHROPIC_API_KEY= \ No newline at end of file diff --git a/apps/studio/src/lib/editor/engine/style/index.ts b/apps/studio/src/lib/editor/engine/style/index.ts index 2189156a0..450a0210c 100644 --- a/apps/studio/src/lib/editor/engine/style/index.ts +++ b/apps/studio/src/lib/editor/engine/style/index.ts @@ -108,10 +108,51 @@ export class StyleManager { const newMap = new Map(); let newSelectedStyle = null; for (const selectedEl of selectedElements) { - const styles = { - ...selectedEl.styles?.computed, - ...selectedEl.styles?.defined, - }; + // Debug log to check what styles are coming from the DOM + console.log('Selected element:', selectedEl.tagName); + console.log('Computed styles:', selectedEl.styles?.computed); + console.log('Defined styles:', selectedEl.styles?.defined); + + // For text styles like color, prioritize the computed styles from the browser + // which contain the actual rendered values, especially for properties with inheritance + const computedStyles = selectedEl.styles?.computed || {}; + const definedStyles = selectedEl.styles?.defined || {}; + + // Specifically log color values for debugging + if (computedStyles['color']) { + console.log('COMPUTED COLOR:', computedStyles['color']); + } + if (definedStyles['color']) { + console.log('DEFINED COLOR:', definedStyles['color']); + } + + // Create a merged styles object, prioritizing computed styles for critical properties + const criticalStyleKeys = [ + 'color', + 'background-color', + 'font-family', + 'font-size', + 'font-weight', + ]; + const styles: Record = { ...definedStyles }; + + // Ensure critical styles come from computed values when available + for (const key of criticalStyleKeys) { + if (computedStyles[key]) { + styles[key] = computedStyles[key]; + } + } + + // For non-critical styles, use the defined values if available + for (const key in computedStyles) { + if (!styles[key] && computedStyles[key]) { + styles[key] = computedStyles[key]; + } + } + + // Log the final merged styles for debugging + console.log('Final merged styles - color:', styles['color']); + const selectedStyle: SelectedStyle = { styles, parentRect: selectedEl?.parent?.rect ?? ({} as DOMRect), diff --git a/apps/studio/src/lib/editor/styles/index.ts b/apps/studio/src/lib/editor/styles/index.ts index 357f0199f..cefec41e2 100644 --- a/apps/studio/src/lib/editor/styles/index.ts +++ b/apps/studio/src/lib/editor/styles/index.ts @@ -17,6 +17,11 @@ export class SingleStyleImpl implements SingleStyle { ) {} getValue(styleRecord: Record) { + // If this is a color style (key is 'color' or ends with 'Color'), ensure we get the actual value + // This ensures text colors and other color values display correctly in the properties panel + if (this.type === 'color' && styleRecord[this.key]) { + return styleRecord[this.key]; + } return styleRecord[this.key] ?? this.defaultValue; } } diff --git a/apps/studio/src/routes/editor/EditPanel/StylesTab/single/ColorInput/index.tsx b/apps/studio/src/routes/editor/EditPanel/StylesTab/single/ColorInput/index.tsx index 885d10237..0b640283c 100644 --- a/apps/studio/src/routes/editor/EditPanel/StylesTab/single/ColorInput/index.tsx +++ b/apps/studio/src/routes/editor/EditPanel/StylesTab/single/ColorInput/index.tsx @@ -38,7 +38,9 @@ const ColorTextInput = memo( backgroundImage?: string; }) => { const inputValue = isFocused ? stagingInputValue : value; - const colorValue = isColorEmpty(inputValue) ? '' : inputValue; + // Don't use isColorEmpty here as it might incorrectly identify valid colors as empty + // If value is a valid hex color (including #000000 for black), show it + const colorValue = inputValue || ''; const displayValue = backgroundImage && !isBackgroundImageEmpty(backgroundImage) ? backgroundImage @@ -95,9 +97,47 @@ const ColorInput = observer( if (!editorEngine.style.selectedStyle?.styles || isFocused) { return Color.from(elementStyle.defaultValue); } - const newValue = elementStyle.getValue(editorEngine.style.selectedStyle?.styles); - return Color.from(newValue); - }, [editorEngine.style.selectedStyle?.styles, elementStyle, isFocused]); + + // For color styles specifically, we need to be careful + if (elementStyle.key === 'color') { + // Get the currently selected element + const selectedEl = editorEngine.elements.selected[0]; + if (selectedEl) { + const tagName = selectedEl.tagName?.toLowerCase(); + + // Check if we have a heading or text element + const isTextElement = + tagName === 'p' || + tagName?.match(/^h[1-6]$/) || + tagName === 'span' || + tagName === 'div'; + + // For text elements, prioritize the actual computed color from the DOM + if (isTextElement && selectedEl.styles?.computed) { + // If we have a computed color, use it + if (selectedEl.styles.computed.color) { + return Color.from(selectedEl.styles.computed.color); + } + } + } + } + + // Standard color handling for non-text elements or fallback + const selectedStyles = editorEngine.style.selectedStyle?.styles; + + // For color, check the direct style value first + if (elementStyle.key === 'color' && selectedStyles.color) { + return Color.from(selectedStyles.color); + } + + // Standard fallback behavior + return Color.from(elementStyle.getValue(selectedStyles)); + }, [ + editorEngine.style.selectedStyle?.styles, + elementStyle, + isFocused, + editorEngine.elements.selected, + ]); // Update color state when getColor changes const [color, setColor] = useState(getColor); diff --git a/packages/utility/src/color.ts b/packages/utility/src/color.ts index dbf7e2371..6370ba7c9 100644 --- a/packages/utility/src/color.ts +++ b/packages/utility/src/color.ts @@ -4,7 +4,16 @@ import parseCSSColor from 'parse-css-color'; import { isNearEqual } from './math'; export function isColorEmpty(colorValue: string) { + // Check for common empty color values + if (!colorValue || colorValue === '' || colorValue === 'none' || colorValue === 'transparent') { + return true; + } + + // Parse the color to check if it's truly transparent const color = Color.from(colorValue); + + // Only consider it empty if it has zero alpha or exactly equals transparent + // Don't consider black (#000000) or other valid colors as empty return color.a === 0 || color.isEqual(Color.transparent); }