ebig-library
A modern, lightweight React + TypeScript UI component library by eBig — 35+ ready-to-use components, a responsive layout system, design-token theming, built-in i18n (en/vi), and optional eBig backend integration for dynamic form/table/page rendering.

Table of Contents
Installation
npm install ebig-library
Import the CSS style files (required for layout and typography utilities):
<link rel="stylesheet" href="https://cdn.ebig.co/library/style/root.min.css" />
<link rel="stylesheet" href="https://cdn.ebig.co/library/style/layout.min.css" />
<link rel="stylesheet" href="https://cdn.ebig.co/library/style/typography.min.css" />
<link rel="stylesheet" href="https://cdn.ebig.co/library/style/toast-noti.min.css" />
These are loaded automatically if you use EbigProvider with loadResources={true} (default).
Setup: EbigProvider
Wrap your app's root with EbigProvider. It sets up routing (BrowserRouter internally), toast notifications, dialogs, token refresh, and optional design token + i18n loading from the eBig backend.
import ReactDOM from 'react-dom/client'
import EbigProvider, { Route } from 'ebig-library'
ReactDOM.createRoot(document.getElementById('root')!).render(
<EbigProvider
pid="your-project-id"
url="https://your-ebig-api.com/"
fileUrl="https://your-file-server.com/"
imgUrlId="https://your-cdn.com/"
theme="light" // "light" | "dark"
loadResources={true} // false → skip backend token/i18n loading
>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</EbigProvider>
)
Important: EbigProvider wraps BrowserRouter internally. Do not add another BrowserRouter in your app.
Props
pid | string | ✅ | eBig project ID (32-char) |
url | string | ✅ | eBig API base URL |
fileUrl | string | ✅ | File server URL |
imgUrlId | string | ✅ | CDN/image URL prefix |
theme | "light" | "dark" | — | Default "light" |
loadResources | boolean | — | Default true. Set to false to skip backend loading |
onInvalidToken | () => void | — | Called on 401 — override to redirect to login |
children | ReactNode | — | <Route> elements |
Global Context
import { useEbigContext } from 'ebig-library'
function MyComponent() {
const {
theme,
setTheme,
userData,
setUserData,
globalData,
setGlobalData,
i18n,
} = useEbigContext()
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle theme
</button>
)
}
Layout System
Use row and col CSS classes for flex layouts. Add remain to let a child fill remaining space.
<div className="row" style={{ gap: 12 }}>
<span>Left</span>
<span className="remain">Stretches to fill space</span>
<span>Right</span>
</div>
<div className="col" style={{ gap: 8 }}>
<span>Top</span>
<span>Bottom</span>
</div>
Style / CSS
| Design tokens (CSS variables) | https://cdn.ebig.co/library/style/root.min.css |
Layout utilities (row, col, grids) | https://cdn.ebig.co/library/style/layout.min.css |
Typography (heading-1…heading-8, body-1…body-3) | https://cdn.ebig.co/library/style/typography.min.css |
| Toast styles | https://cdn.ebig.co/library/style/toast-noti.min.css |
Components
Button & SimpleButton
import { Button, SimpleButton, Ebigicon } from 'ebig-library'
<Button label="Click me" onClick={() => alert('clicked!')} />
<Button label="Save" className="size40 button-primary" onClick={handleSave} />
<Button
label="Upload"
prefix={<Ebigicon src="outline/arrows/cloud-upload" size={16} />}
className="size40 button-neutral"
onClick={handleUpload}
/>
<Button label="Docs" linkTo="https://ebig.co" target="_blank" className="size40 button-grey" />
<Button label="Info" tooltip={{ message: 'More details', position: 'top' }} />
<Button label="Submit" type="submit" className="size40 button-primary" onClick={handleSubmit} />
<SimpleButton label="Save" className="size40 button-primary" onClick={async () => { await save() }} />
Size classes: size24 · size32 (default) · size40 · size48 · size56 · size64
Color classes: button-primary · button-grey · button-neutral · button-black · button-white · button-infor · button-warning · button-error · button-success · button-infor-main · button-warning-main · button-error-main · button-success-main
Ebigicon
SVG icon component. Icons are fetched from https://cdn.ebig.co/icon-library/ and cached in the browser via the Cache API after first load.
import { Ebigicon } from 'ebig-library'
<Ebigicon src="outline/user/user" size={24} />
<Ebigicon src="fill/actions/trash" size={20} color="#E14337" onClick={handleDelete} className="icon-button" />
<Ebigicon src="outline/essential/info-circle" size={20} tooltip={{ message: 'Help', position: 'bottom' }} />
<Ebigicon link="https://your-cdn.com/custom-icon.svg" size={24} />
Style classes: icon-button (adds hover/active styles) · icon-button light · border · dashed
Size classes: size24 · size32 · size40 · size48 · size56 · size64
TextField
import { TextField, Ebigicon } from 'ebig-library'
<TextField placeholder="Enter name" onChange={(e) => setName(e.target.value)} />
<TextField
prefix={<Ebigicon src="outline/user/user" size={16} />}
placeholder="Email"
type="email"
helperText="Invalid email"
className="size40 body-3"
/>
const { register } = useForm()
<TextField placeholder="Username" register={register('username', { required: true })} />
Size classes: size24 · size32 · size40 (default) · size48
TextArea
import { TextArea } from 'ebig-library'
<TextArea placeholder="Write something..." onChange={(e) => setText(e.target.value)} />
SelectDropdown
Single-value dropdown. Supports static options, async lazy-loading, hierarchical (parent/child) options, and react-hook-form.
import { SelectDropdown } from 'ebig-library'
const options = [
{ id: '1', name: 'Option A' },
{ id: '2', name: 'Option B' },
{ id: '3', name: 'Option C', disabled: true },
]
<SelectDropdown
value={selected}
options={options}
placeholder="Choose one"
onChange={(item) => setSelected(item?.id)}
/>
<SelectDropdown
options={[]}
getOptions={async ({ length, search }) => {
const res = await fetchItems({ page: Math.floor(length / 10) + 1, search })
return { data: res.items, totalCount: res.total }
}}
onChange={(item) => setSelected(item?.id)}
/>
Checkbox
import { Checkbox } from 'ebig-library'
<Checkbox value={isChecked} onChange={(val) => setIsChecked(val)} />
<Checkbox value={null} /> {}
Switch
import { Switch } from 'ebig-library'
<Switch value={isOn} onChange={(val) => setIsOn(val)} />
<Switch value={isOn} size="2.4rem" onBackground="#287CF0" onChange={setIsOn} />
RadioButton
import { RadioButton } from 'ebig-library'
<RadioButton value={selected === 'a'} onChange={() => setSelected('a')} label="Option A" />
<RadioButton value={selected === 'b'} onChange={() => setSelected('b')} label="Option B" />
DateTimePicker
import { DateTimePicker } from 'ebig-library'
<DateTimePicker value={date} onChange={(val) => setDate(val)} placeholder="Pick a date" />
NumberPicker
import { NumberPicker } from 'ebig-library'
<NumberPicker value={count} onChange={(val) => setCount(val)} min={0} max={100} />
Slider
import { Slider } from 'ebig-library'
<Slider value={volume} min={0} max={100} onChange={(val) => setVolume(val)} />
Rating
import { Rating } from 'ebig-library'
<Rating value={3} onChange={(val) => setRating(val)} />
InputOtp
import { InputOtp } from 'ebig-library'
<InputOtp length={6} onComplete={(code) => verifyOtp(code)} />
ColorPicker
import { ColorPicker } from 'ebig-library'
<ColorPicker value={color} onChange={(hex) => setColor(hex)} />
Tag
import { Tag } from 'ebig-library'
<Tag label="Active" color="#287CF0" />
<Tag label="Error" color="#E14337" onRemove={() => handleRemove()} />
import { Pagination } from 'ebig-library'
<Pagination
pageIndex={page}
totalCount={total}
pageSize={10}
onChange={(newPage) => setPage(newPage)}
/>
InfiniteScroll
import { InfiniteScroll } from 'ebig-library'
<InfiniteScroll
data={items}
render={(item) => <div key={item.id}>{item.name}</div>}
totalCount={total}
onLoadMore={() => loadNextPage()}
/>
Dialog
import { showDialog, DialogAlignment } from 'ebig-library'
showDialog({
title: 'Confirm delete',
content: 'Are you sure?',
alignment: DialogAlignment.center,
onConfirm: () => handleDelete(),
})
import { Popup, showPopup, closePopup } from 'ebig-library'
import { useRef } from 'react'
const ref = useRef()
<button onClick={(ev) => showPopup({ ref, id: 'my-popup', clickTarget: ev.currentTarget, content: () => <div>Content</div> })}>
Open popup
</button>
<Popup ref={ref} />
ToastMessage
import { ToastMessage } from 'ebig-library'
ToastMessage.success('Saved successfully')
ToastMessage.errors('Something went wrong')
ToastMessage.warning('Check your input')
ProgressBar
import { ProgressBar } from 'ebig-library'
<ProgressBar percent={75} label="Uploading..." />
ProgressCircle
import { ProgressCircle } from 'ebig-library'
<ProgressCircle percent={60} size={80} />
Calendar
import { Calendar } from 'ebig-library'
<Calendar value={date} onChange={(val) => setDate(val)} />
Carousel
import { Carousel } from 'ebig-library'
<Carousel>
<img src="/slide1.jpg" alt="Slide 1" />
<img src="/slide2.jpg" alt="Slide 2" />
</Carousel>
VideoPlayer / AudioPlayer / IframePlayer
import { VideoPlayer, AudioPlayer, IframePlayer } from 'ebig-library'
<VideoPlayer src="https://example.com/video.mp4" />
<AudioPlayer src="https://example.com/audio.mp3" />
<IframePlayer src="https://www.youtube.com/embed/xxxxx" />
ImportFile / UploadFiles
import { ImportFile, UploadFiles } from 'ebig-library'
<ImportFile
value={files}
onChange={(fileList) => setFiles(fileList)}
maxSize={5 * 1024 * 1024}
accept={['.png', '.jpg', '.pdf']}
/>
<UploadFiles
value={uploadedFiles}
onChange={(files) => setUploadedFiles(files)}
/>
CustomCkEditor5
Rich-text editor powered by CKEditor 5. Requires ckeditor5 and @ckeditor/ckeditor5-react to be installed by the consumer.
import { CustomCkEditor5, CkEditorUploadAdapter } from 'ebig-library'
<CustomCkEditor5
value={html}
onChange={(val) => setHtml(val)}
uploadAdapter={CkEditorUploadAdapter}
/>
EbigEditor
Lightweight rich-text editor (no CKEditor dependency). Supports emoji, bold, italic, underline, hyperlinks, and @mention-style suggestion hooks.
import { EbigEditor } from 'ebig-library'
<EbigEditor
placeholder="Write a comment..."
onChange={(value, el) => setContent(value)}
onBlur={(value, el) => handleBlur(value)}
/>
<EbigEditor
customToolbar={['bold', 'italic', 'emoji']}
onChange={(val) => setContent(val)}
/>
<EbigEditor
onSuggest={[{
triggerPattern: '@',
render: (offset, match, select) => (
<MentionList offset={offset} query={match} onSelect={select} />
)
}]}
onChange={(val) => setContent(val)}
/>
IconPicker
import { IconPicker } from 'ebig-library'
<IconPicker value={iconName} onChange={(name) => setIconName(name)} />
EmptyPage
import { EmptyPage } from 'ebig-library'
<EmptyPage
title="No data found"
subtitle="Try adjusting your filters"
button={<Button label="Reset" onClick={reset} />}
/>
Text
Typography component that renders semantic HTML elements with typography class helpers.
import { Text } from 'ebig-library'
<Text className="heading-3">Page title</Text>
<Text className="body-2" maxLine={2}>Truncated body text that wraps at two lines...</Text>
ComponentStatus
import { ComponentStatus, getStatusIcon } from 'ebig-library'
<ComponentStatus status="success" label="Completed" />
const icon = getStatusIcon('warning')
Form Components (react-hook-form)
Pre-built form field wrappers integrating react-hook-form. All accept methods (from useForm()), name, label, required, disabled, placeholder, and className.
import { useForm } from 'react-hook-form'
import {
TextFieldForm,
TextAreaForm,
Select1Form,
SelectMultipleForm,
CheckboxForm,
SwitchForm,
DateTimePickerForm,
NumberPickerForm,
RateForm,
ColorPickerForm,
GroupCheckboxForm,
GroupRadioButtonForm,
RangeForm,
CKEditorForm,
EbigEditorForm,
InputPasswordForm,
IconPickerForm,
UploadMultipleFileTypeForm,
} from 'ebig-library'
const methods = useForm()
<form onSubmit={methods.handleSubmit(onSubmit)}>
<TextFieldForm methods={methods} name="username" label="Username" required />
<TextFieldForm methods={methods} name="price" label="Price" type="money" />
<Select1Form
methods={methods}
name="category"
label="Category"
options={[{ id: '1', name: 'Tech' }, { id: '2', name: 'Finance' }]}
/>
<DateTimePickerForm methods={methods} name="dueDate" label="Due date" />
<EbigEditorForm methods={methods} name="description" label="Description" />
<Button label="Submit" type="submit" className="size40 button-primary" />
</form>
Utility Class (Util)
import { Util } from 'ebig-library'
Util.dateTime_stringToDecimal('2026-04-08T10:00:00Z')
Util.stringToDate('08/04/2026', 'dd/mm/yyyy')
Util.calculateAge('01/01/2000')
Util.formatCurrency(1500000, 'VND')
Util.formatCurrency(99.9, 'USD')
Util.convertCurrency(100, 'USD', 'VND')
Util.hexToRgb('#287CF0')
Util.rgbToHex(40, 124, 240)
Util.toSlug('Hello World!')
Util.randomGID()
Util.getCookie('accessToken')
Util.setCookie('accessToken', token)
Util.clearCookie()
Util.formatFileSize(1048576)
Util.stringToFile('content', 'file.txt')
Util.encodeBase64('string')
Util.decodeBase64('encoded')
Controllers
All controllers require ConfigData.url and ConfigData.pid to be set (done automatically by EbigProvider).
DataController
Generic CRUD for any project data module.
import { DataController } from 'ebig-library'
const ctrl = new DataController('Product')
const res = await ctrl.getListSimple({ page: 1, size: 20, query: '@Category:{Electronics}' })
const item = await ctrl.getById('abc123')
await ctrl.add([{ Name: 'Product A', Price: 100 }])
await ctrl.edit([{ Id: 'abc123', Price: 120 }])
await ctrl.delete(['abc123', 'def456'])
await ctrl.aggregateList({ filter: '@Price:[100 200]', sortby: [{ prop: 'Price', direction: 'ASC' }] })
SettingDataController
For system-level setting entities (chart, form, card, view).
import { SettingDataController } from 'ebig-library'
const ctrl = new SettingDataController('form')
await ctrl.getListSimple({ page: 1, size: 10 })
await ctrl.action('add', { data: [{ Name: 'My Form' }] })
await ctrl.getByIds(['id1', 'id2'])
AccountController
Login, get user info, and password utilities.
import { AccountController } from 'ebig-library'
const acc = new AccountController('Customer')
const res = await acc.login({ type: 'account', username: 'admin', password: 'pass' })
await acc.login({ type: 'google', token: googleToken })
const info = await acc.getInfor()
const hashed = await acc.hashPassword('mypassword')
EbigController
Project-level queries (fetches eBig project metadata). Do not change the internal API paths.
import { EbigController } from 'ebig-library'
const ctrl = new EbigController('Project')
const project = await ctrl.getById('your-project-id')
const results = await ctrl.getListSimple({ query: '@Domain:{ebig.co}', size: 1 })
TableController
CRUD for schema-level settings (table, column, rel, menu, page, layout, designtoken, workflow, process, step).
import { TableController } from 'ebig-library'
const ctrl = new TableController('table')
const tables = await ctrl.getAll()
await ctrl.add([{ Name: 'Orders' }])
await ctrl.edit([{ Id: 'xxx', Name: 'OrdersV2' }])
await ctrl.delete(['xxx'])
IntegrationController
import { IntegrationController } from 'ebig-library'
const integration = new IntegrationController()
await integration.sendEmail({
templateId: 'welcome-email',
templateParams: { to: 'user@example.com', name: 'Alice' }
})
BaseDA
Low-level HTTP helpers used by all controllers. Use directly only when you need calls outside the standard controller pattern.
import { BaseDA, ConfigData } from 'ebig-library'
const data = await BaseDA.get(`${ConfigData.url}data/custom-endpoint`, {
headers: { pid: ConfigData.pid }
})
await BaseDA.post(`${ConfigData.url}data/action?action=add`, {
headers: { pid: ConfigData.pid, module: 'Product' },
body: { data: [{ Name: 'Item' }] }
})
const uploaded = await BaseDA.uploadFiles(fileList)
Backend-Driven Modules
Render entire UI sections driven by eBig backend configuration. Requires a valid pid/url in EbigProvider.
import { PageById, PageByUrl, FormById, CardById, ViewById, ChartById, ChartByType } from 'ebig-library'
<PageById id="page-id" />
<PageByUrl url="location.pathname" />
<FormById id="form-id" onSuccess={(data) => console.log(data)} />
<CardById id="card-id" />
<ViewById id="view-id" />
<ChartById id="chart-id" />
<ChartByType type="bar" data={chartData} />
Design Tokens & Theming
Design tokens are loaded from the eBig backend at runtime and injected as CSS custom properties into <head>. Toggle dark mode via setTheme:
const { theme, setTheme } = useEbigContext()
setTheme('dark')
Tokens follow the pattern:
--primary-main-color: #287CF0;
--neutral-text-title-color: #18181B;
--primary-main-color: #4A90E2;
--neutral-text-title-color: #EAEAEC;
Responsive Grid Classes
The layout system uses a 24-column grid. Add these classes to children inside a row.
col1 – col24 | 1/24 – 24/24 | Always applied |
remain | fills rest | flex: 1 |
col1-min – col24-min | at < 576px | phones |
col1-sm – col24-sm | at ≥ 576px | small devices |
col1-md – col24-md | at ≥ 768px | tablets |
col1-lg – col24-lg | at ≥ 992px | laptops |
col1-xl – col24-xl | at ≥ 1200px | desktops |
col1-xxl – col24-xxl | at > 1200px | wide screens |
<div className="row" style={{ gap: 16 }}>
<div className="col24 col12-lg" style={{ "--gutter": "16px" }}>Left panel</div>
<div className="col24 col12-lg" style={{ "--gutter": "16px" }}>Right panel</div>
</div>
License
MIT © eBig / FDITECH