# AWS Cloudscape 设计系统

## AWS Cloudscape 设计系统界面预览

尝试无效名称、选择容量配置，在配置与审核步骤之间切换、更改外观，并在本地确认配置。

## AWS Cloudscape 设计系统设计参考

Cloudscape 组件 3.0.1390 和 design-tokens 3.0.114，采用 visual-refresh 主题。数值取自已发布的令牌 JSON。颜色模式与内容密度是相互独立的维度。这是精选的实现参考，并非完整的令牌导出。

### 浅色与深色模式下的语义化颜色角色

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| color-background-layout-main | light: #ffffff; dark: #161d26 | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-background-container-content | light: #ffffff; dark: #161d26 | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-body-default | light: #0f141a; dark: #c6c6cd | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-body-secondary | light: #424650; dark: #c6c6cd | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-interactive-default | light: #424650; dark: #dedee3 | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-link-default | light: #006ce0; dark: #42b4ff | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-status-error | light: #db0000; dark: #ff7a7a | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-text-status-success | light: #00802f; dark: #2bb534 | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-border-input-default | light: #8c8c94; dark: #656871 | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
| color-background-button-primary-default | light: #006ce0; dark: #42b4ff | 请在该命名角色的预期使用场景中使用它；此处并列展示浅色与深色模式下的取值，并非可互换的色样。 |
### 正文与标题排版

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| font-size-body-m | 14px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-body-s | 12px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-heading-l | 20px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-heading-m | 18px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-heading-s | 16px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-heading-xl | 24px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| font-size-heading-xs | 14px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-body-m | 20px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-body-s | 16px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-heading-l | 24px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-heading-m | 22px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-heading-s | 20px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-heading-xl | 30px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
| line-height-heading-xs | 18px | 搭配使用同一角色的 font-size 和 line-height。Header 和 Box 的变体用于体现组件层级。 |
### 适配密度的间距

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| space-scaled-xxxs | comfortable: 2px; compact: 0px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-xxs | comfortable: 4px; compact: 2px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-xs | comfortable: 8px; compact: 4px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-s | comfortable: 12px; compact: 8px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-m | comfortable: 16px; compact: 12px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-l | comfortable: 20px; compact: 16px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-xl | comfortable: 24px; compact: 20px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-xxl | comfortable: 32px; compact: 24px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
| space-scaled-xxxl | comfortable: 40px; compact: 32px | 根据当前密度使用舒适或紧凑模式下的取值。不要随这些间距变化缩放文本。 |
### 组件形状

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| border-radius-container | 16px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
| border-radius-button | 20px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
| border-radius-input | 8px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
| border-radius-alert | 12px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
| border-radius-dropdown | 8px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
| border-radius-card-embedded | 8px | 保留指定组件的形状。按钮圆角不等于容器的通用圆角。 |
### 交互时序

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| motion-duration-responsive | default: 115ms; disabled: 0ms | 在禁用动态效果模式下，原生动效会归零。避免为同一交互添加无关的过渡效果。 |
| motion-duration-expressive | default: 165ms; disabled: 0ms | 在禁用动态效果模式下，原生动效会归零。避免为同一交互添加无关的过渡效果。 |
| motion-duration-complex | default: 250ms; disabled: 0ms | 在禁用动态效果模式下，原生动效会归零。避免为同一交互添加无关的过渡效果。 |
### 原生组合 API

| 名称 / 规则 | 值 / 配置 | 用途 |
| --- | --- | --- |
| Wizard | activeStepIndex · onNavigate · onSubmit | 在 React 中维护当前步骤；接受请求的下一步索引前先进行验证。 |
| FormField | label · constraintText · errorText | 将格式规则和无效输入反馈与名称输入框放在一起。 |
| Input | value · onChange({ detail }) | 读取 detail.value，而不是 DOM 事件目标。 |
| Select | selectedOption · options · onChange | 保留所选选项对象，包括 label 和 value。 |
| Container | header={<Header variant="h2" />} | 将相关配置字段分组，无需另创一套卡片体系。 |
| ColumnLayout | columns={2} · variant="text-grid" | 使用可响应组件库布局的列展示精简的审核元数据。 |
| SpaceBetween | size="l" | 使用组件库的间距比例分隔字段和审核模块。 |
| applyMode | Mode.Light / Mode.Dark | 切换全局视觉模式，以应用于原生组件和语义令牌。 |
## AWS Cloudscape 设计系统完整指南

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

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

## AWS Cloudscape 设计系统配置架构

### 使用 Wizard 匹配工作流

> 此示例将配置与审核分开。Wizard 提供步骤导航和操作；应用则负责当前索引、字段值、验证规则和最终确认。用户可以返回配置，而无需重新构建表单或丢失所选容量。相比将整个多步骤工作流藏在一个通用 Card 中，这种方式更合适。

### 使用原生容器构建

Container、Header 和 SpaceBetween 用于定义表单区域。h1 介绍操作，h2 标示设置分组。说明文字紧邻其所描述的字段或步骤。外围 1200px 最大宽度和页面内边距是应用明确设置的 CSS，不是导出的 Cloudscape 布局令牌。

## AWS Cloudscape 设计系统语义令牌与视觉模式

### 先选定用途，再选择值

此参考将布局背景、容器内容、正文文本、交互文本和状态反馈区分开来。它们的值并非一组无差别的配色。为自定义 UI 添加样式时，应从 @cloudscape-design/design-tokens 导入具名令牌，而不是在每种状态中复制浅色十六进制值。令牌约定的是用途，具体值则可以演进。

### 通过组件库切换模式

此预览通过 global-styles 中的 Mode.Light 或 Mode.Dark 调用 applyMode。这样会更新组件使用的模式，而不是替换任意 CSS 颜色。深色审核页面仍保留相同的标签、所选容量和导航状态。源 JSON 记录了浅色和深色模式下的解析结果，便于检查二者的区别。

## AWS Cloudscape 设计系统字体排印与标题层级

### 搭配使用字体和行高角色

visual-refresh 中的 body-m 参考值为 14px 字号、20px 行高。heading-xl 为 24px 字号、30px 行高；heading-l 为 20px 字号、24px 行高；heading-m 为 18px 字号、22px 行高。这些角色定义了紧凑的表单层级，并非可以互换的营销展示字号。

### 使用语义化组件变体

使用 Header 的 h1 变体标示“创建工作区”。容器标题使用 h2，Box 的 awsui-key-label 变体则为审核标签提供一致的次级样式。审核值仍使用常规易读文本。不要仅为增强视觉分量，就把每个字段标签都提升为标题。

## AWS Cloudscape 设计系统受控字段与审核组合

### 了解 detail 事件约定

Input 会触发一个事件，新文本位于 event 的 detail.value 中。Select 会触发包含 detail.selectedOption 的事件；它是一个选项对象，而非单独的字符串。完整示例会存储该对象，并在审核视图中显示其 label。这样可以避免常见的集成错误：只传入选项标识符作为 selectedOption，导致 Select 显示为空。

### 将字段说明与字段放在一起

FormField 负责工作区名称标签、约束说明和错误文本。验证规则要求名称长度为 3–30 个字符，仅包含小写字母、数字和连字符，且必须以字母开头。该规则是示例应用的策略，并非 AWS 的通用命名规则。容量说明也注明，其中的配置档案为虚构内容。

- 字段格式规则属于此示例应用。

- 容量选项不代表产品或定价声明。

- 原生组件负责呈现；配置由 React 状态维护。

## AWS Cloudscape 设计系统密度与响应式布局

### 不要将紧凑模式视为缩放级别

已发布的缩放间距值会随密度而异。例如，space-scaled-m 在舒适模式下为 16px，在紧凑模式下为 12px；space-scaled-l 则分别为 20px 和 16px。这些差异会压缩垂直节奏，但不会重新定义内容，也不会任意缩小文字。原生组件会应用各自的密度规则。

### 让步骤和审核布局灵活适配

Wizard 会根据可用宽度调整导航呈现方式；ColumnLayout 会响应式排列审核元数据。应用的 CSS 会在宽度低于 600px 时缩小外围内边距。示例不会将桌面端步骤导航宽度写死，移动端也会保留本地可见的“下一步”“上一步”和“确认”操作。

## AWS Cloudscape 设计系统 Wizard 验证与确认

### 接受导航前先进行验证

onNavigate 会接收 requestedStepIndex。应用会在切换到审核步骤前检查名称；如果名称无效，就保持当前步骤不变。编辑名称时会清除错误，以便下次提交时重新验证。返回设置步骤时，名称和所选选项都会保留。

1. 提交无效名称，停留在配置步骤。

2. 更正名称并选择其他容量配置档案。

3. 前往审核并确认两个值。

4. 使用“编辑设置”返回，同时保留这两个值。

5. 在本地确认并重新开始示例。

### 区分操作示例与资源预置

最终操作会显示本地成功 Alert 和配置摘要，不会假装创建了真实资源。在实际应用中，资源预置期间应让提交操作保持待处理状态，区分请求已受理与资源已创建完成，并提供失败后的恢复方式，同时保留配置。

## AWS Cloudscape 设计系统表单无障碍设计

### 保留标签和导航名称

Wizard 接收 navigationAriaLabel 和已翻译的操作文案。每个 Input 和 Select 都包含在带标签的 FormField 中。Alert 通过原生组件语义传达无效或成功的结果。可见的约束条件用于补充字段标签，而不是替代它。

### 检查整个操作流程中的键盘导航路径

使用键盘定位到名称字段，打开容量选择器，继续下一步、返回、编辑并确认。原生焦点行为会有所帮助，但步骤验证规则及确认操作的含义仍由应用负责。组件库无法自行验证缺失的业务规则。

## AWS Cloudscape 设计系统安装与自定义边界

### 同时安装相关软件包

实现通过各自的软件包子路径导入组件，并且只加载一次 global-styles。design-tokens 提供自定义样式参考。提供的 React 入口文件和精简的 CSS 文件，可在 Vite React 应用中复现此交互示例。请确保 Cloudscape 软件包版本彼此兼容。

### 以提供的示例为实际起点

只有在定义了实际服务模型后，才替换虚构的容量数据。保留事件契约和审核步骤，然后添加异步提交及明确的错误响应。对于任何定制元素，请优先使用现有 Cloudscape 组件；只有在确有需要时，才使用合适的语义令牌引入自定义元素。

## AWS Cloudscape 设计系统组件示例

### main.jsx — 完整配置向导

使用原生 Wizard、FormField、Select 和审核元数据，并通过受控导航和本地确认进行管理。

```
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import Wizard from "@cloudscape-design/components/wizard";
import Container from "@cloudscape-design/components/container";
import Header from "@cloudscape-design/components/header";
import FormField from "@cloudscape-design/components/form-field";
import Input from "@cloudscape-design/components/input";
import Select from "@cloudscape-design/components/select";
import SpaceBetween from "@cloudscape-design/components/space-between";
import ColumnLayout from "@cloudscape-design/components/column-layout";
import Box from "@cloudscape-design/components/box";
import Button from "@cloudscape-design/components/button";
import Alert from "@cloudscape-design/components/alert";
import Toggle from "@cloudscape-design/components/toggle";
import { applyMode, Mode } from "@cloudscape-design/global-styles";
import "@cloudscape-design/global-styles/index.css";
import "./cloudscape.css";
const sizes = [
  { label: "Development · 2 vCPU / 4 GiB", value: "dev" },
  { label: "Standard · 4 vCPU / 8 GiB", value: "standard" },
  { label: "Compute · 8 vCPU / 16 GiB", value: "compute" },
];
function App() {
  const [name, setName] = useState("analytics-sandbox"),
    [size, setSize] = useState(sizes[0]),
    [step, setStep] = useState(0),
    [error, setError] = useState(""),
    [complete, setComplete] = useState(false),
    [dark, setDark] = useState(false);
  function next(index) {
    if (index > 0 && !/^[a-z][a-z0-9-]{2,29}$/.test(name)) {
      setError(
        "Use 3–30 lowercase letters, numbers or hyphens, starting with a letter.",
      );
      return;
    }
    setError("");
    setStep(index);
  }
  function reset() {
    setStep(0);
    setComplete(false);
    setError("");
    setName("analytics-sandbox");
    setSize(sizes[0]);
  }
  return (
    <main className="awsui-typography cloudscape-example">
      <div className="appearance">
        <span>CLOUDSCAPE · RESOURCE CONFIGURATION</span>
        <Toggle
          checked={dark}
          onChange={({ detail }) => {
            setDark(detail.checked);
            applyMode(detail.checked ? Mode.Dark : Mode.Light);
          }}
        >
          Dark mode
        </Toggle>
      </div>
      <Header
        variant="h1"
        description="Configure a fictional compute workspace. This example does not create a cloud resource."
      >
        Create a workspace
      </Header>
      <div className="wizard-content">
        {complete ? (
          <SpaceBetween size="l">
            <Alert type="success" header="Configuration confirmed locally">
              The {name} recipe is ready for review. No cloud API was called and
              no resource was provisioned.
            </Alert>
            <Container header={<Header variant="h2">Workspace recipe</Header>}>
              <ColumnLayout columns={2} variant="text-grid">
                <div>
                  <Box variant="awsui-key-label">Name</Box>
                  {name}
                </div>
                <div>
                  <Box variant="awsui-key-label">Capacity</Box>
                  {size.label}
                </div>
              </ColumnLayout>
            </Container>
            <Button onClick={reset}>Start another example</Button>
          </SpaceBetween>
        ) : (
          <Wizard
            activeStepIndex={step}
            onNavigate={({ detail }) => next(detail.requestedStepIndex)}
            onCancel={reset}
            onSubmit={() => setComplete(true)}
            i18nStrings={{
              stepNumberLabel: (stepNumber) => `Step ${stepNumber}`,
              collapsedStepsLabel: (stepNumber, stepsCount) =>
                `Step ${stepNumber} of ${stepsCount}`,
              skipToButtonLabel: (step) => `Skip to ${step.title}`,
              navigationAriaLabel: "Configuration steps",
              cancelButton: "Reset",
              previousButton: "Previous",
              nextButton: "Next",
              submitButton: "Confirm locally",
              optional: "optional",
            }}
            steps={[
              {
                title: "Configure workspace",
                description: "Choose the identity and capacity.",
                content: (
                  <Container
                    header={<Header variant="h2">Workspace settings</Header>}
                  >
                    <SpaceBetween size="l">
                      <FormField
                        label="Workspace name"
                        constraintText="3–30 characters; lowercase letters, numbers and hyphens."
                        errorText={error}
                      >
                        <Input
                          value={name}
                          onChange={({ detail }) => {
                            setName(detail.value);
                            setError("");
                          }}
                        />
                      </FormField>
                      <FormField
                        label="Capacity profile"
                        description="These profiles are sample application data, not real cloud products or prices."
                      >
                        <Select
                          selectedOption={size}
                          onChange={({ detail }) =>
                            setSize(detail.selectedOption)
                          }
                          options={sizes}
                        />
                      </FormField>
                    </SpaceBetween>
                  </Container>
                ),
              },
              {
                title: "Review configuration",
                description:
                  "Check the values before confirming the local example.",
                content: (
                  <SpaceBetween size="l">
                    <Container
                      header={
                        <Header
                          variant="h2"
                          actions={
                            <Button onClick={() => setStep(0)}>
                              Edit settings
                            </Button>
                          }
                        >
                          Workspace settings
                        </Header>
                      }
                    >
                      <ColumnLayout columns={2} variant="text-grid">
                        <div>
                          <Box variant="awsui-key-label">Workspace name</Box>
                          {name}
                        </div>
                        <div>
                          <Box variant="awsui-key-label">Capacity profile</Box>
                          {size.label}
                        </div>
                      </ColumnLayout>
                    </Container>
                    <Alert type="info">
                      Confirmation changes the preview only. Production
                      provisioning would require a real service, permissions and
                      a verified response.
                    </Alert>
                  </SpaceBetween>
                ),
              },
            ]}
          />
        )}
      </div>
      <footer>
        Native Cloudscape components 3.0.1390 · configuration, validation,
        review and local confirmation.
      </footer>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);
```

代码参考

- 将此代码保存为 src/main.jsx。下一个代码块是导入的 src/cloudscape.css。

### cloudscape.css — 示例页面框架

围绕原生 Cloudscape 组件设置应用宽度和内边距。

```
body {
  margin: 0;
}
.cloudscape-example {
  padding: 24px;
  max-width: 1200px;
  margin: auto;
}
.appearance {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 24px;
}
.appearance > span {
  font-size: 11px;
  letter-spacing: 0.06em;
  font-weight: 700;
}
.wizard-content {
  margin-top: 32px;
}
.cloudscape-example footer {
  font-size: 12px;
  margin-top: 32px;
  color: #5f6b7a;
}
@media (max-width: 600px) {
  .cloudscape-example {
    padding: 16px;
  }
  .appearance {
    align-items: start;
  }
  .appearance > span {
    max-width: 180px;
  }
  .wizard-content {
    margin-top: 24px;
  }
}
```

代码参考

- 请勿使用此应用程序样式表覆盖原生组件类名。

## AWS Cloudscape 设计系统 Agent 设置

### 实现起点

所展示的原生示例随 React 18.3.1 一同打包。请使用你所安装的 Vite 版本支持的 Node.js 版本；并保留应用锁文件中使用的版本。

```
npm create vite@latest cloudscape-workspace -- --template react
cd cloudscape-workspace
npm install
npm install react@18.3.1 react-dom@18.3.1 @cloudscape-design/components@3.0.1390 @cloudscape-design/design-tokens@3.0.114 @cloudscape-design/global-styles
# Replace src/main.jsx and add src/cloudscape.css from the full examples.
npm run dev
```

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

```
使用 Cloudscape 构建资源配置工作流。采用提供的原生 Wizard/Container/FormField/Input/Select 代码和 visual-refresh 设计令牌角色。在各步骤间保留字段值，导航前进行验证，并显示完整的审核信息。示例容量配置仅是领域模型的占位数据，并非真实云产品。只有在提供 API 后才集成资源预配；并明确区分等待处理、失败和已确认状态。
```

## AWS Cloudscape 设计系统来源与范围

OpenDesign 指南，以及使用原生 Cloudscape 组件 3.0.1390 的原始本地工作区配置示例。容量配置是虚构的应用数据。不涉及云账户、资源预配 API 或实际服务定价。

- 向导组件 步骤导航、操作和组件 API。

- 已发布的令牌 JSON 带版本的浅色/深色和舒适/紧凑取值。

- 设计令牌用法 语义命名、导入方式和自定义组件指南。

- 组件代码库 原生源代码及 Apache 许可证。

## AWS Cloudscape 设计系统相关资源

### Backbase 设计系统

使用 Backbase 的 Angular 模块、语义主题导出和明确的审核状态构建品牌银行审核流程。比较 Web API 与单独记录的原生尺寸。

### Dell 设计系统

使用 DDS v3 构建范围明确的设备搜索：采用语义化颜色、响应式字号比例和令牌间距，并组合 InputGroup；筛选行为由应用负责。

### Duet 设计系统

通过日期范围工作流，研究 Duet 的 LocalTapiola 色彩和间距比例；其中包括 ISO 日期值、明确的范围验证、组件焦点方法，以及独立的开源选择器边界。


- [实现参考](https://cloudscape.design/components/wizard/)
- [来源](https://cdn.jsdelivr.net/npm/@cloudscape-design/design-tokens@3.0.114/index-visual-refresh.json)
- [来源](https://cloudscape.design/components/wizard/)
- [代码参考](https://cloudscape.design/components/wizard/)
- [代码参考](https://cloudscape.design/foundation/visual-foundation/layout/)
- [向导组件 步骤导航、操作和组件 API。](https://cloudscape.design/components/wizard/)
- [已发布的令牌 JSON 带版本的浅色/深色和舒适/紧凑取值。](https://cdn.jsdelivr.net/npm/@cloudscape-design/design-tokens@3.0.114/index-visual-refresh.json)
- [设计令牌用法 语义命名、导入方式和自定义组件指南。](https://cloudscape.design/foundation/visual-foundation/design-tokens/)
- [组件代码库 原生源代码及 Apache 许可证。](https://github.com/cloudscape-design/components)
