Skip to content

Commit

Permalink
Designer: Begin migration away from design token definition
Browse files Browse the repository at this point in the history
  • Loading branch information
bheston committed Nov 8, 2024
1 parent 51234a2 commit 7e36583
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 59 deletions.
15 changes: 9 additions & 6 deletions packages/adaptive-ui-designer-figma-plugin/src/ui/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { PluginMessage} from "../core/messages.js";
import SubtractIcon from "./assets/subtract.svg";
import { UIController } from "./ui-controller.js";
import { AppliedDesignTokenItem, StyleModuleDisplay, StyleModuleDisplayList } from "./ui-controller-styles.js";
import { DesignTokenAdd, DesignTokensForm, Drawer, StyleTokenItem, TokenGlyph, TokenGlyphType } from "./components/index.js";
import { AddEventDetail, DesignTokenAdd, DesignTokensForm, DetachEventDetail, Drawer, StyleTokenItem, TokenChangeEventDetail, TokenGlyph, TokenGlyphType } from "./components/index.js";

StyleTokenItem;
TokenGlyph;
Expand Down Expand Up @@ -411,8 +411,8 @@ const template = html<App>`
:designTokens=${(x) => x.controller.designTokens.availableDesignTokens}
@add=${(x, c) =>
x.controller.designTokens.setDesignToken(
(c.event as CustomEvent).detail.definition,
(c.event as CustomEvent).detail.value
((c.event as CustomEvent).detail as AddEventDetail).token,
((c.event as CustomEvent).detail as AddEventDetail).value
)}
></designer-design-token-add>
<adaptive-divider></adaptive-divider>
Expand All @@ -422,10 +422,13 @@ const template = html<App>`
:designTokens=${(x) => x.controller.designTokens.designTokenValues}
@tokenChange=${(x, c) =>
x.controller.designTokens.setDesignToken(
(c.event as CustomEvent).detail.definition,
(c.event as CustomEvent).detail.value
((c.event as CustomEvent).detail as TokenChangeEventDetail).token,
((c.event as CustomEvent).detail as TokenChangeEventDetail).value
)}
@detach=${(x, c) =>
x.controller.designTokens.removeDesignToken(
((c.event as CustomEvent).detail as DetachEventDetail)
)}
@detach=${(x, c) => x.controller.designTokens.removeDesignToken((c.event as CustomEvent).detail)}
></designer-design-tokens-form>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@ import {
ref,
repeat,
} from "@microsoft/fast-element";
import { staticallyCompose } from "@microsoft/fast-foundation";
import { DesignTokenDefinition } from "@adaptive-web/adaptive-ui-designer-core";
import { DesignToken, staticallyCompose } from "@microsoft/fast-foundation";
import CheckmarkIcon from "../../assets/checkmark.svg";
import { DesignTokenField } from "../design-token-field/index.js";
import { UIDesignTokenValue } from "../../ui-controller-tokens.js";
import { designTokenTitle } from "../../util.js";

DesignTokenField;

export type AddEventDetail = UIDesignTokenValue;

const template = html<DesignTokenAdd>`
<select @change="${(x, c) => x.selectHandler(c)}" ${ref("list")}>
<option selected value="-">Add design token override...</option>
${repeat(
x => x.designTokens,
html<DesignTokenDefinition, DesignTokenAdd>`
<option value="${x => x.id}">
${x => x.title} (${x => x.groupTitle})
html<DesignToken<any>, DesignTokenAdd>`
<option value="${x => x.name}">
${x => designTokenTitle(x)}
</option>
`
)}
Expand Down Expand Up @@ -67,38 +70,38 @@ const styles = css`
})
export class DesignTokenAdd extends FASTElement {
@observable
designTokens: DesignTokenDefinition[] = [];
designTokens: DesignToken<any>[] = [];

@observable
selectedDesignToken?: DesignTokenDefinition;
selectedDesignToken?: DesignToken<any>;

list?: HTMLSelectElement;

field?: DesignTokenField;

selectHandler(c: ExecutionContext) {
const selectedTokenId = (c.event.target as unknown as HTMLSelectElement).value;
const selectedTokenName = (c.event.target as unknown as HTMLSelectElement).value;

if (selectedTokenId !== "-") {
if (selectedTokenName !== "-") {
this.selectedDesignToken = this.designTokens.find((token) => {
return token.id === selectedTokenId;
return token.name === selectedTokenName;
});
if (this.list) {
this.list.value = "-";
}

if (this.field) {
this.field.value = "" + this.selectedDesignToken?.token.default;
this.field.value = "" + this.selectedDesignToken?.default;
}
}
}

addHandler() {
if (this.field?.value) {
this.$emit("add", {
definition: this.selectedDesignToken,
token: this.selectedDesignToken,
value: this.field.value,
});
} as AddEventDetail);

this.selectedDesignToken = undefined;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { DesignToken } from "@microsoft/fast-foundation";
import { css, customElement, FASTElement, html, observable } from "@microsoft/fast-element";
import { twoWay } from "@microsoft/fast-element/binding/two-way.js";
import { DesignTokenDefinition, FormControlId } from "@adaptive-web/adaptive-ui-designer-core";
import { DesignTokenMetadata, DesignTokenType } from "@adaptive-web/adaptive-ui";
import { designTokenTitle } from "../../util.js";

export type ChangeEventDetail = string;

const tokenTemplatesByType = {
default: html<DesignTokenField>`
Expand Down Expand Up @@ -36,7 +40,7 @@ const tokenTemplatesByType = {

const template = html<DesignTokenField>`
<label>
<span>${x => x.designToken?.title}</span>
<span>${x => designTokenTitle(x.designToken)}</span>
${x => x.selectTemplate()}
</label>
`;
Expand Down Expand Up @@ -79,19 +83,19 @@ const styles = css`
})
export class DesignTokenField extends FASTElement {
@observable
designToken?: DesignTokenDefinition;
designToken?: DesignToken<any> & DesignTokenMetadata;

@observable
value: string = "";
valueChanged(prev: string, next: string) {
this.$emit("change", this.value);
this.$emit("change", this.value as ChangeEventDetail);
}

selectTemplate() {
if (this.designToken) {
if (this.designToken.formControlId === FormControlId.color) {
if (this.designToken.type === DesignTokenType.color) {
return tokenTemplatesByType.color;
} else if (this.designToken.id === "color.layer.fill.ramp.baseLuminance") {
} else if (this.designToken.name === "color.layer.fill.ramp.baseLuminance") {
return tokenTemplatesByType.luminance;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,27 @@ import {
repeat,
when,
} from "@microsoft/fast-element";
import { staticallyCompose } from "@microsoft/fast-foundation";
import { DesignToken, staticallyCompose } from "@microsoft/fast-foundation";
import SubtractIcon from "../../assets/subtract.svg";
import type { UIDesignTokenValue } from "../../ui-controller-tokens.js";
import { DesignTokenField } from "../design-token-field/index.js";
import { ChangeEventDetail, DesignTokenField } from "../design-token-field/index.js";

DesignTokenField;

export type TokenChangeEventDetail = UIDesignTokenValue;
export type DetachEventDetail = DesignToken<any>;

const template = html<DesignTokensForm>`
<ul>
${repeat(
x => x.designTokens,
html<UIDesignTokenValue, DesignTokensForm>`
<li>
<designer-design-token-field
:designToken=${x => x.definition}
:designToken=${x => x.token}
:value=${x => x.value}
@change="${(x, c) =>
c.parent.changeHandler(x, c.event as CustomEvent)}"
c.parent.changeHandler(x, (c.event as CustomEvent).detail as ChangeEventDetail)}"
></designer-design-token-field>
<adaptive-button
appearance="stealth"
Expand Down Expand Up @@ -69,9 +72,9 @@ export class DesignTokensForm extends FASTElement {
@observable
designTokens: UIDesignTokenValue[] = [];

changeHandler(token: UIDesignTokenValue, e: CustomEvent) {
token.value = e.detail;
this.$emit("tokenChange", token);
changeHandler(token: UIDesignTokenValue, value: string) {
token.value = value;
this.$emit("tokenChange", token as TokenChangeEventDetail);
}

detachHandler(token: UIDesignTokenValue) {
Expand All @@ -83,6 +86,6 @@ export class DesignTokensForm extends FASTElement {
});
this.designTokens.splice(detachIndex, 1);

this.$emit("detach", token.definition);
this.$emit("detach", token.token as DetachEventDetail);
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { calc } from '@csstools/css-calc';
import { observable } from "@microsoft/fast-element";
import { type DesignToken } from "@microsoft/fast-foundation";
import { DesignToken } from "@microsoft/fast-foundation";
import { Color } from "@adaptive-web/adaptive-ui";
import { formatHex8 } from 'culori';
import { DesignTokenDefinition, DesignTokenValue, PluginUINodeData } from "@adaptive-web/adaptive-ui-designer-core";
import { DesignTokenValue, PluginUINodeData } from "@adaptive-web/adaptive-ui-designer-core";
import { UIController } from "./ui-controller.js";
import { ElementsController } from "./ui-controller-elements.js";

Expand All @@ -12,9 +12,9 @@ import { ElementsController } from "./ui-controller-elements.js";
*/
export interface UIDesignTokenValue {
/**
* The definition of the design token.
* The design token.
*/
definition: DesignTokenDefinition;
token: DesignToken<any>;

/**
* Represents the design token value if all selected nodes have the same value.
Expand All @@ -41,7 +41,7 @@ export class DesignTokenController {
* A list of all design tokens which are not already applied to the selected nodes.
*/
@observable
public availableDesignTokens: DesignTokenDefinition[] | null = null;
public availableDesignTokens: DesignToken<any>[] | null = null;

constructor(
private readonly controller: UIController,
Expand All @@ -67,8 +67,8 @@ export class DesignTokenController {

// Get all design tokens that can be added, which is the full list except any already applied.
this.availableDesignTokens = this.controller.designTokenRegistry.entries.filter((definition) =>
this.designTokenValues?.find((appliedToken) => appliedToken.definition.id === definition.id) === undefined
);
this.designTokenValues?.find((appliedToken) => appliedToken.token.name === definition.id) === undefined
).map(def => def.token);
}

/**
Expand All @@ -92,12 +92,11 @@ export class DesignTokenController {

const allDesignTokens = this.controller.designTokenRegistry.entries;

allDesignTokens.forEach(designToken => {
if (tokenValues.has(designToken.id)) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const set = tokenValues.get(designToken.id)!;
allDesignTokens.forEach(def => {
if (tokenValues.has(def.id)) {
const set = tokenValues.get(def.id);
designTokens.push({
definition: designToken,
token: def.token,
value: set.size === 1 ? set.values().next().value : undefined,
multipleValues: set.size > 1 ? [...set].join(", ") : undefined,
});
Expand Down Expand Up @@ -135,57 +134,57 @@ export class DesignTokenController {
return val;
}

private setDesignTokenForNode(node: PluginUINodeData, definition: DesignTokenDefinition, value: any): void {
private setDesignTokenForNode(node: PluginUINodeData, token: DesignToken<any>, value: any): void {
if (value) {
const designToken = new DesignTokenValue(value);
node.designTokens.set(definition.id, designToken);
node.designTokens.set(token.name, designToken);
} else {
node.designTokens.delete(definition.id);
node.designTokens.delete(token.name);
}
// console.log(" after set designTokens", node.id, node.type, node.designTokens);

const element = this.elements.getElementForNode(node);
this.elements.setDesignTokenForElement(element, definition.token, value);
this.elements.setDesignTokenForElement(element, token, value);
}

/**
* Sets a design token value (override) for the selected nodes.
*
* @param definition - The design token definition
* @param token - The design token definition
* @param value - The value for this design token for the selected nodes
*/
public setDesignToken(definition: DesignTokenDefinition, value: any): void {
public setDesignToken(token: DesignToken<any>, value: any): void {
const nodes = this.controller.selectedNodes;

// console.log("--------------------------------");
// console.log("DesignTokenController.setDesignToken", definition, value, typeof value, nodes);
// console.log("DesignTokenController.setDesignToken", token, value, typeof value, nodes);

nodes.forEach(node =>
this.setDesignTokenForNode(node, definition, value)
this.setDesignTokenForNode(node, token, value)
);

this.setupDesignTokenObservables();

this.controller.refreshSelectedNodes("setDesignToken " + definition.id);
this.controller.refreshSelectedNodes("setDesignToken " + token.name);
}

/**
* Removes a design token value (override) from the selected nodes.
*
* @param definition - The design token definition
* @param token - The design token definition
*/
public removeDesignToken(definition: DesignTokenDefinition): void {
public removeDesignToken(token: DesignToken<any>): void {
const nodes = this.controller.selectedNodes;

// console.log("--------------------------------");
// console.log("DesignTokenController.removeDesignToken", definition.id, nodes);
// console.log("DesignTokenController.removeDesignToken", token.name, nodes);

nodes.forEach(node =>
this.setDesignTokenForNode(node, definition, null)
this.setDesignTokenForNode(node, token, null)
);

this.setupDesignTokenObservables();

this.controller.refreshSelectedNodes("removeDesignToken " + definition.id);
this.controller.refreshSelectedNodes("removeDesignToken " + token.name);
}
}
16 changes: 16 additions & 0 deletions packages/adaptive-ui-designer-figma-plugin/src/ui/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { sentenceCase } from "change-case";
import { DesignToken } from "@microsoft/fast-foundation";

export function designTokenTitle(token?: DesignToken<any>): string {
if (token === undefined || token.name === undefined) {
console.log(token);

return "-";
}

// Handle legacy non-hierarchical format for `custom-recipes.ts`.
const name = token.name.indexOf(".") > -1 ? token.name.split(".").slice(1).join("-") : token.name;

const base = name.replace(/-/g, ' ').replace(/density_/, '');
return sentenceCase(base);
}

0 comments on commit 7e36583

Please sign in to comment.