A React component library built for data-intensive admin dashboards. Focused on table-heavy and form-heavy scenarios where other libraries fall short.
npm install fat-design
# or
yarn add fat-design
# or
pnpm add fat-design
import { Button, Message } from 'fat-design'
import 'fat-design/dist/style.css'
function App() {
return (
<Button type="primary" onClick={() => Message.success('Hello!')}>
Click me
</Button>
)
}
Built around useTablePro, a hook that manages query form state, pagination, and row selection together. Designed for list pages with filtering.
import { TablePro } from 'fat-design'
const { useTablePro, renderOperationCell, renderTime, renderBoolean, renderMultiFieldCell } = TablePro
function UserList() {
const tableProProps = useTablePro({
isEnableCrossPageRowSelection: true,
initFormProps: {
schema: {
type: 'object',
properties: {
username: { label: 'Name', component: 'Input' },
status: {
label: 'Status',
component: 'Select',
enums: [
{ label: 'Active', value: 'active' },
{ label: 'Inactive', value: 'inactive' },
],
},
},
},
},
initPaginationProps: { pageSize: 20 },
initTableProps: {
primaryKey: 'id',
columns: [
{ title: 'ID', dataIndex: 'id', width: '120px', lock: 'left' },
{ title: 'Name', dataIndex: 'name', width: '180px', sortable: true },
{ title: 'Created', dataIndex: 'createdAt', width: '180px', cell: renderTime },
{ title: 'Active', dataIndex: 'isActive', width: '100px', cell: renderBoolean },
{
title: 'Actions', dataIndex: 'id', width: '160px', lock: 'right',
cell: (_, __, record) => renderOperationCell([
{ title: 'Edit', onClick: () => openEdit(record) },
{ title: 'Delete', onClick: () => handleDelete(record) },
]),
},
],
},
})
return <TablePro {...tableProProps} />
}
Key features:
renderTime, renderBoolean, renderOperationCell, renderMultiFieldCellDialog.showTable for nested table dialogsThe Form component (internally Form2) supports schema-driven configuration with field-level dependency tracking for precise re-rendering.
import { Form } from 'fat-design'
const FormItem = Form.Item
// Schema-based usage
<Form
schema={{
type: 'object',
properties: {
category: {
label: 'Category',
component: 'Select',
required: true,
enums: () => fetchCategories(),
},
subcategory: {
label: 'Subcategory',
component: 'Select',
deps: ['category'],
enums: (_, { values }) => fetchSubcategories(values.category),
},
},
}}
onSubmit={handleSubmit}
/>
// JSX-based usage with conditional fields
<Form defaultValues={initialValues} onSubmit={handleSubmit}>
<FormItem label="Type" name="type" component="Select" enums={typeOptions} />
<FormItem
label="Detail"
name="detail"
component="Input"
display={(values) => values.type === 'advanced'}
disabled={(values) => values.readonly === true}
isPreview={(values) => values.mode === 'preview'}
/>
<FormItem component="FormButtonGroup" xProps={{ buttons: [
{ component: 'FormSubmit', text: 'Submit', type: 'primary' },
{ component: 'FormReset', text: 'Reset' },
]}} />
</Form>
Key features:
deps for field dependency tracking — only dependent fields re-render on changedisplay, disabled, isPreview accept value functions for declarative conditional logicenums accepts static array, function, or async functiononCreated callback exposes formStore and formActions for imperative controlautoValidate, autoValidateOnCreated flagsA schema-driven filter form that collapses fields beyond a threshold, with built-in submit/reset and loading state.
import { QueryForm } from 'fat-design'
<QueryForm
schema={schema}
defaultValues={defaultFilters}
onSubmit={fetchData}
/>
import { Dialog } from 'fat-design'
// Imperative API
Dialog.show({ title: 'Confirm', content: 'Are you sure?' })
Dialog.showForm({ title: 'Edit User', schema, onSubmit })
Dialog.showTable({ title: 'Logs', tableProProps })
Dialog.showBatchProcess({ title: 'Batch Import', ... })
| Component | Description |
|---|---|
Table | Base table, used directly without useTablePro |
EditableTable | Inline-editable table rows |
SortableList | Drag-and-drop reordering |
VirtualList | Windowed rendering for large lists |
Upload | File upload with progress, batch support |
Image | Image display with preview lightbox |
Comments | Threaded comment system |
Drawer | Side panel with Drawer.show() imperative API |
PageCard | Standard page content container |
BatchInput | Tag-style multi-value text input |
Select | Dropdown with search, multi-select, remote options |
DatePicker / TimePicker | Date and time selection |
Cascader / CascaderSelect | Hierarchical selection |
TreeSelect | Tree-structured dropdown |
Skeleton | Loading placeholder |
Message / Notification | Global feedback messages |
Import one theme stylesheet:
import 'fat-design/dist/style.css' // default
import 'fat-design/dist/theme-blue1.css'
import 'fat-design/dist/theme-blue2.css'
import 'fat-design/dist/theme-green.css'
import 'fat-design/dist/theme-green2.css'
import 'fat-design/dist/theme-orange.css'
import 'fat-design/dist/theme-red.css'
import 'fat-design/dist/theme-pink.css'
import 'fat-design/dist/theme-purple.css'
import { utils } from 'fat-design'
const { pReactDOM, log, StorageInstance } = utils
// React 16/17/18 compatibility
pReactDOM.configReactDOM18(ReactDOM, ReactDOMClient)
// Unified storage (localStorage + localForage)
const store = new StorageInstance('my-app')
await store.setItem('key', value)
const value = await store.getItem('key')
Available hooks via hooks export:
useSize — element resize observerusePersistFn — stable function referenceusePreciseStore — granular reactive storeuseCurrentState — ref-synced stateuseValueOnChange — controlled/uncontrolled value bridgeuseOnKeyPressSave — Ctrl+S / Cmd+S handlernpm run dev
Opens a component browser at http://localhost:5173 with live examples for all components.