Skip to content

Commit e4bb73f

Browse files
rcoenenclaude
andcommitted
Add textDecorationColor property for Text nodes
When set, underline and line-through decorations use this color instead of the text fill color. Falls back to existing behavior (gradient or fill) when not set. Addresses #2037 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 811d62a commit e4bb73f

File tree

1 file changed

+31
-4
lines changed

1 file changed

+31
-4
lines changed

src/shapes/Text.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export interface TextConfig extends ShapeConfig {
7171
fontVariant?: string;
7272
textDecoration?: string;
7373
underlineOffset?: number;
74+
textDecorationColor?: string;
7475
align?: string;
7576
verticalAlign?: string;
7677
padding?: number;
@@ -242,6 +243,7 @@ export class Text extends Shape<TextConfig> {
242243
fill = this.fill(),
243244
textDecoration = this.textDecoration(),
244245
underlineOffset = this.underlineOffset(),
246+
textDecorationColor = this.textDecorationColor(),
245247
shouldUnderline = textDecoration.indexOf('underline') !== -1,
246248
shouldLineThrough = textDecoration.indexOf('line-through') !== -1,
247249
n;
@@ -318,8 +320,12 @@ export class Text extends Shape<TextConfig> {
318320
// just /15 looks good enough
319321
context.lineWidth = fontSize / 15;
320322

321-
const gradient = this._getLinearGradient();
322-
context.strokeStyle = gradient || fill;
323+
if (textDecorationColor) {
324+
context.strokeStyle = textDecorationColor;
325+
} else {
326+
const gradient = this._getLinearGradient();
327+
context.strokeStyle = gradient || fill;
328+
}
323329
context.stroke();
324330
context.restore();
325331
}
@@ -405,8 +411,12 @@ export class Text extends Shape<TextConfig> {
405411
translateY + lineTranslateY + yOffset
406412
);
407413
context.lineWidth = fontSize / 15;
408-
const gradient = this._getLinearGradient();
409-
context.strokeStyle = gradient || fill;
414+
if (textDecorationColor) {
415+
context.strokeStyle = textDecorationColor;
416+
} else {
417+
const gradient = this._getLinearGradient();
418+
context.strokeStyle = gradient || fill;
419+
}
410420
context.stroke();
411421
context.restore();
412422
}
@@ -771,6 +781,7 @@ export class Text extends Shape<TextConfig> {
771781
lineHeight: GetSet<number, this>;
772782
textDecoration: GetSet<string, this>;
773783
underlineOffset: GetSet<number, this>;
784+
textDecorationColor: GetSet<string, this>;
774785
text: GetSet<string, this>;
775786
wrap: GetSet<string, this>;
776787
ellipsis: GetSet<boolean, this>;
@@ -1078,6 +1089,22 @@ Factory.addGetterSetter(
10781089
getNumberValidator()
10791090
);
10801091

1092+
/**
1093+
* get/set text decoration color. When set, underline and line-through decorations
1094+
* use this color instead of the text fill color.
1095+
* @name Konva.Text#textDecorationColor
1096+
* @method
1097+
* @param {String} textDecorationColor
1098+
* @returns {String}
1099+
* @example
1100+
* // get text decoration color
1101+
* var color = text.textDecorationColor();
1102+
*
1103+
* // set text decoration color
1104+
* text.textDecorationColor('#18A0FB');
1105+
*/
1106+
Factory.addGetterSetter(Text, 'textDecorationColor', '');
1107+
10811108
/**
10821109
* get/set per-character render hook. The callback is invoked for each grapheme before drawing.
10831110
* It can mutate the provided context (e.g. translate, rotate, change styles) and should return void.

0 commit comments

Comments
 (0)