Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@import "@esri/calcite-design-tokens/dist/css/component.css";
@import "@esri/calcite-design-tokens/dist/scss/index";
@import "@esri/calcite-design-tokens/dist/scss/core";

Expand Down
23 changes: 23 additions & 0 deletions packages/calcite-components/tailwind.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Config } from "tailwindcss";
import calcitePreset from "@esri/calcite-tailwind-preset";
import { invert } from "@esri/calcite-tailwind-preset/dist/utils";
import plugin from "tailwindcss/plugin";

const config: Config = {
presets: [calcitePreset],
Expand All @@ -17,6 +19,27 @@ const config: Config = {
},
},
},
plugins: [
plugin(({ addUtilities }) => {
addUtilities({
// we override preset focus utils to allow using the internal focus color
".focus-base": {
"outline-color": "transparent",
},
".focus-normal": {
outline: "2px solid var(--calcite-internal-color-focus)",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should we use a var for 2px? Maybe the border width var? var(--calcite-spacing-base)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good idea. I'll do that in a follow-up since I'll also have to update the preset utils.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

PR submitted! #12348

},
".focus-outset": {
outline: "2px solid var(--calcite-internal-color-focus)",
"outline-offset": invert("2px", "--calcite-offset-invert-focus"),
},
".focus-inset": {
outline: "2px solid var(--calcite-internal-color-focus)",
"outline-offset": invert("-2px", "--calcite-offset-invert-focus"),
},
});
}),
],
};

export default config;
85 changes: 85 additions & 0 deletions packages/calcite-design-tokens/src/build/format/component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import prettierSync from "@prettier/sync";
import type { FormatFn, TransformedToken } from "style-dictionary/types";
import { fileHeader } from "style-dictionary/utils";
import StyleDictionary from "style-dictionary";
import { Config, PlatformConfig } from "../../types/extensions.js";
import { RegisterFn, Stylesheet } from "../../types/interfaces.js";
import { fromTokens } from "../utils/dictionary.js";
import { light } from "../dictionaries/index.js";
import { Platform } from "../utils/enums.js";
import { createVarList } from "./utils/index.js";

export const FormatComponent = "calcite/format/component";

export const registerFormatComponent: RegisterFn = () => {
StyleDictionary.registerFormat({
name: FormatComponent,
format: formatComponentFile,
});
};

export const formatComponentFile: FormatFn = async (args) => {
const { file, options, platform } = args;
const platformConfig = platform as PlatformConfig;

if (platformConfig.options.platform !== Platform.css) {
throw new Error("Only css platform is supported.");
}

const header = await fileHeader({ file });
const stylesheetFormat: Stylesheet = platformConfig.options.platform;

const lightDictionary = await light.getPlatformTokens(options.platform, { cache: true });
const filteredTokens: TransformedToken[] = [];
const componentTokens = lightDictionary.allTokens.filter((token) => {
const isComponent = token.attributes?.scope === "component";
if (!isComponent) {
filteredTokens.push(token);
}
return isComponent;
});

const componentTokenDictionary = fromTokens(componentTokens, filteredTokens);
const componentVarDeclarations = createVarList(stylesheetFormat, componentTokenDictionary, {
...args,
options: {
...args.options,
// assumes all component tokens need to use a reference (custom CSS prop) as the value
outputReferences: true,
},
})
.split(";")
.filter(Boolean)
.map((varDeclaration) => varDeclaration.split(":").map((part) => part.trim()));

const prefix = (options as Config).platforms[platformConfig.options.platform].prefix!;
const componentScopedVars = componentVarDeclarations.map(([name, value]) => {
// we define internal variables to allow overrides at a global or component level
const internalVarName = name.replace(prefix, `${prefix}-internal`);

return `${internalVarName}: var(${name}, var(${getLegacyVarName(name, prefix)}, ${value.trim()}))`;
});

const content = `:host {${componentScopedVars.join(";\n")}}`;

return prettierSync.format(`${header}${content}`, {
parser: stylesheetFormat,
});
};

/**
* This is based on the focus color variable, but we could use additional token attributes to get the proper legacy var name
*
* @param name - The name of the token.
* @param prefix - The prefix used in the token name.
*/
function getLegacyVarName(name: string, prefix: string): string {
const legacyPrefix = `${prefix}-ui`;
const suffix = name
.slice(name.indexOf(prefix) + prefix.length)
.split("-")
.filter(Boolean)
.reverse()
.join("-");
return `--${legacyPrefix}-${suffix}`;
}
21 changes: 9 additions & 12 deletions packages/calcite-design-tokens/src/build/format/index-file.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import prettierSync from "@prettier/sync";
import type { Dictionary, FormatFn, FormatFnArguments } from "style-dictionary/types";
import { fileHeader, formattedVariables } from "style-dictionary/utils";
import type { FormatFn } from "style-dictionary/types";
import { fileHeader } from "style-dictionary/utils";
import StyleDictionary from "style-dictionary";
import { PlatformConfig } from "../../types/extensions.js";
import { RegisterFn, Stylesheet } from "../../types/interfaces.js";
import { fromTokens } from "../utils/dictionary.js";
import { isThemed } from "../utils/token-types.js";
import { dark, light } from "../dictionaries/index.js";
import { Platform } from "../utils/enums.js";
import { createVarList } from "./utils/index.js";

export const registerFormatIndex: RegisterFn = () => {
StyleDictionary.registerFormat({
Expand Down Expand Up @@ -37,12 +38,16 @@ export const formatIndexFile: FormatFn = async (args) => {
const varLists = {
light: createVarList(
commonVarFormat,
fromTokens(lightDictionary.allTokens.filter((token) => isThemed(token, { theme: "light" }))),
fromTokens(
lightDictionary.allTokens.filter((token) => isThemed(token) && token.attributes?.scope !== "component"),
),
args,
),
dark: createVarList(
commonVarFormat,
fromTokens(darkDictionary.allTokens.filter((token) => isThemed(token, { theme: "dark" }))),
fromTokens(
darkDictionary.allTokens.filter((token) => isThemed(token) && token.attributes?.scope !== "component"),
),
args,
),
} as const;
Expand Down Expand Up @@ -72,12 +77,4 @@ function importUrl(fileName: string, fileExtension: string) {
return `@import ${fileExtension === ".css" ? `url("./${fileBaseName}")` : `"./${fileBaseName}"`};`;
}

function createVarList(format: Stylesheet, dictionary: Dictionary, args: FormatFnArguments) {
return formattedVariables({
format,
dictionary,
...args.options,
});
}

export const FormatIndex = "calcite/format/index";
3 changes: 3 additions & 0 deletions packages/calcite-design-tokens/src/build/format/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import { registerFormatDocs } from "./docs.js";
import { registerFormatJs } from "./javascript.js";
import { registerFormatTypography } from "./typography.js";
import { registerFormatIndex } from "./index-file.js";
import { registerFormatComponent } from "./component.js";

export function registerFormats(): void {
registerFormatDocs();
registerFormatJs();
registerFormatTypography();
registerFormatIndex();
registerFormatComponent();
}

export { FormatCalciteJs } from "./javascript.js";
export { FormatCalciteDocs } from "./docs.js";
export { FormatTypography } from "./typography.js";
export { FormatIndex } from "./index-file.js";
export { FormatComponent } from "./component.js";
25 changes: 23 additions & 2 deletions packages/calcite-design-tokens/src/build/format/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { TransformedToken } from "style-dictionary/types";
import type { FormatFnArguments, Dictionary, TransformedToken } from "style-dictionary/types";
import { formattedVariables } from "style-dictionary/utils";
import { Stylesheet } from "../../../types/interfaces.js";

/**
* Helper function to remove extraneous token attributes
*
* Removal of these fields are to get output as similar as possible to production
* Removal of these fields is to get output as similar as possible to production
* it can be removed afterward
*
* @param token
Expand Down Expand Up @@ -31,3 +33,22 @@ export function cleanAttributes(token: TransformedToken): void {
delete token.$extensions;
}
}

/**
* Util to create a var list from a format's arguments
*
* @param format
* @param dictionary
* @param args
*/
export function createVarList(
format: Stylesheet,
dictionary: Dictionary,
args: FormatFnArguments,
): ReturnType<typeof formattedVariables> {
return formattedVariables({
format,
dictionary,
...args.options,
});
}
45 changes: 44 additions & 1 deletion packages/calcite-design-tokens/src/build/overrides/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import StyleDictionary from "style-dictionary";
import type { Transform } from "style-dictionary/types";
import type { Config, Transform, TransformedToken, ValueTransform } from "style-dictionary/types";
import { alignTypes, excludeParentKeys } from "@tokens-studio/sd-transforms";
import { PlatformConfig } from "../../types/extensions.js";
import { isBreakpoint, isBreakpointRelated, isFontRelated } from "../utils/token-types.js";
Expand Down Expand Up @@ -73,8 +73,51 @@ function overrideTokenStudioPreprocessors(): void {
}

function overrideTokenStudioTransforms(): void {
function transformThemeColor(
theme: "light" | "dark",
target: any,
context: {
token: TransformedToken;
transform: ValueTransform;
config: PlatformConfig;
options: Config;
},
): void {
context.token.value.color = context.token.value[theme];
target[theme] = (
context.transform.transform(context.token, context.config, context.options) as {
color: string;
}
).color;
delete context.token.value.color;
}

const sd = StyleDictionary;

overrideTransform("ts/color/css/hexrgba", sd, (ogTransform) => ({
transform: (token, config, options) => {
const isLegacyThemeToken = typeof token.value === "object" && "light" in token.value;
if (isLegacyThemeToken) {
const ogType = token.type;
token.type = "shadow"; // force the transform to process object structure
const transformed = {};
const context = {
token,
transform: ogTransform as ValueTransform,
config: config as PlatformConfig,
options,
} as const;
transformThemeColor("light", transformed, context);
transformThemeColor("dark", transformed, context);
token.type = ogType;

return transformed;
}

return ogTransform.transform(token, config, options);
},
}));

overrideTransform("ts/size/px", sd, (ogTransform) => ({
filter: (token, options) => {
const shouldSkip = token.isSource && isBreakpointRelated(token);
Expand Down
15 changes: 13 additions & 2 deletions packages/calcite-design-tokens/src/build/utils/dictionary.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import type { Dictionary } from "style-dictionary/types";
import { convertTokenData } from "style-dictionary/utils";

export function fromTokens(tokens: Parameters<typeof convertTokenData>[0]): Dictionary {
return {
export function fromTokens(
tokens: Parameters<typeof convertTokenData>[0],
unfilteredTokens?: Parameters<typeof convertTokenData>[0],
): Dictionary {
const dictionary: Dictionary = {
tokens: convertTokenData(tokens, { output: "object" }),
allTokens: convertTokenData(tokens, { output: "array" }),
tokenMap: convertTokenData(tokens, { output: "map" }),
};

if (unfilteredTokens) {
dictionary.unfilteredTokens = convertTokenData(unfilteredTokens, { output: "object" });
dictionary.unfilteredAllTokens = convertTokenData(tokens, { output: "array" });
dictionary.unfilteredTokenMap = convertTokenData(tokens, { output: "map" });
}

return dictionary;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { OutputReferences } from "style-dictionary/types";

export const primitiveValueOutputReferences: Exclude<OutputReferences, boolean> = (token) => {
return !!(token.type === "color" && token.path.includes("focus"));
};
4 changes: 4 additions & 0 deletions packages/calcite-design-tokens/src/config/color/dark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { expandTypesMap as sdTypes } from "@tokens-studio/sd-transforms";
import type { Config } from "../../types/extensions.js";
import { transformers, filters, headers, formats } from "../../build/registry/index.js";
import { Platform } from "../../build/utils/enums.js";
import { primitiveValueOutputReferences } from "../../build/utils/output-references.js";

const config: Config = {
source: ["src/tokens/semantic/color/dark.json"],
Expand All @@ -29,6 +30,7 @@ const config: Config = {
platform: Platform.scss,
fileExtension: ".scss",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
},
[Platform.css]: {
Expand All @@ -46,6 +48,7 @@ const config: Config = {
platform: Platform.css,
fileExtension: ".css",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
},
[Platform.es6]: {
Expand All @@ -57,6 +60,7 @@ const config: Config = {
platform: Platform.es6,
fileExtension: ".js",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
files: [
{
Expand Down
4 changes: 4 additions & 0 deletions packages/calcite-design-tokens/src/config/color/light.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { expandTypesMap as sdTypes } from "@tokens-studio/sd-transforms";
import type { Config } from "../../types/extensions.js";
import { transformers, filters, headers, formats } from "../../build/registry/index.js";
import { Platform } from "../../build/utils/enums.js";
import { primitiveValueOutputReferences } from "../../build/utils/output-references.js";

const config: Config = {
source: ["src/tokens/semantic/color/light.json"],
Expand All @@ -29,6 +30,7 @@ const config: Config = {
platform: Platform.scss,
fileExtension: ".scss",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
},
[Platform.css]: {
Expand All @@ -46,6 +48,7 @@ const config: Config = {
platform: Platform.css,
fileExtension: ".css",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
},
[Platform.es6]: {
Expand All @@ -57,6 +60,7 @@ const config: Config = {
platform: Platform.es6,
fileExtension: ".js",
fileHeader: headers.HeaderDefault,
outputReferences: primitiveValueOutputReferences,
},
files: [
{
Expand Down
Loading
Loading