数据分析 · 新资源

Semrush Intergalactic 设计系统.

一份星际主题指南,包含当前语义令牌和图表令牌、原生筛选控件、固定比例对比、选中项详情,以及完整的可复现测试样例。

OpenDesign 指南8 个章节38 条参考条目原始应用指南
01

Semrush Intergalactic 设计系统界面预览

筛选关键词、仅显示已跟踪记录、更改指标,并检查所选值,同时保留刻度上下文。

比较一组虚构关键词打开完整示例
采用 @semcore/ui 17.6.0 和 @semcore/theme 2.3.1 中的原生 Intergalactic 控件;原创 HTML 柱状图比较。 · 实现参考
02

Semrush Intergalactic 设计系统设计参考

采用 @semcore/ui 17.6.0 和 @semcore/theme 2.3.1 中的原生 Intergalactic 控件;原创 HTML 柱状图比较。

语义浅色角色

来源
名称 / 规则值 / 配置用途
--intergalactic-bg-primary-neutraloklch(1 0 0)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-bg-secondary-neutraloklch(0.98 0.001 180)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-text-primaryoklch(0.1 0.03 137 / 0.899)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-text-secondaryoklch(0.088 0.026 147.7 / 0.583)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-border-primaryoklch(0.137 0.026 175.7 / 0.161)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-control-primary-infooklch(0.23 0.01 140)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-control-primary-info-hoveroklch(0.32 0.007 140)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-control-primary-info-activeoklch(0 0 140)固定主题中的当前语义值,包括 OKLCH 表达式。
--intergalactic-control-rounded6px固定主题中的当前语义值,包括 OKLCH 表达式。

文本尺寸

来源
名称 / 规则值 / 配置用途
--intergalactic-fs-5010px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-10012px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-20014px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-30016px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-40020px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-50024px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-60032px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-70036px已发布的文本尺寸级别;根据信息层级选择对应角色。
--intergalactic-fs-80048px已发布的文本尺寸级别;根据信息层级选择对应角色。

间距

来源
名称 / 规则值 / 配置用途
--intergalactic-spacing-1x4px主题样式表中命名的间距级别。
--intergalactic-spacing-2x8px主题样式表中命名的间距级别。
--intergalactic-spacing-3x12px主题样式表中命名的间距级别。
--intergalactic-spacing-4x16px主题样式表中命名的间距级别。
--intergalactic-spacing-5x20px主题样式表中命名的间距级别。
--intergalactic-spacing-6x24px主题样式表中命名的间距级别。
--intergalactic-spacing-8x32px主题样式表中命名的间距级别。
--intergalactic-spacing-10x40px主题样式表中命名的间距级别。
--intergalactic-spacing-05x2px主题样式表中命名的间距级别。

圆角

来源
名称 / 规则值 / 配置用途
--intergalactic-rounded-extra-small2px根据组件选择合适的圆角,不要一律使用较大的圆角。
--intergalactic-rounded-small4px根据组件选择合适的圆角,不要一律使用较大的圆角。
--intergalactic-rounded-medium6px根据组件选择合适的圆角,不要一律使用较大的圆角。
--intergalactic-rounded-large12px根据组件选择合适的圆角,不要一律使用较大的圆角。
--intergalactic-rounded-extra-large24px根据组件选择合适的圆角,不要一律使用较大的圆角。

前六种图表颜色

来源
名称 / 规则值 / 配置用途
--intergalactic-chart-palette-order-1oklch(0.58 0.168 278.2)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
--intergalactic-chart-palette-order-2oklch(0.82 0.15 170)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
--intergalactic-chart-palette-order-3oklch(0.74 0.17 303)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
--intergalactic-chart-palette-order-4oklch(0.82 0.18 80)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
--intergalactic-chart-palette-order-5oklch(0.74 0.19 22)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
--intergalactic-chart-palette-order-6oklch(0.82 0.088 272.1)按顺序排列的数据系列颜色。此样例只有一个系列,因此使用第一个角色。
03

Semrush Intergalactic 设计系统完整指南

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

DESIGN-semrush-intergalactic.md

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

下载指南

Semrush Intergalactic 设计系统分析工作区布局

明确比较问题

此样例使用一个选定指标比较六个虚构关键词。筛选器、仅显示已跟踪选项和指标按钮位于结果上方。独立的信息面板会显示所选词条的两项指标,方便用户对照排名视图与原始数值。

摘自本 OpenDesign 指南

区分编制数据与测量数据

每个数字都来自固定的示例数据,并标注为仅供说明。页面不会将搜索量或难度显示为当前的 Semrush 测量结果。柱状图不依赖网络查询、分析账号或下载的客户数据。

Semrush Intergalactic 设计系统主题与令牌生成

有意识地使用当前主题 package

运行时固定使用 @semcore/ui 17.6.0 和 @semcore/theme 2.3.1。原生组件需要当前主题 package,入口文件会导入其 light.css。表格保留该样式表中的 OKLCH 值,而不是将其替换为无关的旧版十六进制默认值。

区分组件角色与图表角色

原生控件通过 Intergalactic 样式呈现外观,而原创柱状图比较使用图表调色板中的第一个系列角色。选中状态通过克制的行背景和按下状态来传达。不要不加区分地将系列颜色用于所有操作或错误颜色。

Semrush Intergalactic 设计系统:密集结果中的排版

让标签、单位和值保持关联

每个柱状图行都包含词条和明确标出的数值。小型坐标轴注释会说明刻度代表样本搜索量,还是满分 100 的分数。信息面板会再次标明这两种单位,避免用户因柱长相似而误以为这些指标可以互换。

精简文字,但不隐藏上下文

原生输入框采用较大的尺寸,便于用户进行筛选。结果标签保持紧凑,工作区标题和分区标题则使用较大的字号。在窄屏上,关键词会移到条形图和值的上方,避免被截断成难以辨认的片段。

Semrush Intergalactic 设计系统:图表刻度与排序

筛选时保持刻度稳定

数量图表的最大值始终为 8,100,难度图表的最大值始终为 100。筛选不会将剩余数据中最长的条形拉伸至全宽。这项有意设定的选择能在用户缩小数据范围时保留比较的意义。

按当前指标排序

Semrush Intergalactic 设计系统:原生输入框与复选框

使用组合式输入框结构

Input 提供外层组件,Input.Value 则是实际可编辑的控件。其 onChange 回调会将字符串值作为第一个参数,这与将其视为标准 DOM 更改事件不同。可见标签通过 Value id 与控件关联。

让布尔筛选与文本筛选彼此独立

原生 Checkbox 的 onChange 会接收布尔值 checked。推导结果行时会同时应用文本筛选和“仅显示已跟踪项”状态,因此任一筛选都可能合理地得到空结果。重置筛选会还原这两个控件,同时保留已选中的检查器上下文。

Semrush Intergalactic 设计系统:选中项详情与空状态

让选择始终关联到对应项

选中的词条会独立于数组顺序保存。点击条形图会更新该词条及其按下状态,检查器则会查找对应的完整示例记录。按另一个指标排序,不会让检查器悄然指向不同的行索引。

说明筛选后仍保留的选择

如果选中的词条不再显示,检查器仍会保留,并提供文字说明。在筛选前后比较某个项目时,这种做法很有用。结果为空时会显示明确的重置操作,而不是呈现空白图表面板。

Semrush Intergalactic 设计系统:无障碍数据比较

确保无需依赖颜色也能理解图表

条形图由真实按钮内部的装饰性 span 构成。词条和数值共同形成无障碍文本,aria-pressed 用于标识选中状态。即使看不到条形长度或系列色相,数据仍然清晰易懂。键盘焦点样式与选中行样式明显区分。

  1. 选择 Difficulty,查看重新排序后的条形图和分数单位。
  2. 筛选一个无法匹配的词条,然后使用 Reset filters。
  3. 选中一个词条,将其筛选掉,然后阅读保留选择的说明。

测试筛选后的恢复流程

原生输入框和复选框会公开其实际控件。指标切换通过带有按下状态的按钮实现,原有的重置操作会清除两个筛选条件。布局始终显示结果标题和单位说明,让空状态与非空状态拥有相同的上下文。

Semrush Intergalactic 设计系统:组件导入与主题设置

导入组件入口

@semcore/ui 根入口会有意抛出错误,而不是导出所有组件。此代码从各自的专用入口导入 button、input 和 checkbox,并导入 @semcore/theme/light.css。完整入口包含示例数据和全部推导逻辑。

  • 从专用入口导入 @semcore/ui/button、input 和 checkbox。
  • 固定使用 @semcore/theme/light.css。
  • 完整 JSX 中原有的固定刻度条形图和示例数据逻辑。

不要将自定义条形图标注为原生 D3 图表

Semrush Intergalactic 设计系统组件示例

main.jsx — 完整可运行示例

比较一组虚构的关键词。下方源代码是完整的 React 入口,包含所有状态和验证逻辑。

jsx
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import Button from "@semcore/ui/button";
import Input from "@semcore/ui/input";
import Checkbox from "@semcore/ui/checkbox";
import "@semcore/theme/light.css";
import "./intergalactic.css";
const data = [
  { term: "design tokens", volume: 8100, difficulty: 42, tracked: true },
  { term: "component library", volume: 6600, difficulty: 58, tracked: false },
  { term: "accessible forms", volume: 2900, difficulty: 31, tracked: true },
  {
    term: "responsive typography",
    volume: 1900,
    difficulty: 24,
    tracked: false,
  },
  { term: "semantic colors", volume: 1300, difficulty: 18, tracked: false },
  { term: "design system audit", volume: 720, difficulty: 36, tracked: true },
];
function App() {
  const [q, setQ] = useState(""),
    [tracked, setTracked] = useState(false),
    [metric, setMetric] = useState("volume"),
    [selected, setSelected] = useState("design tokens");
  const rows = data
    .filter((d) => d.term.includes(q.toLowerCase()) && (!tracked || d.tracked))
    .sort((a, b) => b[metric] - a[metric]);
  const max = metric === "volume" ? 8100 : 100;
  const item = data.find((d) => d.term === selected);
  return (
    <main className="research">
      <header>
        <p>RESEARCH WORKSPACE / FICTIONAL DATA</p>
        <h1>Compare a keyword set</h1>
        <span>
          Six authored sample records · figures are illustrative, not Semrush
          measurements
        </span>
      </header>
      <div className="research-toolbar">
        <div className="research-search">
          <label htmlFor="term-search">Filter keywords</label>
          <Input size="l">
            <Input.Value
              id="term-search"
              placeholder="Find a sample term"
              value={q}
              onChange={setQ}
            />
          </Input>
        </div>
        <Checkbox
          label="Tracked only"
          checked={tracked}
          onChange={setTracked}
        />
        <div
          className="metric-options"
          role="group"
          aria-label="Comparison metric"
        >
          <Button
            use={metric === "volume" ? "primary" : "secondary"}
            aria-pressed={metric === "volume"}
            onClick={() => setMetric("volume")}
          >
            Volume
          </Button>
          <Button
            use={metric === "difficulty" ? "primary" : "secondary"}
            aria-pressed={metric === "difficulty"}
            onClick={() => setMetric("difficulty")}
          >
            Difficulty
          </Button>
        </div>
      </div>
      <div className="research-grid">
        <section className="chart-panel">
          <div className="chart-heading">
            <h2>
              {metric === "volume"
                ? "Illustrative monthly volume"
                : "Illustrative difficulty score"}
            </h2>
            <span>{rows.length} terms</span>
          </div>
          <p className="axis-note">
            {metric === "volume"
              ? "Fixed scale: 0–8,100 sample searches"
              : "Fixed scale: 0–100 sample score"}
          </p>
          {rows.length ? (
            <div className="bars">
              {rows.map((r) => (
                <button
                  className={
                    "bar-row " + (r.term === selected ? "selected" : "")
                  }
                  key={r.term}
                  onClick={() => setSelected(r.term)}
                  aria-pressed={r.term === selected}
                >
                  <span className="bar-name">{r.term}</span>
                  <span className="bar-track" aria-hidden="true">
                    <i style={{ width: (r[metric] / max) * 100 + "%" }} />
                  </span>
                  <strong>{r[metric].toLocaleString("en-US")}</strong>
                </button>
              ))}
            </div>
          ) : (
            <div className="no-results">
              <h3>No matching terms</h3>
              <p>
                Clear the text and tracked filter to restore the full
                comparison.
              </p>
              <Button
                onClick={() => {
                  setQ("");
                  setTracked(false);
                }}
              >
                Reset filters
              </Button>
            </div>
          )}
          <p className="chart-note">
            Values are written beside every bar. Click a term to inspect both
            metrics.
          </p>
        </section>
        <aside>
          <h2>{item.term}</h2>
          <dl>
            <dt>Sample volume</dt>
            <dd>{item.volume.toLocaleString("en-US")}</dd>
            <dt>Sample difficulty</dt>
            <dd>{item.difficulty} / 100</dd>
            <dt>Tracking</dt>
            <dd>{item.tracked ? "Tracked" : "Not tracked"}</dd>
          </dl>
          <div className="inspector-note">
            <h3>Comparison context</h3>
            <p>
              The bar scale stays fixed when filters change. Difficulty and
              volume have separate units and are not added together.
            </p>
          </div>
          {!rows.some((r) => r.term === selected) && (
            <p className="retained">
              Selected term is outside the current filter; details are retained.
            </p>
          )}
        </aside>
      </div>
      <footer>
        Native Intergalactic Input, Checkbox and Button from @semcore/ui 17.6.0.
        Original accessible HTML bar comparison; no analytics service request.
      </footer>
    </main>
  );
}
createRoot(document.getElementById("root")).render(<App />);

代码参考

  • 创建 Vite React 项目,保留 <div id="root"></div>,并将以下内容保存为 src/main.jsx。

intergalactic.css — 原创响应式组合

围绕原生组件构建的应用布局。

css
* {
  box-sizing: border-box;
}
body {
  margin: 0;
  font:
    14px/1.5 Arial,
    sans-serif;
  color: var(--intergalactic-text-primary);
  background: #fff;
}
.research {
  padding: 28px;
}
.research header {
  border-bottom: 1px solid #e0e1e9;
  padding-bottom: 24px;
}
.research header p {
  font-size: 12px;
  color: #6c6e79;
  margin: 0 0 10px;
  letter-spacing: 0.07em;
}
.research h1 {
  font-size: 28px;
  margin: 0 0 8px;
}
.research header span {
  color: #6c6e79;
}
.research-toolbar {
  display: flex;
  align-items: flex-end;
  gap: 24px;
  flex-wrap: wrap;
  padding: 24px 0;
}
.research-search {
  min-width: 220px;
  flex: 1;
}
.research-search label {
  display: block;
  font-weight: 600;
  margin-bottom: 8px;
}
.metric-options {
  display: flex;
  gap: 8px;
}
.research-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.6fr) minmax(250px, 0.8fr);
  gap: 24px;
}
.chart-panel,
.research aside {
  border: 1px solid #c4c7cf;
  border-radius: 8px;
  padding: 24px;
  min-width: 0;
}
.chart-heading {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  align-items: flex-start;
}
.research h2 {
  font-size: 18px;
  margin: 0;
}
.chart-heading > span,
.axis-note,
.chart-note {
  font-size: 12px;
  color: #6c6e79;
}
.axis-note {
  margin: 8px 0 24px;
}
.bar-row {
  display: grid;
  grid-template-columns: 165px minmax(0, 1fr) 58px;
  align-items: center;
  gap: 12px;
  width: 100%;
  border: 0;
  background: white;
  text-align: left;
  padding: 12px 8px;
  border-radius: 4px;
  cursor: pointer;
  font: inherit;
  color: inherit;
}
.bar-row.selected {
  background: #f0e8ff;
}
.bar-name {
  font-size: 13px;
}
.bar-track {
  height: 18px;
  background: #f4f5f9;
  border-radius: 3px;
  overflow: hidden;
}
.bar-track i {
  display: block;
  height: 100%;
  background: var(--intergalactic-chart-palette-order-1);
  border-radius: 3px;
}
.bar-row strong {
  text-align: right;
  font-size: 12px;
}
.bar-row:focus-visible {
  outline: 2px solid #008ff8;
  outline-offset: 2px;
}
.chart-note {
  margin-top: 24px;
}
.research dl {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 16px;
  margin: 24px 0;
}
.research dt {
  color: #6c6e79;
}
.research dd {
  margin: 0;
  font-weight: 600;
}
.inspector-note {
  padding: 16px;
  background: #f4f5f9;
  border-radius: 6px;
}
.inspector-note h3 {
  font-size: 14px;
  margin: 0 0 8px;
}
.inspector-note p {
  font-size: 12px;
  margin: 0;
}
.retained {
  font-size: 12px;
  margin: 16px 0 0;
}
.no-results {
  text-align: center;
  padding: 32px 16px;
}
.no-results h3 {
  font-size: 18px;
}
.research footer {
  font-size: 12px;
  color: #6c6e79;
  margin-top: 24px;
}
@media (max-width: 950px) {
  .research-grid {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 550px) {
  .research {
    padding: 16px;
  }
  .chart-panel,
  .research aside {
    padding: 16px;
  }
  .research-toolbar {
    gap: 16px;
  }
  .research-search {
    flex-basis: 100%;
  }
  .bar-row {
    grid-template-columns: minmax(0, 1fr) 50px;
    gap: 8px;
  }
  .bar-name {
    grid-column: 1/-1;
  }
  .bar-track {
    grid-column: 1;
  }
  .metric-options {
    flex-wrap: wrap;
  }
}

代码参考

  • 将其保存在 main.jsx 旁边。这些自定义组合规则有别于库的设计令牌参考。
04

Semrush Intergalactic 设计系统 AI Agent 设置

实现起点

已打包固定的原生示例,并在本地浏览器中完成检查。该示例仅使用本地应用状态。

sh
npm create vite@latest intergalactic-compare -- --template react
cd intergalactic-compare
npm install
npm install [email protected] [email protected] @semcore/[email protected] @semcore/[email protected] @semcore/[email protected] @semcore/illustration
# Replace src/main.jsx and add src/intergalactic.css.
npm run dev

适用于你项目的提示词

Agent 提示词
使用原生 Intergalactic 控件、专用导入和当前主题令牌,构建紧凑的分析对比视图。确保单位、固定刻度、排序和选中项标识保持一致。提供文本值和空状态恢复方式。对于示例指标和原创图表代码,应如实标注,不要声称数据来自 Semrush 的实际测量。
05

Semrush Intergalactic 设计系统来源与范围

OpenDesign 应用指南。六条关键词记录及所有指标均为虚构内容。原生 Intergalactic 控件搭配原创的 HTML 图表;这并非 Semrush 报告,也不是原生 D3 图表实现。