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

huda-ui

v1.1.0

Published

A professional React UI component library for non-designers

Readme

huda-ui

A professional React UI component library with 120+ components, a token-driven design system, and built-in dark mode support. Zero external dependencies beyond React and Emotion.

Features

  • 120+ production-ready components — from basic primitives to complex data visualizations
  • Token-driven theming — change one file to re-skin your entire app
  • Dark mode — built-in light/dark mode with useColorMode()
  • TypeScript-first — full type safety with exported types for every component
  • Tree-shakable — named exports only, sideEffects: false
  • ResponsiveResponsiveValue<T> prop system with { base, sm, md, lg, xl } breakpoints
  • Polymorphic — layout components accept an as prop to render as any HTML element
  • Figma-compatible — import Figma tokens directly with adaptFigmaTokens()
  • Lightweight — no external UI dependencies, just React + Emotion

Installation

npm install huda-ui @emotion/react @emotion/styled

Quick Start

import { TokensProvider, Button, Card, Text } from 'huda-ui';

function App() {
  return (
    <TokensProvider>
      <Card>
        <Text>Hello from huda-ui</Text>
        <Button variant="solid" colorScheme="primary">
          Get Started
        </Button>
      </Card>
    </TokensProvider>
  );
}

Theming

Token-Driven Design

huda-ui uses a design token system. Tokens define your brand's colors, typography, spacing, radii, shadows, and more. Change one token file — every component updates automatically.

import { TokensProvider } from 'huda-ui';
import type { DesignTokens } from 'huda-ui';

const myTokens: DesignTokens = {
  colors: {
    primary: {
      50: '#EEF2FF', 100: '#E0E7FF', 200: '#C7D2FE',
      300: '#A5B4FC', 400: '#818CF8', 500: '#6366F1',
      600: '#4F46E5', 700: '#4338CA', 800: '#3730A3', 900: '#312E81',
    },
    neutral: { /* 50–900 gray scale */ },
    error: { /* 50–900 red scale */ },
    success: { /* 50–900 green scale */ },
    warning: { /* 50–900 yellow scale */ },
    info: { /* 50–900 blue scale */ },
    white: '#FFFFFF',
    black: '#000000',
    light: {
      background: '#FFFFFF',
      surface: '#F9FAFB',
      text: '#111827',
      textSecondary: '#6B7280',
      border: '#E5E7EB',
      focus: '#6366F1',
    },
    dark: {
      background: '#111827',
      surface: '#1F2937',
      text: '#F9FAFB',
      textSecondary: '#9CA3AF',
      border: '#374151',
      focus: '#818CF8',
    },
  },
  typography: {
    fontFamily: '"Inter", sans-serif',
    fontFamilyMono: '"Fira Code", monospace',
    fontSizes: { xs: '0.75rem', sm: '0.875rem', md: '1rem', lg: '1.125rem', xl: '1.25rem', '2xl': '1.5rem', '3xl': '2rem', '4xl': '2.5rem', '5xl': '3.25rem' },
    fontWeights: { normal: 400, medium: 500, semibold: 600, bold: 700 },
    lineHeights: { tight: 1.2, normal: 1.5, relaxed: 1.8 },
  },
  spacing: { 0: '0px', 1: '4px', 2: '8px', 3: '12px', 4: '16px', 5: '20px', 6: '24px', 8: '32px', 10: '40px', 12: '48px', 16: '64px', 20: '80px', 24: '96px' },
  radii: { none: '0px', sm: '4px', md: '8px', lg: '12px', xl: '16px', full: '9999px' },
  shadows: {
    light: { none: 'none', sm: '0 1px 2px rgba(0,0,0,0.05)', md: '0 4px 6px rgba(0,0,0,0.07)', lg: '0 10px 15px rgba(0,0,0,0.1)', xl: '0 20px 25px rgba(0,0,0,0.1)' },
    dark: { none: 'none', sm: '0 1px 2px rgba(0,0,0,0.3)', md: '0 4px 6px rgba(0,0,0,0.4)', lg: '0 10px 15px rgba(0,0,0,0.5)', xl: '0 20px 25px rgba(0,0,0,0.6)' },
  },
  borderWidth: { none: '0px', thin: '1px', default: '2px', thick: '4px' },
  transitions: { fast: '120ms ease-out', normal: '200ms ease-out', slow: '350ms ease-out' },
  breakpoints: { sm: '640px', md: '768px', lg: '1024px', xl: '1280px' },
  zIndices: { base: 0, dropdown: 1000, sticky: 1100, overlay: 1300, modal: 1400, toast: 1500 },
};

function App() {
  return (
    <TokensProvider tokens={myTokens} defaultColorMode="light">
      {/* Your app */}
    </TokensProvider>
  );
}

Partial Tokens

You don't have to provide every value. Pass a partial object and missing keys fall back to sensible defaults:

<TokensProvider tokens={{ colors: { primary: myPrimaryScale } }}>
  {/* Everything else uses defaults */}
</TokensProvider>

Token Validation

Tokens are validated at runtime in development mode. Use useTokens() to access validation results:

import { useTokens } from 'huda-ui';

function DebugPanel() {
  const { tokens, validation } = useTokens();

  if (!validation.ok) {
    console.log(validation.errors);   // string[]
    console.log(validation.warnings); // string[]
  }

  return <pre>{JSON.stringify(tokens, null, 2)}</pre>;
}

Figma Token Adaptation

Import tokens directly from Figma using Tokens Studio, W3C Design Tokens, or flat key formats:

import { adaptFigmaTokens, TokensProvider } from 'huda-ui';
import rawFigma from './figma-export.json';

const tokens = adaptFigmaTokens(rawFigma);

function App() {
  return (
    <TokensProvider tokens={tokens}>
      {/* Figma tokens driving every component */}
    </TokensProvider>
  );
}

Supported formats:

  • Tokens Studio{ value: "#6366F1" }
  • W3C Design Tokens{ $value: "#6366F1" }
  • Flat keys{ "primary-500": "#6366F1" }

Dark Mode

import { useColorMode } from 'huda-ui';

function ThemeToggle() {
  const { colorMode, toggleColorMode } = useColorMode();

  return (
    <button onClick={toggleColorMode}>
      Current: {colorMode}
    </button>
  );
}

Components

Core (14)

| Component | Description | |-----------|-------------| | Box | Polymorphic base layout primitive | | Flex | Flexbox container with shorthand props | | Stack | Vertical/horizontal stack with spacing | | Text | Text rendering with typography tokens | | Heading | Semantic heading (h1–h6) | | Label | Form label with required indicator | | Icon | SVG icon wrapper with sizing | | Button | Button with variants, sizes, loading state | | IconButton | Icon-only button | | Spinner | Loading spinner | | Card | Card container with Header, Body, Footer | | Badge | Status badge with color schemes | | Avatar | User avatar with fallback initials | | Divider | Horizontal/vertical divider |

Layout (8)

| Component | Description | |-----------|-------------| | Grid | CSS Grid with responsive columns | | SimpleGrid | Auto-responsive grid | | Container | Max-width content container | | Center | Center children horizontally and vertically | | Wrap | Flex wrap with gap | | Spacer | Flexible spacer for flex layouts | | AspectRatio | Maintain aspect ratio | | Show / Hide | Responsive visibility |

Form (17)

| Component | Description | |-----------|-------------| | FormControl | Form field wrapper with label, error, helper | | FormGroup | Group related form fields | | Form | Form wrapper with spacing | | FormField | Label + input + error combo | | FormError | Error message display | | FormHelperText | Helper text below inputs | | Input | Text input with variants and sizes | | Textarea | Multi-line text input | | Select | Dropdown select | | MultiSelect | Multi-value select with tags | | Checkbox | Checkbox with label | | Radio / RadioGroup | Radio buttons | | Switch | Toggle switch | | Slider | Range slider | | DatePicker | Date selection | | TimePicker | Time selection | | DateTimePicker | Combined date + time picker | | OTPInput | OTP/PIN code input |

Navigation (7)

| Component | Description | |-----------|-------------| | Tabs | Tab navigation with panels | | Breadcrumb | Breadcrumb navigation | | Pagination | Page navigation | | Navbar | Top navigation bar | | Sidebar | Collapsible side navigation | | Menu | Dropdown menu | | BottomNavigation | Mobile bottom tab bar |

Feedback (17)

| Component | Description | |-----------|-------------| | Modal | Modal dialog with Header, Body, Footer | | Drawer | Slide-in panel | | Dialog | Confirmation dialog | | Alert | Inline alert messages | | ToastProvider / useToast | Toast notifications | | Snackbar | Bottom snackbar | | Notification | Notification card | | Tooltip | Hover tooltip | | Progress | Progress bar | | ProgressBar | Standalone progress bar | | ProgressCircle | Circular progress | | Skeleton | Content loading placeholder | | SkeletonText | Text loading placeholder | | SkeletonCircle | Circle loading placeholder | | EmptyState | Empty state with icon and action | | ErrorState | Error state display | | NoDataState | No data available state |

Data Display (14)

| Component | Description | |-----------|-------------| | Table | Data table with sorting | | DataTable | Full-featured data table | | Accordion | Expandable sections | | Tag | Removable tag/chip | | Image | Image with fallback | | Link | Styled anchor | | Code | Inline/block code | | Kbd | Keyboard shortcut display | | List | Ordered/unordered lists | | Timeline | Vertical timeline | | Stat | Statistic display with trend | | Carousel | Image/content carousel | | Calendar | Calendar display | | EventCard | Event card with date/time |

Overlay (5)

| Component | Description | |-----------|-------------| | Popover | Click-triggered popover | | ContextMenu | Right-click context menu | | HoverCard | Hover-triggered card | | ActionSheet | Mobile action sheet | | BottomSheet | Draggable bottom sheet |

Layout Templates (11)

| Component | Description | |-----------|-------------| | PageLayout | Full page layout structure | | AuthLayout | Authentication page layout | | DashboardLayout | Dashboard with sidebar | | Section | Content section | | Header | Page header | | Footer | Page footer | | Content | Content area with max-width | | Page | Full page wrapper | | AppLayout | App shell layout | | SidebarLayout | Sidebar + content layout |

Advanced (13)

| Component | Description | |-----------|-------------| | SearchBar | Search input with suggestions | | CommandPalette | Command palette (Cmd+K) | | FileUpload | File upload with drag-and-drop | | Stepper | Multi-step wizard | | KeyboardShortcutHint | Keyboard shortcut display | | ThemeSwitcher | Light/dark/system theme toggle | | LanguageSwitcher | Language/locale selector | | UserMenu | User avatar dropdown menu | | NotificationCenter | Notification list panel | | RichTextEditor | Rich text editor | | MediaViewer | Image/video viewer | | SettingsPanel | Settings form panel | | PermissionsGuard / RoleGuard | Permission-based rendering |

Auth Forms (4)

| Component | Description | |-----------|-------------| | LoginForm | Login form with validation | | RegisterForm | Registration form | | ForgotPasswordForm | Forgot password form | | ResetPasswordForm | Password reset form |

Interactive (5)

| Component | Description | |-----------|-------------| | LocationPicker | Location coordinate picker | | DragAndDrop | Drag and drop container | | ResizablePanel | Resizable panel | | InfiniteScroll | Infinite scroll wrapper | | VirtualizedList | Virtualized list for large datasets |

Data Visualization (8)

| Component | Description | |-----------|-------------| | CalendarView | Calendar with month/week/day views | | Charts | Chart wrapper | | LineChart | Line chart | | BarChart | Bar chart | | PieChart | Pie chart | | AreaChart | Area chart | | ChartContainer | Chart container with title/legend | | MapView | Map display with markers |

Utility (3)

| Component | Description | |-----------|-------------| | Portal | Render children in a portal | | VisuallyHidden | Accessible hidden content | | CloseButton | Close/dismiss button |

Hooks

| Hook | Description | |------|-------------| | useTheme() | Access the current resolved theme | | useColorMode() | Get/set color mode (light/dark) | | useTokens() | Access design tokens and validation | | useBreakpoint() | Current active breakpoint | | useBreakpointValue() | Responsive value based on breakpoint | | useDisclosure() | Open/close state management | | useDebounce() | Debounced value | | useDebouncedCallback() | Debounced callback function | | useModal() | Modal state management | | useForm() | Form state, validation, and submission | | useToast() | Trigger toast notifications | | usePermissions() | Access permissions context |

Responsive Props

Layout components support responsive values:

<Box
  padding={{ base: '16px', md: '32px', xl: '48px' }}
  display={{ base: 'block', lg: 'flex' }}
>
  <Text fontSize={{ base: 'sm', md: 'lg' }}>
    Responsive text
  </Text>
</Box>

Compound Components

Several components use the compound component pattern:

<Card variant="outlined">
  <Card.Header>Title</Card.Header>
  <Card.Body>Content</Card.Body>
  <Card.Footer>Actions</Card.Footer>
</Card>

<Modal isOpen={isOpen} onClose={onClose}>
  <Modal.Header>Confirm</Modal.Header>
  <Modal.Body>Are you sure?</Modal.Body>
  <Modal.Footer>
    <Button onClick={onClose}>Cancel</Button>
    <Button variant="solid">Confirm</Button>
  </Modal.Footer>
</Modal>

<Tabs defaultIndex={0}>
  <Tabs.List>
    <Tabs.Tab>Tab 1</Tabs.Tab>
    <Tabs.Tab>Tab 2</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel>Panel 1</Tabs.Panel>
  <Tabs.Panel>Panel 2</Tabs.Panel>
</Tabs>

Polymorphic as Prop

Layout components can render as any HTML element:

<Box as="section" padding="16px">
  <Text as="label" htmlFor="name">Name</Text>
  <Stack as="nav" direction="horizontal">
    <Link as="a" href="/home">Home</Link>
  </Stack>
</Box>

Template

The template/ directory includes a ready-to-use app template that demonstrates token-driven theming:

template/
  src/
    design-tokens/
      tokens.ts          ← Swap this one line to re-skin
      tokens.default.ts  ← Default indigo theme
      tokens.brandX.ts   ← Example teal brand
    pages/
      TokensDebug.tsx    ← Debug page showing all token values
    App.tsx              ← App root with TokensProvider

To switch brands, edit template/src/design-tokens/tokens.ts:

// Default theme
export { defaultThemeTokens as tokens } from './tokens.default';

// Switch to Brand X
// export { brandXTokens as tokens } from './tokens.brandX';

Development

# Install dependencies
npm install

# Start Storybook
npm run storybook

# Type-check
npm run lint

# Build
npm run build

Build Output

dist/
  index.mjs    ← ESM
  index.js     ← CJS
  index.d.ts   ← TypeScript declarations
  index.d.mts  ← ESM TypeScript declarations

Peer Dependencies

  • react >= 18.0.0
  • react-dom >= 18.0.0

License

ISC