# Palantir Blueprint 设计系统

## Palantir Blueprint 设计系统界面预览

按名称或类型筛选、选择数据集、更改行密度、切换外观，并在更新本地状态前验证审核备注。

## Palantir Blueprint 设计系统设计参考

Blueprint 核心 6.21.0 发布于 CSS，并提供原生 React 组件。此处列出所选的浅色主题令牌值；请使用库的深色主题，不要手动反转这些值。示例 CSS 中标明了应用程序的布局选择。

### 意图颜色和交互状态

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --bp-intent-primary-rest | #2d72d2 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-primary-hover | #215db0 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-primary-active | #184a90 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-primary-disabled | #4c90f0 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-primary-foreground | #ffffff | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-success-rest | #238551 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-success-hover | #1c6e42 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-success-active | #165a36 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-success-disabled | #32a467 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-success-foreground | #ffffff | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-warning-rest | #c87619 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-warning-hover | #935610 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-warning-active | #77450d | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-warning-disabled | #ec9a3c | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-warning-foreground | #111418 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-danger-rest | #cd4246 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-danger-hover | #ac2f33 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-danger-active | #8e292c | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-danger-disabled | #e76a6e | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-intent-danger-foreground | #ffffff | 使用指定的语义角色；将状态与前景色搭配使用。 |
### 字体比例和字重

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --bp-typography-size-body-x-small | 10px | 正文、标签和辅助数据的字体比例；不要将小号元数据用作主要阅读字号。 |
| --bp-typography-size-body-small | 12px | 正文、标签和辅助数据的字体比例；不要将小号元数据用作主要阅读字号。 |
| --bp-typography-size-body-medium | 14px | 正文、标签和辅助数据的字体比例；不要将小号元数据用作主要阅读字号。 |
| --bp-typography-size-body-large | 16px | 正文、标签和辅助数据的字体比例；不要将小号元数据用作主要阅读字号。 |
| --bp-typography-size-heading-small | 16px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-heading-medium | 20px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-heading-large | 24px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-heading-x-large | 28px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-heading-display | 46px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-code-small | 12px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-code-medium | 13px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-size-code-large | 14px | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-weight-default | 400 | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-weight-bold | 600 | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-line-height-default | 1.28581 | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
| --bp-typography-line-height-large | 1.5 | 在指定的层级应用相应角色；表格数字也可以使用等宽数字。 |
### 界面表面、边框和语义文本

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --bp-surface-border-color-default | #5f6b7c1f | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-border-color-strong | #5f6b7c40 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-border-width | 1px | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-border-radius | 4px | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-spacing | 4px | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-background-color-default-rest | #ffffff | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-surface-background-color-default-hover | #f6f7f9 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-typography-color-default-rest | #1c2127 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-typography-color-muted | #5f6b7c | 使用指定的语义角色；将状态与前景色搭配使用。 |
### 焦点与动效

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| --bp-emphasis-transition-duration | 100ms | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-ease-default | cubic-bezier(0.4, 1, 0.75, 0.9) | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-ease-bounce | cubic-bezier(0.54, 1.12, 0.38, 1.11) | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-focus-color | #2d72d2 | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-focus-width | 2px | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-focus-offset | 2px | 使用指定的语义角色；将状态与前景色搭配使用。 |
| --bp-emphasis-motion-reduced | 0 | 使用指定的语义角色；将状态与前景色搭配使用。 |
### 数据集工作台中使用的原生组件

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| HTMLTable | striped · interactive · condensed | 原生语义化表格；condensed 属性可调整密度，而不改变数据。 |
| InputGroup | value · onChange · intent | 受控搜索和审核备注；应用程序验证会设置 danger 意图。 |
| FormGroup | labelFor · helperText · intent | 关联可见的字段标签，并说明备注无效的原因。 |
| HTMLSelect | options · value · onChange | 用于少量固定数据集类型的原生选择框。 |
| Tag | minimal · intent | 将状态文本与 success 或 warning 样式搭配使用。 |
| Button | intent="primary" · type="submit" | 通过真实表单提交本地审核；选择按钮保持次要地位。 |
| Switch | checked · onChange | 相互独立的外观和密度控件。 |
| Callout | intent · title | 说明无结果的情况或操作结果；不要只用颜色传达状态。 |
## Palantir Blueprint 设计系统完整指南

实用指南，介绍如何为真实界面选择、应用和评审此系统。

完整指导、实现起点和源代码链接。

## 围绕数据构建的 Palantir Blueprint 设计系统工作区

### 密集控件与明确的阅读顺序

> 当屏幕需要同时展示集合、筛选器、状态和上下文操作时，Blueprint 尤其适用。此示例将数据集表格放在左侧，将选中的记录放在右侧。读者无需为查看每条记录而打开新页面，即可进行比较。检查器中包含可编辑的审核备注；表格则作为浏览区域。

### 使用 v6 软件包约定

此示例使用 @blueprintjs/core 6.21.0 编译。其 CSS 命名空间为 bp6，已发布的语义令牌以 --bp- 开头。旧版 bp5 样式表不能替代 v6 组件的 CSS。请在应用入口处仅导入一次该软件包的样式表，然后将应用布局规则限定在单独的类中。

## Palantir Blueprint 设计系统的意图与颜色角色

### 将记录状态与选择状态分开

警告 Tag 表示数据集需要审核；带主色调的行表示该记录已选中。两者含义彼此独立。将某行标记为已审核后，其标签和意图会变为成功状态，而选择仍保留在同一数据集上。表格为每种状态保留文字说明，避免仅靠颜色传达全部含义。

### 在组件边界处理深色模式

此示例在包装元素上添加 bp6-dark，使原生组件能够应用对应的深色样式。上方的浅色主题值只是参考快照，并不意味着要覆盖每个组件。引入 Dialog 等门户组件时，请确保其渲染内容也能获得相同的主题上下文；仅靠不包含门户的包装元素并不足够。

## Palantir Blueprint 记录与元数据的设计系统排版

### 先了解正文的字号层级，再选择标题

已发布的正文字号包括 10、12、14 和 16px；中号正文为 14px。数据集名称保持在主要阅读层级。ID 和记录类型使用辅助文本，记录数量则使用等宽数字，便于比较变化中的数值。本指南不建议将 10px 用于主要内容。

### 为检查器建立紧凑的层级

检查器使用 20px 标题和定义列表展示 ID、所有者、类型与数量。标签和值采用稳定的两列对齐方式。审核备注放在这些信息之后，并用分隔线隔开，避免用户误以为该操作会筛选表格。

## Palantir Blueprint 设计系统表格、筛选器与检查器

### 保留表格语义

HTMLTable 提供采用 Blueprint 样式的原生表格。首列中的按钮用于选择记录，并且可通过键盘访问；示例不会将仅支持指针操作的行事件处理程序作为唯一的选择方式。interactive 属性提供行悬停样式，condensed 则独立控制密度，不影响筛选。

### 清晰呈现受控数据流

搜索框和类型选择器从相同的本地行数据中筛选出可见集合。即使筛选器隐藏了所选记录所在的行，检查器中仍可保留该记录；这样，集合筛选条件改变时，已输入的审核备注不会随之消失。生产软件应明确决定并说明这种关系，而不是悄然丢弃编辑内容。

1. 按显示名称查找数据集。

2. 使用类型选择器缩小同一集合的范围。

3. 选择名称按钮以加载检查器。

4. 输入审核备注并提交本地审核。

## Palantir Blueprint 设计系统间距、界面表面与密度

### 采用更小的间距单位，但不必让所有间隔都变得很小

已发布的界面表面间距令牌为 4px。工作台使用该单位的倍数进行布局：筛选控件之间为 12px，集合与检查器之间为 20px，桌面示例周围为 24px。这些是 CSS 中展示的组合布局决策。4px 的圆角令牌让控件和界面的几何形态保持克制。

### 先调整布局，再考虑缩减标签

在示例应用设置的 800px 断点处，检查器会移至集合下方。筛选器会换行，主区域内边距缩至 16px；必要时，表格会使用独立的水平滚动容器。此断点仅适用于本工作台，并非 Blueprint 官方通用断点。

## Palantir Blueprint 设计系统审核与空状态

### 在审核操作中进行验证

提交空备注时，InputGroup 和 FormGroup 会设置为 danger 意图，显示说明性辅助文本，并将焦点移至该字段。输入文字后，错误提示会清除。有效提交只会更改所选的本地记录、清空备注，并显示明确说明未发送任何数据的成功 Callout。

### 在空集合旁提供恢复操作

无结果 Callout 提供“清除筛选条件”操作，会同时重置搜索查询和类型选择器，从而恢复完整集合。此操作不会删除行，也不会更改检查器。以下状态边界均为有意设计：

- 选择操作会更改检查器中显示的记录，不会更改其审核状态。

- 紧凑模式只会改变密度，不会调整记录顺序。

- 主题只会改变视觉外观，不会更改当前筛选条件。

- 本地审核成功后，只会更改一条记录，并会告知用户结果。

## Palantir Blueprint 设计系统焦点与无障碍组件使用

### 为每个原生控件添加标签

InputGroup 为搜索框设置无障碍名称，并为带标签的审核字段设置 id。HTMLSelect 具有自己的名称，Switch 会显示可见标签，每条记录则通过真正的按钮打开。请使用这些库 API，而不要用经过样式处理的 div 替代控件。

### 保留清晰可见的焦点样式

软件包参考中包含 2px 的焦点宽度和 2px 的偏移。请确保焦点指示在 Card 和选中行上清晰可见。键盘用户应能按文档顺序访问筛选器、行按钮和审核表单。示例中的状态段落和成功 Callout 会传达操作结果，无须将用户带到另一个屏幕。

## Palantir Blueprint 设计系统安装与应用边界

### 运行与示例相同的源代码

下方提供完整的 App 源代码和应用 CSS。App 会挂载到 Vite React 模板生成的根元素中。安装指定版本的 core 软件包即可使用原生组件和软件包 CSS；这个纯文本示例不需要任何隐藏的设计资源。

### 通过实际持久化约定扩展审核功能

生产环境审核需要记录标识符、权限、待处理状态和错误响应。请在应用中处理这些事项，同时保留 Blueprint 的 FormGroup 和 intent API。在服务确认接受之前，不要宣布保存成功；本地示例特意不作此类声明。

## Palantir Blueprint 设计系统组件示例

### main.jsx — 完整的数据集审核应用

完整的原生组合示例，包含筛选、选择、密度、主题、字段验证和本地审核结果。

```
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import {
  Button,
  Card,
  Callout,
  FormGroup,
  HTMLSelect,
  HTMLTable,
  InputGroup,
  Switch,
  Tag,
} from "@blueprintjs/core";
import "@blueprintjs/core/lib/css/blueprint.css";
import "./blueprint.css";
const initial = [
  {
    id: "D-1042",
    name: "Harbor sensors",
    type: "Telemetry",
    rows: "18,420",
    owner: "Maya",
    status: "Reviewed",
  },
  {
    id: "D-1043",
    name: "Transit stops",
    type: "Reference",
    rows: "842",
    owner: "Alex",
    status: "Needs review",
  },
  {
    id: "D-1044",
    name: "Water samples",
    type: "Field survey",
    rows: "2,608",
    owner: "Sam",
    status: "Reviewed",
  },
  {
    id: "D-1045",
    name: "Street survey",
    type: "Field survey",
    rows: "4,120",
    owner: "Lee",
    status: "Needs review",
  },
];
function App() {
  const [dark, setDark] = useState(false),
    [compact, setCompact] = useState(false),
    [query, setQuery] = useState(""),
    [rows, setRows] = useState(initial),
    [selected, setSelected] = useState(initial[1]),
    [note, setNote] = useState(""),
    [notice, setNotice] = useState(""),
    [error, setError] = useState(false),
    [type, setType] = useState("All");
  const visible = rows.filter(
    (r) =>
      r.name.toLowerCase().includes(query.toLowerCase()) &&
      (type === "All" || r.type === type),
  );
  function review(e) {
    e.preventDefault();
    if (!note.trim()) {
      setError(true);
      document.getElementById("review-note").focus();
      return;
    }
    const updated = { ...selected, status: "Reviewed" };
    setRows(rows.map((r) => (r.id === selected.id ? updated : r)));
    setSelected(updated);
    setNotice(
      `${selected.name} marked reviewed in this local example. No data was sent.`,
    );
    setNote("");
    setError(false);
  }
  return (
    <main className={"specimen " + (dark ? "bp6-dark" : "")}>
      <header>
        <div>
          <span className="eyebrow">BLUEPRINT · DATA WORKSPACE</span>
          <h1 className="bp6-heading">Dataset review</h1>
          <p className="bp6-text-muted">
            Inspect a record and attach a review note.
          </p>
        </div>
        <Switch
          label="Dark theme"
          checked={dark}
          onChange={(e) => setDark(e.target.checked)}
        />
      </header>
      <div className="workbench">
        <Card className="collection">
          <div className="toolbar">
            <InputGroup
              aria-label="Find a dataset"
              placeholder="Find a dataset…"
              value={query}
              onChange={(e) => setQuery(e.target.value)}
            />
            <HTMLSelect
              aria-label="Dataset type"
              value={type}
              onChange={(e) => setType(e.target.value)}
              options={["All", "Telemetry", "Reference", "Field survey"]}
            />
            <Switch
              label="Compact rows"
              checked={compact}
              onChange={(e) => setCompact(e.target.checked)}
            />
          </div>
          <p className="bp6-text-small bp6-text-muted" role="status">
            {visible.length} matching datasets
          </p>
          <div className="table-scroll">
            <HTMLTable
              striped
              interactive
              condensed={compact}
              style={{ width: "100%" }}
            >
              <thead>
                <tr>
                  <th>Name</th>
                  <th>Records</th>
                  <th>Status</th>
                </tr>
              </thead>
              <tbody>
                {visible.map((r) => (
                  <tr
                    key={r.id}
                    className={selected.id === r.id ? "selected" : ""}
                  >
                    <td>
                      <Button
                        variant="minimal"
                        onClick={() => {
                          setSelected(r);
                          setError(false);
                          setNote("");
                        }}
                        text={r.name}
                      />
                      <div className="bp6-text-small bp6-text-muted">
                        {r.id} · {r.type}
                      </div>
                    </td>
                    <td className="numeric">{r.rows}</td>
                    <td>
                      <Tag
                        minimal
                        intent={r.status === "Reviewed" ? "success" : "warning"}
                      >
                        {r.status}
                      </Tag>
                    </td>
                  </tr>
                ))}
              </tbody>
            </HTMLTable>
          </div>
          {!visible.length && (
            <Callout title="No matching datasets">
              Clear the search or choose a different dataset type.
              <Button
                variant="minimal"
                onClick={() => {
                  setQuery("");
                  setType("All");
                }}
              >
                Clear filters
              </Button>
            </Callout>
          )}
        </Card>
        <Card className="inspector">
          <span className="eyebrow">SELECTED DATASET</span>
          <h2 className="bp6-heading">{selected.name}</h2>
          <dl>
            <dt>Dataset ID</dt>
            <dd>
              <code>{selected.id}</code>
            </dd>
            <dt>Owner</dt>
            <dd>{selected.owner}</dd>
            <dt>Type</dt>
            <dd>{selected.type}</dd>
            <dt>Records</dt>
            <dd>{selected.rows}</dd>
          </dl>
          <form onSubmit={review}>
            <FormGroup
              label="Review note"
              labelFor="review-note"
              intent={error ? "danger" : "none"}
              helperText={
                error
                  ? "Add a note describing what you checked."
                  : "A short note keeps the decision understandable."
              }
            >
              <InputGroup
                id="review-note"
                value={note}
                intent={error ? "danger" : "none"}
                aria-invalid={error}
                onChange={(e) => {
                  setNote(e.target.value);
                  setError(false);
                }}
              />
            </FormGroup>
            <Button intent="primary" type="submit" fill>
              Mark reviewed locally
            </Button>
          </form>
          <p className="bp6-text-small bp6-text-muted">
            Selection, filters and review notes exist only in this preview.
          </p>
        </Card>
      </div>
      {notice && (
        <Callout intent="success" role="status">
          {notice}
        </Callout>
      )}
      <footer>
        Native Blueprint 6.21.0 · HTMLTable, Card, FormGroup, InputGroup,
        Switch, Tag and Callout.
      </footer>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);
```

代码参考

- 将此文件保存为 src/main.jsx，并将下一个示例保存为 src/blueprint.css。

- createRoot 调用使用 Vite React index.html 中的根元素。

### blueprint.css — 响应式工作台布局

应用布局规则与导入的原生 CSS 相辅相成。800px 断点和 260px 检查器宽度是示例中明确设定的值。

```
* {
  box-sizing: border-box;
}
body {
  margin: 0;
}
.specimen {
  padding: 24px;
  background: #f6f7f9;
  color: #1c2127;
  font-size: 14px;
}
.specimen.bp6-dark {
  background: #252a31;
  color: #f6f7f9;
}
.specimen header {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: center;
  margin-bottom: 24px;
}
.eyebrow {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--bp-typography-color-muted);
}
h1.bp6-heading {
  margin: 8px 0;
  font-size: 28px;
}
.workbench {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px;
  gap: 20px;
}
.collection,
.inspector {
  min-width: 0;
}
.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}
.toolbar > .bp6-input-group {
  flex: 1;
  min-width: 150px;
}
.toolbar .bp6-control {
  margin: 0;
}
.table-scroll {
  overflow: auto;
}
table td {
  vertical-align: middle !important;
}
.numeric {
  font-variant-numeric: tabular-nums;
}
tr.selected td {
  background: #2d72d20d !important;
}
.inspector h2 {
  font-size: 20px;
  margin-top: 12px;
}
.inspector dl {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 24px 0;
}
.inspector dt {
  color: var(--bp-typography-color-muted);
}
.inspector dd {
  margin: 0;
}
.inspector form {
  border-top: 1px solid var(--bp-surface-border-color-default);
  padding-top: 20px;
}
.inspector p {
  margin: 16px 0 0;
}
.specimen > .bp6-callout {
  margin-top: 20px;
}
.specimen footer {
  font-size: 11px;
  margin-top: 24px;
  color: var(--bp-typography-color-muted);
}
@media (max-width: 800px) {
  .workbench {
    grid-template-columns: 1fr;
  }
  .specimen {
    padding: 16px;
  }
  .specimen header {
    align-items: start;
  }
  .toolbar {
    gap: 16px;
  }
  h1.bp6-heading {
    font-size: 24px;
  }
}
@media (prefers-reduced-motion: reduce) {
  * {
    transition: none !important;
  }
}

.bp6-dark .eyebrow,
.bp6-dark .inspector dt,
.bp6-dark footer {
  color: #abb3bf;
}
```

代码参考

- bp6-dark 类会启用库主题；示例画布的背景属于应用 CSS。

## Palantir Blueprint 设计系统 Agent 设置

### 实现起点

此原生预览使用 React 18.3.1 和 Blueprint 6.21.0 打包并运行。请使用所选 Vite 版本支持的 Node.js 版本。上文提供了两个应用文件。

```
npm create vite@latest blueprint-review -- --template react
cd blueprint-review
npm install
npm install react@18.3.1 react-dom@18.3.1 @blueprintjs/core@6.21.0
# Replace src/main.jsx and add src/blueprint.css using the complete examples.
npm run dev
```

### 适用于你项目的提示词

```
使用 Blueprint 6.21.0 构建数据集审核工作区。阅读提供的令牌和完整的 React/CSS 示例。保留原生 HTMLTable、带标签的 InputGroup/FormGroup、状态 Tag，以及可通过键盘操作的行选择。筛选、选择、密度、外观和审核状态应彼此独立。只有在提供 API 后才接入真实的保存服务；显示待处理和失败响应时，不要丢失备注。保留响应式检查器和可见的焦点状态。
```

## Palantir Blueprint 设计系统来源与范围

OpenDesign 是一份面向 Blueprint 6.21.0 的应用指南，包含一个原创的数据集审核示例，实际运行 React 包。数据集名称和审核结果均为本地示例数据。工作台布局属于应用代码；参考值来自按版本发布的程序包。

- Blueprint 组件文档 原生组件规范与示例。

- 已发布的 6.21.0 版设计令牌 参考表格中使用的精确版本值。

- Blueprint 源代码仓库 实现、程序包发布历史和 Apache 许可信息。

## Palantir Blueprint 设计系统相关资源

### Pega Bolt

探索 Bolt 的 Pega 品牌内容系统：流动排版、横向与纵向间距分开设置，以及用于编辑资源页面的 Twig 手风琴式组合布局。

### Porsche 设计系统

通过流动式间距、CSS 配色方案、Porsche Next 字体和双选项配置器，探索 Porsche Design System v4。参考内容包含真实的令牌表达式，以及完整的 Vite 入口文件，并采用当前的分段控件事件。

### Red Hat PatternFly

使用 PatternFly 构建运维工作区：引用语义令牌、可选择的服务卡片、三态批量选择、范围审核，以及完整的原生 React 代码。


- [实现参考](https://blueprintjs.com/docs/#core/components/html-table)
- [来源](https://cdn.jsdelivr.net/npm/@blueprintjs/core@6.21.0/lib/css/blueprint-design-tokens.css)
- [来源](https://blueprintjs.com/docs/#core/components)
- [代码参考](https://blueprintjs.com/docs/#core/components)
- [代码参考](https://blueprintjs.com/docs/#core/typography)
- [Blueprint 组件文档 原生组件规范与示例。](https://blueprintjs.com/docs/#core/components)
- [已发布的 6.21.0 版设计令牌 参考表格中使用的精确版本值。](https://cdn.jsdelivr.net/npm/@blueprintjs/core@6.21.0/lib/css/blueprint-design-tokens.css)
- [Blueprint 源代码仓库 实现、程序包发布历史和 Apache 许可信息。](https://github.com/palantir/blueprint)
