讲师中心 微信公众号
AI工具推荐 视频效率加速

探索 Tailwind 4 中的 Typesafe 设计令牌

风杰小哥_2524

风杰小哥_2524

发布时间:2024-11-30 08:18:10

|

833人浏览过

|

来源于dev.to

转载

探索 tailwind 4 中的 typesafe 设计令牌

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 class="p-4 bg-red text-white rounded-lg relative flex justify-center">click me</button>

在上面的示例中,我们可以确定几个可以标记化的值。以下每个类都可以对应于我们设计系统中的一个值:

Add Typescript Best Practices
Add Typescript Best Practices

在 CLAUDE.md 中配置 TypeScript 最佳实践和代码风格规则

下载
  • p-4
  • 背景-红色
  • 文本-白色

现在我们已经确定了可以标记化的值,我们可以将它们分为两组:静态值和动态值。静态值是组件中保持不变的值,而动态值是可以根据传递给组件的 props 进行更改的值。对于我们的示例,我们将使填充 (p-4) 静态,而文本颜色 (text-white) 和背景 (bg-red) 应通过主题属性动态设置。

创建令牌

顺风4配置

首先,我们需要在新的 tailwind css 配置中定义系统令牌:

@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 一样。不幸的是,据我所知,目前这是不可能的。

组件代币

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

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

<button class="p-4 bg-red text-white rounded-lg relative flex justify-center">click me</button>

之前,我们讨论了静态值(如 p-4)和动态值(如 bg-red 和 text-white)之间的区别。这种区别将指导我们如何组织我们的设计令牌。静态属性(如 p-4)应分组在 static 下,而动态属性(如 bg-red 和 text-white)应分组在适当的 prop 标识符下。在这种情况下,由于我们通过 theme 属性控制 bg-red 和 text-white,因此它们应该放置在令牌文件中的 theme 部分下。对于我们的示例,我们将假设 2 个主题变量 - primary 和 secondary。

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.<componentname>.<prop_name><prop_value>.tokenname

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

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

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

在组件中使用设计令牌

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

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

更新按钮组件

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

<button class="p-[--padding] bg-[--backgroundcolor] text-[--textcolor] rounded-lg relative flex justify-center">click me</button>

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

<template>
  <button
    :style="[variableMap(STATIC), variableMap(THEME[props.THEME])]"
    class="p-[--padding] bg-[--backgroundColor] text-[--textColor] 
    rounded-lg relative flex justify-center"
  >
    Click me
  </button>
</template>
<script setup lang="ts">
import { variableMap } from "...";
import { STATIC, THEME } from "Button.tokens.ts";

const props = /*THEME*/
</script>

结论

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

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

如果您觉得这篇文章有趣或有用,请在 bluesky(我在这里最活跃)、medium、dev 和/或 twitter 上关注我。

热门AI工具

更多
音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

相关专题

更多
TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

272

2026.02.13

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

500

2026.02.25

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

351

2026.03.13

TypeScript 全栈开发进阶指南
TypeScript 全栈开发进阶指南

面向有 JavaScript 基础的开发者,深入讲解 TypeScript 的类型系统与全栈开发实践。

266

2026.06.03

TypeScript Node.js 全栈工程化与Monorepo架构实践
TypeScript Node.js 全栈工程化与Monorepo架构实践

本专题围绕 TypeScript 在 Node.js 全栈开发中的工程化实践展开,系统讲解 Monorepo 架构设计、包管理策略、模块复用机制以及服务端与前端统一类型系统的构建方法。通过真实项目案例,帮助开发者提升大型全栈项目的可维护性与协作效率。

538

2026.06.16

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

5924

2023.10.24

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

12900

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1043

2024.02.23

FrankenPHP集成Laravel详细教程
FrankenPHP集成Laravel详细教程

本专题提供FrankenPHP集成Laravel的详细配置指南,全面解析运行原理、开发环境搭建、Caddyfile配置、Octane工作模式、数据库连接、队列任务、定时任务和生产环境优化,解决部署过程中常见的报错与兼容性问题。

0

2026.10.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 5.8万人学习

CSS教程
CSS教程

共754课时 | 96.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn