ICEN UI 原语
Docs ⌘K

原语(统一抽象层)

所有 122 个组件共享同一套抽象:6 个交互基元 class(HTML 显式组合)与 --icen-* 原语变量层(CSS 自洽消费)。换原语只需覆盖少数变量,全局组件自动换肤。

现代:连续几何、轻盈材料、系统排版。中式:宋式器物、纤细边线、书卷排版与疏朗留白。 苏式:纪念建筑、方正构成、厚重秩序与结构投影。像素:整数网格、点阵字体、阶梯投影。 用顶部「原语」切换,配色主题独立保留;也可以进 「现代」原语工作室 实时调节并导出品牌配方。

四种原语,即刻体验真实组件

选择一组,整页随之切换。标题、输入、按钮与浮层使用同一套规则;之后仍可在顶栏单独换主题。

ICEN / MATERIAL STUDY

日常,自有分寸。

瓷白与柔光,轻盈的操作层。

在此输入,感受同一套组件的不同表达。

6 个交互基元composition API

用法(任选其一):

html
<button class="icen-btn icen-pressable icen-focus-ring">  <!-- 类组合,体积最小 --><button class="icen-btn">                  <!-- 自洽,CSS 引用 --icen-* 同一原语 -->

下方演示直接挂原语 class(不带任何组件 class),可见其承载的最小可识别交互:

.icen-pressable 可按压基元:hover 顶部高光、focus-visible 双层环、active 下陷、aria-busy 减淡、disabled 50% 透明。
.icen-control 表单控件 wrapper:hover 边框过渡、focus-within 内嵌阴影 + accent 3px 光晕、:invalid 错误态自动接管。
.icen-field 字段容器:label / hint / error 三段式纵向布局,配合 .control 使用。
.icen-lift 可交互卡片浮起:hover / focus-within 上移 1px + accent 边 + card 阴影。
hover 我浮起
.icen-surface-elevated 静态提升表面:surface 底 + line-soft 边 + card 阴影 + md 圆角,无需 hover 反馈。
静态浮起面板
.icen-focus-ring 显式聚焦环工具类:Tab 键聚焦时 ring-2 + offset-1 等价环。
--icen-* 原语 token变量层

所有组件消费这组原语变量;切换原语(如 data-icen-style="pixel")只覆盖这里的少数变量即可全局生效。

变量说明值(现代原语)
--icen-ring 聚焦环(focus-visible) 0 0 0 2px bg, 0 0 0 4px accent 50%
--icen-ring-soft 柔和聚焦环(嵌套元素) 0 0 0 3px accent 16%
--icen-hover-border 悬停边框过渡 accent 30% + line
--icen-disabled-opacity 禁用透明度 0.5
--icen-press 按下形变 translateY(1px) scale(.985)
--icen-control-focus-shadow 表单控件聚焦阴影 inset + 3px accent 14%
--icen-tx-fast 快速过渡 150ms ease-out
--icen-tx-normal 标准过渡 200ms ease-out
--icen-tx-slow 慢速过渡 300ms ease-out

中式原语的反馈覆盖示例:

css
:root[data-icen-style="chinese"] {  --icen-press: scale(.995);  --icen-hover-border: var(--icen-token-line);  --icen-duration-normal: 240ms;  /* 全部组件自动获得安静的按压、边界与节奏 */}
组件契约约定
状态命名
.is-loading / .is-error / .is-disabled / .is-open / .is-selected / .is-focused / .is-active
aria 等价
[aria-busy=true]↔is-loading、[data-icen-invalid=true]↔is-error、[aria-disabled=true]/[data-icen-disabled]↔is-disabled、[aria-expanded=true]↔is-open、[aria-selected=true]/[aria-current=page]↔is-active
颜色纪律
仅 --icen-token-success / -warning / -error / -info / -accent 五个语义色
间距 / 字号 / 控件高度
--icen-density-space-* / --icen-density-font-size-* / --icen-density-input-height-*
圆角 / 阴影
--icen-radius-* / --icen-token-shadow-*
z-index
--icen-z-base/raised/sticky/chrome/toast/banner/dialog/popover/tooltip
事件体系手势 × 协议 × 策略

组件事件收敛为三层:

  • 手势层:任意容器挂 data-icen-gestures 即开通 icen:click / dblclick / contextmenu / longpress / text-select / swipe-* 归一化手势事件。
  • 协议层:全部 CustomEvent(bubbles + composed + cancelable),detail 统一 { source, originalEvent, x, y, text? };组件作者派发一律走 emitIcen 唯一派生口。
  • 策略层:setEventPolicy 一处赋予 / 覆盖 / 禁用全站默认行为。

绑定收敛为一个入口 onIcen:类型推断(IcenEventMap 注册表)+ 选择器委托 + 子树限定, 返回解绑函数,React / Vue / 原生同写法。领域事件(icen:chart-* / icen:ai-*)与手势层互补不变。

js
import { initGestures, onIcen, setEventPolicy, emitIcen } from '@icen.ai/ui/behaviors/events';initGestures();   // 幂等,全局一次<!-- 任意容器开通手势(空格分隔) --><div class="icen-card" data-icen-gestures="click dblclick contextmenu text-select">…</div><!-- v0.10 新增 swipe(触屏滑动):48px 阈值 + 主轴判定,不吞垂直滚动、与 click 消歧共存 --><div class="icen-card" data-icen-gestures="swipe" id="demo-swipe">左右滑动我</div><script>onIcen('icen:swipe-left',  (e) => { /* 下一张 */ }, { within: document.querySelector('#demo-swipe') });onIcen('icen:swipe-right', (e) => { /* 上一张 */ }, { within: document.querySelector('#demo-swipe') });</script><!-- carousel 组件在触屏(pointer: coarse)下自动开通滑动翻页,无需手写 --><!-- 触屏目标尺寸底线:pointer: coarse 下交互基元自动 ≥40px(WCAG 2.5.5 工程折中) -->// 绑定:一个入口,三种形态(类型安全,返回解绑函数)onIcen('icen:text-select', (e) => console.log('划词:', e.detail.text));onIcen('icen:chart-click', '.icen-chart', (e) => …);          // 选择器委托onIcen('icen:upload', (e) => …, { within: formEl });     // 子树限定// React:useEffect(() => onIcen('icen:tab-change', h), [])   // 直接 return// Vue:  onUnmounted(onIcen('icen:tab-change', h))// 策略层:一处赋予全站默认行为setEventPolicy('icen:contextmenu', (e) => openMyMenu(e.detail.x, e.detail.y));setEventPolicy('icen:dblclick', null);   // 禁用某类默认// 组件作者:派发自定义事件走唯一派生口(勿裸写 new CustomEvent)emitIcen(el, 'icen:my-change', { value });

活演示 —— 对下面卡片单击 / 双击 / 右键 / 长按 / 划词:

手势试验田

这是一段可以划选的文本——试试单击、双击、右键、长按或划选。

等待手势…