ranui
一个建立在原生自定义元素之上的 UI 组件库。每个组件都是一个 <r-*> 标签,所以在 React、Vue、
Svelte、Solid、Astro 乃至一个纯 HTML 文件里,用法完全一样:不需要适配层,也不用操心框架版本。
TypeScript 类型、基于设计令牌的明暗主题、Shadow DOM 封装和服务端渲染都是内置的。
v0.5.0-alpha.7MITesm · cjs · iifepackages/ranui
- ranui 仍处于 alpha 阶段,版本之间可能有破坏性变更。请锁定具体版本号,升级前先读 更新日志。
安装
npm install ranui<!-- 或者直接用 CDN,不需要构建步骤 -->
<script src="https://unpkg.com/ranui/dist/umd/index.umd.cjs"></script>使用
引入即完成注册,之后写标签就行。
import 'ranui'; // 全部组件
import 'ranui/button'; // 或只要一个<r-button type="primary">部署项目</r-button>在任何框架里写的都是同一个标签,差别只在各框架怎么传值、怎么绑事件,这部分 编码规范里有完整说明:
<script src="https://unpkg.com/ranui/dist/umd/index.umd.cjs"></script>
<body>
<r-button>Button</r-button>
</body>import 'ranui';
export const App = () => <r-button type="primary">部署</r-button>;
// 复杂值和事件监听要通过 ref 传,见编码规范。<template>
<r-button type="primary" @click="deploy">部署</r-button>
</template>
<!-- 需要在构建配置的 compilerOptions.isCustomElement 里放行 `r-` 前缀。 -->import 'ranui';
const button = document.createElement('r-button');
button.textContent = '部署';
document.body.appendChild(button);入口
每个入口只注册它名字所指的那部分。页面如果只需要主题,就不会把整个组件库一起打进去。
| 引入 | 内容 |
|---|---|
ranui |
全部组件 |
ranui/<component> |
单个组件,如 ranui/button、ranui/select |
ranui/theme |
明暗主题与令牌覆盖;不含元素 |
ranui/i18n |
翻译引擎;不含元素 |
ranui/fonts |
自托管的 Geist Sans + Geist Mono |
ranui/style |
样式表,供构建工具没有自动引入时使用 |
ranui/builder |
带细粒度响应式的链式 DOM 构建器 |
ranui/ssr、ranui/ssr-stream |
服务端渲染 |
ranui/testing |
在测试中进入 closed shadow root 的助手 |
ranui/typings |
JSX / TS 环境类型声明 |
组件
共 40 个元素。每个元素的属性(attribute / property)、事件、插槽和 ::part() 名称,都列在
元素 API 参考里。
通用:Button 按钮 · Icon 图标 · Loading 加载中
数据录入:Input 输入框 · CheckBox 多选框 · Select 选择框 · ColorPicker 颜色选择器 · Attachments 附件条 · VoiceButton 语音按钮 · 表单
数据展示:Card 卡片 · Section 区块 · Tabs 标签页 · Image 图片 · Progress 进度条 · Radar 雷达图 · Player 播放器 · Preview 预览 · Glass 毛玻璃 · Scratch 刮刮卡 · StateDot 状态点 · DisclosureRow 折叠行
内容渲染:Markdown 富文本 · Math 数学公式 · Mermaid 图表
AI 与对话:Conversation 对话 · Reasoning 思维链 · ToolCard 工具卡片 · TokenMeter 上下文用量
浮层与反馈:Modal 对话框 · Popover 气泡卡片 · Dropdown 下拉面板 · Message 全局提示 · Skeleton 骨架屏
导航:Router 路由 · Route 路由出口 · Link 链接
基础能力:Theme 主题系统 · ThemeSwitch 主题切换 · i18n 国际化
有五个元素没有独立页面,因为它们只会出现在另一个组件内部:<r-option>(Select)、
<r-tabs>(Tabs)、<r-img>(Image)、<r-dropdown-item>(Dropdown)、
<r-content>(Popover)。它们和其他元素一样都在 API 参考里。
实时示例
自定义样式
组件渲染在 closed shadow root 里,页面 CSS 进不去,选择器也穿不透。想定制样式有四条路,按推荐顺序排列如下。
1. 设计令牌(CSS 自定义属性)。它们能穿过 shadow 边界继承下去,所以设在 :root、外层容器或元素本身上都有效:
<r-progress
percent="0.7"
type="drag"
style="--ran-progress-track-background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f)"
></r-progress>2. ::part():做令牌覆盖不到的结构性调整 · 3. sheet 属性:把 CSS 注入 shadow root ·
4. 插槽内容:它本来就留在你的文档里,页面 CSS 直接生效。
令牌名称见设计系统,怎么取舍见 设计规范,机制细节见 编码规范。
事件
组件派发的是 CustomEvent,数据放在 detail 里。请把监听器绑在元素本身上:事件是否冒泡由各组件自行决定,API 参考里逐个标注了。
<r-select id="env"></r-select>
<script>
document.getElementById('env').addEventListener('change', (event) => {
console.log(event.detail.value);
});
</script>onchange="…" 属性写法和 el.onchange = … 赋值写法也都能用(它们本来就是普通 DOM 元素),但这两种写法只能挂一个处理函数,也用不了捕获阶段,所以首选 addEventListener。
接下来读什么
| 如果你想…… | 读 |
|---|---|
| 查某个元素的确切接口 | 元素 API |
| 知道该用哪个令牌、为什么 | 设计系统 |
| 做出像一套系统的界面 | 设计规范 |
| 把 ranui 正确接进应用 | 编码规范 |
| 接入明暗主题,或整体换皮 | 主题系统 |
| 把界面翻译成别的语言 | i18n 国际化 |
| 在服务端渲染 | 服务端渲染 |
| 不用框架写响应式视图 | Builder 构建器 |
| 升级前看看改了什么 | 更新日志 |
兼容性
支持所有现代浏览器:组件库建立在 Custom Elements v1、Shadow DOM v1 和 CSS 自定义属性之上。 不支持 Internet Explorer。

贡献者
延伸阅读
这个库所依据的标准:W3C · ECMA · RFC · Can I use
值得常备的设计参考:Checklist Design · Laws of UX · Geist · Ant Design · Element UI · Animista · WebGradients