Welcome to the UI Library! This guide will help you get started with development, testing, and contributing to the OpenCDx UI component library.
- Getting Started
- Development Workflow
- Interactive Menu
- Testing
- Building & Publishing
- Code Quality
- Security
- Troubleshooting
- Contributing
- Node.js: v21 (see
.nvmrc) - npm: v10+
- Git: For version control
# 1. Clone the repository
cd ui-library
# 2. Use correct Node version (if using nvm)
nvm use
# 3. Install dependencies
npm install
# 4. Verify installation
npm run build
npm run test:component
# 5. Start Storybook to explore components
npm run storybook
# Opens http://localhost:6006./dev.shFor first-time setup, use:
- Option 18: Install dependencies
- Option 21: Show project status
- Option 10: Start Storybook
# Option 1: Use the interactive menu
./dev.sh → 10) Start Storybook
# Option 2: Use npm commands directly
npm run storybook- Create/modify component in
src/[component-name]/ - Add/update tests
- Playwright CT in
tests/component/[ComponentName].spec.tsx(browser behavior) - Vitest unit tests in
tests/unit/[ComponentName].test.tsx(logic/props)
- Playwright CT in
- Add Storybook story in
src/stories/[ComponentName].stories.tsx - Run tests to verify:
npm run test:component # or ./dev.sh → 5) Run component tests - Check in Storybook for visual verification
- Lint code:
npm run lint:fix # or ./dev.sh → 13) Lint and auto-fix
| Task | Interactive Menu | Direct Command |
|---|---|---|
| Develop components | ./dev.sh → 10 |
npm run storybook |
| Run CT tests | ./dev.sh → 5 |
npm run test:component |
| Run unit tests | ./dev.sh → 5 |
npm run test:unit |
| Debug tests | ./dev.sh → 6 |
npm run test:ui |
| Lint & fix | ./dev.sh → 13 |
npm run lint:fix |
| Build library | ./dev.sh → 1 |
npm run build |
| Pre-commit check | ./dev.sh → 23 |
npm run lint && npm test && npm run build |
The dev.sh script provides a user-friendly interface for all development tasks.
╔════════════════════════════════════════════════════════╗
║ UI Library Development Menu v1.0.0 ║
╚════════════════════════════════════════════════════════╝
📦 BUILD & DEVELOPMENT (1-3)
Build, type generation, clean builds
🧪 TESTING (4-9)
All Playwright test options
🎨 STORYBOOK (10-11)
Dev server and static builds
🔍 CODE QUALITY (12-13)
Linting and auto-fixing
🔒 SECURITY & MAINTENANCE (14-17)
Dependency auditing and updates
📦 PACKAGE MANAGEMENT (18-20)
Installation and tarball creation
📊 PROJECT INFO (21-22)
Status dashboard and reports
🚀 QUICK ACTIONS (23-24)
Automated workflows
Shows at-a-glance information:
✓ Dependencies installed
✓ Library built (dist/ exists)
ℹ Node version: v21.x.x
ℹ Package: ui-library v1.0.0
ℹ Component tests: 18 files
Simulates GitHub Actions CI pipeline:
npm run lint # Code quality check
npm run test:component # All 70 tests
npm run build # Production buildUse before:
- Creating a pull request
- Pushing to remote
- Merging to main
Automated validation with 5 checks:
[1/5] Linting code... ✓ Lint passed
[2/5] Running tests... ✓ All tests passed
[3/5] Building library... ✓ Build successful
[4/5] Checking security... ✓ No vulnerabilities
[5/5] Checking git status... ✓ No uncommitted changes
✅ All checks passed! Ready to release.
Use before:
- Publishing to npm
- Creating a release tag
- Version bumping
- Playwright Component Testing for browser behavior
- Vitest for unit tests and coverage (fast, deterministic)
Via Interactive Menu:
./dev.sh
→ 5) Run component tests (fastest)
→ 6) UI mode (best for debugging)
→ 7) Headed mode (see browser)
→ 8) Debug mode (Inspector)
→ 9) Coverage reportVia npm:
## Playwright CTnpm run test:component npm run test:ui npm run test:headed npm run test:debug npm run coverage
## Vitest Unit
npm run test:unit npm run coverage:unit open coverage/index.html
See TESTING.md for comprehensive testing guide including:
- Test structure and patterns
- Best practices
- Common issues and solutions
- Debugging strategies
Quick example:
import { test, expect } from '@playwright/experimental-ct-react';
import { Button } from '../../src/index';
test.describe('Button', () => {
test('should render correctly', async ({ mount }) => {
const component = await mount(<Button>Click me</Button>);
await expect(component).toBeVisible();
await expect(component).toContainText('Click me');
});
});tests/
├── component/ # Component tests (*.spec.tsx)
│ ├── Button.spec.tsx
│ ├── Input.spec.tsx
│ ├── Card.spec.tsx
│ └── ... (18 total)
└── e2e/ # End-to-end tests
# Build library
npm run build
# Creates: dist/index.js (CJS) and dist/index.mjs (ESM)
# Or use menu
./dev.sh → 1) Build libraryTo test the library in another project locally:
# Method 1: Using the menu
./dev.sh → 20) Create tarball
# Method 2: Direct command
npm pack
# Then in your test project:
npm install ../ui-library/ui-library-1.0.0.tgzPre-publish validation:
# Use the automated checklist
./dev.sh → 24) Pre-release checklist
# If all ✅, proceed with:
npm version patch # or minor, major
git push
git push --tags
npm publishWe follow Semantic Versioning:
- MAJOR: Breaking API changes (2.0.0)
- MINOR: New features, backward compatible (1.1.0)
- PATCH: Bug fixes, backward compatible (1.0.1)
# Bump version
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
# Always run pre-release checklist first!
./dev.sh → 24We use ESLint with TypeScript support.
# Check for issues
npm run lint
# or
./dev.sh → 12) Lint code
# Auto-fix issues
npm run lint:fix
# or
./dev.sh → 13) Lint and auto-fix# Type checking happens during build
npm run build
# Generate type definitions
npm run build:types- Formatter: Prettier (integrated with ESLint)
- Style: 2 spaces, single quotes, semicolons
- Imports: Organized by React, libraries, local
- Components: PascalCase
- Files: kebab-case for utilities, PascalCase for components
# Check production dependencies (what gets published)
npm run audit
# or
./dev.sh → 14) Check production dependencies
# Check all dependencies (including dev tools)
npm run audit:dev
# or
./dev.sh → 15) Check all dependencies# Auto-fix (safe updates only)
npm run audit:fix
# or
./dev.sh → 16) Fix vulnerabilities
# Force fix (may break things)
npm audit fix --force
# ⚠️ Use with caution, test thoroughly after# See which packages have newer versions
npm run outdated
# or
./dev.sh → 17) Check outdated packages- Run
npm run auditbefore every release - Fix critical/high vulnerabilities immediately
- Review moderate/low on case-by-case basis
- Keep dependencies updated monthly
- Use exact versions for critical dependencies
See COMPONENT_GUIDELINES.md for:
- Component composition patterns
- NextUI wrapper constraints
- React.Children.map compatibility
- Best practices and examples
- Always export from
src/index.ts - Create a Storybook story for visual testing
- Write Playwright tests (minimum 3-5 tests per component)
- Follow naming conventions:
- Component:
Button.tsx - Hook:
use-button.ts - Test:
Button.spec.tsx - Story:
Button.stories.tsx
- Component:
# Clean and rebuild
./dev.sh → 19) Clean install
./dev.sh → 3) Clean build
./dev.sh → 5) Run tests
# Or manually:
rm -rf node_modules .next dist playwright/.cache
npm install
npm run build
npm run test:component# Check for type errors
npm run build:types
# Clean and rebuild
rm -rf dist
npm run build# Kill port if in use
lsof -ti:6006 | xargs kill -9
# Clear cache and restart
rm -rf node_modules/.cache
npm run storybookAll component imports should come from the main index:
// ✅ Good
import { Button, Card, Input } from '../../src/index';
// ❌ Bad
import Button from '../../src/button/button';-
Check documentation:
- README.md - General usage
- TESTING.md - Testing guide
- COMPONENT_GUIDELINES.md - Component patterns
- This guide (DEV_GUIDE.md) - Development workflows
-
Use the menu:
./dev.sh → 21for project status -
Check existing tests: See
tests/component/for examples -
Review Storybook: Running examples of all components
-
Ask the team: Slack #ui-library channel
-
Create a feature branch:
git checkout -b feature/new-component
-
Make your changes:
- Add/modify components
- Write tests (required)
- Add Storybook stories
- Update documentation
-
Validate locally:
./dev.sh → 23) Full CI workflow
This runs the same checks as GitHub Actions.
-
Commit with conventional commits:
git add . git commit -m "feat(button): add loading state" # or git commit -m "fix(input): resolve focus issue" # or git commit -m "test(card): add accessibility tests"
-
Push and create PR:
git push origin feature/new-component
-
PR will automatically:
- Run all tests
- Check code quality
- Verify build succeeds
- Run security audit
We use Conventional Commits:
<type>(<scope>): <description>
[optional body]
[optional footer]
Types:
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Code style (formatting, missing semicolons, etc.)refactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or updating testschore: Maintenance tasks (deps, config, etc.)
Examples:
feat(modal): add customizable animation duration
fix(button): resolve ripple effect on Safari
docs(readme): update testing section
test(input): add keyboard navigation tests
chore(deps): update Playwright to v1.48Before requesting review, ensure:
- ✅ All tests pass (
./dev.sh → 5) - ✅ No lint errors (
./dev.sh → 12) - ✅ Documentation updated
- ✅ Storybook story added
- ✅ CHANGELOG.md updated
- ✅ Types properly exported
- ✅ No console errors/warnings
# Standard install
npm install
# Clean install (recommended when switching branches)
rm -rf node_modules package-lock.json
npm install
# Or use menu
./dev.sh → 19) Clean installAdding a new dependency:
# Production dependency
npm install package-name
# Dev dependency
npm install -D package-name
# Peer dependency (add to package.json manually)Checking for updates:
npm run outdated
# or
./dev.sh → 17) Check outdated packagesUpdating dependencies:
# Update a specific package
npm update package-name
# Update all to latest (within semver range)
npm update
# Update to latest (breaking changes)
npm install package-name@latestThe library is built with tsup (TypeScript Universal Package builder):
npm run buildOutputs:
dist/index.js- CommonJS (for Node.js)dist/index.mjs- ES Modules (for bundlers)dist/**/*.d.ts- TypeScript types
tsup.config.ts:
- Formats: CJS + ESM
- Source maps: Enabled
- Type declarations: Generated
- Minification: Disabled (bundlers handle this)
# Build and check output
npm run build
ls -la dist/
# Or use menu
./dev.sh → 1) Build library /\
/E2E\ ← Few tests (critical user flows)
/------\
/ API \ ← Some tests (integration)
/----------\
/ Component \ ← Many tests (70+ component tests)
/--------------\
Purpose: Verify individual components work correctly
What to test:
- ✅ Component renders
- ✅ Props are applied
- ✅ User interactions work
- ✅ Accessibility features
- ✅ Different states (disabled, error, loading)
Example:
test('should render with color variant', async ({ mount }) => {
const component = await mount(<Button color="primary">Click</Button>);
const classes = await component.getAttribute('class');
expect(classes).toContain('bg-primary');
});Purpose: Verify complete user workflows
What to test:
- User registration flow
- Form submissions
- Navigation between pages
- Real API integration
- Component coverage: 100% (all exported components)
- Line coverage: 80%+
- Branch coverage: 75%+
- Function coverage: 80%+
# Generate coverage report
npm run coverage
# or
./dev.sh → 9) Generate coverage report
# View report
open playwright-report/index.html- Strict mode: Enabled
- Type safety: No
anytypes (useunknownif needed) - Explicit returns: Always declare return types for functions
- No unused vars: Compiler enforces this
- Hooks: Follow Rules of Hooks
- Memoization: Use
useMemo/useCallbackfor expensive operations - Props: Destructure for clarity
- Event handlers: Use
onPressfor NextUI components (notonClick) - Accessibility: Always provide proper ARIA attributes
src/
├── [component-name]/
│ ├── component-name.tsx # Main component
│ ├── use-component-name.ts # Custom hook
│ ├── component-name-*.tsx # Sub-components
│ └── *-context.ts # Context (if needed)
└── index.ts # Main export file
Always audit before releasing:
./dev.sh → 24) Pre-release checklist
# Includes security auditCurrent status (as of v1.0.1):
- Production dependencies: 0 vulnerabilities ✅
- Dev dependencies: 3 moderate (low risk, dev tools only)
- Daily: Automated in CI/CD
- Weekly: Manual review (
npm run audit) - Before release: Required check (option 24)
- Monthly: Full dependency audit and updates
When adding/changing components:
- ✅ Update README.md if adding new scripts/features
- ✅ Update CHANGELOG.md with changes
- ✅ Add Storybook story with examples
- ✅ Write tests with clear descriptions
- ✅ Add JSDoc comments to component props
- ✅ Update COMPONENT_GUIDELINES.md if adding patterns
| File | Purpose | Update When |
|---|---|---|
README.md |
Getting started, usage | Adding features/scripts |
DEV_GUIDE.md |
Development workflows | Changing dev process |
TESTING.md |
Testing guide | Adding test patterns |
COMPONENT_GUIDELINES.md |
Component patterns | Architecture changes |
CHANGELOG.md |
Release history | Every release |
/**
* Primary button component for user actions.
*
* @param color - Visual style variant (primary, secondary, success, etc.)
* @param size - Size variant (sm, md, lg)
* @param isDisabled - Whether the button is disabled
* @param onPress - Click handler (use onPress, not onClick for NextUI)
*
* @example
* ```tsx
* <Button color="primary" size="lg" onPress={() => console.log('clicked')}>
* Click me
* </Button>
* ```
*/
export interface ButtonProps {
color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger';
size?: 'sm' | 'md' | 'lg';
isDisabled?: boolean;
onPress?: () => void;
}1. Prepare for release:
# Update version in package.json
npm version patch # or minor/major
# Update CHANGELOG.md
# Add release date and version2. Run pre-release checklist:
./dev.sh → 24) Pre-release checklistWait for all 5 checks to complete:
- [1/5] Linting code... ✓
- [2/5] Running tests... ✓
- [3/5] Building library... ✓
- [4/5] Checking security... ✓
- [5/5] Checking git status... ✓
3. If all ✅, publish:
# Commit version bump
git add package.json CHANGELOG.md
git commit -m "chore: release v1.0.1"
# Create tag
git tag v1.0.1
# Push
git push
git push --tags
# Publish to npm
npm publish4. Post-release:
# Create GitHub release with CHANGELOG notes
# Notify team in Slack
# Update dependent projects- All tests pass (70/70)
- No lint errors
- Build succeeds
- No security vulnerabilities in production deps
- CHANGELOG.md updated with version and date
- Documentation reflects new changes
- Version bumped in package.json
- Git tag created
- Published to npm/GitHub Packages
- GitHub release created
- Team notified
💡 Tip: Option 24 in ./dev.sh automates the first 5 items!
- README.md - Start here for basic usage
- DEV_GUIDE.md - This guide (workflows and processes)
- TESTING.md - Comprehensive testing guide
- COMPONENT_GUIDELINES.md - Component architecture
- CHANGELOG.md - Version history
- VERSION_COMPATIBILITY.md - Dependency versions
- Playwright: https://playwright.dev/
- NextUI: https://nextui.org/
- React: https://react.dev/
- TypeScript: https://www.typescriptlang.org/
- Tailwind CSS: https://tailwindcss.com/
- Storybook: https://storybook.js.org/
See how ui-library is used in:
- opencdx-dashboard: Main admin dashboard
- ADR-gui: Analysis Data Repository UI
Fast test feedback loop:
# Run only one test file
npx playwright test Button.spec.tsx --config=playwright-ct.config.ts
# Or watch mode for development
npx playwright test --uiFast build iteration:
# Build watches for changes (add to package.json if needed)
npm run build -- --watchUseful aliases (add to your .zshrc or .bashrc):
alias uilib='cd /path/to/ui-library'
alias uidev='cd /path/to/ui-library && ./dev.sh'
alias uitest='cd /path/to/ui-library && npm run test:ui'VS Code snippets for common patterns:
{
"Playwright Component Test": {
"prefix": "pwtest",
"body": [
"test('should $1', async ({ mount }) => {",
" const component = await mount(<$2 />);",
" await expect(component).toBeVisible();",
"});"
]
}
}Run Storybook and tests side-by-side:
# Terminal 1
npm run storybook
# Terminal 2
npm run test:uiWatch mode for development:
# Terminal 1: Storybook (auto-reloads on changes)
npm run storybook
# Terminal 2: Tests in UI mode (rerun on change)
npm run test:ui| What You Want To Do | Interactive Menu | Direct Command |
|---|---|---|
| Start developing | ./dev.sh → 10 |
npm run storybook |
| Run tests | ./dev.sh → 5 |
npm run test:component |
| Debug a test | ./dev.sh → 6 |
npm run test:ui |
| Fix lint issues | ./dev.sh → 13 |
npm run lint:fix |
| Check security | ./dev.sh → 14 |
npm run audit |
| Before commit | ./dev.sh → 23 |
npm run lint && npm test && npm run build |
| Before release | ./dev.sh → 24 |
See release checklist above |
| Build library | ./dev.sh → 1 |
npm run build |
| Create package | ./dev.sh → 20 |
npm pack |
| View status | ./dev.sh → 21 |
Check files manually |
| What | Where |
|---|---|
| Components | src/[component-name]/ |
| Tests | tests/component/[Component].spec.tsx |
| Stories | src/stories/[Component].stories.tsx |
| Build output | dist/ |
| Test reports | playwright-report/ |
| Documentation | *.md files in root |
Now that you're familiar with the development workflow:
- Explore components in Storybook:
npm run storybook - Read the guides:
- TESTING.md for testing patterns
- COMPONENT_GUIDELINES.md for architecture
- Try the menu:
./dev.shfor guided workflows - Make your first change and run
./dev.sh → 23before committing
- Documentation: This guide + other
.mdfiles - Interactive help:
./dev.shmenu system - Issues: GitHub Issues
- Team chat: Slack #ui-library
- Email: ui-library-team@opencdx.org
Happy coding! 🚀
Last updated: October 12, 2025