# 瑚琏 Hulian (`@hulianui/ui`) — 全量组件使用文档 > 颜值 + 好用的 React 设计系统(Base UI + Tailwind v4 + Motion) · v0.5.0 · 353 个组件文档(自包含,供 AI 一次性消费) 安装 `npm i @hulianui/ui @hulianui/tokens`(tokens 提供主题 CSS,必装);所有组件从根 barrel 导入 `import { X } from "@hulianui/ui"`。 # ━━━━━━━━ 布局 ━━━━━━━━ # AdminLayout > 中后台骨架 · 侧栏(品牌+NavMenu可折叠) + 顶栏(折叠/面包屑/扩展区) + 多页签导航(开/切/关·关闭其他/全部·受控接路由或菜单点击自动维护) + 内容区(复用 NavMenu/ScrollArea/Popover·企业应用外壳) · layout/container ## 何时用 要快速搭一个完整中后台外壳——侧栏菜单 + 顶栏 + 多页签 keep-alive 导航开箱即用——用 AdminLayout,只需喂 `menuItems` 和 `children`。若想自己掌控每一块布局(不要内置页签逻辑、要更原子的拼装),下沉到 [Layout](https://hulianui.haloritual.com/components/layout)。 ## 导入 ```ts import { AdminLayout } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | menuItems* | `NavMenuNode[]` | — | 侧边菜单数据(复用 NavMenu)。 | | selectedKey | `string` | — | 受控菜单选中 key。 | | defaultSelectedKey | `string` | — | 非受控初始选中 key。 | | openKeys | `string[]` | — | 受控展开的子菜单 key。 | | defaultOpenKeys | `string[]` | — | 非受控初始展开。 | | collapsed | `boolean` | — | 受控侧栏折叠态。 | | defaultCollapsed | `boolean` | — | 非受控初始折叠态。 | | showTabs | `boolean` | `true` | 是否显示多页签条。 | | tabs | `AdminTab[]` | — | 受控页签列表;不传则由菜单点击自动维护(非受控)。 | | activeKey | `string` | — | 受控当前激活页签 key。 | | defaultActiveKey | `string` | — | 非受控初始激活页签(亦决定首屏自动打开的页签)。 | | fitViewport | `boolean` | `true` | 是否自占满视口高度。整页应用骨架保持 true(固定 100dvh、内容区内部滚动);嵌入有固定高度的容器预览时置 false,改用 `h-full` 跟随父容器。 | | className | `string` | — | 根容器类名。 | | contentClassName | `string` | — | 内容区类名。 | `AdminTab`:`{ key: string; label: ReactNode; closable?: boolean }`,`closable` 缺省为「打开页签 >1 时可关,最后一个不可关」。 ## Events | 事件 | 类型 | 说明 | |------|------|------| | onMenuSelect | `(key: string, item: NavMenuItem) => void` | 点击菜单叶子项触发。 | | onOpenChange | `(openKeys: string[]) => void` | 子菜单展开变化回调。 | | onCollapsedChange | `(collapsed: boolean) => void` | 侧栏折叠变化回调。 | | onTabChange | `(key: string) => void` | 切换页签回调。 | | onTabClose | `(key: string) => void` | 关闭页签回调。 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 主内容(当前激活页内容,由上层按 activeKey 决定)。 | | logo | `ReactNode` | 品牌区(展开态)。 | | logoCollapsed | `ReactNode` | 品牌区(收起态,默认复用 logo)。 | | breadcrumb | `ReactNode` | 顶栏面包屑区。 | | headerExtra | `ReactNode` | 顶栏右侧扩展区(用户菜单 / 通知 / 主题切换等)。 | ## 示例 ```tsx const [active, setActive] = useState("dashboard"); 瑚琏 Admin} logoCollapsed={} defaultActiveKey="dashboard" defaultSelectedKey="dashboard" defaultOpenKeys={["users"]} onTabChange={setActive} breadcrumb={首页 / {active}} headerExtra={} > ``` ## 禁忌 / 坑 - **`fitViewport` 决定撑高方式**:整页用默认 `true`(自钉 100dvh),别再外面套 `h-dvh` wrapper;嵌入文档示例卡等固定高度容器时务必传 `false`,否则整页滚动而非内容区滚动。详见 [[hulian-adminlayout-fitviewport]]。 - **页签受控/非受控二选一**:不传 `tabs` 时页签由菜单点击自动维护(非受控);一旦传 `tabs` 即受控,须自行配 `onTabChange`/`onTabClose` 维护数组与 `activeKey`。 - `children` 只渲染「当前激活页」,keep-alive 的多页内容缓存需上层按 `activeKey` 自行管理,组件不替你缓存各页 DOM。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # AspectRatio > 比例容器 · CSS aspect-ratio 锁宽高比 + 图片/视频自动铺满(零依赖·RSC) · layout/container ## 何时用 要把图片/视频/卡片锁成固定宽高比(16/9、1/1、4/3)、随宽度自适应高度且不抖动时用。它只锁比例(纯 CSS、可 RSC);要按容器宽度重排布局用 [Viewport](https://hulianui.haloritual.com/components/viewport),要把固定设计稿等比缩放铺满用 [FitScreen](https://hulianui.haloritual.com/components/fit-screen)。 ## 导入 ```ts import { AspectRatio } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | ratio | `number` | `1` | 宽高比(宽 / 高),如 `16/9`、`1`、`4/3`。 | 继承 `HTMLAttributes`。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 子元素(通常 img/video),自动铺满容器。 | ## 示例 ```tsx // 16:9 媒体容器,宽度由外层决定,高度自动
...
``` ```tsx // 1:1 头像/缩略图
``` ## 禁忌 / 坑 - **`ratio` 是数字不是字符串**:传 `16 / 9` 这种除式或 `1.7778`,不要传 `"16/9"`。 - **宽度由外层给**:容器宽度自适应父级,高度据 ratio 推导;外层不限宽时会撑满可用宽度。子元素无需自己写 `w-full h-full`,组件已让其铺满。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # Container > 内容容器 · 限制最大宽度(sm/md/lg/xl/full) + 居中 + 左右安全内距 + as 多态(收口全站 mx-auto max-w-Nxl px-6 样板·零依赖·RSC) · layout/container ## 何时用 页面/区块需要限制内容最大宽度并水平居中、留出左右安全内距时用 Container——收口全站重复的 `mx-auto max-w-Nxl px-6` 样板。它只管宽度约束与居中,不排列子项;子项的方向/间距交给 [Layout](https://hulianui.haloritual.com/components/layout) 或 Stack。需要整页骨架(侧栏+顶栏+多页签)用 [AdminLayout](https://hulianui.haloritual.com/components/admin-layout)。 ## 导入 ```ts import { Container } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | size | `"sm" \| "md" \| "lg" \| "xl" \| "full"` | `"xl"` | 最大宽度档:sm=2xl / md=3xl / lg=4xl / xl=5xl / full=不限 | | padded | `boolean` | `true` | 是否水平居中并加左右安全内距 | | as | `ElementType` | `"div"` | 渲染标签(语义/布局解耦,如 section/main/article) | 其余 `HTMLAttributes` 属性(className/style 等)透传。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 子内容 | ## 示例 ```tsx // 各档最大宽度 内容限制在 4xl 宽度内并居中 // 用语义标签承载 {children} ``` ## 禁忌 / 坑 暂无已知坑。`size` 档位映射的是 Tailwind `max-w-*`(sm=2xl 而非 sm),勿按字面理解。候选坑列表(affix/dialog-portal/dnd-kit/flex-mx-auto/recharts/scrollspy/sticky-glass/vant-toast)均为各自具体场景的容器问题,与本通用宽度容器无直接关系,已剔除。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) # Divider > 带文字分隔 · orientation 左/中/右 + dashed/plain + 行内垂直(纯皮肤·零依赖·RSC·与 Separator 互补) · layout/arrange ## 何时用 需要在分隔线中嵌入文字标题(如「最近更新」「更多」),或要虚线样式、行内竖线时用 Divider。纯几何分隔、无文字、要 ARIA `role="separator"` 语义则用 [Separator](https://hulianui.haloritual.com/components/separator)——二者互补:Divider 偏内容装饰,Separator 偏结构语义。 ## 导入 ```ts import { Divider } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | type | `"horizontal" \| "vertical"` | `"horizontal"` | 方向。vertical 为行内分隔(嵌在一行文本/元素之间) | | orientation | `"left" \| "center" \| "right"` | `"center"` | 嵌入文字的水平位置(仅 horizontal + 有文字时生效) | | dashed | `boolean` | `false` | 虚线 | | plain | `boolean` | `false` | 文字常规字重(默认加粗一档) | | className | `string` | — | 额外类名 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 嵌入分隔线中的文字;不传则为纯分隔线 | ## 示例 ```tsx // 纯分隔线

上段内容

下段内容

// 带文字 + 偏左 最近更新 // 行内竖线
文档 组件
``` ## 禁忌 / 坑 暂无已知坑。`orientation` 仅在 `type="horizontal"` 且有 children 时生效;`type="vertical"` 用作行内竖线,需放在 flex 行内且依赖父级行高。 ## 相关 [Stack](https://hulianui.haloritual.com/components/stack) · [Grid](https://hulianui.haloritual.com/components/grid) · [Spacer](https://hulianui.haloritual.com/components/spacer) · [Separator](https://hulianui.haloritual.com/components/separator) · [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) # FitScreen > 大屏适配 · 固定设计尺寸(默认 1920×1080)等比缩放铺满父容器并居中 + fit/cover/stretch 三模式(纯函数 computeFit 可测·ResizeObserver 监听·SSR 安全·数据可视化大屏刚需) · layout/container ## 何时用 按固定设计稿(如 1920×1080)画好的大屏内容,要整体等比缩放铺满任意父容器并居中时用——典型是数据可视化驾驶舱。它缩放的是「固定设计尺寸」;要按容器宽度重排(不缩放、内容自适应)用 [Viewport](https://hulianui.haloritual.com/components/viewport),只锁单元素宽高比用 [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio)。 ## 导入 ```ts import { FitScreen, computeFit } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | designWidth | `number` | `1920` | 设计稿宽。 | | designHeight | `number` | `1080` | 设计稿高。 | | mode | `"fit" \| "cover" \| "stretch"` | `"fit"` | fit=取 min(等比不裁切,四周可能留黑边);cover=取 max(等比铺满,可能裁切);stretch=非等比拉满(可能变形)。 | | className | `string` | — | 外层容器类名。 | `computeFit(input: FitInput)`:纯函数(`{ outerW, outerH, designW, designH, mode }` → 缩放结果),可单测,组件内部据 ResizeObserver 测量后调用它。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children* | `ReactNode` | 你的固定设计尺寸大屏内容。 | ## 示例 ```tsx // 1920×1080 驾驶舱,等比不裁切铺满父容器 {/* 你的大屏内容,按 1920×1080 绝对布局 */} ``` ```tsx // 铺满不留黑边(可能裁切边缘) ``` ## 禁忌 / 坑 - **内部用 transform: scale 缩放**:headless/CDP 截图工具下,缩放后的几何坐标可能与真实点击错位,验证视觉/交互需注意(参见 [[recharts-headless-screenshot-blank-clippath-animation-starved]]、[[turbopack-dev-cold-route-blank-cdp-screenshot-warm-first]] 这类 headless 验证坑),FitScreen 下真实 click 失准时改用 `dispatchEvent`。 - **ref + style 写入的脱档崩溃**:组件在 effect 里向 ref 写 transform,遇 StrictMode 双挂载/``/Offscreen 重连时 `ref.current` 可能 truthy 但 `.style` 已脱档而崩 —— 见 [[react-offscreen-reconnect-detached-ref-style-crash]],写前应 `if (!el?.style) return` 把守。 - 设计稿尺寸(designWidth/Height)须与 children 的实际绝对布局尺寸一致,否则缩放比算错、内容溢出或留白。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) # Grid > 栅格布局 · grid 原语 cols/gap + GridItem 跨列跨行(零依赖·RSC) · layout/arrange ## 何时用 需要二维行列对齐——固定列数、卡片网格、跨列跨行的局部布局时用 Grid,配 GridItem 控制单元的 `colSpan`/`rowSpan`。只需单轴线性排列(一行或一列)用 [Stack](https://hulianui.haloritual.com/components/stack) 更轻;只想插入定向留白用 [Spacer](https://hulianui.haloritual.com/components/spacer)。 ## 导入 ```ts import { Grid, GridItem } from "@hulianui/ui" ``` ## Props ### Grid | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | cols | `number \| ResponsiveCols` | `1` | 列数。数字=固定列数(任意值,走 inline style);`{base,sm,md,lg}`=响应式(静态类) | | rows | `number` | — | 行数(不填则按内容自动) | | gap | `number` | `0` | 行列间距(× 0.25rem) | | colGap | `number` | — | 列间距,覆盖 gap(× 0.25rem) | | rowGap | `number` | — | 行间距,覆盖 gap(× 0.25rem) | | inline | `boolean` | `false` | 用 inline-grid 而非 grid | | as | `ElementType` | `"div"` | 渲染的元素标签 | ### GridItem | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | colSpan | `number` | — | 跨列数 | | rowSpan | `number` | — | 跨行数 | | as | `ElementType` | `"div"` | 渲染的元素标签 | 两者其余 `HTMLAttributes` 属性透传。 ## Slots ### Grid | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 子元素 | ### GridItem | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 子元素 | ## 示例 ```tsx // 3 列等宽网格 {["1", "2", "3", "4", "5", "6"].map((n) => {n})} // 跨列 跨 2 列 3 ``` ## 禁忌 / 坑 暂无已知坑。`cols` 传数字走 inline style 支持任意列数;传 `{base,sm,md,lg}` 才走静态响应式类。候选坑 body-grid-place-items-center / grid-card-button-tail-row / nested-collapsible-css-grid-rows 均针对各自具体布局场景,与本通用栅格原语无直接关系,已剔除。 ## 相关 [Stack](https://hulianui.haloritual.com/components/stack) · [Spacer](https://hulianui.haloritual.com/components/spacer) · [Divider](https://hulianui.haloritual.com/components/divider) · [Separator](https://hulianui.haloritual.com/components/separator) · [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) # Layout > 整页布局 · 复合 Header/Sider/Content/Footer + Sider 可折叠(受控/断点/trigger) + 宽度过渡(零依赖·尽量 RSC·复用 ScrollArea) · layout/container ## 何时用 需要 Header/Sider/Content/Footer 这种通用页面骨架、且自己掌控菜单与页签逻辑时用 Layout(更原子、更自由)。若要开箱即用的中后台外壳(品牌 + NavMenu + 多页签 keep-alive 已内置),直接用 [AdminLayout](https://hulianui.haloritual.com/components/admin-layout),它就是基于本组件的成品装配。 ## 导入 ```ts import { Layout, LayoutHeader, LayoutSider, LayoutContent, LayoutFooter } from "@hulianui/ui" ``` ## Props ### Layout(也可用 `Layout.Sider` 等点访问) | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | hasSider | `boolean` | 自动探测 | 强制横向(含侧栏)布局。缺省按直接子元素是否含 `Layout.Sider` 判定:含则横向 row,否则纵向 col。异步/条件渲染 Sider 时用它兜底。 | 继承 `HTMLAttributes`。 ### LayoutHeader | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | sticky | `boolean` | `false` | 吸顶(sticky top-0)。 | ### LayoutSider | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | width | `number` | `240` | 展开态宽度(px)。 | | collapsedWidth | `number` | `64` | 收起态宽度(px),留出 icon-only 菜单。 | | collapsible | `boolean` | `false` | 是否可折叠(显示底部 trigger 折叠按钮)。 | | collapsed | `boolean` | — | 受控收起态。传入即受控,须配合 onCollapse 回写。 | | defaultCollapsed | `boolean` | `false` | 非受控初始收起态。 | | breakpoint | `"sm" \| "md" \| "lg" \| "xl" \| "2xl" \| number` | — | 响应式断点:视口 ≤ 该宽度自动收起,> 时展开。 | ### LayoutContent / LayoutFooter 纯 `HTMLAttributes`,无专属 prop。 ## Events ### LayoutSider | 事件 | 类型 | 说明 | |------|------|------| | onCollapse | `(collapsed: boolean, type: "clickTrigger" \| "responsive") => void` | 收起态变化回调(点 trigger 或命中断点时触发)。 | ## Slots ### LayoutSider | 插槽 | 类型 | 说明 | |------|------|------| | trigger | `ReactNode` | 底部折叠触发器内容。`undefined`=默认 chevron;`null`=不渲染触发器(即便 collapsible);传节点=自定义触发器内容(仍由本件包裹为可点按钮)。 | ## 示例 ```tsx // 经典:左 Sider(可折叠)+ 右(Header 顶 / Content 中 / Footer 底) {/* 品牌 + 菜单 */} 顶栏 内容 底栏 ``` ```tsx // 受控折叠:自管 collapsed,trigger/断点回写本地态后驱动菜单 mode function Shell() { const [collapsed, setCollapsed] = useState(false); return ( setCollapsed(c)} > ); } ``` ## 禁忌 / 坑 - **受控/非受控二选一**:`Layout.Sider` 传了 `collapsed` 即进入受控,必须配 `onCollapse` 回写,否则 trigger/断点点了不动;只想非受控用 `defaultCollapsed`。 - **横/纵布局靠子元素探测**:嵌套子 `Layout` 是否横排取决于其直接子是否含 `Layout.Sider`。Sider 异步/条件渲染、或被包装进自定义组件(如 `` 内部才渲染 `Layout.Sider`)时探测会落空,须显式给 `hasSider`。 - 收起态切窄宽用菜单的 `mode="collapsed"`(dogfood NavMenu 自带 icon-only 轨),不要手搓「窄宽裁切 label」。 ## 相关 [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # Masonry > 瀑布流布局 · 确定性 round-robin 分列(item[i]→第 i%列·SSR 安全·顺序稳定·非 CSS columns 抖动) + 响应式列数(base/sm/md/lg·首帧 base 防 hydration mismatch·挂载后 matchMedia 调整) + 列内外统一 gap(泛型·token 主题) · layout/container ## 何时用 要把一组不等高卡片(图片墙、动态流、产物画廊)铺成参差瀑布流、且要 SSR 安全 + 顺序稳定时用。它走确定性 round-robin 分列(非原生 CSS columns),避免填谷重排导致的顺序脱节与 hydration mismatch。要等比锁单元素用 [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio),要规整等宽布局直接用 grid。 ## 导入 ```ts import { Masonry } from "@hulianui/ui" ``` ## Props `Masonry` 泛型组件。 | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | items* | `T[]` | — | 数据源,按源顺序 round-robin 分列。 | | columns | `number \| { base?: number; sm?: number; md?: number; lg?: number }` | `3` | 列数。传数字固定;传对象按断点响应式(base 为 SSR/首帧值,挂载后 matchMedia 切换)。 | | gap | `number` | `16` | 列间 & 列内 item 间距(像素)。 | | className | `string` | — | 根容器类名。 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | renderItem* | `(item: T, index: number) => ReactNode` | 渲染函数:渲染单个 item,返回节点会被包进列内格子。 | ## 示例 ```tsx // 固定 3 列 } /> ``` ```tsx // 响应式列数(base 为首帧/SSR 值) {photo.alt}} /> ``` ## 禁忌 / 坑 - **响应式 columns 首帧用 base**:传对象时 SSR/首帧固定用 `base`,挂载后才按 `matchMedia` 切到当前断点列数——这是为防 hydration mismatch 的刻意设计,别期望首屏就拿到 lg 列数。 - **不做等高填谷**:round-robin 是纯下标取模(`item[i] → 第 i%列`),换来 SSR 一致与顺序稳定,代价是各列高度可能略不平衡;需要严格等高填谷的场景本组件不适用。 - 断点(sm/md/lg=640/768/1024)与 Tailwind 默认对齐,命中最大满足断点否则回落 base。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) # Resizable > 拖拽分栏 · 复合 PanelGroup/Panel/Handle + 横竖向 + min/max + 键盘微调(零依赖·role=separator) · layout/container ## 何时用 要让用户拖动手柄实时改变相邻面板尺寸(IDE 三栏、聊天列表+详情等)时用。它是用户可交互调宽的分栏;若只是按容器宽度自动重排布局用 [Viewport](https://hulianui.haloritual.com/components/viewport),整页固定骨架用 [Layout](https://hulianui.haloritual.com/components/layout)。 ## 导入 ```ts import { ResizablePanelGroup, ResizablePanel, ResizableHandle, applyResize, splitEqually } from "@hulianui/ui" ``` ## Props ### ResizablePanelGroup | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | direction | `"horizontal" \| "vertical"` | `"horizontal"` | horizontal=面板横排(分隔符竖直);vertical=面板竖排(分隔符水平)。 | | sizes | `number[]` | — | 受控尺寸(百分比数组,一项一面板),须配 onSizesChange。 | | defaultSizes | `number[]` | 均分 | 非受控初始尺寸;缺省按面板数均分。 | 继承 `HTMLAttributes`(除 onChange)。 ### ResizablePanel | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | min | `number` | `10` | 最小尺寸百分比下限。 | | max | `number` | `100` | 最大尺寸百分比上限。 | 继承 `HTMLAttributes`。 ### ResizableHandle | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | keyboardStep | `number` | `5` | 键盘方向键每次微调的百分点(role=separator,可聚焦键控)。 | 继承 `HTMLAttributes`(除 aria-orientation)。 ### 工具函数 - `splitEqually(n)` — 生成 n 个面板均分的尺寸数组。 - `applyResize(...)` — 受控模式下据拖拽增量计算新尺寸数组(含 min/max 钳制)。 ## Events ### ResizablePanelGroup | 事件 | 类型 | 说明 | |------|------|------| | onSizesChange | `(sizes: number[]) => void` | 尺寸变化回调。 | ## Slots ### ResizablePanelGroup | 插槽 | 类型 | 说明 | |------|------|------| | children* | `ReactNode` | Panel 与 Handle 交替排列。 | ## 示例 ```tsx // 横向三栏:文件树 / 编辑器 / 预览 ``` ```tsx // 竖向两栏 ``` ## 禁忌 / 坑 - **Panel 与 Handle 必须交替排列**:每两个 `ResizablePanel` 之间放一个 `ResizableHandle`,组件按手柄两侧定位相邻面板做尺寸再分配;漏放或多放会错位。 - **受控时尺寸数组长度须等于面板数**:`sizes`/`defaultSizes` 是百分比数组,一项对应一面板;用 `splitEqually(n)` 起步、`applyResize` 算增量更稳。 - 受控模式记得在 `onSizesChange` 回写 `sizes`,否则拖不动。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # ScrollArea > 滚动区 · Base UI 自定义细滚动条 + 竖/横/双向 · layout/container ## 何时用 需要在限定高/宽的区域内滚动、且想要跨平台一致的细滚动条(替代浏览器默认粗条)时用。它只管「滚动条样式 + 方向」;要拖拽改变区域大小用 [Resizable](https://hulianui.haloritual.com/components/resizable),要按设备宽度做容器查询用 [Viewport](https://hulianui.haloritual.com/components/viewport)。 ## 导入 ```ts import { ScrollArea } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | orientation | `"vertical" \| "horizontal" \| "both"` | `"vertical"` | 滚动方向;`both` 时双向滚动条 + corner。 | | className | `string` | — | 限高/限宽由消费者经此给 Root(如 `h-48` / `w-64`),否则不会出现滚动。 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 滚动内容。 | ## 示例 ```tsx // 竖向滚动:必须经 className 给出限高 {/* 长内容 */} ``` ```tsx // 横向滚动
{/* 横排卡片 */}
``` ## 禁忌 / 坑 - **不给限高/限宽就不滚**:组件不自带尺寸,必须经 `className` 给 Root 限定 `h-*` / `w-*`(横向则限 `w-*`),否则内容撑开容器、滚动条永不出现。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [Viewport](https://hulianui.haloritual.com/components/viewport) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # Separator > 分隔线 · Base UI role=separator + 横/竖几何 · layout/arrange ## 何时用 需要一条带 ARIA `role="separator"` 语义的纯几何分隔线(横线或竖线)时用 Separator——结构性分组、菜单/列表分段。要在分隔线里嵌文字、虚线或左右偏移文字标题则用 [Divider](https://hulianui.haloritual.com/components/divider)。 ## 导入 ```ts import { Separator } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | orientation | `"horizontal" \| "vertical"` | `"horizontal"` | 水平(h-px 横线)/ 垂直(w-px 竖线,需父容器有高度) | | className | `string` | — | 额外类名 | ## 示例 ```tsx // 水平分隔

瑚琏设计系统

吸取式聚合组件库

// 垂直分隔(父容器须有高度)
文档 组件
``` ## 禁忌 / 坑 暂无已知坑。`orientation="vertical"` 的竖线靠 `w-px` + 高度撑开,父容器必须有确定高度(如 flex 行 `h-6`),否则竖线高度为 0 不可见。 ## 相关 [Stack](https://hulianui.haloritual.com/components/stack) · [Grid](https://hulianui.haloritual.com/components/grid) · [Spacer](https://hulianui.haloritual.com/components/spacer) · [Divider](https://hulianui.haloritual.com/components/divider) · [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) # Spacer > 间距 · x/y × 0.25rem 布局留白 + aria-hidden + RSC · layout/arrange ## 何时用 在两个相邻元素之间塞一段固定的定向留白(水平/垂直)时用 Spacer,自带 `aria-hidden` 不进无障碍树。若是给一整组子项统一加间距,优先用 [Stack](https://hulianui.haloritual.com/components/stack)/[Grid](https://hulianui.haloritual.com/components/grid) 的 `gap`(无需逐个插 Spacer);需要可见分隔线用 [Divider](https://hulianui.haloritual.com/components/divider)/[Separator](https://hulianui.haloritual.com/components/separator)。 ## 导入 ```ts import { Spacer } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | x | `number` | — | 水平间距(× 0.25rem,同 Tailwind spacing 刻度) | | y | `number` | — | 垂直间距(× 0.25rem) | | className | `string` | — | 额外类名 | ## 示例 ```tsx // 横向留白 A B // 纵向留白 ``` ## 禁忌 / 坑 暂无已知坑。`x`/`y` 是 Tailwind 刻度倍数(`x={8}` = 2rem)。容器为 flex 行时用 `x`、为 flex 列时用 `y`;方向与父容器主轴不匹配时留白不会生效。 ## 相关 [Stack](https://hulianui.haloritual.com/components/stack) · [Grid](https://hulianui.haloritual.com/components/grid) · [Divider](https://hulianui.haloritual.com/components/divider) · [Separator](https://hulianui.haloritual.com/components/separator) · [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) # Stack > 弹性布局 · flex 原语 direction/gap/align/justify/wrap + as 多态(零依赖·RSC) · layout/arrange ## 何时用 把一组子元素按单一主轴(横/纵)排开并统一间距时用 Stack——一维线性排列、需要 gap/对齐/换行控制的场景。需要二维行列对齐(同时控制列数与跨列跨行)改用 [Grid](https://hulianui.haloritual.com/components/grid);只想在两个元素间塞一段定向留白用 [Spacer](https://hulianui.haloritual.com/components/spacer)。 ## 导入 ```ts import { Stack } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | direction | `StackDirection \| ResponsiveDirection` | `"column"` | 主轴方向。传字符串=固定;传 `{base,sm,md,lg}`=按断点响应式 | | gap | `number` | `0` | 子项间距(× 0.25rem,同 Tailwind spacing 刻度) | | align | `"start" \| "center" \| "end" \| "stretch" \| "baseline"` | — | 交叉轴对齐 | | justify | `"start" \| "center" \| "end" \| "between" \| "around" \| "evenly"` | — | 主轴对齐 | | wrap | `boolean` | `false` | 是否换行(仅 row 有意义) | | inline | `boolean` | `false` | 用 inline-flex 而非 flex(随内容收缩、可与文字基线排列) | | as | `ElementType` | `"div"` | 渲染的元素标签 | `StackDirection = "row" \| "column"`;其余 `HTMLAttributes` 属性(className/style/事件等)透传。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 子元素 | ## 示例 ```tsx // 横向排列,间距 3 A B C // 两端对齐 ``` ## 禁忌 / 坑 暂无已知坑。`gap` 是 Tailwind 刻度倍数而非像素(`gap={3}` = 0.75rem);`wrap`/`justify` 仅在 `direction="row"` 下有实际意义。候选坑 multi-card-stack-trace / swiftui-text-css-font-stack 与本组件无关,已剔除。 ## 相关 [Grid](https://hulianui.haloritual.com/components/grid) · [Spacer](https://hulianui.haloritual.com/components/spacer) · [Divider](https://hulianui.haloritual.com/components/divider) · [Separator](https://hulianui.haloritual.com/components/separator) · [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) # Viewport > 响应式容器 · container-type 容器查询上下文 + web/平板/手机 预设宽度(可 width 覆盖) + 可选设备切换器(dogfood Segmented) · 内部组件用 @md/@5xl 等容器变体按【容器宽度】自适应而非页面视口(跨设备同套布局自动重排) · layout/container ## 何时用 要让同一套布局按「容器宽度」而非「页面视口」重排时用——内部子组件写 `@md:`/`@5xl:` 容器变体即可自适应,并能用内置设备切换器预览 web/平板/手机三态。它建立的是容器查询上下文 + 宽度边框;要锁宽高比用 [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio),要等比缩放固定设计稿用 [FitScreen](https://hulianui.haloritual.com/components/fit-screen)。 ## 导入 ```ts import { Viewport } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | device | `"web" \| "tablet" \| "phone"` | — | 设备预设宽度(受控):web 满宽自适应 / tablet 768px / phone 390px。 | | defaultDevice | `"web" \| "tablet" \| "phone"` | `"web"` | 非受控初始设备。 | | controls | `boolean` | `false` | 顶部显示设备切换器(dogfood Segmented)。 | | width | `number \| string` | — | 自定义宽度,覆盖 device 预设(数字=px 或任意 CSS 长度)。 | | name | `string` | — | 具名容器,用于 `@md/name:` 具名容器查询;缺省匿名容器(用 `@md:`)。 | | framed | `boolean` | `true` | tablet/phone 加设备感边框;web 恒细边框。 | | height | `number \| string` | 随内容 | 固定容器高度(数字=px 或 CSS)。 | | className | `string` | — | 根容器类名。 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onDeviceChange | `(device: "web" \| "tablet" \| "phone") => void` | 设备变化回调。 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children* | `ReactNode` | 容器内容,内部用 `@md:`/`@5xl:` 等容器变体按本容器宽度自适应。 | ## 示例 ```tsx // 设备切换器:点 web/平板/手机,看容器内布局重排 {/* 内部用 @md/@5xl 等容器变体即按容器宽度自适应 */}
``` ```tsx // 自定义宽度,不要设备边框 ``` ## 禁忌 / 坑 - **容器变体 ≠ 屏幕断点**:子组件要写 `@md:`/`@5xl:`(容器查询前缀),不是 Tailwind 默认的 `md:`/`5xl:`(页面视口断点);写错了响应的是浏览器窗口而非本容器宽度。 - 多个并存且要区分时用 `name` 建具名容器并以 `@md/name:` 命中,避免嵌套容器误命中最近祖先。 ## 相关 [Layout](https://hulianui.haloritual.com/components/layout) · [AdminLayout](https://hulianui.haloritual.com/components/admin-layout) · [ScrollArea](https://hulianui.haloritual.com/components/scroll-area) · [Resizable](https://hulianui.haloritual.com/components/resizable) · [AspectRatio](https://hulianui.haloritual.com/components/aspect-ratio) · [FitScreen](https://hulianui.haloritual.com/components/fit-screen) # ━━━━━━━━ 排版 ━━━━━━━━ # AnimatedGradientText > 渐变文字 · 行内 chart 渐变流动 + RSC · typography/text · #animated ## 何时用 给一小段行内文字加流动渐变着色,随文排版(inline),默认吃瑚琏 chart token。要文字内部极光/大标题质感用 [AuroraText](https://hulianui.haloritual.com/components/aurora-text)(二者都基于 chart 渐变,AuroraText 偏标题级面积、本组件偏行内嵌入);要横扫高光徽标用 [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)。 ## 导入 ```ts import { AnimatedGradientText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | colors | `string[]` | 瑚琏 chart token | 渐变停靠色数组 | | speed | `number` | `1` | 流动速度倍率 | 继承 `ComponentPropsWithoutRef<"span">`(除 `color`),如 `className` / `style`。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 要渲染的文字 | ## 示例 ```tsx 🎉 全新瑚琏组件库 ``` ## 禁忌 / 坑 - 行内 ``,靠字号/前景裁切显色,空内容或无字号无可见效果。 - 自定义 `colors` 用瑚琏 token 时须带 `--color-` 前缀才能在渐变里解析(见 hulian token 规范)。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # AnimatedShinyText > 高光文字 · 横扫高光 + 徽标气质 + RSC · typography/text · #animated ## 何时用 给小段文字加一道横扫高光,常用于 pill 徽标 / "Introducing" 提示条这类轻量营销点缀。要彩色极光渐变文字用 [AuroraText](https://hulianui.haloritual.com/components/aurora-text);要行内流动渐变用 [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text);普通文本用 [Text](https://hulianui.haloritual.com/components/text)。 ## 导入 ```ts import { AnimatedShinyText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | shimmerWidth | `number` | `100` | 高光带宽度(px) | 继承 `ComponentPropsWithoutRef<"span">`(`children` / `className` / `style` 等)。 ## 示例 ```tsx
✨ Introducing 瑚琏 Hulian
``` ## 禁忌 / 坑 - 高光靠遮罩横扫文字本体,需要文字有可见前景色才看得出来;放在过亮/过暗背景上高光带可能不明显,配合徽标容器(border + bg-surface)效果最佳。 - 渲染为 ``,无字号/无内容时无可见效果。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text) # ASCIIText > 把文字渲染成 ASCII 字符画 · canvas2d 逐像素亮度采样映射字符 + 正弦波动位移 + 鼠标驱动 hue-rotate 色相(零依赖去 three.js·token·reduced-motion) · typography/text · #animated ## 何时用 Hero / 404 / 极客风装饰位想把一句短文渲染成跳动的字符画时用。要的是平滑渐变发光质感(AuroraText)或闪过的高光(AnimatedShinyText)就用那两个;ASCIIText 是把字形彻底拆成字符网格的重特效,仅适合短文本、装饰位。 ## 导入 ```ts import { ASCIIText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text | `string` | `"瑚琏"` | 要转成字符画的文本,先渲染到离屏 canvas 再按像素亮度逐格映射字符 | | asciiFontSize | `number` | `8` | 字符画字号(px),决定网格密度;越小越密越费算力,建议 6–14 | | textFontSize | `number` | `160` | 离屏源文本字号(px),越大采样分辨率越高;与 asciiFontSize 比值≈字符列数 | | textColor | `string` | `var(--color-foreground)` | 源文本填充色,喂给 canvas fillStyle,须可被 canvas 解析 | | enableWaves | `boolean` | `true` | 字符网格按行做正弦相位偏移营造飘动;reduced-motion 下强制静止 | | enableHue | `boolean` | `true` | 指针相对中心的角度驱动 hue-rotate 色相旋转;关闭则保持单一色相 | | charset | `string` | 经典 70 级 ramp | 字符亮度坡道(暗→亮),索引越大代表越亮的像素,可传自定义风格化 | | className | `string` | — | 透传根容器额外 className | | style | `CSSProperties` | — | 透传根容器内联样式 | ## 示例 ```tsx // 默认:波动 + 鼠标色相,主色字符
// 静态:关波动、关色相,高密度细节 ``` ## 禁忌 / 坑 - canvas2d 重绘:仅适合短文本装饰位,长串字符会让网格列数暴涨、逐帧采样吃满算力。 - textColor 喂的是 canvas fillStyle,须是 canvas 能解析的颜色值;想随主题变可走默认 token,自定义传裸值不会随明暗切换。 - reduced-motion 下波动强制静止(DOM 不变,仅停动画),别依赖动画状态做判断。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # AuroraText > 极光文字 · bg-clip 流动渐变 + chart token + RSC · typography/text · #animated ## 何时用 给一小段标题/品牌词加极光流动渐变(bg-clip 文字裁切),默认吃 4 个瑚琏 chart token 随明暗主题切换。要横扫高光徽标气质用 [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text);要行内随文流动的渐变用 [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text);普通文本用 [Text](https://hulianui.haloritual.com/components/text),不要给大段正文套动效。 ## 导入 ```ts import { AuroraText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | colors | `string[]` | 4 个瑚琏 chart token | 渐变停靠色数组(自动吃明暗主题) | | speed | `number` | `1` | 流动速度倍率,越大越快 | 继承 `ComponentPropsWithoutRef<"span">`(除 `color`),如 `className` / `style`。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 要渲染的文字 | ## 示例 ```tsx 瑚琏 Hulian ``` 加速: ```tsx Aurora ``` ## 禁忌 / 坑 - 渲染为 ``,效果靠 `text-*`/`font-*` 等字号样式撑出可见面积,给空 children 或无字号时看不到流光。 - 自定义 `colors` 须用可解析的 CSS 颜色值;用 token 时注意瑚琏 token 需带 `--color-` 前缀才在 SVG/渐变里解析(见 hulian token 规范)。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text) # BlurText > 模糊解析 · 各词从模糊+位移解析到清晰 + 滚入视口触发(motion · top/bottom 方向 · aria-label 整段 · reduced-motion 直呈清晰) · typography/text · #animated ## 何时用 标题/段落滚入视口时让每段从「模糊+位移」解析到清晰,比纯位移淡入更有镜头对焦质感。只要逐段位移淡入(不模糊)用 [SplitText](https://hulianui.haloritual.com/components/split-text);要随滚动进度持续逐词显影用 [ScrollReveal](https://hulianui.haloritual.com/components/scroll-reveal);普通静态标题用 [Heading](https://hulianui.haloritual.com/components/heading)。 ## 导入 ```ts import { BlurText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text * | `string` | — | 要逐段模糊浮现的文本 | | splitType | `"char" \| "word"` | `"word"` | 切分粒度:word 逐词(按空白切)/ char 逐字(中文友好) | | direction | `"top" \| "bottom"` | `"top"` | 进场方向,伴随 y 位移与中段过冲 | | delay | `number` | `120` | 相邻段错峰毫秒,越大波浪推进越慢 | | blur | `number` | `8` | 起始模糊像素,解析到 0 时清晰 | | stepDuration | `number` | `0.5` | 单段从起始到清晰的整体时长(秒),内部分两步 | | threshold | `number` | `0.3` | 触发动画的视口可见比例(useInView amount),0~1 | 其余 `

` 原生属性透传;`onDrag/onDragStart/onDragEnd/onAnimationStart` 因与 motion 签名冲突被剔除。 ## Events | 事件 | 类型 | 说明 | |------|------|------| | onAnimationComplete | `() => void` | 末段动画结束回调(整句浮现完成时触发一次) | ## 示例 ```tsx ``` ## 禁忌 / 坑 - `text` 只收纯字符串,不能塞 JSX。 - 中文用 `splitType="word"` 会因无空白而整段一次浮现;逐字效果需显式传 `splitType="char"`。 - 进场只触发一次(基于视口可见比例 `threshold`);反复观察需更换 `key` 强制 remount。 - 尊重 `prefers-reduced-motion`:开启减弱动效时直呈清晰终态。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # CircularText > 环形文字 · 每字按等分角排到圆周 + 整体匀速自转 + 悬停调速(加速/减速/暂停/抓狂 · 颜色继承 currentColor · reduced-motion 静态) · typography/text · #animated ## 何时用 徽章/印章/旋转 logo 场景把文本按等分角排到圆周并匀速自转,悬停可调速。要做平铺逐字进场用 [SplitText](https://hulianui.haloritual.com/components/split-text);要故障撕裂用 [GlitchText](https://hulianui.haloritual.com/components/glitch-text);普通静态标题用 [Heading](https://hulianui.haloritual.com/components/heading)。 ## 导入 ```ts import { CircularText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text * | `string` | — | 环绕排布的文本,建议尾部加分隔符(如 `✦`)让首尾衔接更顺 | | spinDuration | `number` | `20` | 转一圈秒数 | | onHover | `"speedUp" \| "slow" \| "pause" \| "goBonkers"` | `"speedUp"` | 悬停行为:加速 / 减速 / 暂停 / 抓狂 | | radius | `number` | `80` | 文字所在圆半径像素 | 其余 `

` 原生属性透传。文字颜色继承 `currentColor`,用 `text-*` 工具类着色。 ## 示例 ```tsx ``` ## 禁忌 / 坑 - `text` 首尾会衔接成环:结尾建议补分隔符(` · ` / `✦` / `★`),否则末字与首字直接相贴。 - 颜色继承 `currentColor`,必须靠 `text-*` 类或父级 color 着色,没有独立颜色 prop。 - 尊重 `prefers-reduced-motion`:开启减弱动效时静止不自转。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # Code > 行内代码 · 等宽皮肤 + tone(default/primary/danger) + RSC · typography/code ## 何时用 正文中嵌入行内代码片段(命令、标识符、路径),等宽皮肤 + tone 着色,可在 RSC 直接渲染。多行/带语法高亮的代码块用 [CodeBlock](https://hulianui.haloritual.com/components/code-block);带复制按钮的命令片段用 [Snippet](https://hulianui.haloritual.com/components/snippet);展示键盘按键用 [Kbd](https://hulianui.haloritual.com/components/kbd)。 ## 导入 ```ts import { Code, codeVariants } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | tone | `"default" \| "primary" \| "danger"` | `"default"` | 配色语气:默认 / 主色(强调)/ 危险(破坏性命令) | 其余 ``(HTMLElement)原生属性透传。`codeVariants` 为 CVA 样式函数,可在自定义元素上复用皮肤类名。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 代码内容 | ## 示例 ```tsx 运行 pnpm install 安装依赖 rm -rf ``` ## 禁忌 / 坑 暂无已知坑。 ## 相关 [CodeBlock](https://hulianui.haloritual.com/components/code-block) · [Snippet](https://hulianui.haloritual.com/components/snippet) · [CodeDiff](https://hulianui.haloritual.com/components/code-diff) · [Kbd](https://hulianui.haloritual.com/components/kbd) · [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) # CodeBlock > 代码块 · 多行
 + 一键复制(剪贴板+反馈) + 可选语言标签 · typography/code

## 何时用

展示多行代码片段,自带语法着色、右上角语言标签与一键复制。单行命令/内联标识用 [Snippet](https://hulianui.haloritual.com/components/snippet);只是一段内联 `code` 文字用 [Code](https://hulianui.haloritual.com/components/code);展示前后差异用 [CodeDiff](https://hulianui.haloritual.com/components/code-diff)。

## 导入
```ts
import { CodeBlock, HighlightedCode, tokenizeCode, type CodeToken, type CodeTokenType } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| code* | `string` | — | 代码文本,多行用 `\n` |
| lang | `string` | — | 右上角语言标签(如 `"tsx"`),同时决定着色规则走 JS 家族还是 Shell |
| copyable | `boolean` | `true` | 是否显示复制按钮 |
| highlight | `boolean` | `true` | 是否语法着色;关掉则纯文本 |
| className | `string` | — | 容器类名 |

## 示例
```tsx


// Shell 走 Shell 着色规则

```

## 禁忌 / 坑

暂无已知坑。

## 相关
[Code](https://hulianui.haloritual.com/components/code) · [Snippet](https://hulianui.haloritual.com/components/snippet) · [CodeDiff](https://hulianui.haloritual.com/components/code-diff) · [Kbd](https://hulianui.haloritual.com/components/kbd) · [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading)


# CodeDiff

> 代码对比 · 零依赖行级 LCS diff(纯函数 diffLines 可测) + unified 单栏/split 双栏 + 增绿删红行底色 + 双行号槽 + filename 头条与 +/− 摘要 · agent 改动/PR 评审 · typography/code

## 何时用

展示两段文本的行级差异(PR 评审、agent 改动回放、配置变更对比),增绿删红、双行号、可挂行级批注。只展示静态代码用 [CodeBlock](https://hulianui.haloritual.com/components/code-block);单行命令用 [Snippet](https://hulianui.haloritual.com/components/snippet)。`diffLines`/`diffStat` 是纯函数,可单独用于自定义渲染或统计。

## 导入
```ts
import { CodeDiff, diffLines, diffStat } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| oldText* | `string` | — | 旧文本 |
| newText* | `string` | — | 新文本 |
| mode | `"unified" | "split"` | `"unified"` | unified 单栏 / split 双栏对照 |
| filename | `string` | — | 头部文件名条;省略则不渲染头部 |
| showLineNumbers | `boolean` | `true` | 显示行号槽 |
| annotations | `CodeDiffAnnotation[]` | — | 行锚定批注:在匹配行渲染 gutter 标记 + 行下方插入整宽 content 槽(仅 unified 模式插 content) |
| className | `string` | — | 容器类名 |

`CodeDiffAnnotation`:`{ side?: "old"|"new"(默认 "new"); line: number(1-based); gutter?: ReactNode; content?: ReactNode }`。

## 示例
```tsx


// 双栏对照

```

## 禁忌 / 坑

- `annotations` 的 `content` 槽**仅在 unified 模式**插入;split 模式只渲染 gutter 标记。需要在差异行下方挂 CodeReviewThread 等内容时用 `mode="unified"`。
- `annotations[].line` 是 1-based 行号,按 `side` 对应旧文件或新文件,别和数组下标混淆。

## 相关
[Code](https://hulianui.haloritual.com/components/code) · [CodeBlock](https://hulianui.haloritual.com/components/code-block) · [Snippet](https://hulianui.haloritual.com/components/snippet) · [Kbd](https://hulianui.haloritual.com/components/kbd) · [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading)


# CurvedLoop

> 沿二次贝塞尔曲线无缝循环滚动的弧形跑马灯文字 · SVG textPath + rAF 续滚 + 可拖拽拨动(零依赖·token/currentColor·reduced-motion) · typography/text · #animated

## 何时用

页眉 / 区块分隔带想要弯曲弧形走向的跑马灯横幅时用。需要随页面滚动加速变向的多行平排跑马灯用 ScrollVelocity;只要一条沿曲线无缝循环、还能手动拨动的弧形文字带就用 CurvedLoop。

## 导入
```ts
import { CurvedLoop } from "@hulianui/ui"
```

## Props

继承 `SVGProps`(去 `ref`),常用如下:

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| text | `string` | — | 跑马灯文案,内部去尾部空白并补不间断空格作词间隔,首尾无缝拼接铺满曲线 |
| speed | `number` | `2` | 滚动速度(px/帧,约 60fps),越大越快 |
| curveAmount | `number` | `320` | 弯曲量(二次贝塞尔控制点垂直偏移,viewBox 像素),正值向下弯/负值向上弯/0 近直线 |
| direction | `"left" \| "right"` | `"left"` | 自动滚动方向 |
| interactive | `boolean` | `true` | 是否允许鼠标/触控拖拽拨动文字(松手后沿拖拽方向续滚) |
| className | `string` | — | 文字颜色 token 类名(如 text-primary);默认 fill 走 currentColor,可由父级 text-* 控制 |

## 示例
```tsx
// 默认:向下弯、左滚


// 向上弯(curveAmount 负值) + 主色


// 右滚高速、纯展示不可拖

```

## 禁忌 / 坑

- 文案末尾习惯带分隔符(如 `" · "`),内部会补不间断空格做词间隔再首尾拼接,缺分隔符会让循环接缝读起来粘连。
- 颜色走 currentColor:用 className 的 `text-*` 控制色,不要直接传 `fill`。
- reduced-motion 下停止自动滚动;交互拨动仍可用,别用动画做核心信息载体。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)


# DecryptedText

> 乱码解码 · 字符翻滚后逐位解码到明文 + view/hover 触发(随机仅客户端 effect 避 hydration mismatch · 等宽 tabular-nums 防抖 · aria-label 明文) · typography/text · #animated

## 何时用

科技/安全/黑客感场景里让文本先翻滚乱码再逐位解码到明文,强调「解密揭示」的戏剧性。要做平滑的模糊对焦用 [BlurText](https://hulianui.haloritual.com/components/blur-text);要做 RGB 错位故障撕裂用 [GlitchText](https://hulianui.haloritual.com/components/glitch-text);普通逐字进场用 [SplitText](https://hulianui.haloritual.com/components/split-text)。

## 导入
```ts
import { DecryptedText } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| text * | `string` | — | 目标明文 |
| speed | `number` | `55` | 每次乱码刷新间隔毫秒 |
| animateOn | `"view" \| "hover"` | `"view"` | 触发方式:view 滚入视口一次性解码 / hover 悬停解码、移出复位 |
| characters | `string` | 大小写字母+数字+符号 | 乱码取样字符集 |

其余 `` 原生属性透传。

## 示例
```tsx



```

## 禁忌 / 坑

- 乱码取样是随机的,仅在客户端 effect 里跑,避免 SSR/hydration mismatch(服务端首帧呈明文)。
- 内部用等宽 `tabular-nums` 防止翻滚时宽度抖动;自定义 `className` 别覆盖等宽设定,否则字符乱跳。
- 暂无其他已知坑。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)


# FallingText

> 文字按词散落物理特效 · 触发后逐词受重力下落/撞墙反弹堆叠 + 指针拖拽抛掷(零依赖 RAF 自写二维刚体·token·reduced-motion) · typography/text · #animated

## 何时用

落地页彩蛋 / 互动 banner 想让一句话按词「散架掉落」并可拖拽抛玩时用。要平滑入场浮现/错峰用 ScrollFloat、Reveal;FallingText 是把每个词当独立刚体做重力碰撞的重交互特效,仅适合短句、装饰互动位。

## 导入
```ts
import { FallingText } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| text | `string` | `""` | 整段文本,按空格切「词块」,每词一个独立刚体下落 |
| highlightWords | `string[]` | `[]` | 需高亮的词(前缀匹配:词 startsWith 任一即高亮) |
| highlightClass | `string` | `"text-primary font-semibold"` | 高亮词额外 className(叠加在词块上) |
| trigger | `"auto" \| "scroll" \| "click" \| "hover"` | `"auto"` | 掉落时机:挂载即播/滚入视口/点击容器/指针移入 |
| gravity | `number` | `1` | 向下加速度系数,越大下落越快堆叠越急,建议 0.3–3 |
| bounce | `number` | `0.6` | 落地/撞墙反弹系数(0 不弹,1 全弹) |
| fontSize | `string` | `"1.5rem"` | 文本字号(CSS 长度,传入根 fontSize) |
| className | `string` | — | 透传根容器额外 className |
| style | `CSSProperties` | — | 透传根容器内联样式 |

## 示例
```tsx
// 默认:自动掉落 + 高亮词


// 点击触发 + 高重力低反弹(迅速堆叠)

```

## 禁忌 / 坑

- 词块按空格切分:中文要靠手动空格分词(如 `"瑚琏 组件库 企业级"`),不空格会整段当一个刚体。
- highlightWords 是前缀匹配(startsWith),不是全等,注意误命中相同前缀的词。
- 默认 `text=""` 不渲染任何词,忘传 text 会得到空舞台。
- reduced-motion 下不做物理掉落动画;别把它当核心内容的唯一呈现方式。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)


# FuzzyText

> 信号噪点模糊标题 · canvas2d 逐行/逐列随机错位扫描 + 悬停增强抖动(零依赖·token·reduced-motion 退静态帧) · typography/text · #animated

## 何时用

404 / 故障页 / 极客风大标题想要信号噪点、扫描错位的「毛刺」质感时用。要逐字翻滚乱码的悬停文字用 ScrambledText;要平滑发光渐变用 AuroraText;FuzzyText 是把字形按行/列像素错位做扫描噪点,适合厚重短标题。

## 导入
```ts
import { FuzzyText } from "@hulianui/ui"
```

## Props

继承 `CanvasHTMLAttributes`(去 `color`/`children`/`style`),核心如下:

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| fontSize | `number \| string` | `"clamp(2rem, 10vw, 10rem)"` | 数字按 px、字符串按任意 CSS 长度(含 clamp),自适应视口 |
| fontWeight | `number \| string` | `900` | 字重,厚笔画下噪点更醒目 |
| fontFamily | `string` | `"inherit"` | 字体族,inherit 读 canvas computed font-family |
| color | `string` | `var(--color-foreground)` | 填充色,随明暗主题;可传任意 CSS 颜色(含 var()/currentColor,内部经 computed style 解析);style.color 优先级更高 |
| enableHover | `boolean` | `true` | 指针在文字范围内时抖动加剧 |
| baseIntensity | `number` | `0.18` | 静息态噪点强度(0–1),越大越「毛」 |
| hoverIntensity | `number` | `0.5` | 悬停态噪点强度(0–1) |
| fuzzRange | `number` | `30` | 每行/列最大像素位移幅度,决定噪点散开范围 |
| direction | `"horizontal" \| "vertical" \| "both"` | `"horizontal"` | 抖动方向:按行左右/按列上下/两者叠加 |
| className | `string` | — | 透传 canvas 额外 className |
| style | `CSSProperties` | — | 透传 canvas 内联样式 |

## Slots

| 插槽 | 类型 | 说明 |
|------|------|------|
| children* | `ReactNode` | 要渲染的文字(仅纯文本,会被拼成一行) |

## 示例
```tsx
// 默认:横向扫描噪点
瑚琏

// 404:高位移 + 主色

  404

```

## 禁忌 / 坑

- 渲染目标是 ``:children 仅支持纯文本,传嵌套元素会被拼接为一行字符串。
- color 喂的是经 computed style 解析的颜色:可传 `var(--color-*)`/`currentColor`,但纯 canvas 不吃 Tailwind 工具类,给颜色走 color prop 或 style.color。
- reduced-motion 下退化为静态帧(保留可读文字),别依赖抖动作为唯一视觉反馈。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)


# GlitchText

> 故障撕裂 · 双伪元素 RGB 错位 + clip-path 切片抖动(纯 CSS 零依赖 RSC · 撕裂色吃 chart token · enableOnHover 门控 · motion-reduce 退普通文本) · typography/text · #animated

## 何时用

赛博朋克/科技感标题做 RGB 错位+切片抖动的故障撕裂效果,纯 CSS 零依赖、可在 RSC 直接渲染。要做乱码逐位解码用 [DecryptedText](https://hulianui.haloritual.com/components/decrypted-text);要做模糊对焦用 [BlurText](https://hulianui.haloritual.com/components/blur-text);普通静态标题用 [Heading](https://hulianui.haloritual.com/components/heading)。

## 导入
```ts
import { GlitchText } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| speed | `number` | `2.5` | 撕裂周期秒数,越小越狂躁 |
| enableOnHover | `boolean` | `false` | 仅悬停时故障,静息为普通文本;默认常驻故障 |

其余 `` 原生属性透传。

## Slots

| 插槽 | 类型 | 说明 |
|------|------|------|
| children * | `string` | 要做撕裂故障效果的文本,必须是纯字符串(供伪元素 `attr(data-text)` 复制) |

## 示例
```tsx
HULIAN


  GLITCH

```

## 禁忌 / 坑

- `children` 必须是纯字符串:伪元素靠 `attr(data-text)` 复制文本制造错位层,传入 JSX/元素会让撕裂层为空。
- 撕裂色吃 chart token(`var(--color-chart-*)`),随主题切换;自定义颜色须带 `--color-` 前缀或合法 CSS 颜色,裸 `var(--primary)` 在本 Tailwind v4 设定下不解析。
- 尊重 `prefers-reduced-motion`:开启减弱动效时退化为普通文本、不抖动。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text)


# Heading

> 标题 · 1-6 级语义标签 + size/weight + as 多态(纯皮肤·零依赖·RSC) · typography/text

## 何时用

需要语义标题(自动渲染为 h1–h6)并控制视觉尺寸/字重时用 Heading;支持视觉与语义解耦(如语义是 h2、视觉用 lg),以及用 `as` 把标题样式套到非标题标签上。正文、说明文本用 [Text](https://hulianui.haloritual.com/components/text);整段富文本排版用 [Prose](https://hulianui.haloritual.com/components/prose)。

## 导入
```ts
import { Heading } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| level | `1 \| 2 \| 3 \| 4 \| 5 \| 6` | `2` | 标题级别,决定语义标签 `h{level}` 与默认视觉尺寸 |
| as | `ElementType` | `h{level}` | 覆盖渲染标签(视觉/语义解耦,如 level=1 样式渲染为 div) |
| size | `"xs" \| "sm" \| "base" \| "lg" \| "xl" \| "2xl" \| "3xl" \| "4xl"` | 按 level 派生 | 覆盖视觉尺寸(独立于 level) |
| weight | `"normal" \| "medium" \| "semibold" \| "bold"` | `"semibold"` | 字重 |
| balance | `boolean` | `false` | 启用 text-balance 平衡换行(多行标题更匀称) |

继承 `HTMLAttributes`(已 Omit `color`)。

## Slots

| 插槽 | 类型 | 说明 |
|------|------|------|
| children | `ReactNode` | 标题文本 |

## 示例
```tsx
// 语义标签 + 默认尺寸
一级标题

// 视觉/语义解耦:语义 h2,视觉 lg
语义是 h2,视觉是 lg

// 用 div 承载大标题样式 + 平衡换行
大号视觉标题
```

## 禁忌 / 坑

暂无已知坑。`level` 同时决定语义标签和默认尺寸——要保留语义标签但改视觉,用 `size` 覆盖,别为了视觉乱改 `level`(会破坏文档大纲)。注意 Heading 无 `size="md"` 档(只有 base,无 md),来自历史踩坑。

## 相关
[Text](https://hulianui.haloritual.com/components/text) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text)


# Kbd

> 按键 ·  等宽皮肤 + 组合键并排 + RSC · typography/code

## 何时用

标注单个键位/快捷键(`Esc`、`⌘`、`K`),等宽键帽皮肤。组合键由多个 Kbd 并排手动组合(见示例)。它是 RSC,可在服务端组件直接用。展示代码片段用 [CodeBlock](https://hulianui.haloritual.com/components/code-block)/[Snippet](https://hulianui.haloritual.com/components/snippet)。

## 导入
```ts
import { Kbd } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| ...HTMLAttributes | `HTMLAttributes` | — | 透传 `` 原生属性(className、style 等) |

## Slots

| 插槽 | 类型 | 说明 |
|------|------|------|
| children | `ReactNode` | 键位内容 |

## 示例
```tsx
Esc

// 组合键:多个 Kbd 并排

  
  +
  K

```

## 禁忌 / 坑

- 单个 Kbd 只渲染一个键帽,组合键需自行用多个 Kbd 并排拼装,组件不内置 `+` 分隔。

## 相关
[Code](https://hulianui.haloritual.com/components/code) · [CodeBlock](https://hulianui.haloritual.com/components/code-block) · [Snippet](https://hulianui.haloritual.com/components/snippet) · [CodeDiff](https://hulianui.haloritual.com/components/code-diff) · [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading)


# Markdown

> 只读 Markdown 渲染 · 零依赖块级解析(标题/代码块/列表/引用/行内粗斜码链) · 套 Prose 排版 + 围栏代码块委托 CodeBlock · 区别 MarkdownEditor 可编辑 · RSC 安全 · typography/text

## 何时用

把一段 Markdown 源字符串只读渲染成排版好的富文本(标题/围栏代码块/列表/引用/行内粗斜码链)。需要可编辑用 [MarkdownEditor];已经是 HTML/JSX 而非 Markdown 源用 [Prose](https://hulianui.haloritual.com/components/prose) 直接包裹;单段原子文本用 [Text](https://hulianui.haloritual.com/components/text)。`parseBlocks` 导出供需要拿块级 AST 自定义渲染的场景。

## 导入
```ts
import { Markdown, parseBlocks } from "@hulianui/ui"
```

## Props

| 名称 | 类型 | 默认 | 说明 |
|------|------|------|------|
| size | `"sm" \| "base"` | `"base"` | 排版尺寸基准,透传给内部 Prose |
| className | `string` | — | 透传容器类名 |

## Slots

| 插槽 | 类型 | 说明 |
|------|------|------|
| children | `string` | Markdown 源文本(只读渲染;编辑用 MarkdownEditor) |

## 示例
```tsx
{`## 快速排序 \`\`\`js function quickSort(arr) { /* ... */ } \`\`\` 平均复杂度 **O(n log n)**,行内 \`代码\` 与[外链](https://mdn.io)正常渲染。 > 引用块整体排版吃 Prose 语义 token。`}
``` ## 禁忌 / 坑 - 零依赖块级解析输出 JSX(非 `dangerouslySetInnerHTML`/`innerHTML`),不走原生 HTML sink,故无 [[dompurify-vhtml-markdown-sanitize]] 那类存储型 XSS 风险;但若后续改造成「直接注入 HTML」或扩展支持原始 HTML 标签,必须经 DOMPurify 等清洗后再渲染,不要把不可信源直接喂进 innerHTML。 - 只读组件,不接受编辑回调;需要双向编辑改用 MarkdownEditor。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text) # Prose > 排版容器 · 富文本/markdown 后代选择器统一吃语义 token(纯皮肤·零依赖·RSC) · typography/text ## 何时用 包裹一段渲染好的富文本(markdown→HTML、MDX 输出或手写 JSX),用后代选择器把标题/段落/列表/链接/行内代码/引用统一接管为一致阅读排版、自动适配明暗主题。内容已是 Markdown 源字符串时用 [Markdown](https://hulianui.haloritual.com/components/markdown)(它内部就套 Prose);单段/单个标题等原子文本用 [Text](https://hulianui.haloritual.com/components/text) / [Heading](https://hulianui.haloritual.com/components/heading),不要为一句话套 Prose。 ## 导入 ```ts import { Prose } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | as | `ElementType` | `"article"` | 渲染的容器标签 | | size | `"sm" \| "base"` | `"base"` | 整体排版尺寸基准;`sm` 把基准字号降到 text-sm,适合侧栏/卡片内长文 | 继承 `HTMLAttributes`(`className` / `style` 等)。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 富文本内容(HTML/JSX) | ## 示例 ```tsx

瑚琏排版容器 Prose

把渲染好的富文本统一接管为一致阅读排版,链接行内代码 全吃语义 token。

排版即沉默的设计——容器统一规则,内容只管语义。
``` 紧凑场景: ```tsx {/* 侧栏说明、卡片内富文本 */} ``` ## 禁忌 / 坑 - 见 [[chat-bubble-max-w-prose-overflows-narrow-column]]:`max-w-prose`(65ch≈398px)是绝对值、不感知父容器可用宽度,放进移动端窄 flex 列会横向溢出/裁切。约束宽度用 `max-w-[min(65ch,100%)]`,且父链 flex 项加 `min-w-0`;不要叠 `max-w-prose max-w-full`(同属性二选一由 CSS 顺序决定不可靠)。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text) # ScrambledText > 指针靠近文字逐字翻滚乱码再收敛的悬停文字特效 · 半径内越近翻滚越久 + 可自定字符集/速度(零依赖 RAF·reduced-motion) · typography/text · #animated ## 何时用 整段文字想要「指针扫过逐字解码」的悬停互动时用。要的是像素扫描错位的故障质感用 FuzzyText;要平滑入场用 ScrollFloat / Reveal;ScrambledText 适合一段可读正文/小标题,靠鼠标半径触发逐字符乱码翻滚再收敛。 ## 导入 ```ts import { ScrambledText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | radius | `number` | `100` | 指针生效半径(px),落在某字符中心此半径内才触发该字翻滚 | | duration | `number` | `1.2` | 单字乱码翻滚最长时间(秒),离指针越近越接近此值 | | speed | `number` | `0.5` | 翻滚速度(0~1),越大每帧切换乱码越频繁、收敛越快 | | scrambleChars | `string` | `".:"` | 乱码随机替换用的字符集,逐字符循环取样 | | className | `string` | — | 透传根元素额外类名(cn 合并) | | style | `CSSProperties` | — | 透传根元素内联样式 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children* | `ReactNode` | 要逐字打乱的文本(仅纯文本,内部拆成单字符 span) | ## 示例 ```tsx // 默认:.: 字符集 把指针移到这段文字上 — Hover scrambles the glyphs. // 大半径 + 全角符号集 HULIAN UI · Scramble On Hover ``` ## 禁忌 / 坑 - children 仅支持纯文本:内部按字符拆 span,传嵌套元素的结构会被打散。 - 半径基于字符中心:超长段落里离指针远的字几乎不动,这是设计预期而非 bug。 - reduced-motion 下不做翻滚动画,直接显示原文。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # ScrollFloat > 滚动浮现标题:随容器滚过视口逐字符从「下沉 + 纵向拉伸横向压扁 + 透明」拔起到正常 · useScroll 绑进度 + 每字符 useTransform 派生 opacity/y/scaleX/scaleY(去 gsap·吃 text-foreground token·reduced-motion 直出清晰标题) · typography/text · #animated ## 何时用 长页面区块标题想随滚动逐字符「拔起」浮现时用。要通用块级(非逐字)入场用 Reveal;要平滑发光渐变标题用 AuroraText;ScrollFloat 专做随滚动进度逐字符变形浮现的大标题。 ## 导入 ```ts import { ScrollFloat } from "@hulianui/ui" ``` ## Props 继承 `h2` props(去 `children` 与 motion 冲突的 onDrag*/onAnimationStart): | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | scrollContainerRef | `RefObject` | 自动探测 | 自定义滚动容器;不传时优先绑最近可滚动祖先,其次视口,完全无滚动上下文则降级为进入视口自动浮现 | | offset | `[string, string]` | `["start 0.9", "start 0.35"]` | 进度映射区间(对应 useScroll offset):顶进视口 90% 处开始、35% 处完成 | | stagger | `number` | `0.4` | 字符间错峰强度(0~1),每字符进度窗口相对整体的偏移比例 | | yPercent | `number` | `120` | 初始下沉位移百分比(相对字高),随进度回 0 | | scaleY | `number` | `2.3` | 初始纵向拉伸倍率,随进度回 1 | | scaleX | `number` | `0.7` | 初始横向压扁倍率,随进度回 1 | | containerClassName | `string` | — | 外层容器类名(裁切溢出的滚动浮现) | | textClassName | `string` | — | 文本层类名(控制字号/字重/对齐) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children* | `string` | 逐字符滚动浮现的文本(仅字符串,非字符串忽略为空) | ## 示例 ```tsx // 默认:在可滚动区域内逐字符拔起(组件自动绑最近可滚动祖先)
瑚琏组件库
// 强错峰 + 主色大标题 HULIAN ``` ## 禁忌 / 坑 - children 必须是字符串:传入非字符串会被忽略为空,逐字符拆分依赖纯文本。 - 需要可滚动上下文才有「随滚动浮现」效果:组件会自动绑最近可滚动祖先;完全没有滚动容器时降级为进入视口自动浮现(不会卡在 0 进度隐形态),但要逐字符随滚动播放仍需父级可滚动。 - reduced-motion 下直出清晰标题,不做变形动画。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # ScrollReveal > 滚动显影 · 整段随容器滚过视口逐词 opacity+blur 解析(motion useScroll/useTransform · 每词独立进度区间 · reduced-motion 直呈可读) · typography/text · #animated ## 何时用 长文段落随页面滚动进度逐词从模糊/低透明度解析到清晰,营造「读到哪亮到哪」的阅读节奏。要进场一次性逐词淡入(不绑滚动进度)用 [SplitText](https://hulianui.haloritual.com/components/split-text);要进场一次性模糊解析用 [BlurText](https://hulianui.haloritual.com/components/blur-text);普通静态段落用 [Prose](https://hulianui.haloritual.com/components/prose)。 ## 导入 ```ts import { ScrollReveal } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | baseOpacity | `number` | `0.12` | 静息(未滚入解析区间)时每词的基础透明度,0~1;越小入场对比越强 | | baseRotation | `number` | `3` | 整段进入时的初始旋转角(deg),随进度回正到 0;设 0 关闭 | | enableBlur | `boolean` | `true` | 是否伴随模糊解析:未揭示词带模糊随进度消散 | | blurStrength | `number` | `4` | `enableBlur` 为真时词的起始模糊半径(px),随进度降到 0 | 其余 `

` 原生属性透传;`onDrag/onDragStart/onDragEnd/onAnimationStart` 因与 motion 签名冲突被剔除。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children * | `string` | 要随滚动逐词显影的整段文本,仅字符串(内部按空白拆词并保留分隔符) | ## 示例 ```tsx When you scroll this block the words resolve from blur to focus one by one. 纯透明度与旋转 适合追求克制质感的标题段落 ``` ## 禁忌 / 坑 - 效果由滚动进度驱动:组件必须处在可滚动上下文里、上下留出滚动空间才能看到逐词显影;放在不滚动的容器里只会停在静息态。 - `children` 只收纯字符串,不能塞 JSX。 - 尊重 `prefers-reduced-motion`:开启减弱动效时直呈完全可读(不模糊不变透明)。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # ScrollVelocity > 滚动速度跑马灯文字 · 多行交替方向视差 + 随页面滚动加速/变向、静止匀速漂移(motion 速度值驱动·零额外依赖·reduced-motion 冻结自走帧保留 DOM) · typography/text · #animated ## 何时用 页面区块想要多行平排、随页面滚动加速变向的视差跑马灯横幅时用。要单条沿曲线弯曲走向的跑马灯用 CurvedLoop;ScrollVelocity 专做多行交替方向、速度跟随滚动的水平滚动文字带。 ## 导入 ```ts import { ScrollVelocity } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | texts | `string[]` | `[]` | 多行滚动文本,每行独立跑马灯;偶数行左移/奇数行右移形成视差 | | velocity | `number` | `100`(showcase 演示 `80`) | 基础速度(px/秒),静止也匀速漂移;负值整体反向 | | damping | `number` | `50` | 弹簧阻尼,速度变化的黏滞感;越大越慢越稳 | | stiffness | `number` | `400` | 弹簧刚度,速度跟手的劲道;越大越紧绷 | | numCopies | `number` | `6` | 每行复制份数(无缝循环铺满);文本越短需越多份 | | velocityMapping | `{ input: [number, number]; output: [number, number] }` | `{ input: [0,1000], output: [0,5] }` | 滚动速度→加速因子映射(clamp:false 允许外推) | | scrollContainerRef | `RefObject` | window | 自定义滚动容器;不传监听 window 滚动 | | className | `string` | — | 透传每行文本 span 的 className(字号/字色/字重) | | containerClassName | `string` | — | 透传根 section 的 className | | parallaxStyle | `CSSProperties` | — | 透传每行外层(parallax)容器内联样式 | | scrollerStyle | `CSSProperties` | — | 透传每行滚动轨(scroller)内联样式 | ## 示例 ```tsx // 单行匀速漂移 // 双行交替方向(视差) ``` ## 禁忌 / 坑 - 文本越短越要调大 numCopies:份数不足时铺不满视口宽度会露出空隙。 - 字色/字号走 `className`(作用于每行文本 span),容器整体样式走 `containerClassName`,别混用。 - 默认监听 window 滚动:内嵌在自定义可滚动区时要传 scrollContainerRef,否则速度感应绑错滚动源。 - reduced-motion 下冻结跟滚加速、保留匀速自走帧与 DOM,文本仍可读。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # Shuffle > 逐字「洗牌解密」文本动画 · 字位先滚乱码再按方向顺序锁定真字 + 视口/悬停/循环触发(零依赖 rAF·reduced-motion 直落终态·token 着色) · typography/text · #animated ## 何时用 需要标题/短句以「乱码滚动→逐字解密」入场(终端、解密、黑客风)时用。要逐字符随鼠标距离形变用 [TextPressure](https://hulianui.haloritual.com/components/text-pressure);要彩色渐变流光用 [AuroraText](https://hulianui.haloritual.com/components/aurora-text);只是普通排版文字用 [Text](https://hulianui.haloritual.com/components/text)。 ## 导入 ```ts import { Shuffle } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text* | `string` | — | 最终呈现的文本(解析目标) | | duration | `number` | `0.6` | 整段洗牌时长(秒);每字解析点 = 字索引/总字数 × duration | | shuffleDirection | `"left" \| "right"` | `"right"` | 字符解析顺序;left 从右往左定、right 从左往右定 | | scrambleCharset | `string` | 大写字母+数字+少量符号 | 解析前每字位随机取字闪烁的乱码字符集 | | loop | `boolean` | `false` | 解析完成后是否清空重洗循环 | | loopDelay | `number` | `1` | 循环间隔(秒,仅 loop 时生效) | | triggerOnView | `boolean` | `true` | 是否进入视口才触发(IntersectionObserver) | | triggerOnce | `boolean` | `true` | triggerOnView 时进入视口是否只触发一次 | | triggerOnHover | `boolean` | `false` | 鼠标移入时重新洗牌(动画空闲才响应) | | tag | `"p" \| "span" \| "div" \| "h1" \| "h2" \| "h3" \| "h4"` | `"p"` | 渲染标签 | | textAlign | `CSSProperties["textAlign"]` | `"center"` | 文本对齐 | | className | `string` | — | 合并到根元素的类名 | | style | `CSSProperties` | — | 行内样式(与 textAlign 合并) | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onShuffleComplete | `() => void` | 解析完成回调(loop 时每轮结束都触发) | ## 示例 ```tsx // 悬停重洗(关掉视口触发,靠 hover 主动触发) // 循环 + 自定义字符集(十六进制感) ``` ## 禁忌 / 坑 - `triggerOnView` 默认 `true`:组件不在视口内永远不会播放。在固定可见的舞台里调试时记得关掉它(`triggerOnView={false}`),否则会以为没生效。 - `triggerOnHover` 仅在动画空闲时响应,洗牌进行中再移入不会打断重洗。 - reduced-motion 下直接落到终态文本,不播放洗牌——无障碍友好,但视觉演示需注意系统设置。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # Snippet > 代码片段 · 命令提示符 + 一键复制(剪贴板+反馈) · typography/code ## 何时用 展示单行命令/代码片段,前置提示符 + 一键复制,适合安装命令、CLI 指令。多行代码块用 [CodeBlock](https://hulianui.haloritual.com/components/code-block);纯内联标识文字用 [Code](https://hulianui.haloritual.com/components/code)。 ## 导入 ```ts import { Snippet } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text | `string` | — | 复制到剪贴板的文本;缺省时取 children(仅当为字符串时) | | symbol | `string | null` | `"$"` | 命令提示符;传 `null` 不显示,适合非命令片段 | | lang | `string` | — | 语法着色语言(如 `"tsx"`/`"bash"`),仅 children 为字符串时生效 | | highlight | `boolean` | `true` | 是否语法着色,仅 children 为字符串时生效 | | className | `string` | — | 容器类名 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 显示内容(字符串或节点) | ## 示例 ```tsx pnpm add @hulianui/ui // 非命令片段,去掉提示符 const theme = useTheme() ``` ## 禁忌 / 坑 - `text`/`lang`/`highlight` 的着色与复制兜底仅在 `children` 为**字符串**时生效;传入节点时只能手动给 `text` 指定复制内容。 ## 相关 [Code](https://hulianui.haloritual.com/components/code) · [CodeBlock](https://hulianui.haloritual.com/components/code-block) · [CodeDiff](https://hulianui.haloritual.com/components/code-diff) · [Kbd](https://hulianui.haloritual.com/components/kbd) · [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) # SparklesText > 星闪文字 · 随机小星脉冲(客户端生成) + token · typography/text · #animated ## 何时用 给一小段标题/品牌词围绕随机小星脉冲点缀(客户端随机生成星位)。要文字本体彩色流动用 [AuroraText](https://hulianui.haloritual.com/components/aurora-text) / [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text);要横扫高光徽标用 [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text);静态文本用 [Text](https://hulianui.haloritual.com/components/text)。客户端组件(随机星位 + 动画),源文件已含 `"use client"`。 ## 导入 ```ts import { SparklesText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | colors | `string[]` | `[primary, chart-1]` token | 星色数组 | | sparklesCount | `number` | `8` | 星星数量 | 继承 `ComponentPropsWithoutRef<"span">`(除 `color`),如 `className` / `style`。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 要渲染的文字 | ## 示例 ```tsx 瑚琏 Hulian ``` ## 禁忌 / 坑 - 星位在客户端随机生成,不要期待 SSR 与首帧水合后位置一致;本身是 `"use client"` 组件,作为子组件可嵌进 server 页,但不能当纯 RSC 用。 - 自定义 `colors` 用瑚琏 token 时须带 `--color-` 前缀才能在星点着色里解析(见 hulian token 规范)。 - 星数过大(`sparklesCount` 偏高)会增加动画节点数,小面积文字上密集星点可能显得杂乱。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # SplitText > 切字进场 · 文本切字/词 + 滚入视口逐段错峰位移淡入(motion · useInView 触发一次 · aria-label 整段读屏友好 · reduced-motion 直呈终态) · typography/text · #animated ## 何时用 标题/Hero 文案首次滚入视口时做逐字(或逐词)错峰位移淡入,强调登场感。要逐段「从模糊解析到清晰」用 [BlurText](https://hulianui.haloritual.com/components/blur-text);要随滚动进度持续逐词显影(而非进场一次)用 [ScrollReveal](https://hulianui.haloritual.com/components/scroll-reveal);只要普通静态标题用 [Heading](https://hulianui.haloritual.com/components/heading)。 ## 导入 ```ts import { SplitText } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text * | `string` | — | 要逐段进场的文本 | | splitType | `"char" \| "word"` | `"char"` | 切分粒度:char 逐字(中文友好)/ word 逐词(按空白切) | | from | `"bottom" \| "top" \| "left" \| "right"` | `"bottom"` | 进场方向,每段从该方向位移入场 | | delay | `number` | `40` | 相邻段错峰毫秒,越大波浪推进越慢 | | duration | `number` | `0.5` | 单段动画时长(秒) | 其余 `` 原生属性(`className` 等)透传;`onDrag/onDragStart/onDragEnd/onAnimationStart` 因与 motion 签名冲突被剔除。 ## 示例 ```tsx ``` ## 禁忌 / 坑 - `useInView` 只触发一次:进场动画播完不再重放。文档里反复观察需更换 `key` 强制 remount。 - `text` 只收纯字符串(非 children),不能塞 JSX。 - 尊重 `prefers-reduced-motion`:用户开启减弱动效时直呈终态、不播位移淡入。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # Text > 文本 · size/tone/weight + 单行省略/多行截断 + as 多态(纯皮肤·零依赖·RSC) · typography/text ## 何时用 正文、辅助说明、行内文本——需要统一字号/语义色调/字重并支持单行省略或多行截断时用 Text。标题层级(h1–h6 语义 + 标题尺寸)用 [Heading](https://hulianui.haloritual.com/components/heading);整段富文本/Markdown 排版用 [Prose](https://hulianui.haloritual.com/components/prose)。 ## 导入 ```ts import { Text } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | as | `ElementType` | `"p"` | 渲染的元素标签 | | size | `"xs" \| "sm" \| "base" \| "lg" \| "xl"` | `"base"` | 字号 | | tone | `"default" \| "muted" \| "primary" \| "danger"` | `"default"` | 语义色调(明暗自适配) | | weight | `"normal" \| "medium" \| "semibold" \| "bold"` | `"normal"` | 字重 | | truncate | `boolean` | `false` | 单行省略号截断 | | lineClamp | `number` | — | 多行截断(最多 n 行后省略号);设置后优先于 truncate | 继承 `HTMLAttributes`(已 Omit `color`,色调走 tone)。 ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 文本内容 | ## 示例 ```tsx // 语义色调 辅助说明 危险提示 // 多行截断

{longText}
``` ## 禁忌 / 坑 暂无已知坑。`truncate`(单行省略)依赖容器有确定宽度才会触发;`lineClamp` 与 `truncate` 同设时 `lineClamp` 优先。候选坑列表(bff-refresh/cjk-tokenizer/menubar/pdf/regex/sliding-pill/swiftui 各项)均与本纯皮肤文本组件无关,已剔除。 ## 相关 [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) · [AnimatedGradientText](https://hulianui.haloritual.com/components/animated-gradient-text) # TextCursor > 光标拖尾文字特效组件 · 在容器内移动光标时沿轨迹按间距落下一串字形并随机微浮动淡出回收(沿方向旋转 / emoji / 自定义间距上限)(零依赖·motion 运行时·reduced-motion 去浮动) · typography/text · #animated ## 何时用 需要鼠标在某区域内划过时留下一串字形/emoji 拖尾(趣味落地页、hero 互动区)时用。它是「光标在容器内移动」的拖尾,要做光标本身的果冻形态用 [BlobCursor](https://hulianui.haloritual.com/components/blob-cursor);要逐字符压感形变用 [TextPressure](https://hulianui.haloritual.com/components/text-pressure)。 ## 导入 ```ts import { TextCursor } from "@hulianui/ui" ``` ## Props 继承 `Omit, "children">`,额外: | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text | `string` | `"瑚"` | 跟随光标拖出的字形;可传短字符串或 emoji(如 `"✨"`) | | spacing | `number` | `80` | 相邻字形最小像素间距;光标每移动满 spacing 才落一个新字形,越小越密 | | followMouseDirection | `boolean` | `true` | 字形是否沿移动方向旋转对齐(atan2);关则保持水平 | | randomFloat | `boolean` | `true` | 字形落定后随机微浮动(位移+轻旋呼吸);reduced-motion 下自动停用仅保留淡出 | | exitDuration | `number` | `0.5` | 字形淡出秒数(opacity 过渡时长) | | removalInterval | `number` | `30` | 拖尾消减轮询间隔(ms);光标静止 ~100ms 后每隔该值从队首移除一个字形 | | maxPoints | `number` | `5` | 同时存在的字形上限,超出丢弃最旧 | | fontSize | `string` | `"1.875rem"` | 字号(任意 CSS 长度) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 容器内居中内容(提示语/标题),不影响拖尾层 | ## 示例 ```tsx // 默认:在区域内移动光标即留「瑚」字拖尾

在此区域内移动光标 →

// emoji + 大间距(稀疏拖尾) ``` ## 禁忌 / 坑 - 父容器必须有明确高度且 `overflow-hidden`、自身是定位上下文:拖尾层是绝对定位铺满容器,无高度则不可见。 - 拖尾只在「容器内」移动光标时落字,光标移出容器即停止并逐渐回收。 - reduced-motion 下去掉随机浮动,字形落定后仅做淡出。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # TextPressure > 逐字符"压感"标题 · 字形随鼠标距离实时插值字重/宽度/倾斜 + 透明度(零依赖 RAF·token 配色·reduced-motion·系统字体兜底) · typography/text · #animated ## 何时用 需要大标题随鼠标靠近做逐字字重/宽度/倾斜「压感」形变(hero 主标题、互动品牌字)时用。它响应「距离」做轴插值;要随鼠标距离插值可变字体轴并支持容器坐标系/三档衰减用 [VariableProximity](https://hulianui.haloritual.com/components/variable-proximity);要乱码解密入场用 [Shuffle](https://hulianui.haloritual.com/components/shuffle)。 ## 导入 ```ts import { TextPressure } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text | `string` | `"Compressa"` | 渲染文字(逐字符响应鼠标压力形变) | | fontFamily | `string` | 系统无衬线栈 | 字体族;系统字体下用 scaleX+font-weight+opacity 模拟压感,传入真可变字体则驱动 font-variation-settings | | fontUrl | `string` | — | 自定义 @font-face 字体 URL;默认不注入远程字体(遵守禁远程资源门禁),仅显式传本地/自托管地址时注入 | | width | `boolean` | `true` | 是否驱动 wdth 轴 + scaleX 模拟横向挤压 | | weight | `boolean` | `true` | 是否驱动 wght 轴 / font-weight 随接近度变粗 | | italic | `boolean` | `true` | 是否驱动 ital 轴(仅可变字体生效) | | alpha | `boolean` | `false` | 是否驱动 opacity(接近时更不透明) | | flex | `boolean` | `true` | 是否用 flex space-between 横向铺满字符 | | stroke | `boolean` | `false` | 是否描边(字心透明 + token 描边色,空心轮廓) | | scale | `boolean` | `false` | 是否纵向拉伸字块填满容器高度 | | textColor | `string` | `var(--color-foreground)` | 文字颜色(明暗自适配) | | strokeColor | `string` | `var(--color-primary)` | 描边颜色(stroke=true 时生效) | | minFontSize | `number` | `24` | 最小字号(px),容器较窄时下限 | | className | `string` | — | 透传到根 div(cn 合并) | ## 示例 ```tsx // 默认:移入鼠标看逐字压感 // 描边空心(token primary 描边) ``` ## 禁忌 / 坑 - `width`/`italic` 轴需真正的可变字体(含 wght/wdth/ital 轴)才有完整效果;系统字体下 width 退化为 scaleX 模拟、italic 基本无效。这是字体能力限制,不是 bug。 - 喂给 `strokeColor`/`textColor` 的 token 必须带 `--color-` 前缀(如 `var(--color-primary)`),裸 `var(--primary)` 不解析。见 [[hulian-token-color-var-needs-color-prefix]]。 - 默认不注入远程字体;要用自托管可变字体须显式传 `fontUrl`。 - reduced-motion 下不随鼠标形变。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # TrueFocus > 真实焦点 · 句中一词清晰余词模糊 + 焦点循环移动 + 四角框跟随(测量 rect 定位 · 角框吃 chart token · manualMode 悬停聚焦 · reduced-motion 全清晰) · typography/text · #animated ## 何时用 短句逐词聚焦:当前词清晰、其余模糊,四角括号框跟随焦点循环移动,强调「逐词扫读」。要逐词从模糊解析到清晰(不带焦点框、不循环)用 [BlurText](https://hulianui.haloritual.com/components/blur-text);要随滚动进度显影用 [ScrollReveal](https://hulianui.haloritual.com/components/scroll-reveal);普通标题用 [Heading](https://hulianui.haloritual.com/components/heading)。 ## 导入 ```ts import { TrueFocus } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | sentence | `string` | `"True Focus"` | 整句文本,按 `separator` 切词后逐词聚焦 | | separator | `string` | `" "` | 切词分隔符(传给 `String.prototype.split`) | | blurAmount | `number` | `5` | 失焦词的模糊半径(px) | | borderColor | `string` | `"var(--color-chart-1)"` | 四角括号描边色(CSS color,建议吃 token),须带 `--color-` 前缀或合法 CSS 颜色 | | animationDuration | `number` | `1.2` | 单次对焦切换的动画 / 停留秒数 | | pauseBetweenAnimations | `number` | `0.6` | 自动模式下两次切换之间的停顿(秒) | | manualMode | `boolean` | `false` | 为 true 时不自动轮播,改由鼠标悬停某词来对焦 | 其余 `
` 原生属性透传。 ## 示例 ```tsx ``` ## 禁忌 / 坑 - 角框靠测量各词 rect 定位:父容器需给足布局空间(建议固定高度容器),避免换行/挤压让框错位。 - `borderColor` 须带 `--color-` 前缀或合法 CSS 颜色;裸 `var(--primary)` 在本 Tailwind v4 设定下不解析。 - 尊重 `prefers-reduced-motion`:开启减弱动效时全词清晰、不循环聚焦。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # TypingAnimation > 打字机 · 逐字 + 闪烁光标 + 进入视口触发 · typography/text · #animated ## 何时用 逐字"打"出一段文本,带闪烁光标,默认进入视口才开始(适合首屏标语 / hero 文案)。要在固定句式里循环换词用 [WordRotate](https://hulianui.haloritual.com/components/word-rotate);静态文本用 [Text](https://hulianui.haloritual.com/components/text)。客户端组件(用 state + IntersectionObserver),源文件已含 `"use client"`。 ## 导入 ```ts import { TypingAnimation } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | text* | `string` | — | 要逐字打出的文本 | | duration | `number` | `80` | 每字毫秒 | | delay | `number` | `0` | 开始前延迟毫秒 | | startOnView | `boolean` | `true` | 进入视口才开始;设 `false` 立即开始 | | showCursor | `boolean` | `true` | 显示闪烁光标 | 继承 `ComponentPropsWithoutRef<"span">`(除 `children`),如 `className` / `style`。 ## 示例 ```tsx ``` 立即开始(不等进入视口,常用于已在首屏内): ```tsx ``` ## 禁忌 / 坑 - `startOnView` 默认 `true`:若组件初始就在视口外且页面不滚动(如截图/headless 验收),打字永不触发、看似空白——验收/首屏内场景显式传 `startOnView={false}`。 - 客户端组件,含 `"use client"`;可作为子组件嵌进 server 页,但不能当纯 RSC 用。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # VariableProximity > 鼠标邻近驱动的逐字可变字体文本 · 按距离插值 font-variation-settings(wght/opsz 等轴)+ linear/exponential/gaussian 三档衰减(零依赖 RAF · reduced-motion 定格 from · sr-only 完整朗读) · typography/text · #animated ## 何时用 需要文字按鼠标到每个字形的距离实时插值可变字体轴(wght/opsz 等),且要指定容器坐标系与衰减曲线时用。它面向「可变字体轴插值」,支持 from/to 任意轴;要更轻量的压感标题(系统字体兜底、scaleX 模拟)用 [TextPressure](https://hulianui.haloritual.com/components/text-pressure);要乱码解密入场用 [Shuffle](https://hulianui.haloritual.com/components/shuffle)。 ## 导入 ```ts import { VariableProximity } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | label* | `string` | — | 渲染文本(按词与字拆分,空格保留为不可断词隙);sr-only 副本完整朗读 | | fromFontVariationSettings* | `string` | — | 鼠标远端时的可变轴设置,如 `"'wght' 400, 'opsz' 9"`(需可变字体才有视觉变化) | | toFontVariationSettings* | `string` | — | 鼠标贴近时的目标轴设置,逐轴向此插值;缺省轴回退到 from 值 | | containerRef | `RefObject` | — | 计算鼠标相对坐标的参照容器;缺省回退到视口坐标 | | radius | `number` | `50` | 影响半径(px);超出则恢复 from 设置 | | falloff | `"linear" \| "exponential" \| "gaussian"` | `"linear"` | 衰减曲线;exponential 更陡、gaussian 中心更聚拢柔和 | | className | `string` | — | 合并到根 span 的额外类名 | | style | `CSSProperties` | — | 合并到根 span 的内联样式 | > 注:showcase controls 默认演示用 `radius={90}`,但接口默认值为 `50`。 ## Events | 事件 | 类型 | 说明 | |------|------|------| | onClick | `React.MouseEventHandler` | 点击根 span 的回调 | ## 示例 ```tsx function Demo() { const ref = useRef(null); return (
); } ``` ## 禁忌 / 坑 - 视觉变化依赖真正的可变字体:`from/to` 里写的轴(如 `wght`/`opsz`)必须是当前字体真实支持的轴,否则鼠标靠近无变化。这是字体能力限制,不是组件 bug。 - `containerRef` 决定距离坐标系:不传则按视口坐标算距离,文字在页面中部时手感会偏;通常应指向包裹本组件的盒子。 - `toFontVariationSettings` 只插值 `from` 中出现的轴,from 没列的轴不会变。 - reduced-motion 下定格在 from 设置,不随鼠标插值。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # WordRotate > 轮换词 · motion 进出场 + reduced-motion · typography/text · #animated ## 何时用 在一句固定文案里循环切换若干词("让开发 更快/更稳/更美"),用 motion 进出场动画。要逐字打字效果用 [TypingAnimation](https://hulianui.haloritual.com/components/typing-animation);静态文本用 [Text](https://hulianui.haloritual.com/components/text)。本组件是客户端组件(用 motion + state),源文件已含 `"use client"`。 ## 导入 ```ts import { WordRotate } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | words* | `string[]` | — | 轮换的词数组 | | duration | `number` | `2500` | 每词停留毫秒 | 继承 `ComponentPropsWithoutRef<"span">`(除 `children` 及 motion 冲突的 `onDrag`/`onDragStart`/`onDragEnd`/`onAnimationStart`),如 `className` / `style`。 ## 示例 ```tsx
让开发
``` ## 禁忌 / 坑 - 透传给 `motion.span`,故公开类型剔除了 `onDrag`/`onDragStart`/`onDragEnd`/`onAnimationStart`(motion 12 把它们重定义为手势/动画签名,与 DOM 同名 handler 冲突)——别尝试传这几个。 - 客户端组件,不能在纯 RSC 边界直接当 server 组件用;放进 server 页时它本身带 `"use client"` 可正常作为子组件渲染。 - 尊重 `prefers-reduced-motion`,用户开启减弱动效时进出场会退化。 ## 相关 [Text](https://hulianui.haloritual.com/components/text) · [Heading](https://hulianui.haloritual.com/components/heading) · [Prose](https://hulianui.haloritual.com/components/prose) · [Markdown](https://hulianui.haloritual.com/components/markdown) · [AuroraText](https://hulianui.haloritual.com/components/aurora-text) · [AnimatedShinyText](https://hulianui.haloritual.com/components/animated-shiny-text) # ━━━━━━━━ 表单 ━━━━━━━━ # Button > 按钮 · CVA 变体 + press 动效 · forms/button ## 何时用 最常用的操作按钮,含 solid/outline/ghost/link 变体、brand/danger 色调、loading 态与 press 缩放动效。需要特效吸睛 CTA 用 [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button)/[RainbowButton](https://hulianui.haloritual.com/components/rainbow-button)/[PulsatingButton](https://hulianui.haloritual.com/components/pulsating-button);多按钮成组用 [ButtonGroup](https://hulianui.haloritual.com/components/button-group);只要按钮样式不要 ` ``` ## 禁忌 / 坑 - `render` 模式为降低风险**不套 motion**,故无 press 缩放动效(颜色/hover 过渡仍在);文案优先取 Button 的 children。 - `loading` 会自动禁用按钮,无需再手动加 `disabled`。 - 自定义往按钮里塞图标+文字(尤其在特效按钮里)若图标掉到下一行,是 Tailwind Preflight 把 `svg{display:block}` 撑成块级所致,见 [[tailwind-preflight-svg-block-breaks-icon-text-in-nonflex-button]]——容器要 `inline-flex`,本 Button 已处理,自搓 wrapper 时注意。 ## 相关 [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button) · [RainbowButton](https://hulianui.haloritual.com/components/rainbow-button) · [PulsatingButton](https://hulianui.haloritual.com/components/pulsating-button) · [RippleButton](https://hulianui.haloritual.com/components/ripple-button) · [ButtonGroup](https://hulianui.haloritual.com/components/button-group) · [SocialButton](https://hulianui.haloritual.com/components/social-button) # ButtonGroup > 按钮组 · 把若干 Button 连排成一体(抹内侧圆角/合并相邻边框/hover 项抬层) 或分离编组 + 横竖向 · 工具栏分段/拆分按钮/步进器(纯布局壳·不接管子按钮变体) · forms/button ## 何时用 把多个相关 [Button](https://hulianui.haloritual.com/components/button) 编为一组:工具栏分段、拆分按钮(主操作 + 更多)、步进器(减/数/加)。`attached`(默认)让子按钮贴合成一体;想要语义分组但保留间距用 `attached={false}`。它只是纯布局壳,不接管子按钮的 `variant`/`size`——子按钮变体仍各自传。单个独立按钮直接用 Button。 ## 导入 ```ts import { ButtonGroup } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | orientation | `"horizontal" | "vertical"` | `"horizontal"` | 主轴方向 | | attached | `boolean` | `true` | true=子按钮贴合成一体(抹内侧圆角/合并边框/hover 抬层);false=留 gap 仅作语义分组 | | gap | `"sm" | "md"` | `"sm"` | 子项间距档(仅 `attached={false}` 生效) | | className | `string` | — | 透传根节点类名 | | aria-label | `string` | — | 组的无障碍标签 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 一般放若干 ` ``` ```tsx {/* 拆分按钮:主操作 + 更多 */} ``` ## 禁忌 / 坑 暂无已知坑。注意 `gap` 仅在 `attached={false}` 时生效;连排态(`attached`)由组件自行抹圆角/合并边框,不要再给子按钮加外边距。 ## 相关 [Button](https://hulianui.haloritual.com/components/button) · [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button) · [RainbowButton](https://hulianui.haloritual.com/components/rainbow-button) · [PulsatingButton](https://hulianui.haloritual.com/components/pulsating-button) · [RippleButton](https://hulianui.haloritual.com/components/ripple-button) · [SocialButton](https://hulianui.haloritual.com/components/social-button) # Calendar > 日历 · MUI X 桥(DateCalendar) + 对外 ISO 字符串受控 + 瑚琏 token · forms/datetime · MUI 桥 ## 何时用 需要在页面内**常驻铺开**一个月历面板让用户挑日期时用(如日程、筛选侧栏)。若想要点击触发、弹层选日期且带输入框,用 [DatePicker](https://hulianui.haloritual.com/components/date-picker);要选一段区间用 [DateRangePicker](https://hulianui.haloritual.com/components/date-range-picker);要连时间一起选用 [DateTimePicker](https://hulianui.haloritual.com/components/date-time-picker)。 ## 导入 ```ts import { Calendar } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | value | `string \| null` | — | ISO 字符串受控值;传入即受控 | | defaultValue | `string` | — | ISO 字符串非受控默认值 | | minDate | `string` | — | 可选最早日期(ISO),早于此禁选 | | maxDate | `string` | — | 可选最晚日期(ISO),晚于此禁选 | | disabled | `boolean` | `false` | 整体禁用 | | readOnly | `boolean` | `false` | 只读:可查看不可改 | | className | `string` | — | 容器类名 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onValueChange | `(iso: string \| null) => void` | 受控回调,回传 ISO 或 null(替代 MUI 的 onChange) | ## 示例 ```tsx function Demo() { const [v, setV] = useState("2026-06-03"); return ; } ``` ```tsx ``` ## 禁忌 / 坑 - 受控/非受控二选一:给了 `value` 就走受控、必须配 `onValueChange` 才能改动;只想要初值用 `defaultValue`,别同时给。 - 对外值恒为 ISO 字符串(非 Date 对象),回调 `onValueChange` 也回传 ISO 或 null,跨组件传值直接用字符串即可。 ## 相关 [DatePicker](https://hulianui.haloritual.com/components/date-picker) · [DateTimePicker](https://hulianui.haloritual.com/components/date-time-picker) · [DateRangePicker](https://hulianui.haloritual.com/components/date-range-picker) · [TimeField](https://hulianui.haloritual.com/components/time-field) · [Button](https://hulianui.haloritual.com/components/button) · [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button) # Cascader > 级联选择 · 触发器 + Popover 横向逐级面板列 + 路径数组受控 + click/hover 展开 + changeOnSelect · 复用树引擎核 · forms/advanced ## 何时用 省/市/区、分类/子类、组织层级等「有父子层级、要逐级下钻选一条完整路径」的场景用。值是从根到所选节点的 `key` 路径数组。默认须选到叶子;开 `changeOnSelect` 允许任意层提交。若数据是扁平的单层选项,用 [Combobox](https://hulianui.haloritual.com/components/combobox)/[Listbox](https://hulianui.haloritual.com/components/listbox) 即可,不必引入级联。 ## 导入 ```ts import { Cascader, flattenLeafPaths, filterLeafPaths, type CascaderLeafPath } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | nodes* | `TreeNode[]` | — | 层级数据(复用 tree-core 的 `TreeNode`,含 `key`/`label`/`children`/`disabled`) | | value | `string[]` | — | 受控路径(从根到所选节点的 key 数组) | | defaultValue | `string[]` | — | 非受控初始路径 | | expandTrigger | `"click" \| "hover"` | `"click"` | 逐级展开触发方式 | | changeOnSelect | `boolean` | `false` | 任意层节点都可提交(非仅叶子) | | showSearch | `boolean` | — | 浮层顶部出搜索框:扁平成叶子路径模糊匹配,命中行选中即提交全路径 | | searchPlaceholder | `string` | — | 搜索框占位符 | | placeholder | `string` | — | 触发器占位符 | | disabled | `boolean` | — | 禁用 | | invalid | `boolean` | — | 校验失败态 | | size | `"sm" \| "md" \| "lg"` | — | 触发器尺寸 | | className | `string` | — | 容器类名 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onChange | `(path: string[], nodes: TreeNode[]) => void` | 选中变化,回传 key 路径与对应节点链 | ## 示例 ```tsx const [value, setValue] = useState([]); setValue(path)} /> ``` 任意层可提交(如选到省或市即可): ```tsx setValue(path)} /> ``` ## 禁忌 / 坑 - `value` 是**完整 key 路径数组**(如 `["zhejiang","hangzhou","xihu"]`),不是单个叶子 key;回填时要给全路径,否则展开列对不上。 - `disabled` 的节点不可选、其子树也不会因它而展开。 - `onChange` 第二参是节点链(`TreeNode[]`),需要 label 做回显时取它而非自己再查表。 - 暂无其它已知坑。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Listbox](https://hulianui.haloritual.com/components/listbox) · [Mentions](https://hulianui.haloritual.com/components/mentions) · [InputOTP](https://hulianui.haloritual.com/components/input-otp) · [Rating](https://hulianui.haloritual.com/components/rating) # Checkbox > 复选框 · 三态(含半选) + Base UI · forms/basic ## 何时用 单个布尔勾选(同意条款、记住我),或带半选(`indeterminate`)的「全选」父框。多个互相协调的复选项用 [CheckboxGroup](https://hulianui.haloritual.com/components/checkbox-group) 包裹(值数组统一管理);二选一的开关用 [Switch](https://hulianui.haloritual.com/components/switch);互斥单选用 [Radio](https://hulianui.haloritual.com/components/radio)。 ## 导入 ```ts import { Checkbox } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | checked | `boolean` | — | 受控勾选态 | | defaultChecked | `boolean` | — | 非受控初始勾选态 | | indeterminate | `boolean` | `false` | 第三态:半选(Base UI 原生 indeterminate) | | disabled | `boolean` | `false` | 禁用 | | required | `boolean` | `false` | 必填 | | name | `string` | — | 表单字段名 | | value | `string` | — | 表单值;放进 CheckboxGroup 时按此 value 匹配成员 | | id | `string` | — | 关联 label 的 id | | className | `string` | — | 落在 Checkbox.Root | | tabIndex | `number` | — | 透传到 Checkbox.Root(树场景置 -1 退出 Tab 序,焦点由容器 roving 接管) | | aria-label | `string` | — | 无 label 时的无障碍标签 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onCheckedChange | `(checked: boolean) => void` | 勾选变化回调(瑚琏收敛签名,丢 eventDetails) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | label | `ReactNode` | 盒右 inline label(`
` 加 `noValidate`,避免浏览器原生校验抢在规则引擎前弹气泡。 ## 相关 [ModalForm / DrawerForm](https://hulianui.haloritual.com/components/form-dialog) · [ProForm](https://hulianui.haloritual.com/components/pro-form) · [StepsForm](https://hulianui.haloritual.com/components/steps-form) · [LoginForm](https://hulianui.haloritual.com/components/login-form) · [Field](https://hulianui.haloritual.com/components/field) · [SearchForm](https://hulianui.haloritual.com/components/search-form) # ImageCropper > 图片裁剪 · 固定比例框(默认证件照 5:7) + 触屏双指捏合/拖拽对位 + 缩放滑杆 + canvas 出 Blob(尺寸/质量/字节上限可配·react-easy-crop MIT) · forms/advanced ## 何时用 头像、证件照、封面图等「上传前要按固定比例裁一刀并控尺寸/体积」的场景用。给定图片源 + 比例,用户拖拽缩放对位后 `onCropped` 产出目标尺寸的 Blob。通常接在 [Upload](https://hulianui.haloritual.com/components/upload) 选完文件之后(把 File 转 object URL 喂给 `image`)。 ## 导入 ```ts import { ImageCropper, cropImageToBlob } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | image* | `string` | — | 图片源:object URL / data URL / 同源地址 | | aspect | `number` | `5/7` | 裁剪框宽高比(证件照 1 寸/2 寸同比例) | | outputWidth | `number` | `413` | 输出位图宽(px),高按 aspect 推导取整(2 寸 @300DPI) | | outputType | `string` | `"image/jpeg"` | 输出 mime | | quality | `number` | `0.9` | 编码质量 0–1 | | maxBytes | `number` | — | 输出字节上限(如 `200*1024`):超限降质重试一次 | | maxZoom | `number` | `3` | 最大缩放倍数 | | cropAreaClassName | `string` | `h-64 sm:h-80` | 裁剪画布区高度 class | | className | `string` | — | 容器类名 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onCropped* | `(blob: Blob) => void` | 确认裁剪:产出目标尺寸 Blob | | onCancel | `() => void` | 取消按钮点击(不传则不渲染取消按钮) | | onError | `(error: unknown) => void` | 画布导出失败(极旧浏览器 / canvas 受限) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | confirmLabel | `ReactNode` | 确认按钮文案(默认 `"确认"`) | | cancelLabel | `ReactNode` | 取消按钮文案(默认 `"取消"`) | ## 示例 ```tsx /* 存储/上传 */} onCancel={() => /* 关闭 */} /> ``` 方形头像: ```tsx ``` ## 禁忌 / 坑 - `image` 必须**同源可被 canvas 读取**(object URL / data URL / 同源地址);跨域无 CORS 头的图会污染画布导致导出抛错(走 `onError`)。 - `maxBytes` 是「尽力而为」:首次超限只降质重试一次(quality×0.72,下限 0.5),仍超限会原样输出,不保证一定达标。 - 不传 `onCancel` 就不渲染取消按钮(单动作场景)。 - 暂无其它已知坑。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Listbox](https://hulianui.haloritual.com/components/listbox) · [Mentions](https://hulianui.haloritual.com/components/mentions) · [InputOTP](https://hulianui.haloritual.com/components/input-otp) · [Rating](https://hulianui.haloritual.com/components/rating) # Input > 输入框 · Base UI Field + 前后缀 + invalid · forms/basic ## 何时用 单行文本输入。多行文本用 [Textarea](https://hulianui.haloritual.com/components/textarea);从固定选项里选一项用 [Select](https://hulianui.haloritual.com/components/select);布尔/多选/单选分别用 [Switch](https://hulianui.haloritual.com/components/switch) / [Checkbox](https://hulianui.haloritual.com/components/checkbox) / [Radio](https://hulianui.haloritual.com/components/radio)。放进 hulian Field 内会自动接管 label/error/aria 关联。 ## 导入 ```ts import { Input, inputShellVariants } from "@hulianui/ui" ``` ## Props 继承原生 `` 属性(除 `size`/`prefix` 被下方覆盖外,如 `value`/`onChange`/`type`/`placeholder`/`disabled`…)。 | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | size | `"sm" | "md" | "lg"` | `"md"` | 尺寸(CVA 变体,覆盖原生 size) | | invalid | `boolean` | `false` | 独立使用时标红;在 hulian Field 内由 Field.Root invalid 自动驱动,无需重复传 | | disabled | `boolean` | `false` | 禁用 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onChange | `(e: ChangeEvent) => void` | 透传原生输入回调(受控时配合 `value` 使用) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | prefix | `ReactNode` | 前缀内容(如 `¥`) | | suffix | `ReactNode` | 后缀内容(如 `.00`) | ## 示例 ```tsx ``` ```tsx {/* 前后缀 */} ``` ## 禁忌 / 坑 在 hulian Field 内时不要重复传 `invalid`——Field.Root 的 invalid 会自动驱动标红,手动再传会冲突。`invalid` 只在脱离 Field 独立使用时手动传。 ## 相关 [Textarea](https://hulianui.haloritual.com/components/textarea) · [Select](https://hulianui.haloritual.com/components/select) · [Checkbox](https://hulianui.haloritual.com/components/checkbox) · [CheckboxGroup](https://hulianui.haloritual.com/components/checkbox-group) · [Radio](https://hulianui.haloritual.com/components/radio) · [Switch](https://hulianui.haloritual.com/components/switch) # InputOTP > 验证码输入 · 分段自动跳格/退格回退/整段粘贴(零依赖) · forms/advanced ## 何时用 短信/邮箱验证码、PIN、二次验证码这类「定长、分格、填满即提交」的输入用。不要用普通文本框拼正则——本组件内置分段跳格、退格回退、整段粘贴拆分与 `onComplete`。需要任意长度自由文本请用普通 Input/[SecretField](https://hulianui.haloritual.com/components/secret-field)。 ## 导入 ```ts import { InputOTP } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | length | `number` | `6` | 分段数量 | | value | `string` | — | 受控值 | | defaultValue | `string` | — | 非受控初始值 | | type | `"numeric" \| "text"` | `"numeric"` | 仅数字(默认)或任意字符 | | disabled | `boolean` | — | 禁用 | | invalid | `boolean` | `false` | 校验失败态 | | groupGap | `boolean` | — | 中间插入横线分隔符(3-3 分组视觉,如 XXX–XXX) | | className | `string` | — | 容器类名 | | aria-label | `string` | — | 无障碍标签 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onChange | `(value: string) => void` | 值变化回调 | | onComplete | `(value: string) => void` | 填满时回调 | ## 示例 ```tsx const [otp, setOtp] = useState(""); ``` 3-3 分组: ```tsx ``` ## 禁忌 / 坑 - `onComplete` 仅在填满最后一格瞬间触发一次,验证逻辑放这里;不要在 `onChange` 里判 `value.length === length` 重复触发。 - 受控用 `value` 须配 `onChange`,否则格子无法输入。 - 暂无其它已知坑。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Listbox](https://hulianui.haloritual.com/components/listbox) · [Mentions](https://hulianui.haloritual.com/components/mentions) · [Rating](https://hulianui.haloritual.com/components/rating) · [Upload](https://hulianui.haloritual.com/components/upload) # Listbox > 可选列表 · WAI-ARIA roving tabindex + 单/多/纯动作 + typeahead(零依赖) · forms/advanced ## 何时用 需要一段「就地可见、键盘可达」的选项列表(菜单项、设置项、命令列表)时用。要单/多选受控选中态走 `selectionMode="single"/"multiple"`;只想点了就触发动作(不持有选中态)走 `selectionMode="none"` + `onAction`。和 [Combobox](https://hulianui.haloritual.com/components/combobox) 的区别:Combobox 带输入框与浮层、适合海量可搜索选项;Listbox 是常驻的扁平列表,无输入、无弹层。 ## 导入 ```ts import { Listbox } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | items* | `ListboxItemData[]` | — | 列表项;每项含 `key`/`label`,可带 `description`/`startContent`/`endContent`/`disabled` | | selectionMode | `"none" \| "single" \| "multiple"` | `"single"` | none=纯动作列表(不持有选中态);single/multiple=可选 | | selectedKeys | `string[]` | — | 受控选中键 | | defaultSelectedKeys | `string[]` | — | 非受控初始选中键 | | disabledKeys | `string[]` | — | 额外禁用键(与 `item.disabled` 合并) | | className | `string` | — | 容器类名 | | aria-label | `string` | — | 无可见标题时的无障碍标签 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onSelectionChange | `(keys: string[]) => void` | 选中变化回调 | | onAction | `(key: string) => void` | 任意项激活都触发(含 none 模式),用于命令式动作 | ## 示例 ```tsx const [keys, setKeys] = useState(["profile"]); ``` 纯动作列表(不持选中态): ```tsx run(key)} aria-label="动作列表" /> ``` ## 禁忌 / 坑 - `selectionMode="none"` 时组件不持有选中态,要响应点击必须接 `onAction`;`onSelectionChange` 在该模式下不会有意义的输出。 - 无可见标题时务必传 `aria-label`,否则屏幕阅读器读不出列表用途。 - 暂无其它已知坑。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Mentions](https://hulianui.haloritual.com/components/mentions) · [InputOTP](https://hulianui.haloritual.com/components/input-otp) · [Rating](https://hulianui.haloritual.com/components/rating) · [Upload](https://hulianui.haloritual.com/components/upload) # LoginForm > 登录模板 · 自管 useForm(账号/密码必填+记住我) + 提交 loading + logo/footer 插槽(复用 Field/Input/Checkbox/Button·文案接 i18n) · forms/framework ## 何时用 直接落地后台/应用的登录页时用:账号 + 密码 + 记住我的表单状态、必填校验、提交 loading 都由它内部托管,你只接 `onFinish`。与 [Form](https://hulianui.haloritual.com/components/form)/[ProForm](https://hulianui.haloritual.com/components/pro-form) 的区别:那两个是通用表单骨架,需要自己拼字段;LoginForm 是开箱即用的成品模板,登录场景之外不用它。 ## 导入 ```ts import { LoginForm } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | loading | `boolean` | — | 外部 loading 覆盖(父层托管提交态时用) | | showRemember | `boolean` | `true` | 是否显示「记住我」 | | className | `string` | — | 根节点类名 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onFinish | `(values: LoginValues) => void \| Promise` | 校验通过后提交;返回 Promise → 提交按钮 loading | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | title | `ReactNode` | 标题(默认 `locale.loginForm.title`) | | subtitle | `ReactNode` | 副标题(标题下方引导文案,左对齐·muted) | | logo | `ReactNode` | 品牌 logo(头部左上) | | footer | `ReactNode` | 底部附加区(忘记密码 / 注册链接等) | `LoginValues = { username: string; password: string; remember: boolean }`。 ## 示例 ```tsx } subtitle="欢迎回来,请登录你的管理后台" onFinish={async ({ username, password, remember }) => { await api.login(username, password, remember); }} footer={
忘记密码 注册账号
} /> ``` ## 禁忌 / 坑 - 表单状态由组件内部托管,外部拿不到 username/password 的实时值——只能在 `onFinish` 拿到最终 `values`。若父层自己也在管提交态(如全局 loading),用 `loading` prop 覆盖内置 loading,别另写一份。 - `onFinish` 返回 Promise 时提交按钮自动转 loading 并禁用,无需手动 disable。 ## 相关 [Form](https://hulianui.haloritual.com/components/form) · [ModalForm / DrawerForm](https://hulianui.haloritual.com/components/form-dialog) · [ProForm](https://hulianui.haloritual.com/components/pro-form) · [StepsForm](https://hulianui.haloritual.com/components/steps-form) · [Field](https://hulianui.haloritual.com/components/field) · [SearchForm](https://hulianui.haloritual.com/components/search-form) # MarkdownEditor > Markdown 编辑器 · WYSIWYG 罩 TipTap + 值进出 markdown 字符串 + 隐藏 input 桥 Field + 标准集工具栏 · forms/advanced ## 何时用 需要所见即所得地编辑长文本(订单备注、文章详情、富文本说明)且最终存 markdown 字符串时用。值进出都是 markdown 串,可经 `name` 桥接原生表单 / [Field](https://hulianui.haloritual.com/components/field)。纯短文本用普通输入框;只需 @ 提及用 [Mentions](https://hulianui.haloritual.com/components/mentions)。 ## 导入 ```ts import { MarkdownEditor } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | value | `string` | — | 受控 markdown 字符串 | | defaultValue | `string` | — | 非受控初值 | | name | `string` | — | 桥给原生表单 / Field 的隐藏 input name | | placeholder | `string` | `"输入 markdown…"` | 空内容占位文案 | | invalid | `boolean` | `false` | 校验失败态:外壳变 danger(也可由外层 Field 经 data-invalid 驱动) | | disabled | `boolean` | `false` | 禁用 | | minRows | `number` | `6` | 内容区最小高度(行) | | className | `string` | — | 透传到外壳 | | aria-label | `string` | — | 无障碍标签 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onChange | `(markdown: string) => void` | 内容变化回调,参数为 markdown 字符串 | ## 示例 ```tsx // 受控 const [md, setMd] = useState("# 标题"); // 桥接 Field(隐藏 input 承载表单值与校验) ``` ## 禁忌 / 坑 - 值进出是 markdown 字符串而非 TipTap 文档 JSON;不要把内部富文本结构当 value 传入。 - 放进 [Field](https://hulianui.haloritual.com/components/field) 校验时,`invalid` 既可自传、也可由外层 Field 的 `data-invalid` 驱动,二选一即可,不必两边都设。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Listbox](https://hulianui.haloritual.com/components/listbox) · [Mentions](https://hulianui.haloritual.com/components/mentions) · [InputOTP](https://hulianui.haloritual.com/components/input-otp) · [Rating](https://hulianui.haloritual.com/components/rating) # Mentions > @提及输入 · 复用 Textarea 皮肤 + 触发符唤起候选(镜像 div 测光标像素坐标) + aria-activedescendant 虚拟焦点(零依赖) · forms/advanced ## 何时用 多行评论/工单/动态里需要 @ 某人、# 关联工单这类「键入触发符 → 弹候选 → 插入」场景时用。它本质是带候选浮层的 Textarea。和 [Combobox](https://hulianui.haloritual.com/components/combobox) 的区别:Combobox 选「单值」整体替换输入框;Mentions 在自由文本中插入一个个提及片段,候选只在触发符后唤起,正文仍是普通多行文本。 ## 导入 ```ts import { Mentions, MentionText, type MentionTextProps, findTrigger, insertMention, defaultFilter, segmentMentions, type MentionSegment } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | options* | `MentionOption[]` | — | 候选清单;每项 `value`/`label`,可带 `description`/`startContent`/`disabled` | | value | `string` | — | 受控文本值(与 onChange 配套) | | defaultValue | `string` | — | 非受控初始值(不传 value 时生效) | | prefix | `string` | `"@"` | 触发符,可配多字符如 `"@@"`/`"#"`;其前为行首或空白时唤起候选 | | filter | `false \| ((option, query) => boolean)` | 内置子串匹配 | `false`=关闭本地过滤交给 onSearch;函数=自定义;缺省=大小写不敏感子串(label/value) | | size | `"sm" \| "md" \| "lg"` | `"md"` | 文本域皮肤尺寸(复用 Textarea 的 size 变体) | | invalid | `boolean` | `false` | 独立使用时标红 | | placeholder | `string` | — | 占位符(透传 textarea) | | rows | `number` | — | 文本域行数(透传 textarea) | | disabled | `boolean` | `false` | 禁用 | | className | `string` | — | 容器类名 | | popupClassName | `string` | — | 候选浮层额外类名 | > 还透传 `Textarea` 的原生属性(除被 Omit 的 `size`/`value`/`defaultValue`/`onChange`/`onSelect`/`prefix`)。 ## Events | 事件 | 类型 | 说明 | |------|------|------| | onChange | `(value: string) => void` | 文本变化回调(受控必接) | | onSearch | `(query: string) => void` | 查询变化通知(外部/异步过滤用,本身不返回结果) | | onSelect | `(option: MentionOption) => void` | 选中候选回调(回传整条 option) | ## 示例 ```tsx console.log(o)} /> ``` 自定义触发符 `#` 关联工单: ```tsx ``` ## 禁忌 / 坑 - 受控用法 `value` 必须配 `onChange`,否则文本无法编辑(与原生受控 textarea 同理)。 - 插入文本是 `prefix + label + " "`,`label` 即可见名也是写入正文的字面量;要展示和插入不一致请自行用 `onSelect` 接管。 - 外部/异步过滤时设 `filter={false}` 并在 `onSearch` 里刷新 `options`,否则内置子串过滤会再过滤一遍父级已筛好的结果。 - 暂无其它已知坑。 ## 相关 [SecretField](https://hulianui.haloritual.com/components/secret-field) · [Combobox](https://hulianui.haloritual.com/components/combobox) · [Listbox](https://hulianui.haloritual.com/components/listbox) · [InputOTP](https://hulianui.haloritual.com/components/input-otp) · [Rating](https://hulianui.haloritual.com/components/rating) · [Upload](https://hulianui.haloritual.com/components/upload) # ModalForm / DrawerForm > 弹窗/抽屉表单 · 列表页新增/编辑编排件(复用 Dialog/Drawer + useForm + Button footer) · 提交前自动 validate · async onFinish 成功关闭/失败保持 · 文案接 i18n · forms/framework ## 何时用 列表页点「新增/编辑」弹出表单时用:`ModalForm` 居中弹窗、`DrawerForm` 贴边抽屉,二者 API 一致(抽屉多一个 `side`)。它把 Dialog/Drawer + 提交按钮 footer + 校验编排好了。页面内常驻表单用 [ProForm](https://hulianui.haloritual.com/components/pro-form);裸表单容器用 [Form](https://hulianui.haloritual.com/components/form);多步向导用 [StepsForm](https://hulianui.haloritual.com/components/steps-form)。 ## 导入 ```ts import { ModalForm, DrawerForm } from "@hulianui/ui" ``` ## Props 公共(`ModalForm` = `FormDialogBaseProps`;`DrawerForm` 在此基础上加 `side`): | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | title * | `string` | — | 标题(a11y label) | | open | `boolean` | — | 受控开关 | | defaultOpen | `boolean` | — | 非受控初始开关 | | form | `FormInstance` | — | useForm 实例:提供则提交前自动 `validate()`,校验不过保持打开 | | submitText | `string` | `locale.modalForm.submit` | 提交按钮文案 | | cancelText | `string` | `locale.modalForm.cancel` | 取消按钮文案 | | className | `string` | — | 容器类名(控宽度等) | | side | `DrawerSide` | `"right"` | 仅 `DrawerForm`:抽屉贴边方向 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onOpenChange | `(open: boolean) => void` | 开关变化回调 | | onFinish | `(values: FormValues) => void \| boolean \| Promise` | 提交回调;返回 Promise → 按钮 loading;resolve(非 false) 自动关闭;reject 或返回 false 保持打开 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | trigger | `ReactElement` | 触发元素(非受控打开用);受控时可省 | | children | `ReactNode` | 表单字段 | ## 示例 ```tsx const form = useForm({ initialValues: { name: "" } }); const name = form.register("name", { rules: [{ required: true, message: "请输入姓名" }] }); 新增} onFinish={async (values) => { await api.create(values); }} // 校验通过+成功后自动关闭 > ``` ## 禁忌 / 坑 - 关/不关由 `onFinish` 返回值决定:resolve 非 false → 自动关;想留在原地(如自处理错误)reject 或 return false。别在 onFinish 里手动调 onOpenChange(false) 跟自动关闭打架。 - 传了 `form` 才会提交前自动 `validate()` 并在校验不过时保持打开;不传 form 则不校验、直接把 values 交给 onFinish。 - 提交成功后想清空字段需自己调 `form.resetFields()`,组件不会替你重置。 ## 相关 [Form](https://hulianui.haloritual.com/components/form) · [ProForm](https://hulianui.haloritual.com/components/pro-form) · [StepsForm](https://hulianui.haloritual.com/components/steps-form) · [LoginForm](https://hulianui.haloritual.com/components/login-form) · [Field](https://hulianui.haloritual.com/components/field) · [SearchForm](https://hulianui.haloritual.com/components/search-form) # NumberField > 数字步进 · Base UI ±按钮 + 键盘步进 + min/max · forms/basic ## 何时用 需精确录入数字并带 ± 步进按钮、min/max 边界(数量、份数、阈值)时用。只需大致量级、拖动选值用 [Slider](https://hulianui.haloritual.com/components/slider);非数字的任意文本录入用 [Input](https://hulianui.haloritual.com/components/input)。 ## 导入 ```ts import { NumberField } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | value | `number|null` | — | 受控值(null=空) | | defaultValue | `number` | — | 非受控初始值 | | min | `number` | — | 最小值 | | max | `number` | — | 最大值 | | step | `number` | `1` | 步进量 | | disabled | `boolean` | `false` | 禁用 | | readOnly | `boolean` | `false` | 只读 | | required | `boolean` | — | 表单必填 | | name | `string` | — | 原生表单 name | | id | `string` | — | — | | className | `string` | — | — | | aria-label | `string` | — | 无可见标题时提供 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onValueChange | `(value: number|null) => void` | 变化回调(瑚琏收敛签名,丢 Base UI eventDetails) | ## 示例 ```tsx ``` 受控(值可为空): ```tsx const [v, setV] = useState(2); ``` ## 禁忌 / 坑 - 受控值类型是 `number | null`——清空时回调拿到 `null`,state 须用 `useState`,别假设永远是 number。 - 用 `value`/`onValueChange` 即受控,须自管 state;非受控只给 `defaultValue`。 - 无可见标题时给 `aria-label`,否则读屏无名。 ## 相关 [Input](https://hulianui.haloritual.com/components/input) · [Textarea](https://hulianui.haloritual.com/components/textarea) · [Select](https://hulianui.haloritual.com/components/select) · [Checkbox](https://hulianui.haloritual.com/components/checkbox) · [CheckboxGroup](https://hulianui.haloritual.com/components/checkbox-group) · [Radio](https://hulianui.haloritual.com/components/radio) # ProForm > 内联表单编排 · useForm + 自动 footer(提交/重置) + async onFinish loading + 自定义 footer(ModalForm 的内联姊妹件·文案接 i18n) · forms/framework ## 何时用 页面内**常驻**一个表单、要自带提交/重置 footer 和响应式栅格时用(详情页编辑、设置页)。它是 [ModalForm / DrawerForm](https://hulianui.haloritual.com/components/form-dialog) 的内联姊妹件——同样 useForm + 自动 footer,只是不弹层。要弹窗/抽屉提交用 ModalForm/DrawerForm;只要裸容器、自己管 footer 用 [Form](https://hulianui.haloritual.com/components/form);查询条件用 [SearchForm](https://hulianui.haloritual.com/components/search-form)。 ## 导入 ```ts import { ProForm } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | form | `FormInstance` | — | useForm 实例:提供则提交前自动 `validate()`,重置走 `form.resetFields()` | | submitText | `string` | `locale.proForm.submit` | 提交按钮文案 | | resetText | `string` | `locale.proForm.reset` | 重置按钮文案 | | showReset | `boolean` | `true` | 是否显示重置按钮(需 form 才有意义) | | columns | `1 \| 2 \| 3` | `1` | 字段栅格列数;≥2 时按容器宽度自适应(窄塌单列),跨整行用 `` | | footerAlign | `"left" \| "right"` | `"left"` | 底部操作区对齐 | | className | `string` | — | 容器类名 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onFinish | `(values: FormValues) => void \| boolean \| Promise` | 提交回调;返回 Promise → 提交按钮 loading;reject 不抛断(错误反馈交消费者) | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | footer | `ReactNode` | 自定义底部操作区(覆盖默认提交/重置按钮) | | children | `ReactNode` | 表单字段 | ## 示例 ```tsx const form = useForm({ initialValues: { name: "", email: "" } }); const name = form.register("name", { rules: [{ required: true, message: "请输入姓名" }] }); const email = form.register("email", { rules: [{ pattern: /@/, message: "邮箱需含 @" }] }); { await api.save(v); }}> ``` ```tsx // 响应式栅格:columns 走容器查询(窄自动塌单列),跨行字段用 colSpan="full" {}}> ``` ## 禁忌 / 坑 - `columns` 是**容器查询**自适应(按表单容器实际宽度塌列),不是视口断点;别再手搓 grid + media query,跨整行字段用 ``。 - 与 ModalForm 不同,ProForm 的 `onFinish` reject **不抛断**——错误反馈(toast 等)由消费者自己处理。 - 重置按钮只有传了 `form` 才有意义(走 `form.resetFields()`);用 `footer` 自定义底部会**覆盖**默认提交/重置按钮,此时需自己接提交逻辑。 ## 相关 [Form](https://hulianui.haloritual.com/components/form) · [ModalForm / DrawerForm](https://hulianui.haloritual.com/components/form-dialog) · [StepsForm](https://hulianui.haloritual.com/components/steps-form) · [LoginForm](https://hulianui.haloritual.com/components/login-form) · [Field](https://hulianui.haloritual.com/components/field) · [SearchForm](https://hulianui.haloritual.com/components/search-form) # PulsatingButton > 脉冲按钮 · 外扩光环(box-shadow) + RSC · forms/button · #animated ## 何时用 用一圈外扩脉冲光环引导用户注意的 CTA(订阅、提交等)。普通操作用 [Button](https://hulianui.haloritual.com/components/button);边缘游走火花用 [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button);彩虹流光底用 [RainbowButton](https://hulianui.haloritual.com/components/rainbow-button)。 ## 导入 ```ts import { PulsatingButton } from "@hulianui/ui" ``` ## Props | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | pulseColor | `string` | `var(--color-primary)` 的 70% | 脉冲光环色 | | duration | `string` | `1.5s` | 一轮脉冲秒数 | | ...buttonProps | `ComponentPropsWithoutRef<"button">` | — | 透传原生 button 属性 | ## Events | 事件 | 类型 | 说明 | |------|------|------| | onClick | `(e: MouseEvent) => void` | 点击回调,经 `ComponentPropsWithoutRef<"button">` 透传 | ## Slots | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 按钮文案,经原生 button 属性透传 | ## 示例 ```tsx 立即订阅 // 放慢脉冲 立即订阅 ``` ## 禁忌 / 坑 - 自定义往按钮塞图标+文字若图标掉行,是 Tailwind Preflight `svg{display:block}` 所致,见 [[tailwind-preflight-svg-block-breaks-icon-text-in-nonflex-button]]——确保文案容器是 `inline-flex`。 ## 相关 [Button](https://hulianui.haloritual.com/components/button) · [ShimmerButton](https://hulianui.haloritual.com/components/shimmer-button) · [RainbowButton](https://hulianui.haloritual.com/components/rainbow-button) · [RippleButton](https://hulianui.haloritual.com/components/ripple-button) · [ButtonGroup](https://hulianui.haloritual.com/components/button-group) · [SocialButton](https://hulianui.haloritual.com/components/social-button) # Radio > 单选 · RadioGroup 单选组 + 键盘方向键 · forms/basic ## 何时用 一组互斥选项里选且只选一个、且选项数少(约 2–6 个)需全部直接可见时用。选项多需收起或搜索改用 [Select](https://hulianui.haloritual.com/components/select);多选共存改用 [CheckboxGroup](https://hulianui.haloritual.com/components/checkbox-group);横向二三段且要滑块视觉用 [Segmented](https://hulianui.haloritual.com/components/segmented)。 ## 导入 ```ts import { RadioGroup, Radio } from "@hulianui/ui" ``` ## Props `RadioGroup` | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | value | `string` | — | 受控选中值 | | defaultValue | `string` | — | 非受控初始选中值 | | disabled | `boolean` | `false` | 整组禁用 | | required | `boolean` | — | 表单必选 | | name | `string` | — | 原生表单 name | | orientation | `"vertical"|"horizontal"` | `"vertical"` | 仅控布局 | | className | `string` | — | — | | aria-label | `string` | — | 无可见标题时提供 | `Radio` | 名称 | 类型 | 默认 | 说明 | |------|------|------|------| | value * | `string` | — | 必填,标识该选项 | | disabled | `boolean` | `false` | 单项禁用 | | id | `string` | — | — | | className | `string` | — | 落在 Radio.Root | ## Events `RadioGroup` | 事件 | 类型 | 说明 | |------|------|------| | onValueChange | `(value: string) => void` | 选中变化回调 | ## Slots `RadioGroup` | 插槽 | 类型 | 说明 | |------|------|------| | children | `ReactNode` | 内放 `Radio` 项 | `Radio` | 插槽 | 类型 | 说明 | |------|------|------| | label | `ReactNode` | 可选 inline label(点右,原生 `