招聘平台 · 新资源

SEEK Braid 设计系统.

通过原创的求职界面设计了解 Braid:按主题作用域划分的变量、四个真实断点、结合上下文的文本、不同色调的按钮,以及会说明验证原因而非禁用操作的受控字段。

OpenDesign 指南7 个章节35 条参考条目原始应用指南
01

SEEK Braid 设计系统界面预览

编辑并应用职位或城市查询,检查无结果状态,并清空输入框和已应用的搜索条件。

职位搜索示例打开完整示例
对 Braid 搜索构成、层级结构和断点指南的原创离线 HTML 解读;不包含实时 SEEK 数据或 Braid 运行时。预览颜色和实际间距由应用自行决定。 · 实现参考
02

SEEK Braid 设计系统设计参考

当前 Braid 组件和 CSS 参考资料。命名尺寸通过所选主题解析;此处不会推断未经验证的像素等效值,也不会虚构生成的 CSS 变量名称。原生示例明确选择 seekJobs。

响应式断点

来源
名称 / 规则值 / 配置用途
mobile0基础样式。
tablet740px第一个较大视口条件。
desktop992px桌面视口条件。
wide1200px宽屏视口条件。

主题变量 API

来源
名称 / 规则值 / 配置用途
vars.space.mediumTheme-scoped CSS expression直接使用;进行算术运算需使用 calc。
vars.space.gutterTheme gutter expression版面间距。
vars.backgroundColor.bodyTheme body background页面界面表面。
vars.backgroundColor.surfaceTheme surface background容器表面。
vars.backgroundColor.brandAccentTheme brand action background不要假定存在通用十六进制值。
vars.foregroundColor.neutralTheme text role主要内容。
vars.foregroundColor.secondaryTheme secondary role元数据。
vars.borderColor.focusTheme focus role可见焦点。
vars.borderRadius.standardTheme radius expression标准形状。

盒式布局 API

来源
名称 / 规则值 / 配置用途
componentdiv by default按需选择语义化的 main、section、form。
paddingNamed space, responsive object allowed示例:移动端 medium / 平板端 xlarge。
gapNamed spacing values同级元素间距。
background="customDark"Context for custom dark surfaces启用匹配的前景行为。
borderRadiusnone / small / standard / large / xlarge / full由主题解析的形状。

文本与字段规范

来源
名称 / 规则值 / 配置用途
label / secondaryLabel / tertiaryLabelThree label levels用途、可选上下文、辅助信息。
descriptionBelow-label context字段获得焦点时播报。
message + tonecritical / positive / caution / neutral说明字段状态。
onClearCallback required for clear action应用重置受控值。
clearLabelAccessible clear-control label本地化。

按钮的视觉强调与行为

来源
名称 / 规则值 / 配置用途
variantsolid / ghost / soft / transparent视觉强调。
tonebrandAccent / formAccent / critical / neutral操作含义。
No explicit toneNeutral ghost by default低调的基准样式。
Explicit tone, no variantSolid default同时指定两者以消除歧义。
sizestandard / small支持的尺寸。
loadingAlso disables interaction仅用于确有待处理工作的情况。
Ordinary disabledNot supported允许用户尝试,并说明错误原因。

文本语义

来源
名称 / 规则值 / 配置用途
sizelarge / standard / small / xsmall主题的类型比例。
weightregular / medium / strong文本强调。
component="p"Paragraph element视觉类型与语义彼此独立。
maxLinesNumber限制用户生成内容的可见范围。
tone="secondary"Metadata emphasis不能替代错误角色。
03

SEEK Braid 设计系统完整指南

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

DESIGN-seek-braid.md

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

下载指南

SEEK Braid 设计系统:选定主题后,视觉规范随之确定

Provider、重置样式与生成的变量协同工作

Braid 面向 SEEK Group 的多个主题。其变量 API 包含带作用域的 CSS 表达式,因此 vars.space.medium 这样的名称是稳定的引用,而生成的自定义属性标识符不应手动复现。本例通过 BraidProvider 选择 seekJobs。

摘自本 OpenDesign 指南

必须先于其他 Braid 样式导入重置样式。在嵌入式应用中,styleBody={false} 可避免 Provider 更改宿主页面 body 的背景和间距。此选项并不能免除主题上下文的必要性。

阅读配套规范

SEEK Braid 设计系统:响应式值使用主题中命名的间距

保留四个实际断点条件

共用的断点阈值为:mobile 从零开始,tablet 为 740px,desktop 为 992px,wide 为 1200px。原生示例通过响应式属性对象,在 tablet 断点调整内边距,不会为同一变化重复编写 CSS 媒体查询。

此处并未将主题的 medium 间距臆测为某个像素值。间距优先使用 Box 和 Stack。当布局无法通过这些组件实现时,可将 vars 作为更底层的备用方案;由于其值是 CSS 表达式,乘法应使用 calc,而不是 JavaScript 数值运算。

阅读配套规范

SEEK Braid 设计系统:文本角色会承接周围的颜色上下文

分别选择层级与语义

Text 提供命名尺寸和字重,Heading 则用于表达标题层级。职位所在城市可以使用次要色调,但职位标题应保持足够醒目,以便识别搜索结果。如果内容是段落,可通过 component="p" 让 Text 渲染为段落,而不是仅因默认外观而选择某个 HTML 元素。

在深色背景上下文中,Braid 会调整前景色调。使用原始图片或自定义背景时,可通过 Box 的 customDark 上下文说明这种关系。不能假定手动设置颜色的 div 也具备相同的上下文行为。

阅读配套规范

SEEK Braid 设计系统:tone 表示含义,variant 表示强调程度

将品牌强调色留给搜索操作

本例明确为 Search jobs 搭配 solid variant 和 brandAccent。Clear search 是更克制的 ghost 操作。formAccent 可用于强调可重复执行的表单操作;critical 用于表示破坏性后果,不应仅为提高普通控件的醒目程度而使用。

Braid 的默认行为需要留意:未另行指定时,中性按钮为 ghost;设置 tone 后,隐式 variant 会变为 solid。在关键操作中明确写出这两个属性,有助于保持预期层级清晰。Actions 会处理常见的移动端纵向排列和较宽视口下的行内排列。

阅读配套规范

SEEK Braid 设计系统:提供可操作的错误信息,胜过禁用按钮

遵循受控字段的约定

TextField 的 onChange 回调会接收 React 输入事件。示例读取 event.target.value 并保存为草稿文本,只有用户触发 Search 后才应用搜索内容。示例还提供了清除回调,因为该控件无法自行清除应用状态。

message 用于说明查询为空的错误,critical tone 则提供其视觉状态。description 用于持久显示的上下文。Braid 不支持常规的禁用状态 Button;操作会保持可用,让访客能够了解如何继续。离线预览还会将焦点移至无效字段。

  1. 将编辑内容保留在草稿查询状态中。
  2. 点击 Search 时,要求查询内容经去除首尾空格后不为空。
  3. 失败时显示有帮助的关键信息。
  4. 成功后应用查询,并明确显示无匹配结果的状态。

阅读配套规范

SEEK Braid 设计系统:此示例仅搜索原始数据

本地搜索结果不代表实时职位空缺

预览中包含三条虚构的职位记录,附有职位、城市和工作场所元数据。搜索会忽略大小写,对比职位名称和城市。它不会获取 SEEK 的实时职位列表,搜索结果也会标明为示例。

将草稿文本与已应用的结果分开,可以让交互状态一目了然:编辑职位不会在按下 Search 之前悄然替换当前结果。清除搜索会重置这两个值。没有匹配项时,结果列表会说明这一情况,同时保持搜索控件可用。

  • 应用查询后显示结果数量。
  • 编辑过程中,让上一次已应用的查询保持清晰可见。
  • 不要在示例列表中添加没有实际作用的 Apply 提交按钮。

阅读配套规范

SEEK Braid 设计系统:使用可提取 Braid 样式的构建流程

安装软件包只是配置工作的一部分

官方配置针对 sku 进行了优化。在自定义打包工具中使用 Braid 的 Vanilla Extract 样式,需要集成构建流程;重置样式和选定主题也必须按文档所述顺序引入应用。所提供的代码是适用于现有兼容 sku 项目的完整入口,并不意味着随便放入一个 script 标签就能运行 Braid。

Braid 会执行开发环境断言,并根据环境发出警告。官方构建指南建议在生产环境构建时移除断言并替换环境变量。请在实现流程中考虑这一点;本页的离线 HTML 示例不依赖此类软件包构建。

阅读配套规范

SEEK Braid 设计系统组件示例

完整的独立交互示例

将完整文档保存为 index.html 并在浏览器中打开。这是对 Braid 搜索组合方式、层级和断点指南的独立离线 HTML 解读;不接入实时 SEEK 数据,也不运行 Braid。预览配色和实际间距均为应用自行选择。

html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Braid sample job search interpretation</title><style>*{box-sizing:border-box}body{margin:0;background:#f5f5f5;color:#222;font:16px/1.5 system-ui,sans-serif}header{background:white;padding:16px 32px;border-bottom:1px solid #ddd;display:flex;align-items:center;justify-content:space-between}header strong{color:#0d3880;font-size:20px}header span{font-size:14px;color:#666}.hero{background:#0d3880;color:white;padding:32px}.hero-inner{max-width:980px;margin:auto}h1{font-size:32px;line-height:1.2;margin:0 0 24px}form{display:grid;grid-template-columns:1fr auto auto;gap:16px;align-items:end}label{display:block;font-weight:600;margin-bottom:8px}input{height:48px;border:1px solid #aaa;border-radius:4px;padding:10px 12px;font:inherit;width:100%;min-width:0;color:#222}input[aria-invalid=true]{border:2px solid #c90040}button{height:48px;border:1px solid transparent;border-radius:4px;font:600 16px/1.2 system-ui;padding:0 24px;cursor:pointer}.search{background:#e60278;color:white}.clear{background:transparent;color:white;border-color:white}button:focus-visible,input:focus-visible{outline:3px solid #69d8ff;outline-offset:3px}.error{background:white;color:#b70040;padding:8px 12px;margin:16px 0 0;border-radius:4px}.error:empty{display:none}.help{font-size:14px;color:#e4eaf6;margin:16px 0 0}main{max-width:1044px;margin:32px auto;padding:0 32px}.results-head{display:flex;justify-content:space-between;gap:16px;margin-bottom:20px}h2{font-size:24px;line-height:1.3;margin:0 0 8px}.applied{font-size:14px;color:#555}article{display:grid;grid-template-columns:1fr 100px;gap:24px;padding:24px;background:white;border:1px solid #ddd;border-radius:4px;margin-bottom:16px}.company{font-size:14px;color:#555}.meta{margin:16px 0;display:flex;gap:8px;flex-wrap:wrap}.meta span{background:#f0f4fb;padding:4px 8px;font-size:12px;border-radius:4px}article p{margin:0;color:#555;font-size:14px}.monogram{background:#f1e5f4;color:#673b78;height:72px;width:72px;border-radius:12px;display:grid;place-items:center;font-weight:700;font-size:24px;justify-self:end}.monogram.blue{color:#0d3880;background:#e4efff}.monogram.green{color:#326342;background:#e8f4eb}.notice{background:white;border:1px solid #ddd;padding:24px}.boundary{font-size:12px;color:#666;margin:24px 0}@media(max-width:739px){header{padding:16px}header span{display:none}.hero{padding:24px 16px}h1{font-size:28px}form{grid-template-columns:1fr;gap:12px}form button{width:100%}main{padding:0 16px;margin:24px auto}article{padding:20px;grid-template-columns:1fr 48px;gap:12px}.monogram{height:48px;width:48px;font-size:18px}article h2{font-size:20px}.results-head{display:block}}</style><header><strong>Possibilities</strong><span>Original job-search specimen</span></header><section class="hero"><div class="hero-inner"><h1>Find your next possibility.</h1><form novalidate><div><label for="query">Role or city</label><input id="query" type="search" placeholder="Try designer or Melbourne" aria-describedby="error help"></div><button class="search" type="submit">Search jobs</button><button class="clear" type="button" id="clear">Clear search</button></form><div id="error" class="error" role="alert"></div><p id="help" class="help">Search three original sample roles. These are not live vacancies.</p></div></section><main><div class="results-head"><div><h2 id="count">3 sample results</h2><div class="applied" id="applied">Showing all sample roles</div></div></div><div id="results"></div><p class="boundary">Independent HTML interpretation of Braid’s search composition and responsive guidance. Original content and application palette; no SEEK data, account or application service is connected.</p></main><script>const jobs=[{title:'Product designer',city:'Melbourne',company:'North Studio',type:'Full time',mode:'Hybrid',initial:'NS',color:'',description:'Shape useful experiences with a small multidisciplinary product team.'},{title:'Design systems engineer',city:'Sydney',company:'Harbour Works',type:'Full time',mode:'Flexible',initial:'HW',color:'blue',description:'Build accessible components and improve the way teams deliver interfaces.'},{title:'UX researcher',city:'Melbourne',company:'Fern Collective',type:'Contract',mode:'On site',initial:'FC',color:'green',description:'Turn thoughtful field research into clear product opportunities.'}];const input=document.querySelector('#query'),error=document.querySelector('#error');let applied='';function render(){let matches=jobs.filter(j=>(j.title+' '+j.city).toLowerCase().includes(applied.toLowerCase()));document.querySelector('#count').textContent=matches.length+' sample '+(matches.length===1?'result':'results');document.querySelector('#applied').textContent=applied?'Applied search: '+applied:'Showing all sample roles';document.querySelector('#results').innerHTML=matches.length?matches.map(j=>`<article><div><h2>${j.title}</h2><div class="company">${j.company} · ${j.city}</div><div class="meta"><span>${j.type}</span><span>${j.mode}</span><span>Sample listing</span></div><p>${j.description}</p></div><div class="monogram ${j.color}" aria-hidden="true">${j.initial}</div></article>`).join(''):'<div class="notice">No sample roles match. Try another role or city, or clear your search.</div>'}document.querySelector('form').onsubmit=e=>{e.preventDefault();if(!input.value.trim()){error.textContent='Enter a role or city.';input.setAttribute('aria-invalid','true');input.focus();return}error.textContent='';input.removeAttribute('aria-invalid');applied=input.value.trim();render()};input.oninput=()=>{error.textContent='';input.removeAttribute('aria-invalid')};document.querySelector('#clear').onclick=()=>{input.value='';applied='';error.textContent='';input.removeAttribute('aria-invalid');render();input.focus()};render();</script></html>

代码参考

  • 搜索范围仅包括示例中虚构的职位。使用原生 Braid 入口需要配置样式提取构建流程,并选择 seekJobs 主题。

草稿查询、已应用的搜索和明确的恢复方式

受控 TextField 用于验证本地查询,Actions 用于组合两种不同样式的按钮,而 Card/Stack/Heading/Text 则用于呈现原创搜索结果。

jsx
// Entry module in an existing sku application:
// npm install braid-design-system
import 'braid-design-system/reset'; // Keep this first.
import React,{useState} from 'react';
import {createRoot} from 'react-dom/client';
import seekJobsTheme from 'braid-design-system/themes/seekJobs';
import {BraidProvider,Box,Stack,Heading,Text,TextField,Button,Actions,Card} from 'braid-design-system';
const jobs=[{id:1,title:'Product designer',city:'Melbourne'},{id:2,title:'Design systems engineer',city:'Sydney'},{id:3,title:'UX researcher',city:'Melbourne'}];
function JobSearch(){
 const [draft,setDraft]=useState(''),[query,setQuery]=useState(''),[error,setError]=useState('');
 const results=jobs.filter(j=>(j.title+' '+j.city).toLowerCase().includes(query.toLowerCase()));
 function search(){if(!draft.trim()){setError('Enter a role or city.');return;}setError('');setQuery(draft.trim());}
 function clear(){setDraft('');setQuery('');setError('');}
 return <Box component="main" padding={{mobile:'medium',tablet:'xlarge'}}>
  <Stack space="large">
   <Heading level="2">Find your next possibility</Heading>
   <TextField id="job-query" label="Role or city" value={draft}
     onChange={event=>{setDraft(event.target.value);setError('');}}
     onClear={()=>setDraft('')} clearLabel="Clear role or city"
     tone={error?'critical':'neutral'} message={error||'Search three original sample roles.'}/>
   <Actions><Button tone="brandAccent" variant="solid" onClick={search}>Search jobs</Button>
    <Button variant="ghost" onClick={clear}>Clear search</Button></Actions>
   <Text>{results.length} sample results</Text>
   {results.map(job=><Card key={job.id}><Stack space="small"><Heading level="3">{job.title}</Heading><Text tone="secondary">{job.city}</Text></Stack></Card>)}
   {!results.length&&<Text>No sample roles match. Try a different title or city.</Text>}
   <Text size="small" tone="secondary">These are sample listings, not live vacancies.</Text>
  </Stack>
 </Box>;
}
createRoot(document.getElementById('root')).render(<BraidProvider theme={seekJobsTheme}><JobSearch/></BraidProvider>);

代码参考

  • onChange 接收的是输入事件,而不是原始字符串。
  • 查询为空时,Search 仍可用,并会提示用户输入内容。
  • 清除搜索会同时重置草稿文本和已应用的结果。
04

SEEK Braid 设计系统 Agent 配置

实现起点

这是适用于现有 sku 构建流程的完整应用入口,官方配置可直接支持该流程。自定义打包工具需要集成 Vanilla Extract。必须将重置样式的导入保留在第一位。离线预览不声称能够原生编译软件包。

jsx
// Entry module in an existing sku application:
// npm install braid-design-system
import 'braid-design-system/reset'; // Keep this first.
import React,{useState} from 'react';
import {createRoot} from 'react-dom/client';
import seekJobsTheme from 'braid-design-system/themes/seekJobs';
import {BraidProvider,Box,Stack,Heading,Text,TextField,Button,Actions,Card} from 'braid-design-system';
const jobs=[{id:1,title:'Product designer',city:'Melbourne'},{id:2,title:'Design systems engineer',city:'Sydney'},{id:3,title:'UX researcher',city:'Melbourne'}];
function JobSearch(){
 const [draft,setDraft]=useState(''),[query,setQuery]=useState(''),[error,setError]=useState('');
 const results=jobs.filter(j=>(j.title+' '+j.city).toLowerCase().includes(query.toLowerCase()));
 function search(){if(!draft.trim()){setError('Enter a role or city.');return;}setError('');setQuery(draft.trim());}
 function clear(){setDraft('');setQuery('');setError('');}
 return <Box component="main" padding={{mobile:'medium',tablet:'xlarge'}}>
  <Stack space="large">
   <Heading level="2">Find your next possibility</Heading>
   <TextField id="job-query" label="Role or city" value={draft}
     onChange={event=>{setDraft(event.target.value);setError('');}}
     onClear={()=>setDraft('')} clearLabel="Clear role or city"
     tone={error?'critical':'neutral'} message={error||'Search three original sample roles.'}/>
   <Actions><Button tone="brandAccent" variant="solid" onClick={search}>Search jobs</Button>
    <Button variant="ghost" onClick={clear}>Clear search</Button></Actions>
   <Text>{results.length} sample results</Text>
   {results.map(job=><Card key={job.id}><Stack space="small"><Heading level="3">{job.title}</Heading><Text tone="secondary">{job.city}</Text></Stack></Card>)}
   {!results.length&&<Text>No sample roles match. Try a different title or city.</Text>}
   <Text size="small" tone="secondary">These are sample listings, not live vacancies.</Text>
  </Stack>
 </Box>;
}
createRoot(document.getElementById('root')).render(<BraidProvider theme={seekJobsTheme}><JobSearch/></BraidProvider>);

适用于你项目的提示词

Agent 提示词
使用 seekJobs 主题组合 Braid 搜索界面,先导入重置样式,并通过 TextField 事件管理状态,再使用 Actions。单个主搜索按钮采用明确的 brandAccent 实心样式,重置按钮采用中性幽灵样式。允许提交空搜索并说明错误;不要禁用普通 Button 来隐藏验证提示。
05

SEEK Braid 设计系统来源与适用范围

独立的 OpenDesign 参考示例。职位列表为原创内容,不包含实时职位空缺,也不支持提交申请。命名的 Braid 变量会根据选定主题解析。