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

@ozura/ui

v0.9.0

Published

Shared UI components and design tokens for Ozura frontends

Downloads

2,065

Readme

@ozura/ui

The shared design system for all Ozura frontends — Dashboard, Vault, and Developer Tools.

npm: @ozura/ui | GitHub: Ozura-Inc/ozura-ui

Why @ozura/ui exists

Ozura has 3 customer-facing frontends that must look and feel like one product:

| App | Repo | Port | Purpose | |-----|------|------|---------| | Dashboard | ozurapay-frontend-v2 | 3000 | Merchant/ISO/ISV management | | Vault | token-vault-frontend | 3001 | PCI token storage | | Developer Tools | PayAPI-FE | 3002 | API sandbox, logs, webhooks |

@ozura/ui is the single source of truth for:

  • Design tokens (colors, fonts, spacing) via globals.css
  • Shared components (sidebar, header, toasts)
  • Consistent behavior (theme toggle, cross-app theme sync)

If a UI element appears in more than one frontend, it belongs in @ozura/ui.


Installation

npm install @ozura/ui sonner

Setup

1. Import the design tokens

In your app's globals.css, import the base tokens before Tailwind:

@import "@ozura/ui/globals.css";
@import "tailwindcss";

/* App-specific overrides and styles go below */

This gives you all the Ozura design tokens (colors, sidebar, status, radius, etc.) for both light and dark themes, plus the Tailwind v4 @theme inline mappings.

You can add app-specific overrides after the imports. The base tokens are inherited — only override what's different for your app.

2. Root layout

import type { Metadata } from "next";
import { Rubik, Inter, JetBrains_Mono } from "next/font/google";
import { ThemeProvider } from "next-themes";
import { OzuraToaster } from "@ozura/ui";
import "./globals.css";

const rubik = Rubik({ subsets: ["latin"], variable: "--font-rubik", weight: ["300","400","500","600","700"] });
const inter = Inter({ subsets: ["latin"], variable: "--font-inter", weight: ["400","500","600"] });
const jetbrainsMono = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains-mono", weight: ["400","500"] });

export const metadata: Metadata = {
  icons: { icon: "/icon.svg" },
  title: { default: "Ozura App", template: "%s — Ozura" },
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={`${rubik.variable} ${inter.variable} ${jetbrainsMono.variable} font-rubik`}>
        <ThemeProvider attribute="class" defaultTheme="light" enableSystem={false}>
          {children}
          <OzuraToaster />
        </ThemeProvider>
      </body>
    </html>
  );
}

3. Layout structure

┌─────────────────────────────────────────────────┐
│  OzuraHeader (fixed, top, left: 260px)          │
│  [leftContent]              [theme] [profile ▾] │
├──────────┬──────────────────────────────────────┤
│  Ozura   │  Content Area (px-8 py-6)            │
│  Sidebar │  pt-16 offset for header             │
│  260px   │                                      │
│  fixed   │                                      │
└──────────┴──────────────────────────────────────┘

Components

OzuraShell (Recommended)

The all-in-one layout component. Handles sidebar, header, mobile responsiveness, and content padding. This is the recommended way to use @ozura/ui in any app.

import { OzuraShell } from '@ozura/ui';
import type { NavItem } from '@ozura/ui';
import { LayoutDashboard, KeyRound, Users } from 'lucide-react';

const navItems: NavItem[] = [
  { label: 'Dashboard', href: '/', icon: LayoutDashboard },
  { label: 'Tokens', href: '/tokens', icon: KeyRound },
  { label: 'Members', href: '/members', icon: Users },
];

export default function AppLayout({ children }) {
  return (
    <OzuraShell
      navItems={navItems}
      user={{ name: 'Max', email: '[email protected]' }}
      onLogout={() => { window.location.href = '/login'; }}
      leftContent={<SearchBar />}
      settingsHref="/settings"
    >
      {children}
    </OzuraShell>
  );
}

What OzuraShell handles

| Feature | Desktop (≥768px) | Mobile (<768px) | |---------|-----------------|-----------------| | Sidebar | Fixed left, 260px | Hidden, opens as overlay via hamburger | | Header | Fixed top, profile + theme toggle | Compact with hamburger + logo + avatar | | Content | padding: 24px 32px, offset for sidebar/header | padding: 16px, offset for mobile header | | Navigation | Click navigates normally | Click navigates + closes sidebar overlay | | Body scroll | Normal | Locked when sidebar overlay is open |

OzuraShell Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | navItems | NavItem[] | required | Sidebar navigation items | | user | { name, email, avatarUrl? } | — | Profile dropdown in header | | onLogout | () => void | — | Logout handler | | leftContent | ReactNode | — | Header left slot (search, project selector) | | showThemeToggle | boolean | true | Show sun/moon theme toggle | | settingsHref | string | /settings | Settings route in sidebar | | backLink | { label, href } | — | Back link in sidebar (e.g. "← Dashboard") | | docsUrl | string | https://docs.ozura.com | Documentation link | | darkLogoSrc | string | /logos/ozura-logo-dark.svg | Logo for light theme | | lightLogoSrc | string | /logos/ozura-logo-white.svg | Logo for dark theme | | children | ReactNode | required | Page content |

OzuraSidebar

import { OzuraSidebar } from '@ozura/ui';
import type { NavItem } from '@ozura/ui';
import { LayoutDashboard, KeyRound } from 'lucide-react';

const navItems: NavItem[] = [
  { label: 'Dashboard', href: '/', icon: LayoutDashboard },
  { label: 'Tokens', href: '/tokens', icon: KeyRound },
];

<OzuraSidebar navItems={navItems} settingsHref="/settings" />

| Prop | Type | Default | Description | |------|------|---------|-------------| | navItems | NavItem[] | required | Nav items | | backLink | { label, href } | — | Back link (e.g. DevTools → Dashboard) | | docsUrl | string | https://docs.ozura.com | Docs link | | settingsHref | string | /settings | Settings route | | darkLogoSrc | string | /logos/ozura-logo-dark.svg | Logo for light theme | | lightLogoSrc | string | /logos/ozura-logo-white.svg | Logo for dark theme |

OzuraHeader

import { OzuraHeader } from '@ozura/ui';

<OzuraHeader
  user={{ name: 'Max', email: '[email protected]' }}
  onLogout={() => { window.location.href = '/login'; }}
  showThemeToggle={true}
  leftContent={<YourSearchBar />}
/>

| Prop | Type | Default | Description | |------|------|---------|-------------| | user | { name, email, avatarUrl? } | — | Profile dropdown info | | onLogout | () => void | — | Logout handler | | leftContent | ReactNode | — | Left slot (search, project selector) | | showThemeToggle | boolean | true | Show sun/moon toggle | | sidebarWidth | number | 260 | Header left offset |

Toasts (Sonner)

All apps use Sonner for notifications via ozToast:

import { ozToast } from '@ozura/ui';

// Success
ozToast.success('Payment processed');

// Error with description
ozToast.error('Transaction failed', 'Insufficient funds');

// Warning
ozToast.warning('Rate limit approaching');

// Loading → resolves
ozToast.promise(fetchData(), {
  loading: 'Processing...',
  success: 'Done!',
  error: 'Failed',
});

Setup: Add <OzuraToaster /> once in your root layout (see Setup section above).

Pattern: Never use alert(), console.log() for user-facing messages, or custom toast implementations. Always use ozToast.


Design Standards

| Standard | Value | |----------|-------| | Sidebar width | 260px | | Header height | 64px (h-16) | | Content padding | px-8 py-6 | | Fonts | Rubik (primary), Inter (data/body), JetBrains Mono (code) | | CSS format | Hex values with @theme inline (Tailwind v4) | | Theme storage | localStorage key "theme", values "light" / "dark" | | Dark mode | class="dark" on <html> via next-themes | | Mobile breakpoint | 768px | | Border radius | --radius: 0.5rem, --radius-button: 0.375rem | | Toast library | Sonner via ozToast | | Title pattern | { default: "App Name", template: "%s — Ozura" } |


Required Assets

Copy public/logos/ from this repo to your app's public/ directory:

  • public/logos/ozura-logo-dark.svg
  • public/logos/ozura-logo-white.svg
  • public/icon.svg — favicon (place in src/app/icon.svg)
  • public/favicon.svg — fallback favicon

Making Changes

To shared components (sidebar, header, toasts)

  1. Clone: git clone [email protected]:Ozura-Inc/ozura-ui.git
  2. Edit in src/components/
  3. Test locally: npm run build && npm linknpm link @ozura/ui in your app
  4. Bump version in package.json
  5. Publish: npm publish --access public
  6. Update all 3 apps: npm install @ozura/ui@<version>

To design tokens (colors, spacing)

  1. Edit src/globals.css in this repo
  2. Publish new version
  3. All apps inherit the changes automatically (they import @ozura/ui/globals.css)

To app-specific styles

Edit the app's own globals.css — add overrides AFTER the imports. Don't duplicate tokens that exist in @ozura/ui/globals.css.

Rule: If it should look the same everywhere → put it in @ozura/ui. If it's app-specific → keep it in the app.


Development

npm install
npm run build   # Build with tsup
npm run dev     # Watch mode
npm run lint    # Type check