@abstraks-dev/ui-library
v2.3.0
Published
User Interface library
Readme
ui-library
A comprehensive React UI component library with modern styling and robust testing.
Installation
npm install @abstraks-dev/ui-libraryUsage
import {
Button,
Card,
TextInput,
Header,
Hero,
Alert,
Modal,
} from '@abstraks-dev/ui-library';
import '@abstraks-dev/ui-library/dist/styles/main.css';
function App() {
return (
<div>
<Header />
<Hero title='Welcome' subtitle='Get started with our UI library' />
<Alert type='success' message='Library loaded successfully!' />
<Card>
<TextInput label='Name' placeholder='Enter your name' />
<Button variant='primary'>Submit</Button>
<Button variant='transparent'>Cancel</Button>
</Card>
</div>
);
}Available Components
Core Components
Button
Multiple variants and sizes with accessibility support.
<Button variant="primary" size="md">Primary Button</Button>
<Button variant="secondary" size="lg">Secondary Button</Button>
<Button variant="transparent" size="sm">Transparent Button</Button>
<Button variant="error" isOutline={true}>Error Outline</Button>Available variants: primary, secondary, success, error, warning, transparent
Available sizes: xs, sm, md, lg, xl
Card
Container component for grouping related content.
<Card>
<h3>Card Title</h3>
<p>Card content goes here</p>
</Card>Header
Navigation header with authentication support.
<Header />Hero
Hero section component for landing pages.
<Hero
title='Welcome to Our App'
subtitle='Build amazing experiences with our UI library'
/>Form Components
TextInput
Text input with label and validation support.
<TextInput label='Email' placeholder='Enter your email' type='email' />TextArea
Multi-line text input.
<TextArea label='Message' placeholder='Enter your message' rows={4} />Checkbox
Checkbox input with label.
<Checkbox name='subscribe' label='Subscribe to newsletter' />Radio
Radio button input.
<Radio name="gender" value="male" label="Male" />
<Radio name="gender" value="female" label="Female" />Select
Dropdown select component.
<Select
label='Country'
options={[
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
]}
/>FileInput
File upload component.
<FileInput label='Upload Document' accept='.pdf,.doc,.docx' />Layout Components
Form
Form wrapper with validation support.
<Form onSubmit={handleSubmit}>
<TextInput label='Name' />
<Button type='submit'>Submit</Button>
</Form>Tabs
Tabbed content component.
<Tabs>
<Tab label='Tab 1'>Content 1</Tab>
<Tab label='Tab 2'>Content 2</Tab>
</Tabs>Feedback Components
Alert
Alert messages with different types.
<Alert type="success" message="Operation completed!" />
<Alert type="error" message="Something went wrong!" />
<Alert type="warning" message="Please check your input!" />
<Alert type="info" message="New features available!" />Modal
Accessible modal dialog component with portal rendering.
import { useState } from 'react';
import { Modal, Button } from '@abstraks-dev/ui-library';
function MyComponent() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button onClick={() => setIsOpen(true)}>Open Modal</Button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title='Confirm Action'
size='md'
footer={
<>
<Button variant='ghost' onClick={() => setIsOpen(false)}>
Cancel
</Button>
<Button variant='primary' onClick={handleConfirm}>
Confirm
</Button>
</>
}
>
<p>Are you sure you want to proceed with this action?</p>
</Modal>
</>
);
}Available sizes: sm, md, lg, xl, full
Props:
isOpen- Controls modal visibilityonClose- Callback when modal requests to closetitle- Modal titlechildren- Modal body contentfooter- Custom footer content (typically buttons)size- Modal width size (default:md)closeOnBackdropClick- Allow closing by clicking backdrop (default:true)closeOnEscape- Allow closing with Escape key (default:true)showCloseButton- Show X close button in header (default:true)preventBodyScroll- Lock body scroll when open (default:true)
Error
Error message component.
<Error severity='error'>Please fill in all required fields</Error>Loader
Loading spinner component.
<Loader size='large' />Navigation Components
Search
Search input with results.
<Search placeholder='Search...' onSearch={handleSearch} />SideMenu
Collapsible side navigation menu.
<SideMenu />Utility Components
Avatar
User avatar component.
<Avatar src='user-photo.jpg' alt='John Doe' size='large' />Anchor
Accessible link component.
<Anchor href='/about'>About Us</Anchor>Typography Components
Heading
Semantic heading component.
<Heading level={1} variant="primary">Main Title</Heading>
<Heading level={2} variant="secondary">Subtitle</Heading>Paragraph
Paragraph text component.
<Paragraph size='large'>This is a paragraph with large text.</Paragraph>Label
Form label component.
<Label htmlFor='email' required>
Email Address
</Label>Icons
The library includes a comprehensive set of icons:
import {
Heart,
Home,
Search,
ArrowRight,
CheckCircle,
LoadingSpinner
} from '@abstraks-dev/ui-library';
<Heart size={24} color="red" />
<Home size={20} />
<ArrowRight dimensions={16} />Available icons: AccountBox, AccountCircle, ArrowIcon, ArrowRight, BookOpen, CameraIcon, CaretDown, CheckCircle, ChevronDown, Close, Comment, EditSquare, Ellipses, Explore, Filter, Group, GroupReview, Hamburger, Heart, Home, LoadingSpinner, LogOut, Magnify, News, PlusCircle, Review, SaveIcon, TrashX
Development
Setup
npm install
npm test
npm run storybookBuilding
npm run buildSCSS Development
The library uses SCSS for styling. Available SCSS commands:
# Build CSS from SCSS
npm run build-css
# Watch SCSS files for changes (development)
npm run build-css:watch
# Build compressed CSS for production
npm run build-css:compressedProduction Storybook
You can view the latest production build of the UI Library Storybook here:
Deployment
This library supports both manual and automated deployment to npm using GitHub Actions.
Automated Version Bumping
The library includes automated version bumping based on commit message conventions:
Conventional Commits
Use these commit message prefixes to automatically bump versions:
feat:orfeature:→ Minor version bump (1.0.0 → 1.1.0)fix:orbugfix:→ Patch version bump (1.0.0 → 1.0.1)feat!:orBREAKING CHANGE→ Major version bump (1.0.0 → 2.0.0)
Examples:
git commit -m "feat: add new Button component variants" # Minor bump
git commit -m "fix: resolve focus issue in TextInput" # Patch bump
git commit -m "feat!: remove deprecated props from Card" # Major bumpUsing Auto Tool
You can also use the configured auto tool:
# Automatic release based on PR labels
npm run release
# Or use auto directly
npx auto shipitManual Deployment
- Push a version tag (e.g.,
v1.0.0) to trigger automatic deployment - The workflow will run tests, build the library, and publish to npm
Manual Deployment
- Go to the Actions tab in GitHub
- Select "Deploy to NPM" workflow
- Click "Run workflow" and choose version bump type (patch/minor/major)
Setting Up NPM Token
- Generate an npm token at https://www.npmjs.com/settings/tokens
- Add it as
NPM_TOKENin repository secrets (Settings → Secrets and variables → Actions)
Version Tags
# Create and push a version tag
git tag v1.0.0
git push origin v1.0.0UI Library Testing
This document explains how to run and write tests for the UI Library components.
🏃♂️ Running Tests
Basic Commands
# Run all tests
npm test
# Run tests in watch mode (automatically re-runs when files change)
npm run test:watch
# Run tests with coverage report
npm run test:coverageTest Files Structure
src/
├── components/
│ ├── __tests__/
│ │ ├── Button.test.jsx
│ │ ├── Heading.test.jsx
│ │ ├── Label.test.jsx
│ │ ├── Checkbox.test.jsx
│ │ └── MenuHover.test.jsx
│ └── [component files]
├── icons/
│ ├── __tests__/
│ │ ├── ChevronDown.test.jsx
│ │ └── ArrowRight.test.jsx
│ └── [icon files]
└── setupTests.js✅ Current Test Coverage
We have comprehensive unit tests for:
Components
- Button - 9 tests covering props, events, states, and rendering
- Heading - 8 tests covering different heading levels and props
- Label - 12 tests covering label text, required states, and children
- Checkbox - 15 tests covering state management, props, and interactions
- MenuHover - 8 tests covering toggle behavior, CSS classes, and props
Icons
- ChevronDown - 8 tests covering SVG properties, styling, and props
- ArrowRight - 10 tests covering multi-path SVG structure and props
Total: 70 tests passing ✅
🧪 Testing Framework
Tech Stack
- Jest - Test runner and assertion library
- React Testing Library - Component testing utilities
- @testing-library/user-event - User interaction simulation
- @testing-library/jest-dom - Extended Jest matchers
Configuration
- Jest Config:
jest.config.json - Babel Config:
babel.config.json - Setup File:
src/setupTests.js
Key Features
- CSS Import Mocking - CSS files are automatically mocked
- Custom Test ID Attribute - Uses
data-test-idinstead ofdata-testid - SVG Testing - Proper handling of SVG components
- User Interaction Testing - Simulated clicks, form inputs, etc.
📝 Writing New Tests
Basic Test Structure
import React from 'react';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { YourComponent } from '../YourComponent';
describe('YourComponent', () => {
test('renders correctly', () => {
render(<YourComponent />);
expect(screen.getByRole('button')).toBeInTheDocument();
});
test('handles user interaction', async () => {
const user = userEvent.setup();
const handleClick = jest.fn();
render(<YourComponent onClick={handleClick} />);
await user.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});Testing Patterns
1. Component Rendering
test('renders with default props', () => {
render(<Button>Click me</Button>);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
expect(button).toHaveTextContent('Click me');
});2. Props Testing
test('applies custom className', () => {
render(<Button additionalClassName='custom'>Test</Button>);
const button = screen.getByRole('button');
expect(button).toHaveClass('button', 'custom');
});3. User Interactions
test('handles click events', async () => {
const user = userEvent.setup();
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
await user.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});4. State Testing
test('toggles state when clicked', async () => {
const user = userEvent.setup();
render(<Checkbox labelText='Test' setName='test' />);
const checkbox = screen.getByRole('checkbox');
expect(checkbox).not.toBeChecked();
await user.click(checkbox);
expect(checkbox).toBeChecked();
});5. SVG/Icon Testing
test('renders SVG with correct attributes', () => {
render(<ChevronDown size={32} color='blue' />);
const svg = document.querySelector('svg');
expect(svg).toHaveAttribute('width', '32');
expect(svg).toHaveAttribute('height', '32');
const path = svg.querySelector('path');
expect(path).toHaveAttribute('stroke', 'blue');
});Best Practices
- Use semantic queries - Prefer
getByRole(),getByLabelText(), etc. - Test user behavior - Focus on what users do, not implementation details
- Use data-test-id sparingly - Only when semantic queries aren't sufficient
- Mock external dependencies - Keep tests isolated and fast
- Test error states - Include edge cases and error conditions
- Keep tests readable - Use descriptive test names and clear assertions
Common Queries
// Semantic queries (preferred)
screen.getByRole('button')
screen.getByLabelText('Email')
screen.getByText('Submit')
screen.getByPlaceholderText('Enter email')
// Test ID queries (when semantic queries aren't enough)
screen.getByTestId('custom-component')
// Query variants
getBy* // Throws error if not found
queryBy* // Returns null if not found
findBy* // Async, waits for element to appear🐛 Debugging Tests
Common Issues
- Element not found - Check if element is rendered and query is correct
- CSS not loading - CSS is automatically mocked, so style-based queries won't work
- Async operations - Use
findBy*queries orwaitFor()for async updates - SVG elements - Use
document.querySelector()instead ofgetByRole()
Debug Tools
// Print rendered HTML
screen.debug();
// Print specific element
screen.debug(screen.getByRole('button'));
// Log available roles
screen.logTestingPlaygroundURL();📊 Coverage Goals
- Statements: 80%+
- Branches: 80%+
- Functions: 80%+
- Lines: 80%+
Current coverage is low because we only have tests for a few components. Add tests for remaining components to improve coverage.
🚀 Next Steps
- Add tests for remaining components - Cover all components in the library
- Integration tests - Test component interactions and workflows
- Visual regression tests - Consider adding Chromatic or similar tools
- Performance tests - Test rendering performance for complex components
- Accessibility tests - Add automated a11y testing
Happy testing! 🧪✨
Accessibility Utilities Usage Guide
Overview
The utils/accessibility.js module provides safe, SSR-compatible utilities for common accessibility patterns throughout the UI library. These utilities help ensure consistent, robust accessibility implementations across components and stories.
Available Utilities
announceToScreenReader(message, priority, timeout)
Safe screen reader announcements using ARIA live regions.
- Parameters:
message(string): Message to announcepriority('polite'|'assertive'): Announcement priority (default: 'polite')timeout(number): Cleanup timeout in ms (default: 1000)
- Returns: Cleanup function for manual cleanup
- SSR Safe: Yes (returns no-op function)
createLiveRegion(priority)
Creates a persistent live region for multiple announcements.
- Parameters:
priority('polite'|'assertive'): Announcement priority (default: 'polite')
- Returns: Object with
announce(message)anddestroy()methods - SSR Safe: Yes (returns no-op methods)
safeFocus(element, options)
Safely focuses an element with fallback handling.
- Parameters:
element(HTMLElement|string): Element or selector to focusoptions(object): Focus options (optional)
- Returns: Boolean indicating focus success
- Features: Error handling, selector support, focus verification
Updated Components
✅ Components Using Accessibility Utilities
Error.jsx
- Uses built-in ARIA live regions (no manual utilities needed)
- Serves as example of proper component-level accessibility
Form.jsx
- Updated: Uses
safeFocusfor error field focusing - Updated: Uses
announceToScreenReaderfor form validation announcements - Location: Lines 1-4 (imports), Line 184 (focus call)
- Updated: Uses
DragAndDrop.jsx
- Updated: Uses
safeFocusfor keyboard navigation - Location: Lines 12 (import), 123 (drag start), 174 & 184 (keyboard navigation)
- Updated: Uses
✅ Stories Using Accessibility Utilities
Avatar.stories.js
- Updated: Replaced manual DOM manipulation with
announceToScreenReader - Removed: 13 lines of unsafe DOM manipulation code
- Benefits: SSR safety, consistent behavior, proper cleanup
- Updated: Replaced manual DOM manipulation with
AnimationGroup.stories.js
- Updated: Replaced manual DOM manipulation with
announceToScreenReader - Removed: 15 lines of unsafe DOM manipulation code
- Benefits: Better positioning, consistent ARIA attributes
- Updated: Replaced manual DOM manipulation with
AnimationToggle.stories.js
- Updated: Uses
safeFocusfor focus management - Updated: Uses
announceToScreenReaderfor state announcements - Benefits: Safer focus operations, proper error handling
- Updated: Uses
Card.stories.js
- Updated: Replaced manual DOM manipulation with
announceToScreenReader - Updated: Uses
safeFocusfor ellipses menu focus management - Removed: 14 lines of duplicate DOM manipulation code
- Updated: Replaced manual DOM manipulation with
DragAndDrop.stories.js
- Updated: Uses
announceToScreenReaderinstead of setState pattern - Benefits: More reliable announcements, consistent with other stories
- Updated: Uses
Components That Could Benefit Further
🔄 Potential Future Updates
AnimationToggle.jsx (Component level)
- Could use
safeFocusfor internal focus management - Currently relies on native focus which works well
- Could use
Crud.jsx
- Has built-in screen reader announcements (lines 538-542)
- Could potentially use
createLiveRegionfor efficiency with many operations - Current implementation is already quite good
Button.jsx
- Has comprehensive ARIA support
- Focus management handled by browser - no updates needed
Select.jsx, TextInput.jsx, TextArea.jsx, Radio.jsx, Checkbox.jsx
- These form elements have focus/blur handlers
- Current native focus handling is appropriate for form elements
- No updates recommended - browser handles focus well for form controls
❓ Stories with Existing Accessibility Patterns
Crud.stories.js
- Has comprehensive ARIA live regions built into component
- No manual DOM manipulation found - well implemented
Button.stories.js
- Uses component's built-in ARIA features
- No manual screen reader code found - good as is
Best Practices
✅ When to Use These Utilities
Use
announceToScreenReaderwhen:- Making dynamic announcements in Storybook stories
- Announcing user actions or state changes
- Providing feedback for asynchronous operations
Use
createLiveRegionwhen:- Making multiple announcements in succession
- Need more control over announcement timing
- Building components with frequent status updates
Use
safeFocuswhen:- Focusing elements that might not exist
- Implementing custom focus management
- Focus operations that could fail (dynamic content, conditional elements)
❌ When NOT to Use These Utilities
Don't use for:
- Form elements with native focus handling
- Components with built-in ARIA live regions
- Simple static content that doesn't need announcements
Prefer component-level ARIA for:
- Built-in component state announcements
- Semantic HTML with proper roles
- Standard form validation messages
Implementation Benefits
🚀 Improvements Achieved
- Safety: SSR-compatible with browser environment checks
- Consistency: Standardized ARIA attributes and cleanup patterns
- Maintainability: Centralized accessibility logic
- Reliability: Proper error handling and fallbacks
- Performance: Efficient DOM cleanup and reuse patterns
📈 Code Quality Improvements
- Removed: 57+ lines of duplicate DOM manipulation code
- Added: 3 robust, reusable utilities
- Improved: Error handling for focus operations
- Enhanced: Screen reader announcement reliability
Testing Recommendations
Screen Reader Testing
- Test with NVDA, JAWS, VoiceOver to verify announcements
- Verify announcements work in different browser environments
- Test SSR scenarios to ensure no client-side errors
Focus Management Testing
- Test keyboard navigation flows
- Verify focus indicators are visible
- Test with dynamic content scenarios
Cross-browser Testing
- Verify utilities work across different browsers
- Test in high contrast mode
- Verify reduced motion preferences are respected
Future Enhancements
Potential Additional Utilities
- Focus Trap: For modal dialogs and complex widgets
- ARIA State Manager: For complex state announcements
- Keyboard Navigation Helper: For arrow key navigation patterns
- High Contrast Utilities: For dynamic high contrast adaptations
This comprehensive integration ensures the UI library follows accessibility best practices while maintaining clean, maintainable code.
Deployment Guide
This guide explains how to deploy the UI library to npm using the automated GitHub Actions workflow.
Prerequisites
- NPM Account: Ensure you have an npm account and access to publish packages
- Repository Access: Admin access to the GitHub repository to configure secrets
- Package Configuration: Verify
package.jsonis properly configured
Setup Process
1. Configure NPM Token
- Go to npm Access Tokens
- Click "Generate New Token"
- Select "Automation" (for CI/CD use)
- Copy the generated token
2. Add GitHub Secret
- Go to your repository on GitHub
- Navigate to Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
NPM_TOKEN - Value: Paste your npm token
- Click "Add secret"
3. Package Configuration
Ensure your package.json has:
{
"name": "your-package-name",
"version": "1.0.0",
"main": "dist/index.js",
"files": ["dist"],
"scripts": {
"build": "npm run build-command"
}
}Deployment Methods
Method 1: Tag-based Deployment (Recommended)
This method automatically deploys when you push a version tag:
# Make sure your code is ready
git add .
git commit -m "Prepare for release v1.0.0"
git push origin main
# Create and push a version tag
git tag v1.0.0
git push origin v1.0.0The workflow will:
- ✅ Run all tests
- ✅ Build the library
- ✅ Publish to npm
- ✅ Create a GitHub release
Method 2: Manual Deployment
Use this for immediate deployment or when you want to control the version bump:
- Go to GitHub Actions tab in your repository
- Select "Deploy to NPM" workflow
- Click "Run workflow"
- Choose version bump type:
- patch: Bug fixes (1.0.0 → 1.0.1)
- minor: New features (1.0.0 → 1.1.0)
- major: Breaking changes (1.0.0 → 2.0.0)
- Click "Run workflow"
Workflow Steps
The deployment workflow performs these steps:
1. Testing Phase
- ✅ Checkout code
- ✅ Setup Node.js
- ✅ Install dependencies
- ✅ Run test suite
- ✅ Generate coverage report
2. Build and Deploy Phase
- ✅ Build the library
- ✅ Version management
- ✅ Verify build artifacts
- ✅ Publish to npm
- ✅ Create GitHub release (for tags)
Monitoring Deployment
Check GitHub Actions
- Go to Actions tab in your repository
- Click on the running/completed workflow
- Review logs for each step
- Verify success or investigate failures
Verify NPM Publication
- Check npmjs.com
- Verify the new version is available
- Test installation:
npm install your-package-name@latest
Test Installation
# Create a test project
mkdir test-installation && cd test-installation
npm init -y
# Install your package
npm install your-package-name
# Test import
node -e "console.log(require('your-package-name'))"Troubleshooting
Common Issues
❌ NPM_TOKEN not set
- Error:
npm ERR! need auth - Solution: Verify the NPM_TOKEN secret is correctly configured
❌ Package name already exists
- Error:
npm ERR! 403 Forbidden - Solution: Choose a unique package name or scope it (
@username/package-name)
❌ Build failures
- Error: Various build errors
- Solution: Run
npm run buildlocally first to identify issues
❌ Test failures
- Error: Tests fail in CI
- Solution: Ensure all tests pass locally with
npm test
Debug Steps
Local verification:
npm ci npm test npm run build ls -la dist/ # Verify build outputCheck workflow logs:
- Go to Actions → Failed workflow → Click on failed step
- Review error messages and stack traces
Test npm authentication:
npm whoami # Should show your npm username
Best Practices
Version Management
- Use semantic versioning (semver)
- Document changes in CHANGELOG.md
- Test thoroughly before releasing
Quality Gates
- All tests must pass
- Code coverage maintained
- Build artifacts verified
- Documentation updated
Release Notes
- Use descriptive commit messages
- Tag releases with clear version numbers
- Maintain changelog for users
Security Considerations
- 🔒 NPM tokens have write access - keep them secure
- 🔒 Use "Automation" tokens for CI/CD (not "Publish" tokens)
- 🔒 Regularly rotate tokens
- 🔒 Monitor package downloads for suspicious activity
Support
If you encounter issues:
- Check this guide first
- Review GitHub Actions logs
- Verify npm token permissions
- Test build process locally
- Check npm registry status
