Skip to content

Commit 503d487

Browse files
authored
Designer: Added support for individual border thickness (#224)
1 parent 1befc91 commit 503d487

File tree

1 file changed

+87
-16
lines changed
  • packages/adaptive-ui-designer-figma-plugin/src/figma

1 file changed

+87
-16
lines changed

packages/adaptive-ui-designer-figma-plugin/src/figma/node.ts

Lines changed: 87 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,26 @@ function isShapeNode(node: BaseNode): node is
8383
].some((test: (node: BaseNode) => boolean) => test(node));
8484
}
8585

86+
function canHaveIndividualStrokes(node: BaseNode): node is
87+
FrameNode |
88+
ComponentNode |
89+
InstanceNode |
90+
RectangleNode {
91+
return [
92+
isContainerNode,
93+
isRectangleNode,
94+
].some((test: (node: BaseNode) => boolean) => test(node));
95+
}
96+
8697
function canHaveChildren(node: BaseNode): node is
87-
| DocumentNode
88-
| PageNode
89-
| FrameNode
90-
| GroupNode
91-
| BooleanOperationNode
92-
| InstanceNode
93-
| ComponentNode
94-
| ComponentSetNode {
98+
DocumentNode |
99+
PageNode |
100+
FrameNode |
101+
GroupNode |
102+
BooleanOperationNode |
103+
InstanceNode |
104+
ComponentNode |
105+
ComponentSetNode {
95106
return [
96107
isDocumentNode,
97108
isPageNode,
@@ -391,7 +402,7 @@ export class FigmaPluginNode extends PluginNode {
391402
case StyleProperty.gap:
392403
return [
393404
isContainerNode,
394-
].some((test: (node: BaseNode) => boolean) => test(this._node));
405+
].some((test: (node: BaseNode) => boolean) => test(this._node));
395406
case StyleProperty.cornerRadiusTopLeft:
396407
case StyleProperty.cornerRadiusTopRight:
397408
case StyleProperty.cornerRadiusBottomRight:
@@ -510,7 +521,7 @@ export class FigmaPluginNode extends PluginNode {
510521
}
511522

512523
protected handleFontFamily(node: FigmaPluginNode, values: AppliedStyleValues) {
513-
const fontFamily = values?.get(StyleProperty.fontFamily)?.value;
524+
const fontFamily = values.get(StyleProperty.fontFamily)?.value;
514525
// We'll only set the font if the family is provided.
515526
if (fontFamily) {
516527
if (isTextNode(node._node)) {
@@ -541,6 +552,38 @@ export class FigmaPluginNode extends PluginNode {
541552
}
542553
}
543554

555+
/**
556+
* Cleans up stroke values based on what we're about to apply.
557+
*
558+
* @remarks
559+
* Figma has a default invisible stroke width of `1`. If you add a stroke in the UI
560+
* it sets the weight to `1` and adds a default color.
561+
* If you change the weight, then remove the strokes (nothing visible) it maintains
562+
* the old stroke weight, but when you add again it resets to `1`.
563+
*
564+
* @param values - The entire list of values to be applied
565+
*/
566+
private handleStroke(values: AppliedStyleValues) {
567+
const applyingFill = values.has(StyleProperty.borderFillTop)
568+
|| values.has(StyleProperty.borderFillRight)
569+
|| values.has(StyleProperty.borderFillBottom)
570+
|| values.has(StyleProperty.borderFillLeft);
571+
const applyingThickness = values.has(StyleProperty.borderThicknessTop)
572+
|| values.has(StyleProperty.borderThicknessRight)
573+
|| values.has(StyleProperty.borderThicknessBottom)
574+
|| values.has(StyleProperty.borderThicknessLeft);
575+
576+
if (applyingFill && applyingThickness) {
577+
// We only need to reset "individual" strokes here since we'll set a common stroke later anyway.
578+
if (canHaveIndividualStrokes(this._node)) {
579+
(this._node as IndividualStrokesMixin).strokeTopWeight = 0;
580+
(this._node as IndividualStrokesMixin).strokeRightWeight = 0;
581+
(this._node as IndividualStrokesMixin).strokeBottomWeight = 0;
582+
(this._node as IndividualStrokesMixin).strokeLeftWeight = 0;
583+
}
584+
}
585+
}
586+
544587
protected safeNumber(value: string, defaultValue: number = 0) {
545588
return value === STYLE_REMOVE ? defaultValue : Number.parseFloat(value);
546589
}
@@ -549,6 +592,8 @@ export class FigmaPluginNode extends PluginNode {
549592
// Fonts are complicated in Figma, so pull them out of the normal loop.
550593
this.handleFontFamily(this, values);
551594

595+
this.handleStroke(values);
596+
552597
// Paint all applied design tokens on the node
553598
values.forEach((styleValue, target) => {
554599
// console.log("applied design token eval", target, applied);
@@ -591,7 +636,7 @@ export class FigmaPluginNode extends PluginNode {
591636
case StyleProperty.borderThicknessBottom:
592637
case StyleProperty.borderThicknessLeft:
593638
this.setBoxSizing();
594-
this.paintStrokeWidth(value);
639+
this.paintStrokeWidth(target, value);
595640
break;
596641
case StyleProperty.cornerRadiusTopLeft:
597642
case StyleProperty.cornerRadiusTopRight:
@@ -879,16 +924,42 @@ export class FigmaPluginNode extends PluginNode {
879924
(this._node as MinimalFillsMixin).fills = paint ? [paint] : [SOLID_BLACK];
880925
break;
881926
case StyleProperty.borderFillTop:
927+
case StyleProperty.borderFillRight:
928+
case StyleProperty.borderFillBottom:
929+
case StyleProperty.borderFillLeft:
882930
// TODO: Figma only supports one border color, though it can be hacked using inner shadow.
883931
(this._node as MinimalStrokesMixin).strokes = paintValue;
884932
break;
885933
}
886934
}
887935

888-
private paintStrokeWidth(value: string): void {
889-
(this._node as MinimalStrokesMixin).strokeWeight = this.safeNumber(value);
890-
if ((this._node as MinimalStrokesMixin).strokes.length === 0) {
891-
(this._node as MinimalStrokesMixin).strokes = [SOLID_TRANSPARENT];
936+
private paintStrokeWidth(target: StyleProperty, value: string): void {
937+
try {
938+
const numValue = this.safeNumber(value);
939+
if (canHaveIndividualStrokes(this._node)) {
940+
switch (target) {
941+
case StyleProperty.borderThicknessTop:
942+
(this._node as IndividualStrokesMixin).strokeTopWeight = numValue;
943+
break;
944+
case StyleProperty.borderThicknessRight:
945+
(this._node as IndividualStrokesMixin).strokeRightWeight = numValue;
946+
break;
947+
case StyleProperty.borderThicknessBottom:
948+
(this._node as IndividualStrokesMixin).strokeBottomWeight = numValue;
949+
break;
950+
case StyleProperty.borderThicknessLeft:
951+
(this._node as IndividualStrokesMixin).strokeLeftWeight = numValue;
952+
break;
953+
}
954+
} else {
955+
(this._node as MinimalStrokesMixin).strokeWeight = this.safeNumber(value);
956+
}
957+
958+
if ((this._node as MinimalStrokesMixin).strokes.length === 0) {
959+
(this._node as MinimalStrokesMixin).strokes = [SOLID_TRANSPARENT];
960+
}
961+
} catch (error) {
962+
console.error("paintStrokeWidth", { target, value, error, ...this.debugInfo });
892963
}
893964
}
894965

@@ -1010,7 +1081,7 @@ export class FigmaPluginNode extends PluginNode {
10101081
}]
10111082
}];
10121083

1013-
y += restComponent.height + spacing;
1084+
y += restComponent.height + spacing;
10141085
});
10151086

10161087
this._node.resize(x - spacing + paddingRight, y - spacing + paddingBottom);

0 commit comments

Comments
 (0)