@qkit-emr/web-ui
v1.6.0
Published
Shared UI Component Library for EMR Monorepo
Downloads
13
Readme
@qkit-emr/web-ui
Thư viện UI component dùng chung cho hệ thống EMR (Electronic Medical Record) Monorepo, được xây dựng trên nền tảng React, TypeScript và Tailwind CSS với tích hợp shadcn/ui.
🚀 Tính năng chính
- Atomic Design: Tổ chức component theo nguyên tắc Atomic Design (atoms, molecules, organisms, templates, pages)
- shadcn/ui Integration: Tích hợp đầy đủ các component từ shadcn/ui với customization
- TypeScript: Full TypeScript support với type safety
- Tailwind CSS: Built on Tailwind CSS với utility-first approach
- Responsive Design: Mobile-first responsive design với breakpoints chuẩn
- Accessibility: WCAG 2.1 AA compliant components
- Theme Support: Light/dark theme switching
- Healthcare UI: Components được tối ưu cho giao diện y tế
- Performance: Optimized cho healthcare applications
📦 Cài đặt
npm install @qkit-emr/web-ui🎯 Sử dụng cơ bản
Import components
Có 2 cách import components:
1. Import mặc định (atoms, molecules, organisms, hooks, utils)
import { Button, Card, Input, Badge } from '@qkit-emr/web-ui';
function App() {
return (
<div className="p-4">
<Card className="p-6">
<h2 className="text-xl font-bold mb-4">Quản lý bệnh nhân</h2>
<Input placeholder="Tìm kiếm bệnh nhân..." className="mb-4" />
<Button>Thêm bệnh nhân mới</Button>
</Card>
</div>
);
}2. Import UI components riêng (pure shadcn/ui components)
import { Button } from '@qkit-emr/web-ui/ui';
function App() {
return (
<Button variant="default" size="lg">
Click me
</Button>
);
}Setup Tailwind CSS
Thêm preset vào file tailwind.config.js:
module.exports = {
content: [
"./src/**/*.{js,ts,jsx,tsx}",
"./node_modules/@qkit-emr/web-ui/dist/**/*.{js,ts,jsx,tsx}",
],
presets: [require("@qkit-emr/web-ui/tailwind.preset")],
}Import styles
import '@qkit-emr/web-ui/styles';🏗️ Cấu trúc component chi tiết
📋 ATOMS - Thành phần cơ bản nhất
Self-Implemented Atoms (Complex - có thư mục riêng)
import {
Button,
ButtonGroup,
ButtonGroupItem,
useButtonGroup,
Input,
InputAtom,
MemoizedInputAtom,
Label,
LabelAtom,
MemoizedLabelAtom,
Icon
} from '@qkit-emr/web-ui';
// Button với variants và medical-specific features
<Button variant="primary" size="md" medical>Khám bệnh</Button>
<ButtonGroup>
<ButtonGroupItem>Lưu</ButtonGroupItem>
<ButtonGroupItem>Hủy</ButtonGroupItem>
</ButtonGroup>
// Input với validation và medical masks
<Input placeholder="Nhập tên bệnh nhân" />
<InputAtom type="phone" mask="(999) 999-9999" />
// Label với accessibility
<Label htmlFor="patient-name">Họ và tên</Label>
// Icon với medical icon mapping
<Icon name="stethoscope" size="md" />UI-Dependent Atoms (Simple - single file)
import {
// Data Display
BadgeAtom,
StatusBadgeAtom,
ProgressAtom,
TimelineAtom,
DataTableAtom,
// Form Controls
DatePickerAtom,
TimePickerAtom,
MultiSelectAtom,
RadioGroupAtom,
InputOTPAtom,
SecureInputAtom,
// UI Enhancement
ModalAtom,
DrawerAtom,
TabsAtom,
AccordionAtom,
TooltipAtom,
CarouselAtom,
// Medical-Specific
LabResultAtom,
// Utilities
SpinnerAtom as Spinner,
DividerAtom as Divider,
TypographyAtom as Typography,
FileInputAtom
} from '@qkit-emr/web-ui';
// Medical status badges
<StatusBadgeAtom status="critical" />
<StatusBadgeAtom status="stable" />
<StatusBadgeAtom status="discharged" />
// Progress indicators
<ProgressAtom value={75} label="Tiến độ điều trị" />
// Medical timeline
<TimelineAtom items={medicalEvents} />
// Lab results display
<LabResultAtom
testName="Xét nghiệm máu"
result="120 mg/dL"
normalRange="70-100 mg/dL"
status="high"
/>
// Secure input for sensitive data
<SecureInputAtom
placeholder="Nhập mật khẩu"
showToggle={true}
/>
// OTP input for 2FA
<InputOTPAtom length={6} />
// Medical file upload
<FileInputAtom
accept=".pdf,.jpg,.png"
maxSize={5 * 1024 * 1024} // 5MB
medical={true}
/>Typography Atoms
import {
Heading1,
Heading2,
Heading3,
Paragraph,
Caption,
ErrorText,
SuccessText
} from '@qkit-emr/web-ui';
<Heading1>Tiêu đề chính</Heading1>
<Heading2>Tiêu đề phụ</Heading2>
<Paragraph>Nội dung văn bản</Paragraph>
<ErrorText>Thông báo lỗi</ErrorText>
<SuccessText>Thông báo thành công</SuccessText>🧬 MOLECULES - Kết hợp Atoms
import {
FormField,
SearchBar,
Alert,
Badge,
Card,
Modal
} from '@qkit-emr/web-ui';
// Form field với validation
<FormField
label="Họ và tên"
error="Tên không được để trống"
required
>
<Input placeholder="Nhập họ và tên" />
</FormField>
// Search bar với medical context
<SearchBar
placeholder="Tìm kiếm bệnh nhân, mã BHYT..."
onSearch={(value) => console.log(value)}
medical={true}
/>
// Medical alert
<Alert
type="warning"
title="Cảnh báo thuốc"
description="Bệnh nhân có tiền sử dị ứng với Penicillin"
/>🧠 ORGANISMS - Components phức tạp
import {
Header,
Sidebar,
Navigation,
DataTable,
Breadcrumb,
Pagination
} from '@qkit-emr/web-ui';
// Medical data table
<DataTable
data={patients}
columns={[
{ key: 'name', label: 'Họ tên' },
{ key: 'age', label: 'Tuổi' },
{ key: 'diagnosis', label: 'Chẩn đoán' },
{ key: 'status', label: 'Trạng thái' }
]}
pagination={{
currentPage: 1,
totalPages: 10,
onPageChange: (page) => console.log(page)
}}
medical={true}
/>
// Medical navigation
<Navigation
items={[
{ label: 'Dashboard', icon: 'dashboard', href: '/' },
{ label: 'Bệnh nhân', icon: 'users', href: '/patients' },
{ label: 'Lịch hẹn', icon: 'calendar', href: '/appointments' },
{ label: 'Báo cáo', icon: 'chart', href: '/reports' }
]}
medical={true}
/>📄 TEMPLATES - Layout patterns
import {
AuthTemplate,
DashboardTemplate,
DetailTemplate,
ErrorTemplate,
FormTemplate,
ListTemplate
} from '@qkit-emr/web-ui';
// Medical dashboard template
<DashboardTemplate
header={<Header title="Dashboard Bệnh viện" />}
sidebar={<Sidebar />}
content={<DashboardContent />}
medical={true}
/>
// Patient detail template
<DetailTemplate
header={<PatientHeader patient={patient} />}
content={<PatientDetails patient={patient} />}
actions={<PatientActions patient={patient} />}
medical={true}
/>
// Medical form template
<FormTemplate
title="Thêm bệnh nhân mới"
form={<PatientForm />}
actions={<FormActions />}
medical={true}
/>📱 RESPONSIVE SYSTEM - Mobile-first development
import {
// Responsive Providers & Hooks
ResponsiveProvider,
useResponsive,
// Responsive Layout Components
ResponsiveLayoutContainer,
ResponsiveGrid,
// Mobile Components
MobileLayout,
MobileStack,
MobileContainer,
MobileBottomNavigation,
MobileDrawerNavigation,
MobileHamburgerMenu,
// Tablet Components
TabletLayout,
TabletContainer,
TabletStack,
// Desktop Components
DesktopLayout,
DesktopContainer,
DesktopStack,
DesktopGrid,
// Responsive Form Components
ResponsiveForm,
ResponsiveFormField,
ResponsiveInputField,
ResponsiveSelectField,
ResponsiveTextareaField,
ResponsiveCheckboxField,
ResponsiveRadioField,
ResponsiveFormActions
} from '@qkit-emr/web-ui';
// Responsive medical form
<ResponsiveProvider>
<ResponsiveForm>
<ResponsiveFormField label="Họ và tên">
<ResponsiveInputField placeholder="Nhập họ và tên" />
</ResponsiveFormField>
<ResponsiveFormField label="Ngày sinh">
<ResponsiveInputField type="date" />
</ResponsiveFormField>
<ResponsiveFormActions>
<Button>Lưu</Button>
<Button variant="outline">Hủy</Button>
</ResponsiveFormActions>
</ResponsiveForm>
</ResponsiveProvider>🎨 Theme và Styling
Theme Provider
import { ThemeProvider } from '@qkit-emr/web-ui';
function App() {
return (
<ThemeProvider>
<YourApp />
</ThemeProvider>
);
}Theme Toggle
import { useThemeToggle } from '@qkit-emr/web-ui';
function ThemeToggle() {
const { toggleTheme, theme } = useThemeToggle();
return (
<Button onClick={toggleTheme}>
{theme === 'dark' ? '🌞' : '🌙'}
</Button>
);
}Medical Theme Colors
// Primary medical colors
className="bg-blue-600 text-white" // Medical blue
className="bg-green-500 text-white" // Success green
className="bg-red-600 text-white" // Error red
className="bg-yellow-500 text-white" // Warning yellow
// Medical status colors
className="bg-red-100 text-red-800" // Critical
className="bg-yellow-100 text-yellow-800" // Warning
className="bg-green-100 text-green-800" // Stable
className="bg-blue-100 text-blue-800" // Info🔧 Customization
Override component styles
import { Button } from '@qkit-emr/web-ui';
// Sử dụng className để override
<Button className="bg-blue-600 hover:bg-blue-700">
Custom Button
</Button>Medical variants
import { Button } from '@qkit-emr/web-ui';
// Button với medical variant
<Button variant="medical" size="lg">
Khám bệnh
</Button>📱 Responsive Design
Tất cả components đều hỗ trợ responsive design với breakpoints:
- Mobile: 320px - 640px (default)
- Tablet: 640px+ (
sm:) - Desktop: 1024px+ (
lg:,xl:,2xl:)
<Card className="p-4 sm:p-6 lg:p-8">
<h1 className="text-xl sm:text-2xl lg:text-3xl">
Responsive Title
</h1>
</Card>♿ Accessibility
Tất cả components đều tuân thủ WCAG 2.1 AA:
- Keyboard navigation support
- Screen reader compatibility
- Focus management
- ARIA labels
- Color contrast compliance
<Button aria-label="Thêm bệnh nhân mới">
<Icon name="plus" />
</Button>🧪 Testing
Unit Testing
import { render, screen } from '@testing-library/react';
import { Button } from '@qkit-emr/web-ui';
test('Button renders correctly', () => {
render(<Button>Test Button</Button>);
expect(screen.getByRole('button')).toBeInTheDocument();
});Storybook
Chạy Storybook để xem tất cả components:
npm run storybookTruy cập online: https://qkit-emr-share-ui.web.app/
📚 API Reference
Button Component
interface ButtonProps {
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'medical';
size?: 'default' | 'sm' | 'lg' | 'icon';
disabled?: boolean;
loading?: boolean;
children: React.ReactNode;
onClick?: () => void;
className?: string;
medical?: boolean; // Medical-specific styling
}Input Component
interface InputProps {
type?: 'text' | 'email' | 'password' | 'number' | 'tel';
placeholder?: string;
value?: string;
onChange?: (value: string) => void;
error?: string;
disabled?: boolean;
className?: string;
mask?: string; // Input mask for phone, date, etc.
medical?: boolean; // Medical-specific validation
}Medical Components
// LabResultAtom
interface LabResultAtomProps {
testName: string;
result: string;
normalRange: string;
status: 'normal' | 'high' | 'low' | 'critical';
unit?: string;
date?: Date;
}
// StatusBadgeAtom
interface StatusBadgeAtomProps {
status: 'critical' | 'warning' | 'stable' | 'discharged' | 'admitted';
size?: 'sm' | 'md' | 'lg';
}
// SecureInputAtom
interface SecureInputAtomProps {
placeholder?: string;
showToggle?: boolean;
medical?: boolean; // HIPAA compliance
}🔗 Dependencies
Peer Dependencies
{
"react": "^18.2.0",
"react-dom": "^18.2.0",
"@radix-ui/react-*": "^1.0.0",
"tailwindcss": "^3.3.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"tailwind-merge": "^2.0.0"
}Dev Dependencies
{
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"typescript": "~5.8.2"
}🚀 Development
Build
npm run buildDevelopment mode
npm run devStorybook
npm run storybook
npm run build-storybookTesting
npm test
npm run test:watchLinting
npm run lint
npm run lint:fix📦 Exports
Main exports
// UI Components (shadcn/ui)
export * from './components/ui';
// Atoms - Basic building blocks
export * from './components/atoms';
// Molecules - Complex components
export * from './components/molecules';
// Organisms - Page-level components
export * from './components/organisms';
// Templates - Layout components
export * from './components/templates';
// Pages - Complete page components
export * from './components/pages';
// Hooks
export * from './hooks';
// Responsive System
export * from './responsive';
// Utils
export * from './lib/utils';Named exports
import {
Button,
Input,
Card,
useTheme,
ThemeProvider,
cn,
ResponsiveProvider,
useResponsive
} from '@qkit-emr/web-ui';🤝 Contributing
- Fork repository
- Tạo feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Tạo Pull Request
Development Guidelines
- Tuân thủ Atomic Design principles
- Viết TypeScript với strict mode
- Thêm unit tests cho mọi component
- Tạo Storybook stories
- Đảm bảo accessibility compliance
- Responsive design cho mọi component
- Medical-specific features cho healthcare UI
📄 License
MIT License - xem file LICENSE để biết thêm chi tiết.
🆘 Support
- Issues: GitHub Issues
- Documentation: Storybook
- Email: [email protected]
🔄 Changelog
Xem CHANGELOG.md để biết lịch sử thay đổi.
Made with ❤️ by EMR Team
