Tailwind 组件系统 · 新资源

Preline UI 设计系统.

使用原生 Preline 设计的行程规划工具,包含关联选项卡、受约束的数字输入插件、已安装的主题别名、实际的 Tailwind 尺度,以及随所选行程更新的本地材料估算。

OpenDesign 指南9 个章节31 个参考条目原始应用指南
01

Preline UI 设计系统界面预览

比较三个原创创作时段,调整团队人数,并保存仅供本地使用的材料估算。

周六工作室计划打开完整示例
Preline 4.2.0 HSTabs 和 HSInputNumber,搭配 Tailwind CSS 4.3.3 与打包的默认主题。· 实现参考
02

Preline UI 设计系统设计参考

Preline npm 4.2.0 与 Tailwind CSS 4.3.3;默认主题来自已安装的包。营销/文档网站可能会显示较新版本的横幅,因此可执行示例明确锁定了版本。主题别名仍保持为别名;不猜测其十六进制转换值。

默认浅色语义主题

来源
名称 / 规则值 / 配置用途
--backgroundvar(--color-white)默认背景角色。
--foregroundvar(--color-gray-800)主文本角色。
--bordervar(--color-gray-200)共享边框角色。
--primaryvar(--color-primary-600)活动标签和主要操作。
--primary-foregroundvar(--color-white)主按钮上的文本。
--primary-hovervar(--color-primary-700)悬停状态。
--primary-focusvar(--color-primary-700)焦点状态。
--primary-activevar(--color-primary-700)活动状态。
--layervar(--color-white)数量控件表面。
--layer-linevar(--color-gray-200)数量边界。
--layer-hovervar(--color-gray-50)悬停界面表面。
--cardvar(--color-white)场次卡片和分组卡片。
--card-linevar(--color-gray-200)卡片边界。
--muted-foreground-1var(--color-gray-500)辅助性文本。

实际使用的 Tailwind 间距刻度

来源
名称 / 规则值 / 配置用途
p-2 / gap-20.5rem数量控件外壳和标签间距。
px-3 / gap-30.75rem标签内边距和数字控件间距。
p-51.25rem卡片和默认页面内边距。
sm:p-82rem from 640px小屏断点下的页面内边距。
mt-71.75rem规划器上方的间距。
text-xs0.75rem / 1rem辅助标签。
text-sm0.875rem / 1.25rem控件和说明文案。
text-lg1.125rem / 1.75rem分组标题。
text-2xl1.5rem / 2rem场次标题。
text-3xl1.875rem / 2.25rem页面标题和总计。
rounded-lg / rounded-xl0.5rem / 0.75rem控件 / 卡片;Tailwind 默认圆角值。

原始应用和插件约束

来源
名称 / 规则值 / 配置用途
Group sizemin 1 / max 6 / step 1HSInputNumber 数据选项与 HTML 输入约束一致。
Print studio allowance$12 per participant虚构的材料费用估算。
Clay workshop allowance$18 per participant虚构的材料费用估算。
Drawing walk allowance$5 per participant虚构的材料费用估算。
LayoutFlexible session + 280px group card; stack at 760px原始响应式布局。
Theme mappingbg-primary → --color-primary → --primary语义化 Tailwind 工具类通过 Preline 别名解析。
03

Preline UI 设计系统完整指南

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

DESIGN-preline-ui.md

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

下载指南

Preline UI 设计系统:Preline 将工具类标记与行为插件结合

Preline 将实用工具标记与行为插件相结合

规划器使用两个原生 Preline 插件:HSTabs 用于选择场次面板,HSInputNumber 用于管理带上下限的递增和递减控件。大部分视觉样式由 Tailwind 类提供。原始场次插图和预算计算属于应用本身,并非虚构的全能预订组件。

摘自本 OpenDesign 指南

复制示例时,区分这些部分很重要。仅安装 JavaScript 软件包不会编译工具类,也不会提供应用标记。反过来,只复制 HTML 而不初始化插件,标签和数字控件的行为也不完整。下面的完整集成示例会明确提供每个部分。

阅读配套规范

Preline UI 设计系统:沿语义别名追溯到对应的调色板角色

沿用语义别名,追溯至其调色板角色

在软件包默认浅色主题中,--primary 指向 --color-primary-600,其底层主色阶为蓝色。主色前景解析为白色;悬停、焦点和激活状态使用 700 色阶。选中标签和保存操作通过语义化工具类共用这一颜色体系。

卡片使用 --card 和 --card-line,数量字段使用 --layer 和 --layer-line。将这些角色分开定义,比到处散用白色和灰色字面量类更便于预测未来的主题变更。表格保留官方别名,而不是把计算后的近似值当作源令牌。

阅读配套规范

Preline UI 设计系统:使用 Tailwind 的实际刻度,并标明原始设计中的例外

使用 Tailwind 的实际比例,并标明特殊值

页面标题和费用估算使用 text-3xl,场次标题使用 text-2xl,表单文案使用 text-sm。卡片内边距 p-5 在默认间距单位下等于 1.25rem。较大的 sm:p-8 页面内边距从 Tailwind 的 640px 小屏断点开始启用,而原始网格则在 760px 时切换为单列。

本地样式表使用 system-ui,不会加载 Preline 主题文件中列出的可选自定义字体。在 280px 宽度下,标签会换成两行,分组卡片会移到场次卡片下方。这些是应用有意采用的布局方式,并不意味着所有 Preline 布局都采用这种几何结构。

阅读配套规范

Preline UI 设计系统:通过稳定 ID 将标签控件与面板关联

通过稳定 ID 关联标签控件与面板

每个标签的 data-hs-tab 都指向一个唯一面板。标签的 aria-controls 和面板的 aria-labelledby 也会重复这一关联,以便辅助技术识别。初始状态下,恰好只有一个标签带有 active 和 aria-selected=true,其余面板均处于隐藏状态。原生 HSTabs 会在用户切换时更新这些状态。

激活状态的视觉样式使用 hs-tab-active:bg-primary 和 hs-tab-active:text-primary-foreground。这些变体来自 Preline 的 variants.css;如果未导入该文件,即使 JavaScript 正确更改了类名,选中状态在视觉上也可能不明显。应用会监听选中项变化,以更新旁边的摘要。

  1. 选择“陶艺工作坊”,并确认其标题、材料和时长。
  2. 将参与人数从两人增加到三人,并核对 54 美元的费用估算。
  3. 保存本地计划,然后切换标签以清除先前的确认信息。

阅读配套规范

Preline UI 设计系统:插件选项必须与输入约束一致

插件选项必须与输入限制一致

数量控件容器通过 data-hs-input-number 设置最小值 1、最大值 6 和步长 1。原生数字输入框也重复设置了这些约束。这样,插件按钮和浏览器有效性检查遵循相同的允许范围,不会出现手动输入的数字绕过仅在按钮处理器中设置的限制的情况。

摘要会监听 input、change 事件以及插件的 change 回调。手动输入无效值时,总计会替换为破折号,并禁用保存;保存处理器还会在读取数值前调用 reportValidity。六人上限是示例中的规划约束,并不代表实际可用名额。

阅读配套规范

Preline UI 设计系统:根据当前面板计算,而非读取过时的标签

从活动面板计算,而不是依赖过时的标签

每个面板都通过数据属性存储稳定的场次名称、价格和时长。更新函数会读取当前显示的面板,并将其费用额度乘以有效的分组人数。这样,“版画工作室”“陶艺工作坊”和“写生漫步”就是真正不同的选项,而不是切换标签后仍显示同一张占位卡片。

显示的费用估算仅包含材料费。原始说明会解释费用额度的用途,页面也明确指出此功能不会预订名额。这些数字背后没有支付、库存检查或外部日程系统。真实的预订流程需要单独接入这些系统,并进行服务器端验证。

阅读配套规范

Preline UI 设计系统:使用此软件包版本导出的手动入口

在此包版本中使用导出的手动输入项

经验证的 4.2.0 软件包从 preline/non-auto 导出名为 HSTabs 和 HSInputNumber 的内容。示例会导入它们,并在标记就绪后调用各自的 autoInit 方法。尽管名称中有 autoInit,这里仍需由应用显式调用并扫描页面,而不是依赖整个软件包隐式注册的页面加载钩子。

验证过程中发现,各插件的 .mjs 路径未提供默认类;根据软件包的副作用元数据,从这些路径进行裸导入也可能被移除。使用导出的手动入口解决了这一具体构建问题。因此,示例展示的是经过验证、可运行的版本化导入方式,而非未经测试的通用插件导入。

阅读配套规范

Preline UI 设计系统:计划变更时让确认信息失效

计划变更时让确认信息失效

点击「保存本地方案」后,会显示包含确切场次、人数和材料总额的状态说明,然后禁用按钮。修改人数或切换所选标签页时,都会调用 update,恢复常规说明并重新计算是否允许保存。已保存的状态说明不能继续关联到新的方案。

本地测试选择了「陶艺工作坊」,将人数增加到 3 人,并检查了显示 $54 的状态。测试还检查了 280px 宽度下实际渲染的页面。静态总额或仅改变自身标签的按钮,都无法证明这两个原生插件与应用状态已正确连接。

  • 使用状态区域显示准确的本地结果。
  • 无效数值不得计入计算总额。
  • 调整标记时,保留稳定的标签页/面板 ID。

阅读配套规范

Preline UI 设计系统:编译主题、变体与实际源标记

编译主题、变体和实际源标记

样式表先导入 Tailwind,再导入 Preline 变体和打包的默认主题。显式源文件路径包括本地 HTML、应用程序 JavaScript 和 Preline 发布文件,因此,生成的 CSS 中包含依赖状态的实用类。原有布局样式表紧随这些导入项之后。

独立预览会内嵌编译后的 CSS 和打包后的 JavaScript,且不会发出 CDN 请求。生产项目可以将相同的输出作为独立文件提供。文件路径应相对于实际的 CSS 入口文件;以下可复现示例将所有源文件放在项目根目录,以避免依赖隐藏的临时工作区。

阅读配套规范

Preline UI 设计系统组件示例

完整的语义化规划器标记

包含标签页 ID、面板关联、数字输入钩子和明确的本地状态区域。

html
<main class="max-w-5xl mx-auto p-5 sm:p-8"><header><p class="text-xs font-semibold tracking-widest text-muted-foreground-1">STUDIO SATURDAY · SAMPLE PROGRAM</p><h1 class="text-3xl font-semibold tracking-tight mt-3">Choose a different kind of afternoon.</h1><p class="text-sm text-muted-foreground-1 leading-6 mt-3 max-w-2xl">Explore three creative sessions and calculate a sample materials budget for your group. This planner does not book a place.</p></header><div class="planner-grid mt-7"><section class="min-w-0"><nav class="flex flex-wrap gap-2 mb-5" role="tablist" aria-label="Creative sessions"><button type="button" id="tab-print" data-hs-tab="#panel-print" role="tab" aria-controls="panel-print" aria-selected="true" class="active hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Print studio</button><button type="button" id="tab-ceramics" data-hs-tab="#panel-ceramics" role="tab" aria-controls="panel-ceramics" aria-selected="false" class=" hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Clay workshop</button><button type="button" id="tab-drawing" data-hs-tab="#panel-drawing" role="tab" aria-controls="panel-drawing" aria-selected="false" class=" hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Drawing walk</button></nav><div id="panel-print" role="tabpanel" aria-labelledby="tab-print" class="" data-name="Print studio" data-price="12" data-duration="90 minutes"><div class="session-art print" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">09:30–11:00 · 90 minutes</p><h2 class="text-2xl mt-3 font-semibold">Ink, paper, repeat.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Make a two-color print from a simple cut-paper composition.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Cobalt ink</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Warm white stock</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Registration guide</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $12 per person</p></div></div><div id="panel-ceramics" role="tabpanel" aria-labelledby="tab-ceramics" class="hidden" data-name="Clay workshop" data-price="18" data-duration="120 minutes"><div class="session-art ceramics" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">13:00–15:00 · 120 minutes</p><h2 class="text-2xl mt-3 font-semibold">A shape held by hand.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Build a small pinch vessel and explore three surface textures.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Stoneware clay</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Wooden modeling tool</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Texture samples</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $18 per person</p></div></div><div id="panel-drawing" role="tabpanel" aria-labelledby="tab-drawing" class="hidden" data-name="Drawing walk" data-price="5" data-duration="60 minutes"><div class="session-art drawing" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">16:00–17:00 · 60 minutes</p><h2 class="text-2xl mt-3 font-semibold">Notice the edges.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Make a sequence of quick drawings along an original sample walking route.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Pocket sketchbook</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Soft graphite pencil</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Portable drawing board</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $5 per person</p></div></div></section><aside class="bg-card border border-card-line rounded-xl p-5 self-start"><h2 class="text-lg font-semibold">Your group</h2><label for="people" class="block text-sm mt-5 mb-2">Participants</label><div id="quantity" data-hs-input-number='{"min":1,"max":6,"step":1}' class="flex items-center gap-3 border border-layer-line rounded-lg p-2 bg-layer"><button type="button" data-hs-input-number-decrement aria-label="Decrease participants" class="size-9 shrink-0 rounded-md border border-border disabled:opacity-40">−</button><input id="people" type="number" value="2" min="1" max="6" step="1" data-hs-input-number-input class="w-full min-w-0 text-center bg-transparent"/><button type="button" data-hs-input-number-increment aria-label="Increase participants" class="size-9 shrink-0 rounded-md border border-border disabled:opacity-40">+</button></div><p class="text-xs text-muted-foreground-1 mt-2">1–6 participants · sample planning limit</p><dl class="mt-6 space-y-3 text-sm"><div><dt class="text-muted-foreground-1">Selected session</dt><dd id="selected-name" class="font-semibold mt-1"></dd></div><div><dt class="text-muted-foreground-1">Duration</dt><dd id="selected-duration" class="font-semibold mt-1"></dd></div><div class="pt-4 border-t border-border"><dt class="text-muted-foreground-1">Materials estimate</dt><dd id="total" class="text-3xl font-semibold mt-1"></dd></div></dl><button id="save" class="mt-6 w-full py-3 px-4 bg-primary text-primary-foreground rounded-lg font-medium text-sm hover:bg-primary-hover disabled:opacity-50" type="button">Save local plan</button><p id="feedback" role="status" class="text-xs leading-5 mt-3 text-muted-foreground-1">No booking or payment is created.</p></aside></div></main>

代码参考

  • 三个场次及其价格均为原创示例数据。
  • 原生输入控件采用与插件相同的约束。

完整的插件初始化与计算逻辑

从导出的非自动入口手动初始化;所选场次和人数共同用于计算摘要。

javascript
import {HSTabs,HSInputNumber} from 'preline/non-auto';
HSTabs.autoInit();HSInputNumber.autoInit();
const quantity=document.querySelector('#people'),save=document.querySelector('#save'),feedback=document.querySelector('#feedback');
function selected(){return document.querySelector('[role=tabpanel]:not(.hidden)')}
function update(){const panel=selected(),count=Number(quantity.value);document.querySelector('#selected-name').textContent=panel.dataset.name;document.querySelector('#selected-duration').textContent=panel.dataset.duration;document.querySelector('#total').textContent=quantity.checkValidity()&&count>=1?'$'+count*Number(panel.dataset.price):'—';save.disabled=!quantity.checkValidity()||count<1;feedback.textContent='No booking or payment is created.'}
document.querySelectorAll('[data-hs-tab]').forEach(button=>button.addEventListener('click',()=>queueMicrotask(update)));
new MutationObserver(update).observe(document.querySelector('nav'),{subtree:true,attributes:true,attributeFilter:['aria-selected']});
quantity.addEventListener('input',update);quantity.addEventListener('change',update);
const instance=HSInputNumber.getInstance('#quantity');instance.on('change',update);
save.addEventListener('click',()=>{if(!quantity.reportValidity())return;const panel=selected();feedback.textContent=`Saved locally: ${panel.dataset.name}, ${quantity.value} people, $${Number(quantity.value)*Number(panel.dataset.price)} materials estimate.`;save.disabled=true});update();

代码参考

  • 使用 preline/non-auto 中的具名导出。
  • 带版本号的插件子路径 .mjs 文件不会导出默认类。
  • 输入变更事件和插件变更回调都会更新摘要。

完整的原创响应式布局

在原生标签页和数字输入插件周围,点缀装饰性的版画、陶土与绘图插画。

css
html,body{margin:0;height:auto;min-height:0}body{background:#f7f8fb;font-family:ui-sans-serif,system-ui,sans-serif;color:var(--foreground)}button{cursor:pointer}button:disabled{cursor:default}.planner-grid{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:24px}.session-art{height:200px;position:relative;overflow:hidden;border-radius:12px 12px 0 0}.session-art i,.session-art b,.session-art span{display:block;position:absolute}.print{background:#e2e9f4}.print i{width:160px;height:140px;left:15%;top:45px;background:#2456a7;transform:rotate(-13deg)}.print b{width:150px;height:150px;right:14%;top:30px;background:#f0a979;border-radius:50%;mix-blend-mode:multiply}.print span{width:180px;height:8px;left:20%;top:160px;background:#f9f8ef;transform:rotate(-13deg)}.ceramics{background:#e8d9c8}.ceramics i{width:150px;height:100px;left:25%;top:65px;border-radius:15% 15% 50% 50%;background:#a87862}.ceramics b{width:150px;height:32px;border-radius:50%;left:25%;top:53px;background:#704a3d;box-shadow:inset 0 0 0 10px #bd8f78}.ceramics span{width:150px;height:12px;left:25%;top:171px;background:#c7b39e;border-radius:50%}.drawing{background:#e2e8de}.drawing i{width:160px;height:145px;left:23%;top:25px;background:#fffdf4;transform:rotate(8deg);border:1px solid #d6d8cb}.drawing b{height:90px;width:80px;left:33%;top:49px;border:2px solid #4d655b;transform:rotate(-18deg);border-radius:50% 50% 10% 10%}.drawing span{width:130px;height:7px;background:#ad754c;left:45%;top:145px;transform:rotate(-33deg)}@media(max-width:760px){.planner-grid{grid-template-columns:minmax(0,1fr)}.session-art{height:170px}}@media(max-width:360px){main{padding:14px!important}.session-art i,.session-art b,.session-art span{transform:scale(.8)}.session-art{height:150px}h1{font-size:26px!important}}

代码参考

  • 插画为原创 CSS,并设为 aria-hidden。
  • 此样式表位于 Tailwind 和 Preline 导入项之后。
04

Preline UI 设计系统 Agent 设置

实现起点

已针对原生 Preline 4.2.0 验证。上文提供了完整的标记、逻辑和 CSS。input.css 中的源文件路径假定全部四个源文件都位于项目根目录。

bash
# Create an empty directory and run:
npm init -y
npm install [email protected] [email protected] @tailwindcss/[email protected] esbuild
# Save the complete examples above as body.html, app.js and style.css.
# Create input.css with exactly:
# @import "tailwindcss" source(none);
# @import "./node_modules/preline/variants.css";
# @import "./node_modules/preline/css/themes/theme.css";
# @source "./body.html";
# @source "./app.js";
# @source "./node_modules/preline/dist/*.js";
# @import "./style.css";
npx @tailwindcss/cli -i input.css -o bundle.css --minify
npx esbuild app.js --bundle --format=iife --outfile=bundle.js
# Assemble the actual root document without placeholder markup:
node -e 'const f=require("fs");f.writeFileSync("index.html",`<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Studio planner</title><link rel="stylesheet" href="bundle.css"></head><body>${f.readFileSync("body.html","utf8")}<script src="bundle.js"></script></body></html>`)'
# Serve this directory with your existing static server.

适用于你项目的提示词

Agent 提示词
使用 Preline 4.2.0,从 preline/non-auto 导入具名 HSTabs 和 HSInputNumber,并显式初始化这两个插件。保留 Studio Saturday 的三个工作坊、1 到 6 人的数量范围,以及所选工作坊的材料费用。根据当前面板和人数计算总额;任一项发生变化后,都应使已保存的方案失效,并在本地保存前验证人数是否在有效范围内。包含所提供的 Tailwind 主题/变体设置和原创布局。不要将本地工作室方案转换为预约或付款确认。
05

Preline UI 设计系统:资源与范围

原生 Preline npm 4.2.0 和 Tailwind CSS 4.3.3。原创场次说明、插画和虚构的材料费用。保存操作仅写入本地页面状态;不会创建预约、付款,也不会发送外部消息。