npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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

Readme

unisys-ui-components

A production-ready React component library featuring accessible, themeable UI components.

npm version License: MIT

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-components

Component Demos (CodeSandbox)

Preview and interact with each component live on CodeSandbox:

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" /> // Complete

Toaster (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