Skip to content

Conversation

@juliaroldi
Copy link
Contributor

@juliaroldi juliaroldi commented Nov 25, 2025

Introduce a new TransformTableBorderColor that enable border color transformation when the editor switch from light to dark mode.
TableBorderColorsFixed

@juliaroldi juliaroldi changed the title U/juliaroldi/table borders Support color transformation in table borders Nov 27, 2025
@juliaroldi juliaroldi marked this pull request as ready for review November 27, 2025 15:09
isDarkMode,
darkColorHandler
);
this.adjustTableColor(contentDiv, isDarkMode, darkColorHandler);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this should not be here. The function adjustContainerColor is only for changing color of editor container DIV, not the editor content. And it is only called once when initialize editor.

Border color should be rendered by content model only, no direction DOM modification from other ways.

format[key] = value == 'none' ? '' : value;
}

if (isElementOfType(element, 'th') || isElementOfType(element, 'td')) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why only TH and TD?

}

if (isElementOfType(element, 'th') || isElementOfType(element, 'td')) {
const borderValues = extractBorderValues(format[key]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggest we do a string search first, for example, search for "--var" in the string and only when it exist, we call extractBorderValues and do color transformation.

if (borderValues.color) {
const color = getColorInternal(
borderValues.color,
false,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add inline comments

}
});

if (isElementOfType(element, 'th') || isElementOfType(element, 'td')) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, why only TD and TH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we apply this change to all elements? Should image borders be affected by this change?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be PM's decision if we want to support other elements as well. My personal opinion is we can support all. After all this is just for dark mode, it will not change the final HTML. So think about a table and some other element has the same border color, then switch to dark mode, table border color changed, but others do not, which seems like a bug to me.

About this comment, my point is no matter if we want to support for other elements, this check should not be here. This is just a format handler, it should only care format, but not element. It should not know any detail about the element.

If we only want to apply this behavior to table, then build two separate format handlers, one for table and one for others. They can share some code, but should be two entry points.

});

if (isElementOfType(element, 'th') || isElementOfType(element, 'td')) {
for (const key of BorderKeys) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine this for loop with previous one at line 86

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And for dark mode, first calculate dark color, then reuse the same line at 89 for setting back styles.

Comment on lines 64 to 75
const color =
(isBackground ? element.style.backgroundColor : element.style.color) ||
element.getAttribute(isBackground ? 'bgcolor' : 'color') ||
fallback;

if (color && DeprecatedColors.indexOf(color) > -1) {
color = isBackground ? undefined : BlackColor;
} else if (darkColorHandler && color) {
return color ? getColorInternal(color, isBackground, isDarkMode, darkColorHandler) : undefined;
}

/**
* @internal
*/
export function getColorInternal(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a good idea to split the code of getting color from DOM and transform to light mode. Actually we can refactor it even better. Let's split it into 3 parts:
Prepare: create a BorderKey type (you can put it in types package) then create some string arrays and maps:

type BorderKey = 'borderTop' | 'borderRight' | 'borderBottom' | 'borderLeft';

/**
 * Keys of border items
 */
export const BorderKeys: (BorderKey & keyof BorderFormat & keyof CSSStyleDeclaration)[] = [
    'borderTop',
    'borderRight',
    'borderBottom',
    'borderLeft',
];

export const BorderColorKeyMap: {
    [key in BorderKey]: string & keyof CSSStyleDeclaration;
} = {
    borderTop: 'borderTopColor',
    borderRight: 'borderRightColor',
    borderBottom: 'borderBottomColor',
    borderLeft: 'borderLeftColor',
};
  1. retrieveElementColor(element, isDarkMode, source: 'text' | 'background' | BorderKey, fallback?: string): string {...}. This will retrieve color from element according to its source string. When retrieve from text or background, keep the existing code to get from CSS then HTML attribute, for others, we can have a map from this border keys to the border color property names, for example:
function retrieveElementColor(
    element: HTMLElement,
    source: 'text' | 'background' | BorderKey,
    fallback?: string
): string | undefined {
    switch (source) {
        case 'text':
            return element.style.color || element.getAttribute('color') || fallback;

        case 'background':
            return element.style.backgroundColor || element.getAttribute('bgcolor') || fallback;

        default:
            return element.style.getPropertyValue(BorderColorKeyMap[source]) || fallback;
    }
}
  1. getLightModeColor(...), this is to transform dark color to light color (same with your getColorInternal)
  2. getColor(), keep the same parameter list and call to this two functions to keep compatibility:
function getColor(...) {
   const color = retrieveElementColor(element, isDarkMode, isBackground ? 'background' : 'color', fallback);

  return getLightModeColor(color, ...);
}

Then, you just need to call retrieveElementColor() and getLightModeColor() for borders in borderFormatHandler, no need to call extractBorderValues to avoid an extra RegEx call when parse.

Then for the setColor function, we can do a similar refactoring, the difference is when set color we don't need to set border color separately, but reuse the similar way you have to set borderLeft/Top/Right/Bottom in a single string.

* @param isDarkMode Whether element is in dark mode now
* @param darkColorHandler @optional The dark color handler object to help manager dark mode color
*/
export function setColorOnBorder(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refer to my previous comment, no need to have a separate setColorOnBorder function, but just set them together with border width and border style.

'textColor',
'htmlAlign',
'size',
'borderColor',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two "borderColor"

BorderKeys.forEach(key => {
const style = element.style[key];
if (style) {
const border = extractBorderValues(style);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can use something like element.style.borderLeftColor and others to get border color directly, no need to call extractBorderValues() here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as you are directly operating on DOM element, you can use these attributes, no need to extract from the string.

darkColorHandler
);
if (transformedColor) {
element.style[key] = combineBorderValue({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, directly set element.style.borderColor

Comment on lines +55 to +59
const borderStyles = combineBorderValue({
...borderValues,
color: transformedColor,
});
element.style[key] = borderStyles;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to combine them back, just set border[Direction]Color is enough.

export const BorderColorKeyMap: {
[key in BorderKey]: string & keyof CSSStyleDeclaration;
} = {
borderTop: 'borderTopColor',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See you already have these attributes, just use them when set/get colors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants