Appearance
基础 UI 组件
@mbjia/ui
基础 UI 组件
@mbjia/ui 提供模板加业务中常用的基础 React 组件。它不是完整替代 Ant Design,而是在 AntD 4 和内部业务样式基础上封装按钮、弹窗、输入框、浮层、分页、上传触发等能力。
何时使用
适合普通 React 页面里使用统一的模板加基础交互组件,例如按钮、弹窗、输入框、下拉、浮层、分页、文件选择入口。
如果要接入素材管理、全局上传、AI 搜索、支付权益等强业务能力,应查看 业务组件。
公共能力
| 能力 | 说明 |
|---|---|
| AntD 继承 | Button、Modal、Pagination、SolidArrowSelect 等组件继承或组合 AntD 4 能力。 |
| 主题样式 | Button 支持模板加主题、普通主题、渐变样式和定制主题样式。 |
| 弹层能力 | Popup 提供 click、hover、focus、right-click 等触发方式,DropDown 基于 Popup 封装。 |
| 受控能力 | 部分组件支持受控值,例如 Pagination.page、Popup.open、SolidArrowSelect.value。 |
| 回调出参 | 组件通过 onChange、action、onClose、onConfirm 等回调向业务侧返回值。 |
| 样式依赖 | 需要业务项目能处理 Less、CSS Modules、styled-components 和 AntD 样式。 |
同页接入参考
工程前置条件
基础 UI 的接入门槛低于业务组件,但仍需要业务项目满足 React、AntD 和样式编译要求。
| 项目 | 要求 | 说明 |
|---|---|---|
| React | ~17.0.0 | 当前源码按 React 17 开发和验证。 |
| Ant Design | 4.24.x | 多个组件继承或组合 AntD 4。 |
| 样式 | Less / CSS Modules / styled-components | 组件源码混合使用这些样式方案。 |
常用数据类型
基础 UI 常见类型主要来自组件回调和选项数据。业务素材模型、上传任务等大型结构见 公共数据结构。
| 类型 | 用途 | 结构 |
|---|---|---|
OptionItemType | DropDown 选项 | { type, title?, value?, disabled?, checked? } |
BreadcrumbItem | BreadCrumb 路径项 | { id: string; title: string } |
PopupActions | Popup ref | open / close / toggle / isOpen |
事件和回调规则
基础 UI 主要通过组件回调返回数据,不依赖全局事件协议。业务组件的跨模块事件见 事件协议。
| 组件 | 回调 | 返回值 |
|---|---|---|
| Input | onChange | ChangeEvent<HTMLInputElement> |
| DropDown | onChange | string | number |
| Pagination | onChange | number |
| Upload | action | File[] | FileList |
组件总览
Button
封装 AntD Button,增加模板加主题、尺寸和渐变样式。
效果预览
模板加主题
渐变按钮
使用示例
tsx
import { Button } from '@mbjia/ui'
export default function Demo() {
return (
<Button mbjia w={120} h={42} onClick={() => console.log('click')}>
确定
</Button>
)
}Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
w | number | string | 否 | 120 | 按钮宽度。传 100% 时外层容器也会设置为 100%。 |
h | number | string | 否 | 42 | 按钮高度,同时影响圆角尺寸。 |
gradient | 'light' | 'dark' | 'none' | 否 | null | 渐变样式。 |
mbjia | boolean | 否 | false | 使用模板加主题按钮样式。 |
normal | boolean | 否 | false | 使用普通按钮样式。 |
theme | boolean | 否 | false | 使用定制主题样式。 |
containerClassname | string | 否 | - | 外层容器 class。 |
其余属性继承 AntD ButtonProps,例如 onClick、disabled、loading、type。
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onClick | MouseEvent | 继承 AntD Button 点击事件。 |
Modal
封装 AntD Modal,默认隐藏 footer,适合业务自己控制操作按钮。
效果预览
弹窗标题
默认隐藏 footer,内容区域由业务自行控制。
使用示例
tsx
import { Modal } from '@mbjia/ui'
<Modal open title="标题" onCancel={onClose}>
内容
</Modal>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
rounded | boolean | 否 | true | 是否使用圆角弹窗样式。 |
closeIconOutside | boolean | 否 | false | 关闭图标是否展示在弹窗外侧。 |
其余属性继承 AntD ModalProps。组件内部固定 footer={null},并隐藏 cancel 按钮。
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onCancel | MouseEvent | 继承 AntD Modal 关闭回调。 |
onOk | MouseEvent | 可透传,但默认无 footer,通常由业务按钮自行触发。 |
Input
封装 AntD Input,内置本地输入状态,并支持错误态、ghost、小尺寸、自动聚焦和防抖回调。
效果预览
普通输入框
搜索输入框
使用示例
tsx
import { Input } from '@mbjia/ui'
<Input
placeholder="搜索素材"
debounceDelay={200}
onChange={(event) => console.log(event.target.value)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
onChange | (e: ChangeEvent<HTMLInputElement>) => void | 是 | - | 输入变化回调。 |
placeholder | string | 是 | '' | 占位文本。 |
customStyle | CSSProperties | 否 | - | 外层容器样式。 |
ghost | boolean | 否 | - | 是否使用 ghost 样式。 |
small | boolean | 否 | - | 是否使用小尺寸样式。 |
errMsg | string | 否 | '' | 有值时显示错误样式。 |
h | string | number | 否 | 34px | 输入框高度。 |
debounceDelay | number | 否 | 0 | onChange 防抖延迟,单位毫秒。 |
maxLength | number | 否 | 50 | 最大输入长度。 |
focus | boolean | 否 | false | 挂载后自动聚焦。 |
其余属性继承 AntD InputProps。
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onChange | ChangeEvent<HTMLInputElement> | 可通过 event.target.value 读取当前输入值。 |
注意事项
源码类型中存在历史字段 maxlength,实际传给 AntD 的是 maxLength。
DropDown
基于 Popup 封装的业务下拉选择,支持分割线、禁用项、自定义渲染和弹层样式。
效果预览
最新
最热
文件名
最热
文件名
使用示例
tsx
import { DropDown } from '@mbjia/ui'
<DropDown
value="new"
options={[
{ type: 'option', title: '最新', value: 'new' },
{ type: 'dash' },
{ type: 'option', title: '最热', value: 'hot' },
]}
onChange={(value) => console.log(value)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
options | OptionItemType[] | 是 | - | 下拉选项。 |
onChange | (v: string | number) => void | 否 | - | 点击选项回调。 |
value | string | number | string[] | number[] | 否 | '' | 当前值。源码类型写作 never,实际运行中会调用 value?.includes?.(...)。 |
title | string | 否 | - | 自定义触发器标题。 |
disabled | boolean | 否 | false | 禁用下拉。 |
titleGrey | boolean | 否 | false | 标题置灰。 |
wrapperStyle | CSSProperties | 否 | {} | 弹层内容样式。 |
customStyle | CSSProperties | 否 | {} | 触发器样式。 |
itemStyle | CSSProperties | 否 | {} | 选项样式。 |
popupRef | RefObject<PopupActions> | 否 | - | Popup ref。 |
alignLeft | boolean | 否 | false | 选项左对齐。 |
renderItem | (data: OptionItemType) => ReactNode | 否 | null | 自定义选项渲染。 |
zIndex | number | 否 | 3002 | 弹层层级。 |
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onChange | string | number | 当前点击选项的 value。禁用项不会触发。 |
数据类型
ts
type OptionItemType = {
type: 'dash' | 'option'
disabled?: boolean
checked?: boolean
title?: string
value?: string | number
}Popup
通用浮层组件,支持 hover、click、focus、右键触发,也支持受控打开。
效果预览
弹层内容
使用示例
tsx
import { Popup } from '@mbjia/ui'
<Popup trigger={<button>打开</button>} position="bottom center">
<div>弹层内容</div>
</Popup>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
children | ReactNode | 是 | - | 弹层内容。 |
trigger | JSX.Element | (isOpen: boolean) => JSX.Element | 否 | null | 触发元素;为空时按 modal 行为处理。 |
on | EventType | EventType[] | 否 | ['click'] | 触发方式。 |
position | PopupPosition | PopupPosition[] | 否 | 'bottom center' | 弹层位置。 |
defaultOpen | boolean | 否 | false | 默认打开。 |
open | boolean | 否 | - | 受控打开。 |
disabled | boolean | 否 | false | 禁用。 |
nested | boolean | 否 | false | 是否嵌套弹层。 |
arrow | boolean | 否 | true | 是否显示箭头。 |
modal | boolean | 否 | false | 是否按 modal 行为渲染。 |
lockScroll | boolean | 否 | false | modal 时锁定 body 滚动。 |
closeOnDocumentClick | boolean | 否 | true | 点击外部关闭。 |
closeOnEscape | boolean | 否 | true | ESC 关闭。 |
repositionOnResize | boolean | 否 | true | 窗口尺寸变化时重新定位。 |
mouseEnterDelay | number | 否 | 100 | hover 打开延迟。 |
mouseLeaveDelay | number | 否 | 200 | hover 关闭延迟。 |
contentStyle | CSSProperties | 否 | {} | 弹层内容样式。 |
overlayStyle | CSSProperties | 否 | {} | 遮罩样式。 |
arrowStyle | CSSProperties | 否 | {} | 箭头样式。 |
className | string | 否 | '' | 弹层 class。 |
keepTooltipInside | boolean | string | 否 | false | 是否限制在容器内。 |
回调与 ref
| 名称 | 出参 / 返回值 | 说明 |
|---|---|---|
onOpen | (event?: SyntheticEvent) => void | 打开后回调。 |
onClose | (event?: SyntheticEvent | KeyboardEvent | TouchEvent | MouseEvent) => void | 关闭后回调。 |
ref.open() | void | 打开弹层。 |
ref.close() | void | 关闭弹层。 |
ref.toggle() | void | 切换打开状态。 |
ref.isOpen() | boolean | 返回当前打开状态。 |
数据类型
ts
type EventType = 'hover' | 'click' | 'focus' | 'right-click'
type PopupPosition =
| 'top left' | 'top center' | 'top right'
| 'right top' | 'right center' | 'right bottom'
| 'bottom left' | 'bottom center' | 'bottom right'
| 'left top' | 'left center' | 'left bottom'
| 'center center'
type PopupActions = {
open: () => void
close: () => void
toggle: () => void
isOpen: () => boolean
}BreadCrumb
面包屑组件,用于展示目录或页面层级。超过 maxCount 时会保留前两个和后两个,中间用 ... 浮层展示。
效果预览
首页 > 素材管理 > 图片素材
使用示例
tsx
import { BreadCrumb } from '@mbjia/ui'
<BreadCrumb
maxCount={5}
list={[
{ id: 'root', title: '首页' },
{ id: 'asset', title: '素材管理' },
]}
onChange={(id, name) => console.log(id, name)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
list | BreadcrumbItem[] | 是 | - | 面包屑列表。 |
maxCount | number | 是 | - | 超过后折叠中间项。 |
onChange | (id: string, name?: string) => void | 是 | - | 点击面包屑回调。 |
数据类型
ts
interface BreadcrumbItem {
title: string
id: string
}回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onChange | id: string, name?: string | 点击项的 id 和标题。折叠项点击时源码中部分路径只传 id。 |
BreadCrumbLevels
横向可拖动的层级面包屑,基于 AntD Breadcrumb 和 react-indiana-drag-scroll。适合目录层级较长、需要横向滚动查看的场景。
效果预览
使用示例
tsx
import { BreadCrumbLevels } from '@mbjia/ui'
<BreadCrumbLevels
items={[
{ id: 'root', name: '全部素材', type: 'all' },
{ id: 'brand', name: '品牌素材', type: 'brand' },
]}
changeTabs={(item) => console.log(item)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
items | BreadcrumbLevelsItem[] | 是 | [] | 面包屑层级列表。 |
changeTabs | (item: BreadcrumbLevelsItem) => void | 否 | - | 点击项后的外部回调。 |
separator | ReactNode | 否 | '>' | 分隔符。 |
maxChartLength | number | 否 | 6 | 名称超过该长度时截断并显示 Tooltip。 |
数据类型
ts
interface BreadcrumbLevelsItem {
id: string
name: string
onClick?: (item: BreadcrumbLevelsItem) => void
className?: string
[propName: string]: unknown
}回调和事件
| 名称 | 出参 | 说明 |
|---|---|---|
item.onClick | BreadcrumbLevelsItem | 点击当前项时先触发。 |
changeTabs | BreadcrumbLevelsItem | 点击当前项后触发。 |
eventBus.emit('global:updateFolderType') | item.type | 组件内部会发出该全局事件。 |
Pagination
封装 AntD Pagination,固定隐藏 pageSize 切换和快速跳转。
效果预览
...
使用示例
tsx
import { Pagination } from '@mbjia/ui'
<Pagination
page={1}
pageSize={20}
total={100}
onChange={(page) => console.log(page)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
page | number | 是 | - | 当前页。 |
pageSize | number | 否 | - | 每页数量,传给 AntD defaultPageSize。 |
total | number | 是 | - | 总数。 |
onChange | (value: number) => void | 是 | - | 页码变化回调。 |
disabled | boolean | 否 | false | 是否禁用。 |
组件内部固定 hideOnSinglePage、showSizeChanger={false}、showQuickJumper={false}。
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onChange | number | 当前页码。 |
Upload
文件选择触发组件,内部调用 @mbjia/utils 的 showPicker。
效果预览
使用示例
tsx
import { Upload } from '@mbjia/ui'
<Upload accept="video/*" mimeType="video" action={(files) => console.log(files)}>
<button>选择视频</button>
</Upload>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
children | ReactNode | 是 | - | 触发内容。 |
action | (files: File[] | FileList) => void | 是 | - | 文件选择后回调。 |
accept | string | 是 | - | 文件类型。传 video/* 时内部会把 mimeType 当作 video。 |
mimeType | 'music' | 'media' | 'excle' | 'img' | 'video' | 否 | 'media' | 选择器类型。 |
multiple | boolean | 否 | true | 是否多选。 |
回调与 ref
| 名称 | 出参 / 返回值 | 说明 |
|---|---|---|
action | File[] | FileList | 文件选择结果。 |
ref.dispatch() | void | 主动打开文件选择器。 |
Skeleton
基于 styled-components 的骨架屏占位组件。
效果预览
使用示例
tsx
import { Skeleton } from '@mbjia/ui'
<div style={{ width: 240, height: 80 }}>
<Skeleton />
</div>Props
Skeleton 是 styled div,没有额外业务 Props。常用方式是在父容器上控制宽高。
SolidArrowSelect
基于 AntD Dropdown 的多级选择组件,支持受控值、默认值、菜单项和选中项文本溢出 Tooltip。
使用示例
tsx
import { SolidArrowSelect } from '@mbjia/ui'
<SolidArrowSelect
defaultValue={1}
options={[
{ key: 1, label: '全部' },
{ key: 2, label: '图片' },
]}
onChange={(value, keyPath, item) => console.log(value, keyPath, item)}
/>Props
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
options | AntD Menu items | 是 | - | 菜单选项,支持 children。 |
defaultValue | number[] | number | 是 | - | 默认选中值。 |
value | number[] | number | 否 | - | 受控值。 |
trigger | 'hover' | 'click' | 否 | - | 样式标识;当前源码中没有控制 Dropdown open 状态。 |
overlayClassName | string | 否 | - | 弹层 class。 |
hide | boolean | 否 | - | 隐藏样式。 |
onChange | (value: number, keyPath: string[], item: any) => void | 否 | - | 菜单项点击回调。 |
其余属性会透传给 AntD Dropdown。
回调出参
| 回调 | 出参 | 说明 |
|---|---|---|
onChange | value: number | 当前选中项 key 转为数字。 |
onChange | keyPath: string[] | AntD 菜单 keyPath。 |
onChange | item: any | 根据 keyPath 在 options 中找到的选项。 |
HeadlessBaseBtn
无样式基础按钮容器,源码是一个 styled.div,只设置了 cursor: pointer。适合业务需要完全自定义视觉,但希望保持可点击指针样式的场景。
效果预览
自定义可点击区域
使用示例
tsx
import { HeadlessBaseBtn } from '@mbjia/ui'
<HeadlessBaseBtn onClick={() => console.log('click')}>
自定义内容
</HeadlessBaseBtn>Props
HeadlessBaseBtn 是 styled div,没有额外业务 Props。可使用普通 div 支持的属性,例如 className、style、onClick。