企业产品设计 · 新资源

Maersk 设计系统.

通过真实的浅色主题角色、标题与正文的字号层级、嵌套圆角和标识符处理方式,了解 Maersk 的运营界面语言。示例货运查询展示精确匹配参考编号及无障碍事件历史,但不声称能够访问实时物流数据。

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

Maersk 设计系统 界面预览

查询两个原始样例编号,查看路线历史,并区分格式错误的查询与缺失记录。

样例货运查询打开完整示例
基于公开文档中的 Maersk 浅色主题角色和间距,通过原生 HTML 实现的离线版本。未使用私有 MDS 运行时或品牌字体文件,也未连接实时货运数据。 · 实现参考
02

Maersk 设计系统 设计参考

MDS 基础规范和组件用法的公开文档。原生组件包位于 Maersk 私有软件包注册表中;可运行示例使用原生 HTML 和公开文档中的令牌快照,并未虚构 mc-* API。

Maersk 浅色主题角色

来源
名称 / 规则值 / 配置用途
--mds_brand_appearance_primary_default_background-color#141414 主要填充操作。
--mds_brand_appearance_primary_default_on-background-color#FFFFFF 主要填充色上的文本。
--mds_brand_appearance_primary_default_link-color#0077B2 链接文本。
--mds_brand_appearance_secondary_default_background-color#42B0D5 品牌次要填充色。
--mds_brand_appearance_secondary_default_on-background-color#141414 次要填充色上的文本。
--mds_brand_appearance_secondary_weak_background-color#E2F3F9 克制的次要界面表面。
--mds_brand_appearance_neutral_default_border-color#D4D4D4 默认边框。
--mds_brand_appearance_neutral_weakest_text-color#6A6A6A 辅助性文本。
--mds_brand_appearance_neutral_weakest_background-color#F7F7F7 克制的页面表面。

文本比例

来源
名称 / 规则值 / 配置用途
--mds_brand_typography_text_font-familyMaersk Text原生品牌字体。
text_large desktop/mobile18px / 28px line height两个平台相同。
text_medium desktop/mobile16px / 24px line height默认正文字号。
text_small desktop/mobile14px / 20px line height紧凑元数据。
text_x-small desktop/mobile12px / 16px line height最小参考字号。
normal / light / medium / semibold / bold400 / 300 / 500 / 600 / 700文档规定的文本字重。

标题比例

来源
名称 / 规则值 / 配置用途
headline_large desktop50px / 56px, weight 300大型展示标题。
headline_large mobile38px / 38px, weight 300移动端对应规格。
headline_medium desktop40px / 40px, weight 300页面标题。
headline_medium mobile26px / 32px, weight 300移动端页面标题。
headline_small desktop26px / 32px, weight 400区块标题。
headline_small mobile22px / 26px, weight 400移动端分区标题。
headline_x-small desktop/mobile20px / 24px, weight 400小标题。

圆角半径

来源
名称 / 规则值 / 配置用途
radius-xs2px较小的嵌套元素。
radius-sm4px复选框尺寸的元素。
radius-md6px按钮和输入框。
radius-lg8px通知和表格。
radius-xl12px带有嵌套控件的卡片。
radius-2xl16px大尺寸图片和对话框。
radius-full9999px完全圆角的形状。

间距与密度

来源
名称 / 规则值 / 配置用途
Base rhythm4px multiples内边距、外边距和间隔。
Fine component exceptions2px, 6px, 10px组件对齐的小幅调整。
Responsive dimensionsNot required to be divisible by 4相邻元素的间距保持一致节奏。

操作层级

来源
名称 / 规则值 / 配置用途
Primary actionPrimary + Filled单一主要操作。
Secondary actionNeutral + Outlined开放表单中的辅助操作。
Tertiary actionNeutral + Plain清除、重置或重复显示内容。
Secondary in a dialogNeutral + Filled避免出现相互竞争的轮廓。
Brand hero exceptionSecondary + Filled非默认表单操作。
03

Maersk 设计系统 完整指南

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

DESIGN-maersk.md

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

下载指南

Maersk 设计系统 公开规则和私有组件是不同的资源

如实选择采用方式

MDS 公开提供了大量基础规范和用法指南,而其开发者指南说明,软件包存放在 Maersk Global 的 GitHub Packages 和 Nexus 私有仓库中。阅读组件页面并不意味着获得软件包或字体的分发权限。

摘自本 OpenDesign 指南

获授权的团队应使用与其企业环境相对应的软件包和 Storybook。本公开参考则完整地以原生 HTML 实现可见规则,让读者无需依赖虚构的公开安装命令,也能查看其行为。

  1. 选择原生软件包方案前,请确认有权访问企业软件包仓库。
  2. 确保组件文档与已安装版本相符。
  3. 通过原始 HTML 示例公开探索,无需依赖私有资源。

阅读配套规范

Maersk 设计系统 先理解角色,再识别品牌色

浅色主题中的主要操作采用深色

Maersk 蓝具有较高辨识度,但浅色主题中的主要填充角色使用 #141414,前景文字为白色。次要填充角色使用 #42B0D5,搭配深色文字。明确区分这两种角色,可以避免所有控件都变成鲜亮的品牌色点缀。

样例中的主要查询操作使用深色主要角色。浅色次要界面表面用于衬托路线研究,中性色边框则将辅助记录组织起来。令牌名称体现层级、项目、变体、平台、状态和属性,因此即使主题发生变化,角色仍然清晰易懂。

阅读配套规范

Maersk 设计系统 将标题个性与阅读密度分开处理

采用实际的桌面端和移动端字号组合

Maersk Headline 和 Maersk Text 用途不同。中号标题从桌面端的 40/40 调整为移动端的 26/32,而中号正文保持 16/24。若对所有文本样式都按同一比例缩放,就无法体现这种有意的差异。

原始预览使用 Arial,因为它不会重新分发品牌字体文件。预览遵循文档规定的字号层级:轻盈的页面标题、清晰的分区标签,以及易于阅读的 14px 事件元数据。参考标识符保留为可选中文本,方便读者检查前导零并复制准确字符串。

阅读配套规范

Maersk 设计系统 密度来自间距,而非删减信息

在紧凑的运营界面中保留信息间的关系

MDS 采用 4px 的间距节奏,另有 2、6 和 10px 的例外值,用于细致调整组件对齐。密度令牌支持 Default、Compact 和 Spacious 模式,但不能仅凭这些名称猜测未经验证的特定软件包密度值。

示例使用 8px 和 16px 的间距来组织标签、事件和元数据,并用 24px 和 32px 的间距分隔较大的区域。在较窄的屏幕上,路线和事件历史会改为上下排列。信息仍然完整保留,而不是为了让小尺寸截图更简洁就将其隐藏。

阅读配套规范

Maersk 设计系统 外层容器需要为内部控件留出空间

圆角比例体现嵌套关系

卡片采用 12px 基准,按钮和字段采用 6px,大型图片或对话框采用 16px。圆角指南明确指出,当一个组件包含另一个组件时,外层圆角应更大。

示例将路线插图置于圆角卡片内,而查询字段的圆角更小。此处边框用于结构分隔,并非为每行文字都添加装饰性描边。文档规定的全局边框为 1px 实线。

阅读配套规范

Maersk 设计系统 货运编号是标识符,不是数值

不要让数字输入框改变编号

MDS 输入指南区分数量与货柜号、参考编号等标识符。数字输入框可能会丢弃前导零,也可能因意外步进而改变数值。因此,示例使用 type="text"、inputmode="numeric",并将编号键精确保留为字符串。

六位数字格式是此示例自身的约束,并非 Maersk 对货运编号的规定。空输入或格式错误时显示特定的纠正提示;格式正确但查无记录时,则显示单独的无匹配结果。切勿将这两种情况都归为笼统的“无效”错误。

  • 将标签置于字段上方。
  • 将每一位标识符数字都作为字符串保留。
  • 使用 aria-describedby 关联格式帮助文本和错误文本。
  • 仅在格式错误时设置 aria-invalid;记录不存在但格式正确时不要设置。

阅读配套规范

Maersk 设计系统 让主要查询操作区别于示例快捷入口

使用句首字母大写的动词,并明确说明操作结果

“查看货运”是唯一的填充式操作按钮。示例参考编号快捷入口采用低强调样式,用于填入同一查询,而不是作为多个主要按钮与之竞争。在展开的表单中,主要操作在键盘和阅读顺序上都应先于辅助操作。

预览会以有序列表呈现所选示例的事件历史。事件标签以文字说明状态,因此蓝色标记和连接线仅起辅助作用。记录明确标注为虚构内容;其中没有任何 ETA 或路线信息被描述为实时运营信息。

阅读配套规范

Maersk 设计系统 深色主题需要独立的语义取值

不要直接反转截图颜色

公开的深色主题表将主要文字改为 #F0F0F0,将主要填充色改为白色,并将中性画布色改为 #141414。这些是有意设计的角色映射,并非要求反转每个 RGB 值。

此示例采用文档规定的浅色主题。扩展至深色模式时,需要一致地替换整套角色取值,包括悬停、边框和背景上的文字颜色。之后还应单独检查原路线图示的对比度,而不是套用全局滤镜。

阅读配套规范

Maersk 设计系统组件示例

完整的独立交互示例

将完整文档保存为 index.html,然后在浏览器中打开。这是依据文档所述 Maersk 浅色角色和间距实现的原创建议性 HTML 离线原生方案。不包含私有 MDS 运行时、品牌字体文件或实时货运连接。

html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Sample shipment lookup</title><style>*{box-sizing:border-box}body{font:16px/24px Arial,sans-serif;background:#f7f7f7;color:#141414;margin:0}button,input{font:inherit}button{cursor:pointer}button:focus-visible,input:focus-visible{outline:3px solid #0077b2;outline-offset:3px}header{background:#fff;padding:20px 32px;display:flex;justify-content:space-between;gap:16px;border-bottom:1px solid #d4d4d4}header b{font-weight:500;letter-spacing:1px}header span{font-size:12px;color:#6a6a6a}main{max-width:1120px;margin:auto;padding:32px}h1{font-size:40px;line-height:40px;font-weight:300;margin:8px 0 16px}p{margin:0 0 16px}.subtitle{color:#6a6a6a}.search{background:#fff;border:1px solid #d4d4d4;padding:24px;border-radius:12px;margin:24px 0}.search label{display:block;margin-bottom:8px}.entry{display:flex;gap:8px}.entry input{border:1px solid #8a8a8a;border-radius:6px;padding:12px 16px;max-width:360px;min-width:0;width:100%;background:#fff;color:#141414}.entry button{border:0;background:#141414;color:#fff;border-radius:6px;padding:12px 24px}.hint{font-size:14px;color:#6a6a6a;margin:8px 0 0}.error{color:#b80012;margin:8px 0 0}.error:empty{display:none}.layout{display:grid;grid-template-columns:250px 1fr;gap:24px}aside{background:#fff;border-radius:12px;border:1px solid #d4d4d4;padding:24px}aside h2{font-size:20px;line-height:24px;font-weight:400;margin:0 0 16px}.record{display:block;text-align:left;background:none;border:0;border-top:1px solid #e2e2e2;padding:16px 0;width:100%;color:#141414}.record strong,.record small{display:block}.record strong{font-size:16px;font-weight:500}.record small{color:#6a6a6a;font-size:12px;margin-top:4px}.record[aria-pressed=true]{color:#0077b2}.record[aria-pressed=true] strong:after{content:' →'}.detail{background:#fff;border:1px solid #d4d4d4;border-radius:12px;padding:24px;min-width:0}.detail h2{font-size:26px;line-height:32px;font-weight:400;margin:0}.topline{display:flex;justify-content:space-between;gap:16px;margin-bottom:20px}.tag{font-size:12px;border-radius:4px;background:#e2f3f9;color:#141414;padding:4px 8px;align-self:start;white-space:nowrap}.route{height:148px;border-radius:12px;background:#e2f3f9;display:flex;align-items:center;justify-content:space-between;padding:24px;position:relative;gap:16px}.port{position:relative;z-index:1;font-size:14px;max-width:40%}.port b{display:block;font-size:20px;line-height:24px;font-weight:400}.port:last-child{text-align:right}.route:before{content:'';height:2px;background:#42b0d5;position:absolute;left:24px;right:24px;top:52%}.port{background:#e2f3f9;padding:8px}.history{list-style:none;margin:24px 0 0;padding:0}.history li{position:relative;padding:0 0 24px 28px;border-left:2px solid #d4d4d4;margin-left:5px}.history li:last-child{padding-bottom:0;border-color:transparent}.history li:before{content:'';position:absolute;left:-6px;top:7px;width:10px;height:10px;background:#42b0d5;border-radius:50%}.history b{font-weight:500;display:block}.history small{font-size:14px;line-height:20px;color:#6a6a6a;display:block;margin-top:4px}.notice{padding:32px 0;max-width:430px}footer{font-size:12px;line-height:16px;color:#6a6a6a;margin-top:24px}@media(max-width:650px){header{padding:16px}header span{max-width:115px}main{padding:24px 16px}h1{font-size:26px;line-height:32px}.layout{grid-template-columns:1fr}aside{padding:16px}.record{padding:12px 0}.search,.detail{padding:20px}.entry{flex-wrap:wrap}.entry input{max-width:none}.entry button{width:100%}.topline{flex-wrap:wrap}.route{padding:8px}.port b{font-size:18px}.route:before{left:16px;right:16px}}
</style><header><b>CARGO / WORKSPACE</b><span>Independent MDS interpretation</span></header><main><h1>Follow the next milestone.</h1><p class="subtitle">A reference lookup and event history, using original sample records.</p><form id="lookup" class="search" novalidate><label for="reference">Shipment reference</label><div class="entry"><input id="reference" type="text" inputmode="numeric" value="000042" required aria-describedby="hint error"><button type="submit">Show shipment</button></div><p class="hint" id="hint">Try 000042 or 000108. Keep the leading zeros.</p><p class="error" id="error" role="alert"></p></form><div class="layout"><aside><h2>Sample shipments</h2><button class="record" data-id="000042" aria-pressed="true"><strong>000042</strong><small>Rotterdam → Singapore</small></button><button class="record" data-id="000108" aria-pressed="false"><strong>000108</strong><small>Hamburg → New York</small></button></aside><section class="detail" id="result" aria-live="polite"></section></div><footer>All references, routes and events are fictional. No live tracking, shipment status or transport commitment is represented.</footer></main><script>const data={'000042':{from:'Rotterdam',to:'Singapore',status:'In transit',events:[['Booking received','Sample milestone 1 · Reference created'],['Loaded at origin','Sample milestone 2 · Origin handling complete'],['In transit','Sample milestone 3 · Next event pending']]},'000108':{from:'Hamburg',to:'New York',status:'Awaiting handover',events:[['Booking received','Sample milestone 1 · Reference created'],['Awaiting origin handover','Sample milestone 2 · Cargo handover pending']]}};const input=document.querySelector('#reference'),result=document.querySelector('#result'),error=document.querySelector('#error');function resetError(){error.textContent='';input.setAttribute('aria-invalid','false')}function show(){resetError();const id=input.value.trim();document.querySelectorAll('.record').forEach(x=>x.setAttribute('aria-pressed',String(x.dataset.id===id)));result.replaceChildren();if(!/^\d{6}$/.test(id)){error.textContent='Use a six-digit sample reference, including leading zeros.';input.setAttribute('aria-invalid','true');input.focus();result.innerHTML='<p class="notice">Correct the reference to view a sample event history.</p>';return}const r=data[id];if(!r){result.innerHTML='<h2>No sample shipment found</h2><p class="notice">This reference does not match the two sample records. Try 000042 or 000108.</p>';return}result.innerHTML=`<div class="topline"><h2>Shipment ${id}</h2><span class="tag">${r.status}</span></div><div class="route"><div class="port"><small>ORIGIN</small><b>${r.from}</b></div><div class="port"><small>DESTINATION</small><b>${r.to}</b></div></div><ol class="history">${r.events.map(([a,b])=>`<li><b>${a}</b><small>${b}</small></li>`).join('')}</ol>`}document.querySelector('#lookup').onsubmit=e=>{e.preventDefault();show()};document.querySelectorAll('.record').forEach(x=>x.onclick=()=>{input.value=x.dataset.id;show()});input.oninput=()=>{resetError();document.querySelectorAll('.record').forEach(x=>x.setAttribute('aria-pressed','false'));result.innerHTML='<p class="notice">Select Show shipment to look up the edited reference.</p>'};show();</script></html>

代码参考

  • 只能查找所包含的示例货运参考编号。精确字符串匹配可保留标识符;本文档不包含 Maersk 私有组件或追踪访问权限。

将货运参考编号作为文本保留

原生表单遵循 MDS 输入指南,并使用公开的令牌角色。精确匹配示例数据可保留前导零,并区分格式错误与查无匹配记录。

html
<!doctype html>
<html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width">
<title>Sample shipment lookup</title><style>
/* Local snapshot of documented Maersk light roles; not an MDS package import. */
:root{--mds_brand_appearance_primary_default_background-color:#141414;
--mds_brand_appearance_primary_default_on-background-color:#fff;
--mds_brand_appearance_neutral_default_border-color:#d4d4d4;
--mds_brand_appearance_secondary_weak_background-color:#e2f3f9}
body{font:16px/24px Arial,sans-serif;color:#141414;margin:32px}
main{max-width:48rem;margin:auto}label{display:block;margin-bottom:8px}
input,button{font:inherit;padding:12px 16px;border-radius:6px}
input{border:1px solid var(--mds_brand_appearance_neutral_default_border-color);max-width:100%;box-sizing:border-box}
button{border:0;background:var(--mds_brand_appearance_primary_default_background-color);color:var(--mds_brand_appearance_primary_default_on-background-color)}
.actions{display:flex;gap:8px;flex-wrap:wrap}li{padding:12px 0}#error{color:#b80012}#result{margin-top:24px;padding:24px;border-radius:12px;background:var(--mds_brand_appearance_secondary_weak_background-color)}
</style><main><h1>Find a sample shipment</h1>
<form id="lookup" novalidate><label for="reference">Shipment reference</label>
<p id="hint">Try 000042 or 000108. These are original sample records.</p>
<div class="actions"><input id="reference" type="text" inputmode="numeric" value="000042" aria-describedby="hint error" required>
<button type="submit">Show shipment</button></div><p id="error" role="alert"></p></form>
<section id="result" aria-live="polite"></section></main>
<script>
const shipments={'000042':{route:'Rotterdam → Singapore',events:['Booking received','Loaded at origin','In transit']},'000108':{route:'Hamburg → New York',events:['Booking received','Awaiting origin handover']}};
const input=document.querySelector('#reference'),result=document.querySelector('#result'),error=document.querySelector('#error');
function lookup(e){e.preventDefault();const id=input.value.trim();error.textContent='';input.setAttribute('aria-invalid','false');result.replaceChildren();
 if(!/^\d{6}$/.test(id)){error.textContent='Use a six-digit sample reference, including leading zeros.';input.setAttribute('aria-invalid','true');input.focus();return;}
 const record=shipments[id];if(!record){result.textContent='No sample shipment matches this reference. Try 000042 or 000108.';return;}
 const heading=document.createElement('h2');heading.textContent=id+' · '+record.route;
 const list=document.createElement('ol');record.events.forEach(x=>{const li=document.createElement('li');li.textContent=x;list.append(li)});
 result.append(heading,list);
}
document.querySelector('#lookup').addEventListener('submit',lookup);
input.addEventListener('input',()=>{error.textContent='';input.setAttribute('aria-invalid','false');result.replaceChildren();});
</script></html>

代码参考

  • type="text" 可保留标识符中的数字;inputmode 仅用于提示键盘类型。
  • 可见标签、常驻提示和关联错误文本各司其职。
  • 此代码为原创实现,并非私有 MDS Input 组件 API。
04

Maersk 设计系统 AI Agent 设置

实现起点

公开的开发者页面说明了私有注册表的访问方式。由于无法获取代码片段,我们不会臆造精确的原生导入语句或事件签名。提供的 HTML 是基于公开基础规范构建的完整可运行方案。

文本
Native MDS adoption (authorized Maersk teams):
1. Obtain access to Maersk Global GitHub Packages or the private Nexus registry.
2. Use the corporate authentication and SSO flow in the official developer guide.
3. Install the approved component or core package and its documented token/font dependencies.
4. Read exact component properties and events in the MDS Storybook for that installed release.

Public reference specimen:
Save the complete HTML example as index.html and open it in a browser.
It requires no registry, external script or private asset.
Its token declarations are a local light-theme snapshot; they do not initialize MDS Web Components.

适用于你项目的提示词

Agent 提示词
创建一个受 Maersk 启发的运营查询界面,采用文档规定的浅色角色、深色主要操作、基于 4px 的间距、6px 输入框圆角和 12px 卡片。将货运标识符作为文本保留,区分格式错误输入和查无记录,并以有序列表展示事件历史。不要臆造公开的软件包访问方式或私有组件 API。
05

Maersk 设计系统 来源与范围

独立的 OpenDesign 参考实现。原生 MDS 软件包需要经过授权的企业访问权限。预览中的所有货运标识符、路线和事件均为虚构示例数据;页面不会调用追踪服务。