unisys-ui-components
v1.0.35
Published
Production-ready React component library with accessible, themeable components - Button, Checkbox, Slider, Loader, Toaster, Input, TextArea, Radio, Toggle, Select, Accordion, Tooltip, Modal
Maintainers
Readme
unisys-ui-components
A production-ready React component library featuring accessible, themeable UI components.
Features
- 🎨 Themeable - All components use CSS variables for easy customization
- ♿ Accessible - WCAG AA compliant with full keyboard support
- 🌳 Tree-shakeable - Import only what you need
- 📦 Lightweight - Zero runtime dependencies
- 🔧 TypeScript - Full type definitions included
- ⚛️ React 18+ - Modern React with hooks and forwardRef
- 🔄 Flexible - All props forwarded, refs supported, fully customizable
Installation
npm install unisys-ui-componentsComponent Demos (CodeSandbox)
Preview and interact with each component live on CodeSandbox:
- Checkbox
- Chips
- Lookup
- Buttons
- Input Fields
- Text Areas
- Radio Buttons
- Toggle Switch
- Slider
- Modal Popup
- Tooltip
- Accordion
- Loaders
- Toasters
Quick Start
import {
Button,
Checkbox,
Input,
Modal,
Tooltip,
Toaster,
ToasterRoot
} from 'unisys-ui-components';
import 'unisys-ui-components/styles.css';
function App() {
return (
<ToasterRoot>
<Button variant="primary" onClick={() => Toaster.success('Hello!')}>
Click Me
</Button>
</ToasterRoot>
);
}Components
| Component | Description |
|-----------|-------------|
| Button | Versatile button with 3 variants and 5 sizes |
| Checkbox | Custom checkbox with indeterminate state |
| Chips | Tag/filter chips with 5 variants (success, selected, attention, failed, disabled) |
| Lookup | Multi-select search input with chips and dropdown |
| Input | Text input with validation states |
| TextArea | Multi-line text input |
| Select | Dropdown select component |
| Radio | Radio button for single selection |
| Toggle | Toggle switch component |
| Slider | Range slider with keyboard navigation |
| Accordion | Collapsible content sections |
| Tooltip | Informational tooltip with arrow |
| Modal | Modal dialog with actions |
| Loader | Loading indicators (Spinner, SegmentedLoader, CircularProgress) |
| Toaster | Toast notification system |
Usage Examples
Button
import { Button } from 'unisys-ui-components';
// Variants
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
// Sizes
<Button size="xs">Extra Small</Button>
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="xl">Extra Large</Button>
// States
<Button loading>Loading...</Button>
<Button disabled>Disabled</Button>
// With click handler
<Button variant="primary" onClick={() => console.log('Clicked!')}>
Click Me
</Button>Checkbox
import { useState } from 'react';
import { Checkbox } from 'unisys-ui-components';
function Example() {
const [checked, setChecked] = useState(false);
return (
<Checkbox
checked={checked}
onCheckedChange={setChecked}
label="Accept terms and conditions"
/>
);
}
// Indeterminate state
<Checkbox checked="indeterminate" label="Select all" />
// Disabled
<Checkbox disabled label="Disabled option" />Chips
import { Chips } from 'unisys-ui-components';
// All variants
<Chips label="Success" variant="success" closable onClose={() => {}} />
<Chips label="Selected" variant="selected" closable onClose={() => {}} />
<Chips label="Attention" variant="attention" closable onClose={() => {}} />
<Chips label="Failed" variant="failed" closable onClose={() => {}} />
<Chips label="Disabled" variant="disabled" />
// Different sizes
<Chips label="Small" size="sm" variant="success" />
<Chips label="Medium" size="md" variant="success" />
<Chips label="Large" size="lg" variant="success" />
// With custom icon
<Chips
label="Custom"
variant="success"
icon={<span>★</span>}
closable
/>
// Clickable chip
<Chips
label="Click me"
variant="selected"
onClick={() => console.log('Clicked!')}
/>Lookup
import { useState } from 'react';
import { Lookup, LookupOption } from 'unisys-ui-components';
const options: LookupOption[] = [
{ value: '1', label: 'Differential psychology' },
{ value: '2', label: 'Cognition' },
{ value: '3', label: 'Behavioral neuroscience' },
{ value: '4', label: 'Psychological statistics' },
];
function Example() {
const [selected, setSelected] = useState<string[]>([]);
return (
<Lookup
label="Label Name"
required
options={options}
value={selected}
onChange={setSelected}
placeholder="Search..."
/>
);
}
// With max selections
<Lookup
label="Select up to 3"
options={options}
maxSelections={3}
/>
// With error state
<Lookup
label="Required Field"
options={options}
error
errorMessage="Please select at least one option"
/>
// Custom width
<Lookup
label="Wide Lookup"
options={options}
width={600}
/>Input
import { useState, ChangeEvent } from 'react';
import { Input } from 'unisys-ui-components';
function Example() {
const [value, setValue] = useState('');
return (
<Input
label="Your Name"
placeholder="Enter your name"
value={value}
onChange={(e: ChangeEvent<HTMLInputElement>) => setValue(e.target.value)}
helperText="This is a helper text"
/>
);
}
// With validation states
<Input label="Email" error helperText="Invalid email format" />
<Input label="Username" success helperText="Username is available" />
// Disabled
<Input label="Disabled" disabled value="Cannot edit" />TextArea
import { useState, ChangeEvent } from 'react';
import { TextArea } from 'unisys-ui-components';
function Example() {
const [value, setValue] = useState('');
return (
<TextArea
label="Description"
placeholder="Enter description..."
value={value}
onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setValue(e.target.value)}
rows={4}
/>
);
}
// With validation
<TextArea label="Bio" maxLength={500} helperText="Max 500 characters" />Select
import { useState } from 'react';
import { Select } from 'unisys-ui-components';
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' },
];
function Example() {
const [value, setValue] = useState('');
return (
<Select
options={options}
value={value}
onChange={setValue}
placeholder="Select an option"
/>
);
}
// With label
<Select options={options} label="Choose an option" />
// Disabled
<Select options={options} disabled placeholder="Disabled" />Radio
import { useState } from 'react';
import { Radio } from 'unisys-ui-components';
function Example() {
const [value, setValue] = useState('');
return (
<div>
<Radio
name="plan"
value="basic"
label="Basic Plan"
checked={value === 'basic'}
onChange={() => setValue('basic')}
/>
<Radio
name="plan"
value="pro"
label="Pro Plan"
checked={value === 'pro'}
onChange={() => setValue('pro')}
/>
<Radio
name="plan"
value="enterprise"
label="Enterprise Plan"
checked={value === 'enterprise'}
onChange={() => setValue('enterprise')}
/>
</div>
);
}Toggle
import { useState } from 'react';
import { Toggle } from 'unisys-ui-components';
function Example() {
const [enabled, setEnabled] = useState(false);
return (
<Toggle
checked={enabled}
onCheckedChange={setEnabled}
label="Enable notifications"
/>
);
}
// Disabled
<Toggle disabled label="Disabled toggle" />Slider
import { useState } from 'react';
import { Slider } from 'unisys-ui-components';
function Example() {
const [value, setValue] = useState(50);
return (
<div>
<p>Value: {value}</p>
<Slider
value={value}
onChange={setValue}
min={0}
max={100}
/>
</div>
);
}
// With step
<Slider value={value} onChange={setValue} min={0} max={100} step={10} />
// Disabled
<Slider value={50} disabled />Modal
import { useState } from 'react';
import { Modal, Button } from 'unisys-ui-components';
function Example() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button variant="primary" onClick={() => setIsOpen(true)}>
Open Modal
</Button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="Confirm Action"
primaryButtonLabel="CONFIRM"
onPrimaryClick={() => {
console.log('Confirmed!');
setIsOpen(false);
}}
secondaryButtonLabel="CANCEL"
onSecondaryClick={() => setIsOpen(false)}
>
<p>Are you sure you want to proceed with this action?</p>
</Modal>
</>
);
}Tooltip
import { Tooltip } from 'unisys-ui-components';
// Different directions
<Tooltip direction="down">Down Arrow</Tooltip>
<Tooltip direction="up">Up Arrow</Tooltip>
<Tooltip direction="left">Left Arrow</Tooltip>
<Tooltip direction="right">Right Arrow</Tooltip>Accordion
import { AccordionGroup, AccordionItem } from 'unisys-ui-components';
// Basic usage
<AccordionGroup>
<AccordionItem title="Section 1" itemId="1">
<p>This is the content of section 1.</p>
</AccordionItem>
<AccordionItem title="Section 2" itemId="2">
<p>This is the content of section 2.</p>
</AccordionItem>
</AccordionGroup>
// Allow multiple open
<AccordionGroup allowMultiple>
<AccordionItem title="Section 1" itemId="1">Content 1</AccordionItem>
<AccordionItem title="Section 2" itemId="2">Content 2</AccordionItem>
</AccordionGroup>
// Default open items
<AccordionGroup defaultOpenItems={['1']}>
<AccordionItem title="Open by default" itemId="1">Content</AccordionItem>
<AccordionItem title="Closed by default" itemId="2">Content</AccordionItem>
</AccordionGroup>Loader (Spinner, SegmentedLoader, CircularProgress)
import { Spinner, SegmentedLoader, CircularProgress } from 'unisys-ui-components';
// Spinner - indeterminate loading
<Spinner size="sm" />
<Spinner size="md" />
<Spinner size="lg" />
// Segmented Loader - segmented circle animation
<SegmentedLoader size="sm" />
<SegmentedLoader size="md" />
<SegmentedLoader size="lg" />
// Circular Progress - determinate progress
<CircularProgress value={25} size="sm" />
<CircularProgress value={50} size="md" />
<CircularProgress value={75} size="lg" />
<CircularProgress value={100} size="md" /> // CompleteToaster (Toast Notifications)
import { Toaster, ToasterRoot, Button } from 'unisys-ui-components';
// Wrap your app with ToasterRoot
function App() {
return (
<ToasterRoot>
<YourApp />
</ToasterRoot>
);
}
// Show toasts from anywhere in your app
function YourComponent() {
return (
<div>
{/* Basic toasts */}
<Button onClick={() => Toaster.success('Success!')}>
Success Toast
</Button>
<Button onClick={() => Toaster.error('Error!')}>
Error Toast
</Button>
<Button onClick={() => Toaster.info('Info!')}>
Info Toast
</Button>
<Button onClick={() => Toaster.attention('Attention!')}>
Attention Toast
</Button>
{/* With description */}
<Button onClick={() => Toaster.success('Success!', {
description: 'Your action was completed successfully.'
})}>
With Description
</Button>
{/* With title and description */}
<Button onClick={() => Toaster.success('Operation Complete', {
title: 'Notification',
description: 'Your file has been saved successfully.'
})}>
With Title
</Button>
{/* With action button */}
<Button onClick={() => Toaster.info('File deleted', {
action: {
label: 'Undo',
onClick: () => console.log('Undo clicked')
}
})}>
With Action
</Button>
{/* Custom duration (in milliseconds, 0 = no auto-dismiss) */}
<Button onClick={() => Toaster.success('Persistent toast', {
duration: 0
})}>
No Auto Dismiss
</Button>
</div>
);
}
// Using the hook for more control
import { useToaster } from 'unisys-ui-components';
function AdvancedComponent() {
const { show, dismiss, dismissAll } = useToaster();
const showCustomToast = () => {
const toastId = show({
type: 'success',
message: 'Custom toast',
description: 'This is a custom toast',
duration: 10000,
});
// Dismiss specific toast
setTimeout(() => dismiss(toastId), 5000);
};
return (
<div>
<Button onClick={showCustomToast}>Custom Toast</Button>
<Button onClick={dismissAll}>Dismiss All</Button>
</div>
);
}Complete Example
import { useState, ChangeEvent } from 'react';
import {
Button,
Checkbox,
Input,
TextArea,
Select,
Radio,
Toggle,
Slider,
AccordionGroup,
AccordionItem,
Tooltip,
Modal,
Spinner,
SegmentedLoader,
CircularProgress,
Toaster,
ToasterRoot,
} from 'unisys-ui-components';
import 'unisys-ui-components/styles.css';
const selectOptions = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
{ value: 'option3', label: 'Option 3' },
];
function App() {
const [checked, setChecked] = useState(false);
const [inputValue, setInputValue] = useState('');
const [textAreaValue, setTextAreaValue] = useState('');
const [selectValue, setSelectValue] = useState('');
const [radioValue, setRadioValue] = useState('');
const [toggleValue, setToggleValue] = useState(false);
const [sliderValue, setSliderValue] = useState(50);
const [modalOpen, setModalOpen] = useState(false);
return (
<ToasterRoot>
<div style={{ padding: 40, maxWidth: 800, margin: '0 auto' }}>
<h1>Component Library Demo</h1>
{/* Button */}
<section>
<h2>Button</h2>
<Button variant="primary" onClick={() => Toaster.success('Clicked!')}>
Primary
</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="tertiary">Tertiary</Button>
<Button loading>Loading</Button>
</section>
{/* Checkbox */}
<section>
<h2>Checkbox</h2>
<Checkbox
checked={checked}
onCheckedChange={setChecked}
label="Accept terms"
/>
</section>
{/* Input */}
<section>
<h2>Input</h2>
<Input
label="Name"
value={inputValue}
onChange={(e: ChangeEvent<HTMLInputElement>) => setInputValue(e.target.value)}
placeholder="Enter your name"
/>
</section>
{/* TextArea */}
<section>
<h2>TextArea</h2>
<TextArea
label="Description"
value={textAreaValue}
onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setTextAreaValue(e.target.value)}
placeholder="Enter description"
/>
</section>
{/* Select */}
<section>
<h2>Select</h2>
<Select
options={selectOptions}
value={selectValue}
onChange={setSelectValue}
placeholder="Select an option"
/>
</section>
{/* Radio */}
<section>
<h2>Radio</h2>
<Radio name="demo" value="1" label="Option 1" checked={radioValue === '1'} onChange={() => setRadioValue('1')} />
<Radio name="demo" value="2" label="Option 2" checked={radioValue === '2'} onChange={() => setRadioValue('2')} />
</section>
{/* Toggle */}
<section>
<h2>Toggle</h2>
<Toggle
checked={toggleValue}
onCheckedChange={setToggleValue}
label="Enable feature"
/>
</section>
{/* Slider */}
<section>
<h2>Slider: {sliderValue}</h2>
<Slider value={sliderValue} onChange={setSliderValue} min={0} max={100} />
</section>
{/* Accordion */}
<section>
<h2>Accordion</h2>
<AccordionGroup>
<AccordionItem title="Section 1" itemId="1">Content 1</AccordionItem>
<AccordionItem title="Section 2" itemId="2">Content 2</AccordionItem>
</AccordionGroup>
</section>
{/* Tooltip */}
<section>
<h2>Tooltip</h2>
<Tooltip direction="down">Hover me</Tooltip>
</section>
{/* Modal */}
<section>
<h2>Modal</h2>
<Button onClick={() => setModalOpen(true)}>Open Modal</Button>
<Modal
isOpen={modalOpen}
onClose={() => setModalOpen(false)}
title="Confirm"
primaryButtonLabel="OK"
onPrimaryClick={() => setModalOpen(false)}
>
<p>Modal content here</p>
</Modal>
</section>
{/* Loaders */}
<section>
<h2>Loaders</h2>
<Spinner size="md" />
<SegmentedLoader size="md" />
<CircularProgress value={75} size="md" />
</section>
{/* Toaster */}
<section>
<h2>Toaster</h2>
<Button onClick={() => Toaster.success('Success!', { description: 'Action completed.' })}>
Show Toast
</Button>
</section>
</div>
</ToasterRoot>
);
}
export default App;Theming
Override CSS variables to customize the look:
:root {
/* Primary colors */
--unisys-color-primary: #007173;
--unisys-color-accent: #00E28B;
/* Text colors */
--unisys-color-text: #003134;
--unisys-color-text-secondary: #667085;
/* Background colors */
--unisys-color-background: #FFFFFF;
--unisys-color-surface: #F9FAFB;
/* Border colors */
--unisys-color-border: #D0D5DD;
/* Font */
--unisys-font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
/* Border radius */
--unisys-radius-sm: 4px;
--unisys-radius-md: 8px;
--unisys-radius-lg: 12px;
}TypeScript
Full TypeScript support with exported types:
import type {
ButtonProps,
CheckboxProps,
InputProps,
TextAreaProps,
SelectProps,
SelectOption,
RadioProps,
ToggleProps,
SliderProps,
AccordionProps,
AccordionItemProps,
AccordionGroupProps,
TooltipProps,
TooltipDirection,
ModalProps,
SpinnerProps,
SegmentedLoaderProps,
CircularProgressProps,
ToastOptions,
Toast,
ToastAction,
ToasterContextValue,
ToasterProviderProps,
ToasterProps,
CommonProps,
Size,
ButtonVariant,
ToastType,
CheckboxState,
} from 'unisys-ui-components';License
MIT
