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

@marcoschwartz/lite-ui

v0.25.4

Published

A lightweight UI component library built with Tailwind CSS

Downloads

3,362

Readme

Lite UI

A lightweight, modern UI component library built with React, TypeScript, and Tailwind CSS v4.

✨ Features

  • 🎨 21 Production-Ready Components - From basic inputs to complex data tables
  • 🌙 Dark Mode Support - Built-in dark mode with system preference detection
  • 🎭 Theming System - Multiple themes with easy customization
  • 📦 Tree-Shakeable - Only bundle what you use (ESM & CJS)
  • TypeScript First - Full type safety and IntelliSense support
  • 🚀 Server Component Compatible - Works with Next.js App Router and RSC
  • 🎯 Zero Runtime CSS - Styles compiled with Tailwind CSS v4
  • Accessible - ARIA-compliant components

📦 Installation

npm install @marcoschwartz/lite-ui

Setup for Next.js (Required)

⚠️ Important: You must include ColorSchemeScript in your layout to prevent dark mode flashing (FOUC).

// app/layout.tsx
import { ThemeProvider, ColorSchemeScript } from '@marcoschwartz/lite-ui';
import '@marcoschwartz/lite-ui/styles.css';

export default function RootLayout({ children }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <ColorSchemeScript defaultColorMode="system" />
      </head>
      <body>
        <ThemeProvider defaultTheme="default" defaultColorMode="system">
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

Key points:

  • ColorSchemeScript must be in <head> - it prevents flash by setting colors before React hydrates
  • suppressHydrationWarning on <html> is required to avoid React warnings
  • defaultColorMode should match between ColorSchemeScript and ThemeProvider

Setup for Vite/Other React Apps

// main.tsx
import '@marcoschwartz/lite-ui/styles.css';
import { ThemeProvider } from '@marcoschwartz/lite-ui';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <ThemeProvider defaultTheme="default" defaultColorMode="system">
    <App />
  </ThemeProvider>
);

For Vite apps, add the theme script to your index.html:

<head>
  <script>
    (function(){try{var d=document.documentElement,c=localStorage.getItem('lite-ui-color-mode')||'system',r=c;if(c==='system'||!c)r=matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light';d.setAttribute('data-color-mode',r);d.style.colorScheme=r;if(r==='dark'){d.classList.add('dark');d.style.backgroundColor='hsl(0,0%,3.9%)';d.style.color='hsl(0,0%,98%)'}else{d.classList.remove('dark');d.style.backgroundColor='hsl(0,0%,100%)';d.style.color='hsl(0,0%,3.9%)'}}catch(e){}})();
  </script>
</head>

Start using components:

import { Button, Card, TextInput } from '@marcoschwartz/lite-ui';

export default function Page() {
  return (
    <Card>
      <h1>Welcome to Lite UI</h1>
      <TextInput placeholder="Enter your name" />
      <Button variant="primary">Submit</Button>
    </Card>
  );
}

🎨 Components

Form Controls

  • Button - Versatile button with 6 variants and 4 sizes
  • TextInput - Text input with validation and error states
  • Select - Dropdown select with custom styling
  • Checkbox - Checkbox with label and error support
  • Toggle - Switch/toggle component with multiple sizes
  • DatePicker - Date selection input
  • TimePicker - Time selection input
  • DateTimePicker - Combined date and time picker

Layout & Navigation

  • AppShell - Complete app layout with header, navbar, aside, and footer
  • Navbar - Responsive navigation bar
  • Sidebar - Collapsible sidebar with mobile support
  • SidebarNav - Collapsible navigation with icon-only mode and tooltips
  • Drawer - Slide-out drawer panel
  • Modal - Accessible modal dialog
  • Tabs - Tabbed navigation component

Feedback & Overlays

  • Alert - Alert messages with 4 variants
  • Spinner - Loading spinner with 3 sizes
  • Badge - Status badges with 6 variants

Data Display

  • Card - Content container with optional header/footer
  • Table - Data table with sorting and selection
  • Pagination - Page navigation component

Utilities

  • ActionMenu - Dropdown action menu
  • Icons - Set of common UI icons

📖 View Full Component Documentation

🌙 Dark Mode

Lite UI includes built-in dark mode support with three color modes.

Preventing Flash (FOUC)

To prevent the flash of wrong colors on page load, you must use ColorSchemeScript:

// app/layout.tsx
import { ColorSchemeScript, ThemeProvider } from '@marcoschwartz/lite-ui';

<html lang="en" suppressHydrationWarning>
  <head>
    <ColorSchemeScript defaultColorMode="system" />
  </head>
  <body>
    <ThemeProvider defaultColorMode="system">
      {children}
    </ThemeProvider>
  </body>
</html>

Toggling Dark Mode

import { useTheme } from '@marcoschwartz/lite-ui';

function ThemeToggle() {
  const { colorMode, setColorMode } = useTheme();

  return (
    <select value={colorMode} onChange={(e) => setColorMode(e.target.value)}>
      <option value="system">System</option>
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  );
}

⬆️ Upgrading from v0.24.7 or earlier

If you're upgrading from an earlier version, update your layout.tsx:

- import { ThemeProvider, themeScript } from '@marcoschwartz/lite-ui';
+ import { ThemeProvider, ColorSchemeScript } from '@marcoschwartz/lite-ui';

  <html lang="en" suppressHydrationWarning>
    <head>
-     <script
-       dangerouslySetInnerHTML={{ __html: themeScript }}
-       suppressHydrationWarning
-     />
+     <ColorSchemeScript defaultColorMode="system" />
    </head>

The new ColorSchemeScript component:

  • Sets CSS custom properties inline (prevents flash even if CSS loads slowly)
  • Cleaner API than the old themeScript string
  • Supports nonce prop for Content Security Policy

🎭 Theming

Switch between built-in themes or create your own:

import { useTheme } from '@marcoschwartz/lite-ui';

function ThemeSwitcher() {
  const { themeName, setTheme } = useTheme();

  return (
    <div>
      <button onClick={() => setTheme('default')}>Default Theme</button>
      <button onClick={() => setTheme('minimalistic')}>Minimalistic Theme</button>
    </div>
  );
}

Available Themes

  • Default - Vibrant colors, shadows, and smooth animations
  • Minimalistic - Flat design, subtle colors, minimal effects

🚀 Usage Examples

Basic Form

"use client";

import { useState } from 'react';
import { Card, TextInput, Button, Alert } from '@marcoschwartz/lite-ui';

export function ContactForm() {
  const [email, setEmail] = useState('');
  const [submitted, setSubmitted] = useState(false);

  return (
    <Card>
      <h2>Contact Us</h2>
      {submitted && (
        <Alert variant="success">Message sent successfully!</Alert>
      )}
      <TextInput
        label="Email"
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="[email protected]"
      />
      <Button
        variant="primary"
        onClick={() => setSubmitted(true)}
      >
        Send Message
      </Button>
    </Card>
  );
}

Data Table

import { Table } from '@marcoschwartz/lite-ui';

const columns = [
  { key: 'name', label: 'Name', sortable: true },
  { key: 'email', label: 'Email', sortable: true },
  { key: 'status', label: 'Status' },
];

const data = [
  { id: 1, name: 'John Doe', email: '[email protected]', status: 'Active' },
  { id: 2, name: 'Jane Smith', email: '[email protected]', status: 'Inactive' },
];

export function UserTable() {
  return (
    <Table
      columns={columns}
      data={data}
      sortable
      selectable
    />
  );
}

Modal Dialog

"use client";

import { useState } from 'react';
import { Modal, Button } from '@marcoschwartz/lite-ui';

export function ConfirmDialog() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <Button onClick={() => setIsOpen(true)}>Open Dialog</Button>
      <Modal
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        title="Confirm Action"
      >
        <p>Are you sure you want to proceed?</p>
        <div className="flex gap-2 mt-4">
          <Button variant="danger" onClick={() => setIsOpen(false)}>
            Confirm
          </Button>
          <Button variant="secondary" onClick={() => setIsOpen(false)}>
            Cancel
          </Button>
        </div>
      </Modal>
    </>
  );
}

Collapsible Sidebar Navigation

"use client";

import { useState } from 'react';
import {
  AppShell,
  SidebarNav,
  SidebarNavItem,
  SidebarNavSection,
  SidebarNavDivider,
  SidebarNavCollapseToggle,
  HomeIcon,
  UserIcon,
  SettingsIcon,
} from '@marcoschwartz/lite-ui';

export function DashboardLayout({ children }) {
  const [activeItem, setActiveItem] = useState('dashboard');
  const [navbarWidth, setNavbarWidth] = useState<number | undefined>();

  return (
    <AppShell
      title="My App"
      navbar={{
        content: (
          <SidebarNav
            collapsible
            onCollapseChange={(_, width) => setNavbarWidth(width)}
          >
            <SidebarNavSection grow>
              <SidebarNavItem
                icon={<HomeIcon size="sm" />}
                label="Dashboard"
                active={activeItem === 'dashboard'}
                onClick={() => setActiveItem('dashboard')}
              />
              <SidebarNavItem
                icon={<UserIcon size="sm" />}
                label="Users"
                active={activeItem === 'users'}
                onClick={() => setActiveItem('users')}
              />
              <SidebarNavItem
                icon={<SettingsIcon size="sm" />}
                label="Settings"
                active={activeItem === 'settings'}
                onClick={() => setActiveItem('settings')}
              />
            </SidebarNavSection>
            <SidebarNavDivider />
            <SidebarNavCollapseToggle />
          </SidebarNav>
        ),
        width: navbarWidth, // Dynamic width from SidebarNav
      }}
    >
      {children}
    </AppShell>
  );
}

SidebarNav Features:

  • Collapsible mode - Toggle between full and icon-only view
  • Tooltips - Show labels on hover when collapsed
  • Persistent state - Collapse state saved to localStorage
  • Smooth transitions - Animated width changes
  • Mantine-compatible API - Use leftSection as alias for icon

🛠️ Development

Running the Demo

# Clone the repository
git clone https://github.com/marcoschwartz/lite-ui.git
cd lite-ui-js

# Install dependencies
npm install

# Run library + demo app in watch mode
npm run dev:all

This will:

  1. Start the library build in watch mode (auto-rebuilds on changes)
  2. Start the Next.js demo app on http://localhost:3000
  3. Hot-reload changes from the library in the demo app

Building

# Build library
npm run build

# Build CSS only
npm run build:css

📂 Project Structure

lite-ui-js/
├── src/                    # Library source code
│   ├── components/         # React components
│   ├── theme/             # Theme system
│   ├── icons/             # Icon components
│   └── index.ts           # Main exports
├── demo/                  # Demo Next.js app
│   └── app/
│       ├── components/    # Component examples
│       └── page.tsx       # Home page
├── dist/                  # Built library (generated)
└── package.json

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

MIT © Marco Schwartz

🔗 Links

💡 Technology Stack

  • React 19 - UI framework
  • TypeScript 5 - Type safety
  • Tailwind CSS v4 - Utility-first styling
  • tsup - TypeScript bundler
  • Next.js 15 - Demo app framework