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

@h-hemant-p/ui

v1.1.1

Published

Alphastry universal React component library — Core CSS, dark/light mode, NPM & Git Submodule distribution

Readme

@alphastry/ui — Shared React Component Library

Universal React components shared across all Alphastry products.
Pure Core CSS · Dark + Light mode · TypeScript · Git Submodule & NPM distribution.


Table of Contents


Components

| Component | Description | Class Names | |-----------|-------------|-------------| | Button | Primary, secondary, ghost, danger variants · loading state · left/right icon slots | .ui-button, .ui-button--* | | Badge | Status labels — success, warning, danger, info, neutral, accent · dot indicator · dismissible | .ui-badge, .ui-badge--* | | Spinner | Loading indicator — 5 sizes · overlay/full-screen mode · accessible aria-label | .ui-spinner, .ui-spinner--* | | Input | Text input — label · error state · helper text · left/right icon slots · fully accessible | .ui-input-* | | Modal | Dialog overlay — focus trap · scroll lock · keyboard navigation · Modal.Footer sub-component | .ui-modal-* | | CountryCodeSelect | Searchable dial code dropdown selector with flags and search input | .ui-country-select, .ui-country-select__* | | SearchableDropdown | Generic searchable option dropdown list with checks and custom labels | .ui-searchable-dropdown, .ui-searchable-dropdown__* | | Switch | Modern rectangular toggle slide switch replacement for checkbox elements | .ui-switch, .ui-switch__* | | Tabs | Tab navigation list with active pill state and optional icon slots | .ui-tabs, .ui-tabs__* | | Card | Structured containment layout block with header, title, actions and body slots | .ui-card, .ui-card__* | | Avatar | Squircle image/initials renderer with auto local-SVG fallback logic | .ui-avatar, .ui-avatar__* | | Alert | Banner alerts with success, warning, error, info states and inline close action | .ui-alert, .ui-alert--* | | Tooltip | Absolute bubble overlays positioned on top, bottom, left, right on hover | .ui-tooltip, .ui-tooltip__* | | Progress | Quota limit metrics indicator bar with primary, success, warning, danger states | .ui-progress, .ui-progress__* | | Pagination | Controls footer layout showing page numbers with standard SVG arrows | .ui-pagination, .ui-pagination__* | | Skeleton | Animated pulsers for rectangles, lines, and circular skeleton placeholders | .ui-skeleton, .ui-skeleton--* | | Textarea | Multi-line text field — label · helper text · error · fullWidth · fully accessible | .ui-textarea-* | | Select | Native browser select — custom chevron arrow · label · error · helper · left icon slot | .ui-select-* |


Hooks

| Hook | Description | |------|-------------| | useClickOutside | Fires a callback when the user clicks outside a given ref element | | useDebounce | Debounces a value update after a configurable delay (ms) |


Tech Stack

| Layer | Technology | Version | |-------|-----------|---------| | Language | TypeScript | ^5.5 | | UI Library | React | ≥18.0 (peer dep) | | Styling | Core CSS (Vanilla CSS) | — | | CSS Variables | Custom design tokens (tokens.css) | — | | Bundler | tsup | ^8.5 | | Package Manager | npm (or pnpm) | — |


Setup in a New Project (Submodule)

If you are importing the library as a Git submodule, follow these steps:

Step 1 — Add as Git Submodule

Run this from the root of your frontend project:

git submodule add https://gitlab.com/alphastry/code-snippets/react-components.git submodules/react-components
git submodule update --init --recursive

Step 2 — Configure Vite Path Alias

In your vite.config.ts:

import path from 'path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@alphastry/ui': path.resolve(__dirname, './submodules/react-components/src/index.ts'),
    },
  },
});

Step 3 — Configure TypeScript Path Mapping

In your tsconfig.json (or tsconfig.app.json):

{
  "compilerOptions": {
    "paths": {
      "@alphastry/ui": ["./submodules/react-components/src/index.ts"],
      "@alphastry/ui/*": ["./submodules/react-components/src/*"]
    }
  }
}

Step 4 — Import Design Stylesheet

In your root CSS file (e.g. src/index.css):

/* Simply import the compiled CSS stylesheet once */
@import '../submodules/react-components/dist/index.css';

Step 5 — Set the Theme on <html>

The components adapt dynamically to dark and light modes using the data-theme attribute:

// In main.tsx or your theme context:
document.documentElement.setAttribute('data-theme', 'dark');
// or
document.documentElement.setAttribute('data-theme', 'light');

Setup in a New Project (NPM)

If you have installed the package from the NPM registry:

Step 1 — Install the package

npm install @h-hemant-p/ui

Step 2 — Import the stylesheet

In your root layout or React entry point file (e.g., main.tsx or layout.tsx):

import '@h-hemant-p/ui/dist/index.css';

Step 3 — Use the components

import { Button } from '@h-hemant-p/ui';

Running / Development

To run typechecks and compile components locally:

# Install development dependencies
npm install

# Build JavaScript bundles (CJS, ESM, Types) and CSS sheets
npm run build

The output assets will be created in the dist/ directory.


Usage Examples

## Usage Examples

```tsx
import { Button, Badge, Modal, Spinner, Input, CountryCodeSelect, SearchableDropdown, Switch, Tabs, Card, Avatar, Alert, Tooltip, Progress, Pagination, Skeleton, Textarea, Select, useDebounce, useClickOutside } from '@h-hemant-p/ui';

// ── Button ─────────────────────────────────────────────────
<Button variant="primary" size="md" onClick={save}>Save</Button>
<Button variant="danger" loading>Deleting...</Button>
<Button variant="ghost" leftIcon={<PlusIcon />}>Add item</Button>
<Button variant="secondary" rightIcon={<ArrowIcon />}>Next</Button>

// ── Badge ──────────────────────────────────────────────────
<Badge variant="success" dot>Active</Badge>
<Badge variant="danger" onDismiss={() => clearError()}>Error occurred</Badge>
<Badge variant="warning">Pending Review</Badge>

// ── Spinner ────────────────────────────────────────────────
<Spinner size="lg" label="Loading campaigns..." />
<Spinner overlay />   {/* full-screen blocking spinner */}

// ── Input ──────────────────────────────────────────────────
<Input label="Email" type="email" placeholder="[email protected]" />
<Input label="Search" leftIcon={<SearchIcon />} error="This field is required" />
<Input label="Password" type="password" helperText="At least 8 characters" />

// ── Modal ──────────────────────────────────────────────────
<Modal isOpen={open} onClose={() => setOpen(false)} title="Delete Campaign">
  <p>This action cannot be undone.</p>
  <Modal.Footer>
    <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
    <Button variant="danger" onClick={handleDelete}>Delete</Button>
  </Modal.Footer>
</Modal>

// ── CountryCodeSelect ──────────────────────────────────────
<CountryCodeSelect value={dialCode} onChange={(val) => setDialCode(val)} />

// ── SearchableDropdown ─────────────────────────────────────
<SearchableDropdown
  options={[
    { value: 'session_1', label: 'WhatsBot Main', description: '+919999999999', status: 'connected' },
    { value: 'session_2', label: 'Support Line', description: '+18888888888', status: 'disconnected' }
  ]}
  selectedId={selectedSession}
  onChange={(val) => setSelectedSession(val)}
  placeholder="-- Choose a session --"
/>

// ── Switch ─────────────────────────────────────────────────
<Switch
  checked={warmupMode}
  onChange={(val) => setWarmupMode(val)}
  label="Warm-up Mode"
  description="Gradually throttle message volume limits to avoid ban risks."
/>

// ── Tabs ───────────────────────────────────────────────────
<Tabs
  tabs={[
    { id: 'campaigns', label: 'Campaigns' },
    { id: 'team', label: 'Team members' }
  ]}
  activeTabId={activeTab}
  onChange={(id) => setActiveTab(id)}
/>

// ── Card ───────────────────────────────────────────────────
<Card
  title="Safety Settings"
  subtitle="Initiate parameters for automated message warmups"
  extra={<Badge variant="accent">Pro Mode</Badge>}
>
  <p>Configure details for throttle delays and unsaved number protection logs.</p>
</Card>

// ── Avatar ─────────────────────────────────────────────────
<Avatar src={userPhoto} name="Hemant Prasad" size="md" />
<Avatar name="Support Agent" size="sm" />  {/* renders "SA" initials */}

// ── Alert ──────────────────────────────────────────────────
<Alert variant="warning" title="Agent Account Restricted">
  Only workspace owners can configure timezones and trigger invite cards.
</Alert>
<Alert variant="success" onClose={() => dismiss()}>
  Verification code sent successfully.
</Alert>

// ── Tooltip ────────────────────────────────────────────────
<Tooltip content="Switch Reply Modes between manual and AI" position="top">
  <button>Info</button>
</Tooltip>

// ── Progress ───────────────────────────────────────────────
<Progress value={75} variant="success" height={10} />
<Progress value={20} variant="danger" />

// ── Pagination ─────────────────────────────────────────────
<Pagination
  currentPage={currentPage}
  totalPages={10}
  onPageChange={(page) => setCurrentPage(page)}
/>

// ── Skeleton ───────────────────────────────────────────────
<Skeleton variant="circle" width={48} height={48} />
<Skeleton variant="text" width="60%" />
<Skeleton variant="rect" width="100%" height={150} />

// ── Textarea ───────────────────────────────────────────────
<Textarea
  label="Away Message"
  placeholder="Thanks for writing to us..."
  rows={4}
  helperText="Sent automatically during off-hours"
/>

// ── Select ─────────────────────────────────────────────────
<Select label="Timezone" defaultValue="Asia/Kolkata">
  <option value="Asia/Kolkata">India Standard Time (IST)</option>
  <option value="UTC">Coordinated Universal Time (UTC)</option>
</Select>

// ── Hooks ──────────────────────────────────────────────────
const debouncedQuery = useDebounce(searchQuery, 400);

const dropdownRef = useRef<HTMLDivElement>(null);
useClickOutside(dropdownRef, () => setDropdownOpen(false));

Design Tokens

All components use CSS custom properties defined in src/tokens.css. The token file covers both dark and light themes.

Switching theme at runtime:

// Dark mode
document.documentElement.setAttribute('data-theme', 'dark');

// Light mode
document.documentElement.setAttribute('data-theme', 'light');

Key token categories in tokens.css:

| Category | Examples | |----------|---------| | Colors | --ui-bg-base, --ui-bg-surface, --ui-border | | Typography | --ui-font, --ui-text-primary, --ui-text-muted | | Spacing | --ui-radius-sm, --ui-radius-md, --ui-radius-xl | | Shadows | --ui-shadow-sm, --ui-shadow-md, --ui-shadow-modal |

See src/tokens.css for all available variables.


Project Structure

react-components/
├── package.json           # Package metadata + peer deps (React >= 18)
├── tsconfig.json          # TypeScript config
├── tsup.config.ts         # tsup configuration for CJS, ESM and CSS
└── src/
    ├── index.ts           # Public API — imports index.css and exports components/hooks
    ├── index.css          # Master stylesheet combining tokens.css and custom styles
    ├── tokens.css         # CSS custom properties for dark + light themes
    ├── components/
    │   ├── Button/
    │   │   ├── Button.tsx
    │   │   └── index.ts
    │   ├── Badge/
    │   │   ├── Badge.tsx
    │   │   └── index.ts
    │   ├── Spinner/
    │   │   ├── Spinner.tsx
    │   │   └── index.ts
    │   ├── Input/
    │   │   ├── Input.tsx
    │   │   └── index.ts
    │   └── Modal/
    │       ├── Modal.tsx
    │       └── index.ts
    ├── hooks/
    │   ├── useClickOutside.ts
    │   └── useDebounce.ts
    └── types/             # Shared TypeScript type definitions

Adding a New Component

  1. Create the component directory and files:

    src/components/YourComponent/YourComponent.tsx
    src/components/YourComponent/index.ts
  2. Add custom styling classes inside src/index.css using the --ui- variables.

  3. Export from the barrel index.ts:

    // src/components/YourComponent/index.ts
    export { YourComponent } from './YourComponent';
    export type { YourComponentProps } from './YourComponent';
  4. Add to the main public API in src/index.ts:

    export { YourComponent } from './components/YourComponent';
    export type { YourComponentProps } from './components/YourComponent';
  5. Run npm run build to verify compiling.


Repository

GitLab: https://gitlab.com/alphastry/code-snippets/react-components


Part of the Alphastry ecosystem — auth-backend · auth-frontend