首页 >web前端 >css教程 >探索 Tailwind 4 中的 Typesafe 设计标记

探索 Tailwind 4 中的 Typesafe 设计标记

Linda Hamilton
Linda Hamilton原创
2024-12-02 14:32:13136浏览

Exploring Typesafe design tokens in Tailwind 4

Tailwind 4 已经面世一段时间了,团队于 2024 年 3 月首次开源了他们的进展。在我看来,最值得注意的变化之一是转变从基于 JavaScript 的配置到基于 CSS 的配置。 Tailwind 4 目前处于测试阶段,据我所知,团队仍在应对一些挑战,尤其是 Safari 兼容性。

注意:在本文后面,我们将假设您使用基于组件的框架/库,但所讨论的概念可以轻松转移到其他方法。

《顺风4》的变化

迁移到 CSS 配置

我听到了一些对此的抱怨,尤其是来自 TypeScript 用户的抱怨。然而,Tailwind 4.0 的路线图确实包括对经典 tailwind.config.js 的支持作为其首要任务:

支持 JavaScript 配置文件 - 重新引入与经典 tailwind.config.js 文件的兼容性,以便轻松迁移到 v4。

也就是说,这似乎主要是为了迁移目的,可能不是一个可持续的长期解决方案。

这对于类型安全意味着什么

在底层,Tailwind 4 使用新的 @property CSS 规则来定义内部自定义属性。

我们使用 @property 来定义具有适当类型和约束的内部自定义属性

就目前情况而言,我无法在 VS 代码中找到对 @property 规则的语法高亮支持,我已经联系了 Bluesky,看看是否有人比我更幸运。

我希望更好的@property 支持将来能够为我们提供帮助,稍后会详细介绍。

@property CSS 规则是什么

@property 规则表示直接在样式表中注册自定义属性,而无需运行任何 JavaScript。有效的 @property 规则会生成已注册的自定义属性,这类似于使用等效参数调用 registerProperty()。

什么是设计令牌

现在我们已经介绍了 Tailwind 4 中即将发生的变化及其潜在影响,让我们花点时间讨论一下设计令牌。如果您不熟悉这个术语,这里有一个快速解释:设计令牌是一种以一致、可重用的格式(通常作为变量)存储和管理设计决策的方法。它们以结构化的方式代表了设计系统的关键视觉属性,例如颜色、排版、间距、阴影。目标是集中这些设计值,以便它们可以在不同的平台和工具之间轻松更新、维护和共享。

设计系统通常由两种主要类型的值组成:系统值和组件值。例如,您的系统值可能如下所示:

const SYSTEM_TOKENS: ISystemTokens = {
  /* ... */
  COLORS: {
    /* ... */
    GREEN: {
      LIGHT: "#E0E5D9",
      MEDIUM: "#3F6212",
      DARK: "#28331A",
    }
    /* ... */
  },
  TYPOGRAPHY: {
    /* ... */
  }
  /* ... */
}

然后,您可以在组件令牌中引用系统值,如下所示:

import { SYSTEM_TOKENS } from "...";

const BUTTON_VALUES: IButtonTokens = {
  /* ... */
  COLORS: {
    /* ... */
    BACKGROUND: SYSTEM_TOKENS.COLORS.GREEN.DARK,
    /* ... */
  },
  TYPOGRAPHY: {
    /* ... */
  }
  /* ... */
}

如果您有兴趣了解有关设计系统的更多信息,那么值得探索像 Material Design 这样的知名系统。

使用 Tailwind 构建组件设计令牌

大约一周前,我写了一篇文章,讨论我一直使用的使用 Tailwind CSS 创建组件变体的替代方法。简而言之,本文探讨了如何利用 CSS 变量和 Tailwind 来管理复杂的变体,通过动态组件属性和变量映射内联设置变体值。如果您对我是如何得出这种方法感到好奇,您可以在这里阅读更多相关内容:使用 Tailwind CSS 编写组件变体的不同方法。

我们应该首先识别组件中依赖于设计令牌的部分。如前所述,这将包括颜色、排版、间距以及设计中不可或缺的任何其他固定系统值。让我们看一下以下没有设计标记的 Button 组件:

<button>



<p>In the example above, we can pinpoint several values that can be tokenized. Each of the following classes could correspond to a value in our design system:</p>

  • p-4
  • bg-red
  • text-white

Now that we've identified the values that can be tokenised, we can categorise them into two groups: static values and dynamic values. Static values are those in your component that remain constant, while dynamic values are those that can change based on the props passed to the component. For our example we'll make the padding (p-4) static, while the text colour (text-white) and background (bg-red) should be set dynamically via a theme prop.

Creating the tokens

Tailwind 4 config

First we need to define our System tokens in the new Tailwind CSS config:

@import "tailwindcss";

@theme {
  --color-white: #FFFFFF;
  --color-green-light: #E0E5D9;
  --color-green-medium: #3F6212;
  --color-green-dark: #28331A;
  --color-red-light: #F4CCCC;
  --color-red-medium: #D50000;
  --color-red-dark: #640000;

  --spacing-sm: 1rem;
  --spacing-md: 2rem;
}

系统令牌

接下来我们需要创建 system.tokens.ts 文件:

export type TColor = "--color-white" | "--color-green-light" | "--color-green-medium" | "--color-green-dark" | "--color-red-light" | "--color-red-medium" | "--color-red-dark";

export type TSpacing = "--spacing-sm" | "--spacing-md";


interface ISystemTokens {
  COLORS: {
    WHITE: TColor;
    GREEN: {
      LIGHT: TColor;
      MEDIUM: TColor;
      DARK: TColor;
    },
    RED: {
      LIGHT: TColor;
      MEDIUM: TColor;
      DARK: TColor;
    }
  },
  SPACING: {
    SMALL: TSpacing;
    MEDIUM: TSpacing;
  }
}

export const  SYSTEM_TOKENS: ISystemTokens {
  COLORS: {
    WHITE: "--color-white";
    GREEN: {
      LIGHT: "--color-green-light";
      MEDIUM: "--color-green-light";
      DARK: "--color-green-light";
    },
    RED: {
      LIGHT: "--color-red-light";
      MEDIUM: "--color-red-medium";
      DARK: "--color-red-dark";
    }
  },
  SPACING: {
    SMALL: "--spacing-sm";
    MEDIUM: "--spacing-md";
  }
}

系统设计令牌可以在设计中引用,如下所示:
$system.COLORS.GREEN.LIGHT.

在理想的世界中,我们可以直接将 CSS 文件的 @property 规则中的类型导出到 TColor 和 TSpacing 类型中,就像 SCSS 导入如何转换为 JavaScript 一样。不幸的是,据我所知,目前这是不可能的。

组件代币

现在我们已经实现了系统令牌,我们可以开始将它们集成到我们的组件中。第一步是设置我们的 .tokens.ts 文件。为了说明这一点,我们以前面看到的 Button 组件为例,并创建一个相应的 Button.tokens.ts 文件。

回顾一下,我们的 Button 组件的结构如下:

<button>



<p>Earlier, we discussed the distinction between static values (like p-4) and dynamic values (like bg-red and text-white). This distinction will guide how we organise our design tokens. Static properties, like p-4, should be grouped under STATIC, while dynamic properties, like bg-red and text-white, should be grouped under the appropriate prop identifier. In this case, since we’re controlling bg-red and text-white through a theme prop, they should be placed under the THEME section in our tokens file. For our example we'll assume 2 theme variables - PRIMARY and SECONDARY.<br>
</p>

<pre class="brush:php;toolbar:false">import { SYSTEM_TOKENS, TColor, TSpacing } from "./system.tokens.ts";
import { TTheme } from "./Button"; // PRIMARY, SECONDARY

interface IButtonStaticTokens {
  padding: TSpacing;
}

interface IButtonThemeTokens {
  backgroundColor: TColor;
  textColor: TColor;
}

export const STATIC: IButtonStaticTokens {
  padding: "--spacing-sm";
}

export const THEME: IButtonStaticTokens {
  PRIMARY: {
    backgroundColor: "--color-red-dark";
    textColor: "--color-red-light";
  },
  SECONDARY: {
    backgroundColor: "--color-green-dark";
    textColor: "--color-green-light";
  };
}

组件设计标记可以在设计中引用,如下所示:$component.Button.THEME.PRIMARY.backgroundColor。我对命名约定的偏好是使用:
$component...tokenName

$component:区分 $system 和 $component 令牌
:遵循组件的内部文件命名约定
PROP_NAME:常量大小写
PROP_VALUE:应遵循内部 prop 值大小写
代币名称(背景颜色):驼峰式*

这最终是个人喜好问题,由您决定什么最适合您的工作流程。

  • 在命名标记时,如果我需要为元素的状态指定标记,例如 :hover,我会稍微偏离驼峰式大小写。在这些情况下,我会在令牌名称前添加状态前缀,后跟两个下划线,如下所示:hover__backgroundColor.

在组件中使用设计令牌

正如我在文章前面提到的,我之前写过关于探索使用 Tailwind CSS 编写组件变体的不同方法的文章。我将在这里引用该方法,所以如果您还没有阅读过它,首先查看它可能会有所帮助,以了解该方法背后的上下文。

本文的这一部分将假设您正在使用 Javascript 框架或库来构建组件。

更新按钮组件

我们需要将现有的 tokenisable 类替换为由 css 变量支持的 Tailwind 类。请注意,变量名称与我们的 2 个 Button 组件令牌接口 IButtonStaticTokens 和 IButtonThemeTokens 中的变量名称相匹配;




<p>现在我们已经更新了类,我们需要动态应用组件样式并更新变量。为了实现这一点,我们将在组件上使用variableMap 函数。本质上,这个函数将我们的标记从 Button.tokens.ts 直接映射到组件上的内联 CSS 变量,然后我们的类可以引用这些变量。有关变量映射的示例,请参阅本文末尾。<br>
</p>

<pre class="brush:php;toolbar:false">;
  



<h2>
  
  
  结论
</h2>

<p>我期待着 Tailwind 4 的发布以及团队从现在到那时所做的改变。我喜欢尝试各种想法来应对设计令牌、变体和类型安全方面的一些挑战。</p>

<p>这是一种实验性方法,我相信会有一些强烈的意见。</p>

<p>如果您觉得这篇文章有趣或有用,请在 Bluesky(我在这里最活跃)、Medium、Dev 和/或 Twitter 上关注我。</p>


          

            
        

以上是探索 Tailwind 4 中的 Typesafe 设计标记的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn