@omnifyjp/ui
v2.3.3
Published
A comprehensive UI component library for React apps. Contains 67 Shadcn/Radix primitives and 14 domain-specific components with a complete design token system.
Readme
@omnifyjp/ui
A comprehensive UI component library for React apps. Contains 67 Shadcn/Radix primitives and 14 domain-specific components with a complete design token system.
Installation
npm install @omnifyjp/uiPeer Dependencies
npm install react react-dom react-routerQuick Start
import { createBrowserRouter, RouterProvider } from 'react-router';
import { AppShell, initOmnifyI18n } from '@omnifyjp/ui';
import type { ShellConfig } from '@omnifyjp/ui';
import { LayoutDashboard, Users, Settings } from 'lucide-react';
// 1. Initialize i18n with your service translations
import enLocale from './locales/en.json';
import viLocale from './locales/vi.json';
initOmnifyI18n({
namespaces: {
myapp: { en: enLocale, vi: viLocale },
},
});
// 2. Define shell configuration
const config: ShellConfig = {
app: {
name: 'My App',
key: 'myapp',
logo: { icon: LayoutDashboard, text: 'My App', color: 'text-blue-600' },
},
sidebar: {
menuItems: [
{ icon: LayoutDashboard, label: 'Dashboard', path: '/' },
{ icon: Users, label: 'Users', path: '/users' },
{ icon: Settings, label: 'Settings', path: '/settings' },
],
},
header: {
user: {
name: 'John Doe',
email: '[email protected]',
onLogout: () => console.log('logout'),
},
},
organization: {
organizations: [
{ id: '1', name: 'Acme Corp', shortName: 'AC' },
],
branches: [
{ id: '1', name: 'Tokyo Office', organizationId: '1', location: 'Tokyo' },
{ id: '2', name: 'Hanoi Office', organizationId: '1', location: 'Hanoi' },
],
},
};
// 3. Set up routes with AppShell as the layout
const router = createBrowserRouter([
{
path: '/',
element: <AppShell config={config} />,
children: [
{ index: true, element: <Dashboard /> },
{ path: 'users', element: <Users /> },
{ path: 'settings', element: <Settings /> },
],
},
]);
function App() {
return <RouterProvider router={router} />;
}Core Components
AppShell
The main application wrapper. Combines ThemeProvider + I18nextProvider + OrganizationProvider, then renders the sidebar, header, and a React Router <Outlet />.
import { AppShell } from '@omnifyjp/ui';
<AppShell config={config} extra={<ChatWidget />} />| Prop | Type | Description |
|------|------|-------------|
| config | ShellConfig | Full shell configuration (see below) |
| extra | ReactNode | Optional floating elements (e.g., chat widget) |
Sidebar
Collapsible left navigation with context switching, expandable groups, and tooltips when collapsed.
Features:
- Logo area with app icon
- Main menu items with nested groups
- Context switching popover (e.g., project switcher with search)
- Recent items section
- Collapse/expand toggle
- Organization selector badge
Header
Top navigation bar with:
- Organization/branch selector
- Service menu (grid of available apps)
- Global search input
- Notification dropdown with count badge
- Custom action buttons
- User menu (profile, settings, logout)
PageContainer
Flexible page layout wrapper with three variants:
import {
StandardPageContainer,
SplitPageContainer,
FullWidthPageContainer,
} from '@omnifyjp/ui';
// Standard — padded page with title bar
<StandardPageContainer title="Users" subtitle="Manage team members" extra={<Button>Add User</Button>}>
<UserTable />
</StandardPageContainer>
// Split — two-column layout with sidebar
<SplitPageContainer title="Settings" sidebar={<SettingsNav />} sidebarPosition="left">
<SettingsForm />
</SplitPageContainer>
// Full width — no padding (for Kanban boards, Gantt charts)
<FullWidthPageContainer>
<KanbanBoard />
</FullWidthPageContainer>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| title | string | — | Page heading |
| subtitle | string | — | Description text below title |
| extra | ReactNode | — | Header actions (buttons, etc.) |
| children | ReactNode | — | Main content |
| footer | ReactNode | — | Footer content |
| variant | 'standard' \| 'split' \| 'full' | 'standard' | Layout mode |
| sidebar | ReactNode | — | Sidebar content (split mode) |
| sidebarPosition | 'left' \| 'right' | 'right' | Sidebar placement |
| sidebarWidth | string | 'w-80' | Sidebar Tailwind width class |
OrganizationSelector
Two-step modal for switching organizations and branches:
- Step 1: Select organization (shows description + branch count)
- Step 2: Select branch (searchable, shows location)
import { OrganizationSelector } from '@omnifyjp/ui';
<OrganizationSelector variant="header" /> // in header
<OrganizationSelector variant="sidebar" /> // in sidebarServiceMenu
Searchable dropdown grid listing all available services/apps:
const config: ShellConfig = {
services: [
{
category: 'HR',
items: [
{ icon: Users, label: 'Attendance', url: '/attendance', color: 'bg-blue-600' },
{ icon: Calendar, label: 'Leave', url: '/leave', color: 'bg-green-600' },
],
},
],
};Configuration: ShellConfig
interface ShellConfig {
app: {
name: string; // App display name
key: string; // App identifier
logo: {
icon: LucideIcon; // Logo icon
text: string; // Logo text
color?: string; // Icon color class
};
};
sidebar: {
menuItems: SidebarMenuItem[]; // Navigation items
contextMenu?: { // Context switcher (e.g., project selector)
paramName: string; // URL param name
getItems: () => ContextItem[];
getHeader?: () => ReactNode;
getFooterItems?: () => ContextItem[];
};
recentItems?: { // Recent items section
title: string;
items: { label: string; path: string; badge?: string; color?: string }[];
};
footer?: ReactNode; // Custom sidebar footer
};
services?: ServiceCategory[]; // Service menu grid
header?: {
searchPlaceholder?: string;
showSearch?: boolean; // Default: true
actions?: ReactNode; // Custom header buttons
notifications?: {
count: number;
content: ReactNode;
};
user?: {
name: string;
email?: string;
avatar?: string;
onLogout?: () => void;
};
};
organization?: {
organizations: Organization[];
branches: Branch[];
onOrganizationChange?: (org: Organization) => void;
onBranchChange?: (branch: Branch) => void;
};
}SidebarMenuItem
interface SidebarMenuItem {
icon: LucideIcon;
label: string;
path?: string; // Omit for collapsible groups
badge?: number; // Notification count
children?: SidebarMenuItem[]; // Nested items
}Context Providers
ThemeProvider
Dark mode management with system preference detection:
import { useTheme } from '@omnifyjp/ui';
function ThemeToggle() {
const { theme, setTheme } = useTheme();
// theme: 'light' | 'dark' | 'system'
return (
<select value={theme} onChange={(e) => setTheme(e.target.value)}>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="system">System</option>
</select>
);
}Persists selection to localStorage.omnify_theme.
OrganizationProvider
Multi-tenant organization/branch management:
import { useOrganization } from '@omnifyjp/ui';
function OrgInfo() {
const {
selectedOrganization, // Organization | null
selectedBranch, // Branch | null
setSelectedOrganization,
setSelectedBranch,
getBranchesByOrg, // (orgId: string) => Branch[]
isSetupComplete, // true when both selected
} = useOrganization();
return <p>{selectedOrganization?.name} — {selectedBranch?.name}</p>;
}Persists selections to localStorage.selectedOrganizationId and localStorage.selectedBranchId.
i18n (Internationalization)
Supported Languages
| Code | Language |
|------|----------|
| vi | Tieng Viet (default, fallback) |
| en | English |
| ja | Japanese |
Shell Namespace
The shell comes pre-loaded with translations for common UI strings: sidebar labels, header actions, status/priority names, settings pages, login forms, organization selection, date picker, etc.
Adding Service Translations
import { initOmnifyI18n } from '@omnifyjp/ui';
// Add your service namespace
initOmnifyI18n({
namespaces: {
myapp: {
en: { dashboard: { title: 'Dashboard' } },
vi: { dashboard: { title: 'Bang dieu khien' } },
ja: { dashboard: { title: 'dasshubodo' } },
},
},
});
// Use in components
import { useTranslation } from 'react-i18next';
function Dashboard() {
const { t } = useTranslation(['myapp', 'shell']);
return <h1>{t('dashboard.title')}</h1>;
// Falls back to 'shell' namespace for common keys
}Changing Language
import { changeLanguage } from '@omnifyjp/ui';
await changeLanguage('en'); // Persists to localStorageHooks
useDateFormat
Locale-aware date formatting with timezone support:
import { useDateFormat } from '@omnifyjp/ui';
function EventDate({ date }: { date: Date }) {
const {
formatDate, // '01/15/2026' (locale-dependent)
formatDateTime, // '01/15/2026 14:30'
formatRelativeTime, // '5 minutes ago'
formatShortDate, // '01/15'
formatMonthYear, // 'January 2026'
formatDayOfWeek, // 'Mon'
formatDateLong, // 'January 15, 2026'
timezone, // 'Asia/Ho_Chi_Minh'
setTimezone, // Change timezone
dateFnsLocale, // date-fns Locale object
} = useDateFormat();
return <time>{formatDateTime(date)}</time>;
}Supported timezones: Asia/Ho_Chi_Minh, Asia/Tokyo, America/New_York, America/Los_Angeles, Europe/London, UTC.
Package Exports
@omnifyjp/ui → all exports (barrel)
@omnifyjp/ui/components/AppShell → AppShell
@omnifyjp/ui/components/Sidebar → Sidebar
@omnifyjp/ui/components/Header → Header
@omnifyjp/ui/components/PageContainer → PageContainer, Standard/Split/FullWidth variants
@omnifyjp/ui/components/ServiceMenu → ServiceMenu
@omnifyjp/ui/components/OrganizationSelector → OrganizationSelector
@omnifyjp/ui/contexts/ThemeContext → ThemeProvider, useTheme
@omnifyjp/ui/contexts/OrganizationContext → OrganizationProvider, useOrganization
@omnifyjp/ui/hooks/useDateFormat → useDateFormat, timezoneLabels
@omnifyjp/ui/i18n → i18n, initOmnifyI18n, changeLanguage
@omnifyjp/ui/types → ShellConfig, Organization, Branch, etc.TypeScript
Full type definitions are included. Key types:
import type {
ShellConfig,
SidebarMenuItem,
ServiceCategory,
ServiceItem,
Organization,
Branch,
PageContainerProps,
} from '@omnifyjp/ui';Dependencies
This package depends on:
| Package | Purpose |
|---------|---------|
| @omnifyjp/ui | UI component primitives (auto-installed) |
| i18next | Internationalization core |
| react-i18next | React i18n bindings |
| date-fns | Date formatting |
| lucide-react | Icons |
| sonner | Toast notifications |
Peer dependencies (you provide):
| Package | Version |
|---------|---------|
| react | >=18 |
| react-dom | >=18 |
| react-router | >=7 |
Related Packages
| Package | Description |
|---------|-------------|
| @omnifyjp/ui | 53 Shadcn primitives + 14 domain components |
| @omnifyjp/editor | Rich text editors (Tiptap + BlockNote) |
License
MIT
