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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@latimer-woods-tech/ui

v0.2.0

Published

Accessible, reusable UI primitives for all Factory apps (Button, Input, Modal, etc.)

Readme

@latimer-woods-tech/ui

Accessible, reusable UI components for all Factory applications.

A comprehensive component library built with React, TypeScript, and WCAG 2.2 accessibility standards. All components use design tokens from @latimer-woods-tech/design-tokens for consistency across all Factory apps.

Installation

npm install @latimer-woods-tech/ui @latimer-woods-tech/design-tokens react react-dom

Quick Start

import { Button, Input, Label, Alert } from '@latimer-woods-tech/ui';

export function LoginForm() {
  return (
    <form>
      <Label htmlFor="email" required>
        Email
      </Label>
      <Input
        id="email"
        type="email"
        placeholder="[email protected]"
        required
        hint="We'll never share your email"
      />

      <Button type="submit" variant="primary" size="md">
        Sign In
      </Button>
    </form>
  );
}

Components

Button

Accessible button component with multiple variants and sizes.

import { Button } from '@latimer-woods-tech/ui';

// Variants: primary, secondary, tertiary, danger
<Button variant="primary">Save</Button>
<Button variant="secondary">Cancel</Button>
<Button variant="danger">Delete</Button>

// Sizes: sm, md, lg
<Button size="lg">Large Button</Button>

// States
<Button disabled>Disabled</Button>
<Button isLoading>Loading...</Button>

// Events
<Button onClick={handleClick}>Click me</Button>

Features:

  • Type-safe variant and size props
  • Keyboard accessible with visible focus indicators (WCAG 2.4.7)
  • Loading state with spinner
  • Disabled state with visual feedback
  • Minimum 44x44px touch target (WCAG)
  • Smooth transitions and hover effects

Input

Fully accessible text input component.

import { Input } from '@latimer-woods-tech/ui';

// Basic usage
<Input
  label="Name"
  placeholder="Enter your name"
  required
/>

// Different input types
<Input label="Email" type="email" />
<Input label="Password" type="password" />

// With hints
<Input
  label="Password"
  type="password"
  hint="Minimum 8 characters"
/>

// With error messaging
<Input
  label="Email"
  type="email"
  error="Invalid email address"
/>

// With icons
<Input
  label="Username"
  startIcon={<UserIcon />}
/>

Features:

  • Associated label via htmlFor/id
  • Error state with aria-invalid
  • Helper text and error messages
  • Icon support (start/end)
  • Proper focus management
  • Error messages linked via aria-describedby
  • Input types: text, email, password, number, etc.

Label

Semantic label component for form fields.

import { Label } from '@latimer-woods-tech/ui';

<Label htmlFor="username">Username</Label>
<Input id="username" />

// With required indicator
<Label htmlFor="email" required>
  Email
</Label>

Features:

  • Semantic <label> element
  • Proper htmlFor/id linking
  • Required indicator (*) when needed
  • Accessible font sizing

Alert

Alert component for messages, warnings, and errors.

import { Alert } from '@latimer-woods-tech/ui';

// Variants: info, success, warning, error
<Alert variant="info">Information message</Alert>
<Alert variant="success">Operation completed!</Alert>
<Alert variant="warning">Please review this change</Alert>
<Alert variant="error">An error occurred</Alert>

// With title
<Alert title="Error" variant="error">
  Something went wrong
</Alert>

// With icon
<Alert icon={<AlertIcon />} variant="warning">
  Be careful with this action
</Alert>

Features:

  • Semantic role="alert" for screen readers
  • Color + icon + text (not color alone)
  • 4 severity levels: info, success, warning, error
  • Optional title and icon
  • High contrast text for readability

Coming Soon

The following components are in development and will be added soon:

  • Dialog — Modal dialogs with focus management
  • Toast — Notification toasts with auto-dismiss
  • Card — Container component for grouped content
  • EmptyState — Empty state placeholder with icon and CTA
  • LoadingState — Skeleton loaders and spinners
  • Tabs — Tab navigation with keyboard support
  • FormField — Wrapper combining Label, Input, and validation

Accessibility

All components meet WCAG 2.2 AA standards:

Color Contrast — 4.5:1 minimum for text
Focus Indicators — 3px visible outline (WCAG 2.4.7)
Keyboard Navigation — All interactive elements keyboard accessible
Screen Reader Support — Proper ARIA labels, roles, and descriptions
Motion — Respects prefers-reduced-motion setting
Touch Targets — Minimum 44x44px for interactive elements

Testing for Accessibility

// Use your test framework + axe-core for automated testing
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

it('Button is accessible', async () => {
  const { container } = render(<Button>Click</Button>);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

Integration with Design Tokens

All components use design tokens from @latimer-woods-tech/design-tokens:

// Components automatically use these tokens:
// - colors.primary, colors.success, colors.danger, etc.
// - spacing.*, typography.*, motion.*, focus.*, radii.*

// To customize colors for your app, update tokens at theme level
import { tokens } from '@latimer-woods-tech/design-tokens';

const customTheme = {
  ...tokens,
  colors: {
    ...tokens.colors,
    primary: '#FF6600', // Override primary color for your app
  },
};

TypeScript Support

All components are fully typed with TypeScript strict mode:

import { ButtonProps, InputProps, AlertProps } from '@latimer-woods-tech/ui';

const buttonProps: ButtonProps = {
  variant: 'primary', // ✅ Type-safe
  size: 'md',
  children: 'Click me',
};

// This would error:
// variant: 'invalid', // ❌ Type error

Styling & Customization

Components use inline styles (React.CSSProperties) for portability:

  • No CSS-in-JS dependencies
  • No global CSS requirements
  • Components are fully self-contained
  • Custom styling via className prop
<Button className="my-custom-class">Click</Button>

Testing

npm test

All components include:

  • Unit tests for rendering and interactions
  • Accessibility tests (a11y)
  • Focus management tests
  • Event handler tests
  • Type safety verification

Contributing

When adding new components:

  1. Create component file (src/ComponentName.tsx)
  2. Add tests (src/ComponentName.test.tsx)
  3. Add to exports (src/index.ts)
  4. Update README with usage examples
  5. Ensure all tests pass: npm test
  6. Ensure TypeScript strict mode: npm run typecheck
  7. Ensure no lint errors: npm run lint

Component Template

import React, { forwardRef } from 'react';
import { colors, spacing, focus, radii } from '@latimer-woods-tech/design-tokens';

export interface ComponentProps extends HTMLAttributes<HTMLDivElement> {
  children: ReactNode;
  ref?: React.Ref<HTMLDivElement>;
}

export const Component = forwardRef<HTMLDivElement, ComponentProps>(
  ({ children, ...props }, ref) => {
    return <div ref={ref} {...props}>{children}</div>;
  },
);

Component.displayName = 'Component';

Browser Support

  • Chrome (latest 2 versions)
  • Firefox (latest 2 versions)
  • Safari (latest 2 versions)
  • Edge (latest 2 versions)
  • Mobile browsers (iOS Safari, Chrome Mobile)

License

Part of the Factory monorepo. Internal use only.

Examples

Form with Validation

import { useState } from 'react';
import { Button, Input, Label, Alert } from '@latimer-woods-tech/ui';

export function SignUpForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState<string | null>(null);

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    
    if (!email || !password) {
      setError('Email and password are required');
      return;
    }
    
    // Call API...
  };

  return (
    <form onSubmit={handleSubmit}>
      {error && <Alert variant="error">{error}</Alert>}

      <Label htmlFor="email" required>
        Email
      </Label>
      <Input
        id="email"
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        required
      />

      <Label htmlFor="password" required>
        Password
      </Label>
      <Input
        id="password"
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        required
        hint="Minimum 8 characters"
      />

      <Button type="submit" variant="primary">
        Create Account
      </Button>
    </form>
  );
}