starry-sky-ui
v0.7.2
Published
starry-sky-ui — 轻量级 React UI 组件库
Maintainers
Readme
Starry Sky UI — 轻量级 React UI 组件库
一套轻量级 React UI 组件库,API 参考 Ant Design 标准,提供基础通用组件。
适用于博客、后台管理、个人项目等场景。
📖 文档地址:https://www.adai.org.cn/ad-ui
🏠 码云仓库:https://gitee.com/qqqsdx/starry-sky-ui
安装
npm install starry-sky-ui
# 或
yarn add starry-sky-ui
# 或
pnpm add starry-sky-ui快速开始
import { Message, message, Select, Modal } from 'starry-sky-ui';
import type { SelectOption, ModalProps } from 'starry-sky-ui';
function App() {
return (
<div>
<Message />
<Select options={[{ label: '选项一', value: '1' }]} />
<button onClick={() => message.success('Hello Starry Sky UI!')}>
提示
</button>
</div>
);
}目录结构
src/components/ad-ui/
├── Message/
│ ├── index.tsx
│ └── index.scss
├── Modal/
│ ├── index.tsx
│ └── index.scss
├── Select/
│ ├── index.tsx
│ └── index.scss
├── Starfield/
│ ├── index.tsx
│ └── index.scss
├── Table/
│ ├── index.tsx
│ └── index.scss
├── Pagination/
│ ├── index.tsx
│ └── index.scss
├── types.ts # 公共类型导出
├── index.ts # 统一导出入口
└── README.mdMessage — 消息提示
全局消息提示,支持 info、success、error、warning、loading 五种类型,自动消失。
基本用法
import { Message, message } from 'starry-sky-ui';
// 1. 在应用根节点挂载 Message 组件
function App() {
return (
<div>
<Message />
{/* your app */}
</div>
);
}
// 2. 通过 message 对象调用
message.success('操作成功');
message.error('操作失败');
message.warning('警告提示');
message.info('这是一条提示');
message.loading('加载中...', 0); // duration=0 不自动消失
// 返回的 MessageInstance 支持 then 语法
message.loading('提交中...');
await submitForm();
message.success('提交成功');通用 open 方法
message.open({
type: 'success',
content: '自定义消息',
duration: 5000,
className: 'my-custom-class',
style: { fontSize: 16 },
onClose: () => console.log('closed'),
});全局配置
message.config({
top: 100, // 距离顶部距离,默认 20
duration: 5000, // 默认显示时长,默认 3000ms
maxCount: 3, // 最大显示数量,超出时移除最早的消息
getContainer: () => document.getElementById('msg-area')!,
});销毁所有消息
message.destroy();API 速查
| 方法 | 说明 |
|------|------|
| message.info(content, duration?, onClose?) | 信息提示 |
| message.success(content, duration?, onClose?) | 成功提示 |
| message.error(content, duration?, onClose?) | 错误提示 |
| message.warning(content, duration?, onClose?) | 警告提示 |
| message.loading(content, duration?, onClose?) | 加载提示 |
| message.open(config) | 通用打开(支持 className/style) |
| message.config(config) | 全局配置 |
| message.destroy() | 销毁所有消息 |
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| top | number | 20 | 消息距离顶部距离 |
| duration | number | 3000 | 默认自动消失时长(ms),0 为不消失 |
| maxCount | number | Infinity | 最大显示数量 |
| getContainer | () => HTMLElement | — | 自定义挂载容器 |
Select — 下拉选择器
通用下拉选择框,支持搜索、清除、受控/非受控、键盘导航、尺寸调整。
基本用法
import { Select } from 'starry-sky-ui';
import type { SelectOption } from 'starry-sky-ui';
const options: SelectOption[] = [
{ label: 'React', value: 'react' },
{ label: 'Vue', value: 'vue', disabled: true },
{ label: 'Angular', value: 'angular' },
];
// 非受控
<Select
options={options}
defaultValue="react"
onChange={(val, option) => console.log(val, option)}
/>
// 受控
<Select
options={options}
value={value}
onChange={(val) => setValue(String(val))}
placeholder="请选择框架"
/>搜索 & 清除
<Select
options={options}
showSearch // 启用搜索
allowClear // 启用清除按钮
filterOption={(input, opt) => // 自定义过滤
opt.label.includes(input) || opt.value.toString().includes(input)
}
notFoundContent={<span>未找到匹配项</span>}
/>受控展开
<Select
options={options}
open={open}
onOpenChange={(o) => setOpen(o)}
/>Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| options | SelectOption[] | — | 选项列表 |
| value | string \| number | — | 受控:当前选中值 |
| defaultValue | string \| number | — | 非受控:默认选中值 |
| onChange | (value, option) => void | — | 选中回调 |
| placeholder | string | '请选择' | 占位文本 |
| disabled | boolean | false | 禁用 |
| size | 'small' \| 'middle' \| 'large' | 'middle' | 尺寸 |
| allowClear | boolean | false | 显示清除按钮 |
| showSearch | boolean | false | 支持搜索过滤 |
| filterOption | (input, option) => boolean | 按 label 匹配 | 自定义过滤逻辑 |
| notFoundContent | ReactNode | '暂无数据' | 空数据内容 |
| bordered | boolean | true | 是否显示边框 |
| open | boolean | — | 受控:是否展开 |
| onOpenChange | (open) => void | — | 展开变化回调 |
| dropdownMatchSelectWidth | boolean | true | 下拉菜单匹配选择器宽度 |
| listHeight | number | 256 | 下拉菜单最大高度 |
| className | string | '' | 自定义类名 |
| style | CSSProperties | — | 自定义样式 |
| dropdownClassName | string | '' | 下拉菜单类名 |
| onBlur | () => void | — | 失焦回调 |
| onFocus | () => void | — | 聚焦回调 |
| getPopupContainer | () => HTMLElement | — | 自定义下拉容器 |
类型
interface SelectOption {
label: string;
value: string | number;
disabled?: boolean;
}Modal — 弹窗
通用模态弹窗,支持标题、底部按钮、动画、确认/取消、loading 态。
基本用法
import { Modal } from 'starry-sky-ui';
import { useState } from 'react';
const [open, setOpen] = useState(false);
<Modal open={open} onClose={() => setOpen(false)} title="提示">
<p>弹窗内容</p>
</Modal>确认弹窗
<Modal
open={open}
title="确认删除"
onOk={async () => {
await deleteItem();
setOpen(false);
}}
onCancel={() => setOpen(false)}
confirmLoading
okText="删除"
cancelText="取消"
centered
>
<p>确定要删除此项吗?删除后不可恢复。</p>
</Modal>自定义底部 & 隐藏关闭按钮
<Modal
open={open}
onClose={() => setOpen(false)}
title="自定义"
closable={false} // 隐藏关闭按钮
footer={null} // 隐藏底部
>
{/* 自定义内容 */}
</Modal>
<Modal
open={open}
title="自定义底部"
footer={
<div style={{ textAlign: 'center' }}>
<button onClick={() => setOpen(false)}>我知道了</button>
</div>
}
>
<p>内容</p>
</Modal>无遮罩 & 禁止遮罩关闭
<Modal
open={open}
mask={false} // 无遮罩
maskClosable={false} // 禁止点击遮罩关闭
keyboard={false} // 禁止 ESC 关闭
>
<p>必须通过按钮关闭</p>
</Modal>destroyOnClose
<Modal open={open} destroyOnClose>
{/* 关闭后子节点会被销毁,适合包含表单等需要重置的场景 */}
<ExpensiveForm />
</Modal>afterClose
<Modal
open={open}
onClose={() => setOpen(false)}
afterClose={() => console.log('弹窗已完全关闭')}
>
<p>内容</p>
</Modal>Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| open | boolean | false | 是否显示 |
| onClose | () => void | — | 关闭回调 |
| onOk | () => void \| Promise<void> | — | 确认回调(支持 async) |
| onCancel | () => void | — | 取消回调 |
| afterClose | () => void | — | 关闭动画完成后回调 |
| title | ReactNode | — | 标题 |
| children | ReactNode | — | 内容 |
| footer | ReactNode \| null | 默认确定/取消按钮 | 底部,null 隐藏 |
| closeButton | ReactNode | — | 自定义关闭按钮 |
| width | number \| string | 520 | 宽度(数字为 px) |
| height | number \| string | — | 高度 |
| centered | boolean | false | 垂直居中 |
| mask | boolean | true | 是否显示遮罩 |
| maskClosable | boolean | true | 点击遮罩是否关闭 |
| closable | boolean | true | 是否显示关闭按钮 |
| keyboard | boolean | true | 是否支持 ESC 关闭 |
| confirmLoading | boolean | false | 确认按钮 loading 态 |
| destroyOnClose | boolean | false | 关闭时销毁子节点 |
| zIndex | number | 1000 | 自定义 z-index |
| okText | string | '确定' | 确定按钮文案 |
| cancelText | string | '取消' | 取消按钮文案 |
| className | string | '' | 自定义类名 |
| style | CSSProperties | — | 自定义样式 |
| bodyStyle | CSSProperties | — | 内容区样式 |
| getContainer | () => HTMLElement | — | 自定义容器 |
Table — 表格
功能丰富的表格组件,支持排序、分页、行选择、自定义渲染、固定表头、加载态等。
基本用法
import { Table } from 'starry-sky-ui';
import type { ColumnType } from 'starry-sky-ui';
const columns: ColumnType[] = [
{ title: '名称', dataIndex: 'name', key: 'name', sorter: (a, b) => a.name.localeCompare(b.name) },
{ title: '版本', dataIndex: 'version', key: 'version' },
{ title: '使用率', dataIndex: 'usage', key: 'usage', render: (val) => <ProgressBar value={val} /> },
];
const data = [
{ key: '1', name: 'React', version: '18.3.1', usage: '81%' },
{ key: '2', name: 'Vue', version: '3.4.0', usage: '65%' },
];
<Table
columns={columns}
dataSource={data}
rowKey="key"
pagination={{ pageSize: 10, showTotal: true }}
/>排序
在 ColumnType 中设置 sorter 即可启用排序,支持传入排序函数或 true:
const columns: ColumnType[] = [
{ title: '名称', dataIndex: 'name', sorter: (a, b) => a.name.localeCompare(b.name) },
{ title: '版本', dataIndex: 'version', sorter: true },
];传
true时会尝试默认比较,推荐传入具体的比较函数以获得准确排序。
行选择
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
<Table
columns={columns}
dataSource={data}
rowKey="key"
rowSelection={{
selectedRowKeys: selectedKeys,
onChange: (keys, rows) => setSelectedKeys(keys),
getCheckboxProps: (record) => ({ disabled: record.name === 'Angular' }),
}}
/>加载态 & 空态
// 加载中
<Table columns={columns} dataSource={[]} loading />
// 空数据
<Table columns={columns} dataSource={[]} emptyText="暂无数据" />
// 自定义空态
<Table columns={columns} dataSource={[]} emptyText={<Empty description="暂无数据" />} />拖拽排序
传入 onSortEnd 回调即可启用拖拽排序。拖拽完成后会返回排序后的完整数据列表。
<Table
columns={columns}
dataSource={data}
rowKey="key"
onSortEnd={(newData) => {
console.log('排序后的数据:', newData);
setData(newData);
}}
/>拖拽排序会在表格左侧自动生成拖拽手柄列,支持跨行拖拽,拖拽目标行会高亮显示虚线边框。
Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| columns | ColumnType[] | — | 列定义 |
| dataSource | T[] | — | 数据源 |
| rowKey | string \| (record) => string | key 或 id | 行唯一标识 |
| pagination | false \| PaginationConfig | 默认分页 | 分页配置,false 禁用 |
| loading | boolean | false | 加载中 |
| emptyText | ReactNode | '暂无数据' | 空数据展示 |
| size | 'small' \| 'middle' \| 'large' | 'large' | 表格尺寸 |
| bordered | boolean | false | 是否显示列边框 |
| showHeader | boolean | true | 是否显示表头 |
| rowSelection | RowSelectionType | — | 行选择配置 |
| scroll | { y?: number } | — | 设置 y 固定表头 |
| defaultSortBy | { columnKey, order } | — | 默认排序 |
| onChange | (pagination, sorter) => void | — | 分页/排序变化回调 |
| onSortEnd | (newDataSource) => void | — | 拖拽排序完成回调,入参为排序后的完整数据列表 |
| onRow | (record) => { onClick, style, className } | — | 行事件与样式 |
| className | string | '' | 自定义类名 |
PaginationConfig
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| current | number | — | 受控当前页 |
| defaultCurrent | number | 1 | 默认当前页 |
| pageSize | number | — | 受控每页条数 |
| defaultPageSize | number | 10 | 默认每页条数 |
| total | number | dataSource.length | 数据总量 |
| showSizeChanger | boolean | false | 显示每页条数切换 |
| pageSizeOptions | number[] | [10, 20, 50, 100] | 可选的每页条数 |
| showTotal | boolean | false | 显示总条数 |
| simple | boolean | false | 简洁模式 |
| onChange | (page, pageSize) => void | — | 分页变化回调 |
ColumnType
| 属性 | 类型 | 说明 |
|------|------|------|
| title | string | 列标题 |
| dataIndex | string | 数据字段 |
| key | string | 列唯一标识 |
| render | (value, record, index) => ReactNode | 自定义渲染 |
| width | number \| string | 列宽度 |
| align | 'left' \| 'center' \| 'right' | 对齐方式 |
| sorter | boolean \| (a, b) => number | 排序函数(启用排序) |
| className | string | 列类名 |
| fixed | 'left' \| 'right' | 固定列 |
| visible | boolean | 是否显示 |
| minWidth | number | 最小宽度 |
RowSelectionType
| 属性 | 类型 | 说明 |
|------|------|------|
| selectedRowKeys | string[] | 受控选中 key 列表 |
| defaultSelectedRowKeys | string[] | 默认选中 key 列表 |
| onChange | (keys, rows) => void | 选中变化回调 |
| getCheckboxProps | (record) => { disabled } | 复选框属性 |
| columnWidth | number \| string | 选择列宽度 |
Pagination — 分页
分页组件,支持受控/非受控、简洁模式、每页条数切换、快速跳转、禁用态和小尺寸。
基本用法
import { Pagination } from 'starry-sky-ui';
<Pagination
total={200}
defaultCurrent={1}
defaultPageSize={10}
showTotal
showSizeChanger
onChange={(page, pageSize) => console.log(page, pageSize)}
/>受控模式
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
<Pagination
current={page}
pageSize={pageSize}
total={500}
showTotal
onChange={(p, s) => { setPage(p); setPageSize(s); }}
/>简洁模式
<Pagination total={100} simple />快速跳转
<Pagination total={500} showQuickJumper />小尺寸
<Pagination total={200} size="small" showTotal showSizeChanger />Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| current | number | — | 受控:当前页数 |
| defaultCurrent | number | 1 | 非受控:默认当前页数 |
| pageSize | number | — | 受控:每页条数 |
| defaultPageSize | number | 10 | 非受控:默认每页条数 |
| total | number | — | 数据总数(必填) |
| onChange | (page, pageSize) => void | — | 页码或 pageSize 变化回调 |
| showSizeChanger | boolean | false | 是否显示每页条数切换器 |
| pageSizeOptions | number[] | [10, 20, 50, 100] | 每页条数可选值 |
| showTotal | boolean | false | 是否显示总条数 |
| showTotalRender | (total, range) => ReactNode | — | 总条数自定义渲染 |
| simple | boolean | false | 简洁模式(仅显示翻页 + 输入框) |
| disabled | boolean | false | 禁用 |
| showQuickJumper | boolean | false | 是否显示快速跳转输入框 |
| size | 'default' \| 'small' | 'default' | 尺寸 |
| className | string | '' | 自定义类名 |
Starfield — 星空背景
星空背景组件,在容器内生成随机分布的闪烁星星,支持自定义数量、颜色和闪烁速度。
基本用法
import { Starfield } from 'starry-sky-ui';
// 使用默认参数(350 颗星星,紫/蓝/白三色,3s 闪烁)
<Starfield />
// 自定义参数
<Starfield
starCount={500}
starColors={['#ff6b6b', '#ffd93d', '#6bcb77']}
time={5}
className="my-starfield"
/>性能
- 使用
DocumentFragment批量追加 DOM,仅触发一次 reflow - 通过 CSS 自定义属性(
--star-color,--star-glow)传递颜色,避免动态生成大量样式类 - 清理时使用
innerHTML一次性清除所有子节点
Props
| 属性 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| starCount | number | 350 | 星星数量 |
| starColors | string[] | ['#8b5cf6', '#3b82f6', '#ffffff'] | 颜色列表,支持任意 CSS 合法颜色值 |
| time | number | 3 | 闪烁动画最大延迟时间(秒) |
| className | string | '' | 自定义类名 |
类型导出
所有组件类型均可从 starry-sky-ui 直接导入:
import type {
SelectOption,
SelectProps,
ModalProps,
MessageInstance,
MessageOpenConfig,
MessageGlobalConfig,
ColumnType,
TableProps,
PaginationConfig,
RowSelectionType,
PaginationProps,
StarfieldProps,
} from 'starry-sky-ui';