diff --git a/packages/tokens/README.md b/packages/tokens/README.md index 687df5c2506fc4de606584197d6ffed47631132b..4a5cbbc63e6c42e78eed020866fe4c966d47930f 100644 --- a/packages/tokens/README.md +++ b/packages/tokens/README.md @@ -28,6 +28,25 @@ import * as tokens from "@sikt/sds-tokens"; </Button>; ``` +### Tailwind CSS + +This is a v4 config with peer dependency on `tailwindcss@^4.0.0`. It disables Tailwind preflight and rely on CSS resets and variables from `@sikt/sds-core`. + +```css +@import url("@sikt/sds-core"); +@import url("@sikt/sds-tokens/dist/tailwind/config.css"); +``` + +```html +<button class="text-brand-primary-strong">Hello, World!</button> +``` + +#### Caveats + +Theme utilities where we have our own tokens have been disabled in the Tailwind config with `--property-*: initial;`. + +Tailwind spacing (padding/margin) is scale constructed from a base value. This has been disabled and instead you should use our CSS custom properties `p-(--sds-space-padding-small)`. + ## Design Tokens Colors are available in light (default) and dark scheme. diff --git a/packages/tokens/bin/build.mjs b/packages/tokens/bin/build.mjs index a59fbdfb4bb96a496b0424998b4b2b28ac581e09..c5ac7930004b507726521ed3c6280b6796e8ddba 100644 --- a/packages/tokens/bin/build.mjs +++ b/packages/tokens/bin/build.mjs @@ -119,6 +119,74 @@ ${dictionary.allTokens }, }); +/** + * Custom Format: Tailwind @theme + * This adds tokens to @theme. + */ +StyleDictionary.registerFormat({ + name: "format/tailwind/config", + format: ({ dictionary, options }) => { + const colorTokens = dictionary.allTokens.filter( + (prop) => prop.attributes.category === "color", + ); + const typographyTokens = dictionary.allTokens.filter( + (prop) => prop.attributes.category === "typography", + ); + const fontSizeTokens = typographyTokens.filter( + (prop) => + prop.attributes.category === "typography" && + prop.attributes.item.includes("fontsize"), + ); + const lineHeightTokens = typographyTokens.filter( + (prop) => + prop.attributes.category === "typography" && + prop.attributes.item.includes("lineheight"), + ); + const fontWeightTokens = typographyTokens.filter( + (prop) => prop.attributes.type === "weight", + ); + const breakpointTokens = dictionary.allTokens.filter( + (prop) => prop.attributes.type === "breakpoint", + ); + const borderRadiusTokens = dictionary.allTokens.filter( + (prop) => + prop.attributes.type === "border" && prop.attributes.item === "radius", + ); + + return ( + defaultFileHeader + + `@layer theme, base, components, utilities; + +@import "tailwindcss/theme.css" layer(theme); +@import "tailwindcss/utilities.css" layer(utilities); + +@theme inline { + --color-*: initial; +${colorTokens.map((prop) => ` --${prop.name.replace(`${prefix}-`, "")}: var(--${prop.name});`).join("\n")} + + --font-*: initial; + --font-sans: Haffer, Arial, sans-serif; + --font-mono: monospace; + + --text-*: initial; +${fontSizeTokens.map((prop) => ` --text-${prop.attributes.type}-${prop.attributes.item.replace("fontsize-", "")}: var(--${prop.name});`).join("\n")} +${lineHeightTokens.map((prop) => ` --text-${prop.attributes.type}-${prop.attributes.item.replace("lineheight-", "")}--line-height: var(--${prop.name});`).join("\n")} + + --font-weight-*: initial; +${fontWeightTokens.map((prop) => ` --font-weight-${prop.attributes.item}: var(--${prop.name});`).join("\n")} + + --breakpoint-*: initial; +${breakpointTokens.map((prop) => ` --breakpoint-${prop.attributes.item}: ${prop.value};`).join("\n")} + + --spacing-*: initial; + + --radius-*: initial; +${borderRadiusTokens.map((prop) => ` --radius-${prop.attributes.subitem}: var(--${prop.name});`).join("\n")} +}` + ); + }, +}); + const dictionaryTokens = new StyleDictionary({ source: [`${sourcePath}**/!(*.tablet|*.desktop).{json,js,mjs}`], platforms: { @@ -162,6 +230,23 @@ const dictionaryTokens = new StyleDictionary({ }, ], }, + tailwind: { + transforms: [ + "attribute/cti", + "name/kebab", + "time/seconds", + "html/icon", + "color/hex", + ], + buildPath, + prefix, + files: [ + { + format: "format/tailwind/config", + destination: "tailwind/config.css", + }, + ], + }, }, });