零售电商 · 新资源

Adeo Mozaic 设计系统.

使用 Mozaic 的 16px 魔法单位、尺寸匹配的 48px 控件、实际 SCSS 导入和 BEM 类,构建实用的数量控件组合。货架规划器可直观呈现取值范围、输入错误和本地材料汇总。

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

Adeo Mozaic 设计系统界面预览

输入或调整数量,测试其取值范围,并生成本地材料清单。

货架材料规划器打开完整示例
这是对 Mozaic 魔法单位和中号数量控件的原创离线 HTML/CSS 演绎,采用原创插图和应用配色,并非原生库 CSS。· 实现参考
02

Adeo Mozaic 设计系统设计参考

Mozaic SCSS/BEM 文档:基础和安装页面标注版本为 v1.85.0;数量控件代码参考标注版本为 v1.76.0。这些是文档所述的参考约定,并不表示所有页面都对应同一个最新版软件包。

魔法单位参考

来源
名称 / 规则值 / 配置用途
mu0254px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu0508px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu07512px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu10016px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu12520px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu15024px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu17528px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu20032px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu25040px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu30048px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu35056px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu40064px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu50080px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu60096px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。
mu700112px基于 rem 的间距参考;像素等效值以文档所述的 16px 基准为前提。

按钮尺寸

来源
名称 / 规则值 / 配置用途
Small height32px / 2mu用于紧凑型控件。
Medium height48px / 3mu用于移动端数量控件组合。
Large height56px / 3.5mu用于高强调度的大型操作。
Text + icon, small / medium24px icon保持图标与标签的视觉平衡。
Text + icon, large32px icon大型按钮。
Icon-only, medium / large32px icon方形控件。

正文层级

来源
名称 / 规则值 / 配置用途
mt-body-m16px regular默认正文。
Small body14px多行正文建议的最小字号。
Large body18px段落建议的最大字号。

数量组件结构

来源
名称 / 规则值 / 配置用途
mc-quantity-selectorWrapper包含两个控件和一个输入框。
mc-quantity-selector__inputInput element还需应用 mc-text-input。
mc-quantity-selector__button-leftDecrement element还需应用 mc-button--square 和 --bordered。
mc-quantity-selector__button-rightIncrement element还需应用 mc-button--square 和 --bordered。
Small compositionmc-text-input--s + mc-button--s同时调整整个组合的尺寸。
is-disabledVisual state class与原生 disabled 属性配合使用,才能实现实际禁用行为。

构建与自定义

来源
名称 / 规则值 / 配置用途
postcssPluginConfig@mozaic-ds/css-dev-tools/postcssPluginConfig必需的插件列表。
Parserpostcss-scss阅读 SCSS 源码。
Production environmentMOZAIC_ENV=production启用生产环境插件配置。

间距工具类

来源
名称 / 规则值 / 配置用途
mu-mb-10016px bottom margin组件之间的间距。
mu-pl-0508px left padding工具类间距。
make-space-util(m, t, 075)Top margin at mu075生成指定的工具类。
03

Adeo Mozaic 设计系统完整指南

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

DESIGN-adeo-mozaic.md

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

下载指南

Adeo Mozaic 设计系统 SCSS 组件,可配置零售品牌形象

ADEO 是组织名称,不是默认预设

Mozaic 将源样式和设计令牌与字体及 SVG 图标分开提供。其默认设计令牌主题为 Leroy Merlin;ADEO 则是一个明确指定的预设。因此,绿色的原始预览并不能证明该颜色是 ADEO 的官方企业色。

摘自本 OpenDesign 指南

对于 ADEO 预设,创建 mozaic.config.js,设置 preset: "adeo" 和 tokens.localTokensExportPath,然后运行 npx mozaic-tokens-build。自定义令牌目录会按对应 JSON 路径进行深度合并,而非替换无关值。主题生成和组件样式属于不同的构建环节。

  • styles 提供 SCSS 组件。
  • tokens 提供源令牌和生成后的令牌格式。
  • web-fonts 和 icons 提供独立资源。
  • css-dev-tools 提供构建和 lint 配置。

阅读配套规范

Adeo Mozaic 设计系统:使用 magic 单位,避免文本容器尺寸僵化

以 16px 为基准的 rem 单位

Mozaic 尺度中较小的间距以四分之一单位递增,中间范围以半单位递增,较大的距离则以整单位递增。参考表列出了实际命名的级别,无需另行创造一套间距系统。

规划器使用 16px 间距、24px 内部留白和 48px 控件高度。这些设置让组件保持统一节奏,同时允许周围的卡片和文本灵活扩展。控件高度应设置最小值,而不是将翻译后或放大后的标签裁切在固定高度的内容框中。

阅读配套规范

Adeo Mozaic 设计系统:让密集控件旁的正文保持易读

三种实用的正文尺寸

文档中的正文字号以 16px 常规字重为主。多行文本建议使用不小于 14px 的字号,段落建议使用不大于 18px 的字号。预览使用系统字体作为后备,不会假装已打包 Mozaic 的 Web 字体包。

用较大的标题命名项目,用正文说明计算方式,再用较小的辅助文字交代示例范围。材料数值使用真实文本,而不是绘制在货架插图中的文字。

阅读配套规范

Adeo Mozaic 设计系统:一个组件,三个协同元素

包装容器不提供应用状态

数量选择器由一个方形描边减量按钮、一个数字输入框和一个匹配的增量按钮组成。请导入这三个组件的所有样式,包括文本输入框和按钮;仅导入 quantity-selector 并不构成文档所述的组合。

如需紧凑变体,请同时调整按钮和输入框的尺寸。使用指南要求在小屏断点使用中号尺寸,因此在手机上把所有元素都缩小并非正确的优化方式。预览保留 48px 控件,并将周围的组合内容改为纵向堆叠。

阅读配套规范

Adeo Mozaic 设计系统:边界样式必须与实际行为一致

可输入的控件状态不止加号和减号

原始示例会验证 1 到 12 之间的整数。数值为 1 时,减量按钮会被真正禁用;数值为 12 时,增量按钮会被禁用。仅添加 is-disabled 类并不能阻止键盘操作,因此原生 disabled 属性与视觉类会保持同步。

空值或小数形式的输入不会被悄悄转换成看似合理的材料清单。提交时会说明可接受的范围,并将焦点移至输入框。后续编辑会清除之前生成的结果,因为该结果对应的是先前输入的数量。货架计算仅为虚构示例数据,不构成结构或采购建议。

  1. 读取输入值时,不要将空字符串视为零。
  2. 计算示例数量前,先验证输入是否为整数且处于允许范围内。
  3. 同时更新两个边界按钮和无障碍错误状态。
  4. 只有通过验证后,才创建本地快照。

阅读配套规范

Adeo Mozaic 设计系统:为项目目标设置一个实心主操作按钮

将步进操作与生成操作区分开

步进器使用克制的方形描边按钮,因为它用于更改输入值。实心的“准备材料清单”按钮则作用于整个表单。若并排放置两个同色实心操作按钮,会让两者的区别变得模糊。

结果消息明确说明并未下单。这里没有虚假的加载状态、支付流程或网络提交。具体的摘要足以展示数值与操作之间的关系。

阅读配套规范

Adeo Mozaic 设计系统:通过 Mozaic 流程编译文档中列出的导入项

先加载设置,再输出组件

全部设置导入会提供变量、函数和混入,但自身不会输出任何组件 CSS。提供的打包文件会在其后导入 text-input、button 和 quantity-selector。所提供的插件配置会解析 Mozaic 导入路径,并执行其所需的转换。

此设置提供了一个 PostCSS CLI 运行器,因为插件包本身不包含该运行器。在生产环境中,MOZAIC_ENV 会更改插件配置。安装页面现要求使用 Node 20+,并推荐 Dart Sass;不要因较早的文档提到 Node Sass,就将其作为安装已弃用编译器的理由。

阅读配套规范

Adeo Mozaic 设计系统:将工具类间距保留在组件内部样式之外

组件负责自身布局时,使用间距刻度值

Mozaic 的 margin 和 padding 工具类用于设置组件之间的间距。创建新组件时,请在 SCSS 中使用 magic-unit 变量,使组件保持自包含。为了保持预期的节奏,边框可能需要从目标尺寸中扣除,例如使用 calc($mu025 - 1px)。

此离线示例不声称原生执行 Mozaic CSS。它根据文档中的尺寸和数量控件结构进行演绎,采用原创配色、CSS 货架插图以及仅在本地运行的交互。单独的代码块则提供实际的库类名和构建连接方式。

阅读配套规范

Adeo Mozaic 设计系统组件示例

完整的独立交互示例

将完整文档保存为 index.html,然后在浏览器中打开。这是对 Mozaic 魔法单位和中型数量控件的原创离线 HTML/CSS 演绎;插画和应用配色均为原创,并非原生库 CSS。

html
<!doctype html><html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Shelf materials planner</title><style>*{box-sizing:border-box}body{margin:0;background:#f6f5ef;color:#242920;font:16px/1.5 Arial,sans-serif}button,input{font:inherit}button{cursor:pointer}button:focus-visible,input:focus-visible{outline:3px solid #23682c;outline-offset:4px}header{border-bottom:1px solid #d9ddd1;padding:16px 32px;display:flex;justify-content:space-between;gap:16px}header b{font-size:18px}header span,.note{font-size:14px;color:#5a6154}main{max-width:1056px;margin:auto;padding:32px}h1{font-size:36px;line-height:1.1;letter-spacing:-1px;margin:8px 0 16px}p{margin:0 0 16px}.eyebrow{font-size:12px;letter-spacing:2px;color:#23682c;font-weight:bold}.layout{display:grid;grid-template-columns:1.1fr 1fr;gap:32px}.art{background:#e5eadc;border-radius:4px;min-height:350px;display:grid;place-items:center;position:relative;overflow:hidden}.wall{width:78%;height:220px;background:linear-gradient(90deg,transparent 49.6%,#d8dfcf 50%,transparent 50.4%);position:relative}.board{position:absolute;left:0;right:0;top:130px;height:18px;background:repeating-linear-gradient(0deg,#bd9b6e 0 3px,#c6a477 3px 7px);box-shadow:0 10px 12px #26341b20;transform:skewY(-3deg)}.bracket{position:absolute;top:148px;width:12px;height:62px;background:#727867;transform:skewY(-3deg)}.bracket.a{left:15%}.bracket.b{right:15%}.pot{position:absolute;left:23%;top:58px;width:47px;height:72px;background:#c88462;border-radius:3px 3px 15px 15px}.leaf{position:absolute;width:52px;height:34px;background:#3d6e38;left:4px;top:-22px;border-radius:100% 0 100% 0;transform:rotate(-25deg)}.leaf:after{content:'';position:absolute;width:45px;height:30px;background:#638a47;left:20px;top:-15px;border-radius:0 100% 0 100%;transform:rotate(45deg)}.books{position:absolute;top:48px;right:20%;height:80px;display:flex;gap:4px;align-items:end}.books i{width:18px;height:76px;background:#f4efe4;display:block;border-top:6px solid #7f9673}.books i:nth-child(2){height:88px;background:#d3b795}.books i:nth-child(3){height:68px;background:#718268;transform:rotate(-10deg)}.art small{position:absolute;bottom:16px;left:24px;color:#526448}.panel{background:#fff;padding:24px;border:1px solid #d9ddd1;border-radius:4px}h2{font-size:24px;line-height:1.25;margin:0 0 8px}label{display:block;font-weight:bold;margin:24px 0 8px}.quantity{display:flex;max-width:240px;margin-bottom:8px}.quantity button,.quantity input{height:48px;border:1px solid #727a6a;background:#fff}.quantity button{width:48px;color:#23682c;font-size:24px;flex-shrink:0}.quantity button:first-child{border-radius:4px 0 0 4px}.quantity button:last-child{border-radius:0 4px 4px 0}.quantity input{width:96px;min-width:0;border-left:0;border-right:0;text-align:center;appearance:textfield}.quantity input::-webkit-inner-spin-button{appearance:none}button:disabled{color:#a2a69b;background:#f1f2ed;cursor:default}.materials{margin:24px 0;display:grid;grid-template-columns:repeat(3,1fr);border-block:1px solid #d9ddd1;padding:16px 0}.materials strong{font-size:24px;display:block}.materials span{font-size:14px;color:#62695c}.primary{min-height:48px;padding:12px 24px;background:#23682c;color:#fff;border:0;border-radius:4px;width:100%;font-weight:bold}.error{color:#ac2323;margin:8px 0;font-size:14px}.result{margin-top:16px;background:#eaf3e2;padding:16px;border-left:4px solid #23682c}.result:empty{display:none}footer{padding-top:24px;font-size:14px;color:#62695c}@media(max-width:650px){header{padding:16px}header span{max-width:140px}main{padding:24px 16px}h1{font-size:32px}.layout{grid-template-columns:1fr;gap:16px}.art{min-height:260px}.panel{padding:24px}.materials{gap:12px}}
</style><header><b>PROJECT WORKSHOP</b><span>Original Mozaic interpretation</span></header><main><p class="eyebrow">SMALL PROJECT · BIG DIFFERENCE</p><h1>Make room for what matters.</h1><p>Plan a simple shelf arrangement and prepare its sample materials list.</p><div class="layout"><div class="art" role="img" aria-label="Original illustration of a wooden shelf with books and a potted plant"><div class="wall"><div class="board"></div><div class="bracket a"></div><div class="bracket b"></div><div class="pot"><div class="leaf"></div></div><div class="books"><i></i><i></i><i></i></div></div><small>Original shelf illustration</small></div><form class="panel" id="planner" novalidate><h2>Your shelf project</h2><p class="note">Each sample shelf uses one board, two brackets and four screws.</p><label for="quantity">Number of shelves</label><div class="quantity"><button id="minus" type="button" aria-label="Remove one shelf" aria-controls="quantity">−</button><input id="quantity" type="number" min="1" max="12" step="1" required value="2" aria-describedby="hint error"><button id="plus" type="button" aria-label="Add one shelf" aria-controls="quantity">+</button></div><p class="note" id="hint">Choose a whole number from 1 to 12.</p><p class="error" id="error" role="alert"></p><div class="materials" aria-live="polite"><div><strong id="boards">2</strong><span>Boards</span></div><div><strong id="brackets">4</strong><span>Brackets</span></div><div><strong id="screws">8</strong><span>Screws</span></div></div><button type="submit" class="primary">Prepare materials list</button><div id="result" class="result" role="status"></div></form></div><footer>Local interaction example. No order is placed. Sample quantities are illustrative, not structural guidance.</footer></main><script>const input=document.querySelector('#quantity'),minus=document.querySelector('#minus'),plus=document.querySelector('#plus'),error=document.querySelector('#error'),result=document.querySelector('#result');function number(){return input.value.trim()===''?NaN:Number(input.value)}function valid(n){return Number.isInteger(n)&&n>=1&&n<=12}function update(show=false){const n=number(),ok=valid(n);result.textContent='';minus.disabled=ok&&n===1;plus.disabled=ok&&n===12;input.setAttribute('aria-invalid',String(!ok&&show));error.textContent=!ok&&show?'Enter a whole number from 1 to 12.':'';document.querySelector('#boards').textContent=ok?n:'—';document.querySelector('#brackets').textContent=ok?n*2:'—';document.querySelector('#screws').textContent=ok?n*4:'—';return ok}minus.onclick=()=>{input.value=String(Math.max(1,(valid(number())?number():1)-1));update()};plus.onclick=()=>{input.value=String(Math.min(12,(valid(number())?number():0)+1));update()};input.oninput=()=>update();document.querySelector('#planner').onsubmit=e=>{e.preventDefault();if(!update(true)){input.focus();return}result.textContent=`Local list prepared: ${number()} boards, ${number()*2} brackets and ${number()*4} screws. Nothing was ordered.`};update();</script></html>

代码参考

  • 货架数量会生成材料清单,而非订单。原生标记需要使用文档说明的 Mozaic PostCSS 输出;此独立文档包含自行演绎的样式。

限定范围的货架数量和据此生成的材料清单

原生数字输入框外围使用真实的 Mozaic 类。原创 JavaScript 实现整数验证、边界禁用和仅在本地显示的摘要。

html
<!doctype html>
<html lang="en"><meta charset="utf-8"><meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="./mozaic.css"><title>Shelf materials</title>
<main><h1>Plan a shelf project</h1>
<form id="planner" novalidate>
<label for="quantity">Number of shelves</label>
<p id="hint">Choose 1 to 12. Each sample shelf needs two brackets and four screws.</p>
<div class="mc-quantity-selector">
<button type="button" id="minus" class="mc-button mc-button--square mc-button--bordered mc-quantity-selector__button-left" aria-controls="quantity" aria-label="Remove one shelf">−</button>
<input id="quantity" name="quantity" class="mc-text-input mc-quantity-selector__input" type="number" min="1" max="12" step="1" value="2" required aria-describedby="hint error">
<button type="button" id="plus" class="mc-button mc-button--square mc-button--bordered mc-quantity-selector__button-right" aria-controls="quantity" aria-label="Add one shelf">+</button>
</div>
<p id="error" role="alert"></p><p id="counts" aria-live="polite"></p>
<button type="submit" class="mc-button">Prepare materials list</button>
<p id="result" role="status"></p></form></main>
<script>
const input=document.querySelector('#quantity'), minus=document.querySelector('#minus'), plus=document.querySelector('#plus');
const error=document.querySelector('#error'), counts=document.querySelector('#counts'), result=document.querySelector('#result');
function number(){return input.value.trim()===''?NaN:Number(input.value);}
function valid(n){return Number.isInteger(n)&&n>=1&&n<=12;}
function update(showError=false){
 const n=number(),ok=valid(n); result.textContent='';
 minus.disabled=ok&&n===1; plus.disabled=ok&&n===12;
 minus.classList.toggle('is-disabled',minus.disabled);plus.classList.toggle('is-disabled',plus.disabled);
 input.setAttribute('aria-invalid',String(!ok&&showError));
 error.textContent=!ok&&showError?'Enter a whole number from 1 to 12.':'';
 counts.textContent=ok?`${n} boards · ${n*2} brackets · ${n*4} screws`:'Enter a quantity to calculate materials.';
 return ok;
}
minus.onclick=()=>{input.value=String(Math.max(1,(valid(number())?number():1)-1));update();};
plus.onclick=()=>{input.value=String(Math.min(12,(valid(number())?number():0)+1));update();};
input.oninput=()=>update();
document.querySelector('#planner').onsubmit=e=>{e.preventDefault();if(!update(true)){input.focus();return;}result.textContent=`Local list prepared: ${number()} boards, ${number()*2} brackets and ${number()*4} screws. Nothing was ordered.`;};
update();
</script></html>

代码参考

  • 两个步进按钮使用 type="button",因此不会提交表单。
  • 原生 min/max/step 属性仍然有效,自定义校验则用于处理空值和小数输入。
  • 修改数量后,先前准备好的快照将失效。
04

Adeo Mozaic 设计系统 AI Agent 设置

实现起点

使用文档所述 PostCSS 配置的公开 SCSS 工作流。将 HTML 示例保存为 public/index.html。此处未执行原生软件包构建;离线预览是独立的实现诠释。当前安装指南采用 Dart Sass,取代了旧版 PostCSS 页面中对 Node Sass 的描述。

文本
# Node 20+. Use a CommonJS project for this configuration.
npm install @mozaic-ds/styles sass
npm install --save-dev @mozaic-ds/css-dev-tools postcss postcss-cli postcss-scss
# Save the configuration and SCSS below, then build:
npx postcss src/bundle.scss --output public/mozaic.css
# Production build on a POSIX shell:
MOZAIC_ENV=production npx postcss src/bundle.scss --output public/mozaic.css

// postcss.config.js
module.exports = {
  syntax: require('postcss-scss'),
  plugins: require('@mozaic-ds/css-dev-tools/postcssPluginConfig')
};

// src/bundle.scss — settings must precede components.
@import 'settings-tools/all-settings';
@import 'components/c.text-input';
@import 'components/c.button';
@import 'components/c.quantity-selector';

适用于你项目的提示词

Agent 提示词
使用 settings-tools/all-settings,在 text-input、button 和 quantity-selector 之前创建一个 Mozaic SCSS 组合。在小屏幕上采用 48px 中等尺寸控件,将边界按钮设为原生禁用状态,校验输入的整数,并生成仅在本地使用的摘要。使用文档所述的 PostCSS 流程,并区分 Leroy Merlin 默认主题与 ADEO 预设。
05

Adeo Mozaic 设计系统来源与范围

独立的 OpenDesign Mozaic 参考示例。此示例不是 ADEO 或 Leroy Merlin 店面、真实订单,也不提供结构方面的指导。文档快照中的版本标注并不一致。