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

@votekio/3d-ui

v0.1.8

Published

A 3D-styled UI component library built with TailwindCSS

Readme

@votekio/3d-ui

A beautiful 3D-styled UI component library built with React and TailwindCSS. Inspired by shadcn/ui but with a unique 3D aesthetic featuring depth, shadows, and interactive press effects.

npm version License: MIT TypeScript

🌐 Live Demo📦 npm📖 GitHub☕ Buy Me a Coffee


👨‍💻 Author

John Tran

If you find this library useful, consider supporting the project! 🎉

✨ Features

  • 🎨 3D Visual Effects - Realistic depth and shadow effects
  • 🖱️ Interactive Feedback - Press animations and hover states
  • 🌈 Multiple Variants - Primary, Secondary, Accent, Ghost, Danger, Glass
  • 📏 Flexible Sizes - SM, MD, LG, XL, and Icon sizes
  • 🎛️ Customizable Depth - Flat, Shallow, Normal, Deep options
  • Glow Effects - Optional glow on hover
  • Accessible - Keyboard navigation and focus states
  • 🌙 Theme System - 5 pre-built themes + custom theme support
  • 🖥️ SSR Support - Works with Next.js, Remix, Gatsby, etc.
  • 📖 Storybook - Interactive documentation and playground

📦 Components

| Component | Description | | ------------------ | ------------------------------------------- | | Button | 3D buttons with press effects | | Accordion | Collapsible sections | | Dialog | Modal dialogs with portal | | Alert | Alert messages with icons | | TextField | Text inputs with 3D styling | | TextArea | Multiline text inputs | | Badge | Status badges and labels | | Card | Container cards with 3D effects | | Switch | Toggle switches | | Checkbox | Checkbox inputs | | Tabs | Tab navigation | | Select | Dropdown select menus | | Progress | Linear and circular progress indicators | | Avatar | User avatars with status indicators | | Skeleton | Loading placeholders | | Tooltip | Hover tooltips | | Slider | Range sliders | | RadioGroup | Radio button groups | | Toast | Toast notifications | | DropdownMenu | Context menus and dropdowns | | Separator | Visual dividers | | Label | Form labels | | Toggle | Toggle buttons | | Popover | Popover dialogs | | Sheet | Side sheets and drawers | | Collapsible | Collapsible content sections | | HoverCard | Hover-triggered cards | | ScrollArea | Custom scrollable areas | | AspectRatio | Maintain aspect ratios | | Breadcrumb | Navigation breadcrumbs | | Command | Command palette and search | | Menubar | Application menu bars | | NavigationMenu | Navigation menus with dropdowns | | Table | Data tables | | Pagination | Page navigation | | Calendar | Date calendar picker | | DatePicker | Date input with calendar | | TimePicker | Time selection with hours, minutes, seconds | | TimezonePicker | Timezone selection with offset display | | DateTimePicker | Combined date and time picker | | Form | Form components and validation | | Grid | Responsive grid layout system | | FileUpload | File upload with drag & drop support | | Rating | Star rating component (1-5 stars) | | Carousel | Image/content carousel with navigation | | Video | Custom video player with 3D controls | | BarChart | 3D bar charts with gradients | | LineChart | Line charts with smooth curves | | PieChart | Pie and donut charts | | AreaChart | Area charts with gradients | | ScatterChart | Scatter plots for correlation analysis | | RadarChart | Radar/spider charts for comparisons | | ComposedChart | Combined bar, line, and area charts | | GaugeChart | Gauge/speedometer charts for metrics | | ThemeProvider | Theme context provider |

🚀 Getting Started

Installation

npm install @votekio/3d-ui
# or
yarn add @votekio/3d-ui
# or
pnpm add @votekio/3d-ui

Setup TailwindCSS

Add the library to your tailwind.config.js content paths:

module.exports = {
  content: [
    // ... your paths
    "./node_modules/@votekio/3d-ui/dist/**/*.{js,ts,jsx,tsx}",
  ],
  // ... rest of config
};

Import Styles

Import the library styles in your app:

import "@votekio/3d-ui/dist/styles.css";

Use Components

import { Button, ThemeProvider } from "@votekio/3d-ui";

function App() {
  return (
    <ThemeProvider defaultTheme="dark">
      <Button variant="primary" size="lg">
        Click Me!
      </Button>
    </ThemeProvider>
  );
}

🎨 Theme System (CSS-First)

The library uses CSS Variables for theming, optimized for Server Side Rendering.

Method 1: CSS Class (Recommended for SSR)

Add a class or data attribute to the <html> tag:

<!-- Using class -->
<html class="theme-dark">
  <!-- Or data attribute -->
  <html data-theme="dark">
    <!-- Or data-theme with Next.js -->
    <html data-theme="ocean"></html>
  </html>
</html>

Available Themes

  • theme-dark / data-theme="dark" - Dark theme (default)
  • theme-light / data-theme="light" - Light theme
  • theme-ocean / data-theme="ocean" - Cyan/teal
  • theme-sunset / data-theme="sunset" - Orange/pink
  • theme-forest / data-theme="forest" - Green

Customize Colors with CSS

/* Override primary color */
:root {
  --color-primary-500: #ef4444; /* Red */
}

/* Or use utility class */
<html class="theme-dark primary-rose">

/* Available color classes */
.primary-blue, .primary-rose, .primary-violet, .primary-emerald...
.secondary-purple, .secondary-pink, .secondary-teal...
.accent-green, .accent-yellow, .accent-orange...

Full Color Override (CSS)

:root {
  /* Primary - Custom Red */
  --color-primary-50: #fef2f2;
  --color-primary-100: #fee2e2;
  --color-primary-200: #fecaca;
  --color-primary-300: #fca5a5;
  --color-primary-400: #f87171;
  --color-primary-500: #ef4444;
  --color-primary-600: #dc2626;
  --color-primary-700: #b91c1c;
  --color-primary-800: #991b1b;
  --color-primary-900: #7f1d1d;
  --color-primary-950: #450a0a;

  /* Secondary - Custom Purple */
  --color-secondary-500: #8b5cf6;

  /* Accent - Custom Teal */
  --color-accent-500: #14b8a6;
}

Method 2: ThemeProvider (Client-side)

If you need dynamic theme switching with JavaScript:

import { ThemeProvider, useTheme } from "@votekio/3d-ui";

function App() {
  return (
    <ThemeProvider defaultTheme="dark">
      <YourApp />
    </ThemeProvider>
  );
}

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

  return (
    <select value={themeName} onChange={(e) => setTheme(e.target.value)}>
      {availableThemes.map((name) => (
        <option key={name} value={name}>
          {name}
        </option>
      ))}
    </select>
  );
}

🖥️ Server Side Rendering (SSR)

The library is fully compatible with SSR frameworks like Next.js, Remix, and Gatsby.

SSR Utilities

import {
  isBrowser,
  isServer,
  useIsMounted,
  useLocalStorage,
  useWindowSize,
  usePrefersDarkMode,
} from "@votekio/3d-ui";

// Check environment
if (isBrowser) {
  // Client-side only code
}

// Hook to check if component mounted
function MyComponent() {
  const isMounted = useIsMounted();

  if (!isMounted) return <Skeleton />;

  return <div>{window.innerWidth}</div>;
}

// Safe localStorage hook
const [theme, setTheme] = useLocalStorage("theme", "dark");

// Window size hook (SSR-safe)
const { width, height } = useWindowSize();

// Dark mode preference detection
const prefersDark = usePrefersDarkMode();

Next.js App Router

// app/providers.tsx
"use client";

import { ThemeProvider } from "@votekio/3d-ui";

export function Providers({ children }) {
  return <ThemeProvider defaultTheme="dark">{children}</ThemeProvider>;
}

📚 Component Examples

Button

import { Button } from "@votekio/3d-ui";

// Variants
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="accent">Accent</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="danger">Danger</Button>
<Button variant="glass">Glass</Button>

// Sizes
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>

// With icons
<Button leftIcon={<Icon />}>Download</Button>

// Loading state
<Button isLoading>Loading</Button>

TextField

import { TextField, TextArea } from "@votekio/3d-ui";

<TextField
  label="Email"
  placeholder="[email protected]"
  leftElement={<MailIcon />}
  helperText="We'll never share your email"
  fullWidth
/>

<TextField
  label="Password"
  error="Password is required"
  isRequired
/>

<TextArea
  label="Message"
  placeholder="Enter your message..."
  resize
/>

Dialog

import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from "@votekio/3d-ui";

<Dialog>
  <DialogTrigger>
    <Button>Open Dialog</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Dialog Title</DialogTitle>
      <DialogDescription>Dialog description here.</DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="ghost">Cancel</Button>
      </DialogClose>
      <Button>Confirm</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>;

Alert

import { Alert, AlertTitle, AlertDescription } from "@votekio/3d-ui";

<Alert variant="info">
  <AlertTitle>Information</AlertTitle>
  <AlertDescription>This is an info alert.</AlertDescription>
</Alert>

<Alert variant="success">
  <AlertTitle>Success!</AlertTitle>
  <AlertDescription>Operation completed.</AlertDescription>
</Alert>

<Alert variant="warning">
  <AlertTitle>Warning</AlertTitle>
  <AlertDescription>Please check your input.</AlertDescription>
</Alert>

<Alert variant="destructive">
  <AlertTitle>Error</AlertTitle>
  <AlertDescription>Something went wrong.</AlertDescription>
</Alert>

Accordion

import {
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
} from "@votekio/3d-ui";

<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Section 1</AccordionTrigger>
    <AccordionContent>Content for section 1</AccordionContent>
  </AccordionItem>
  <AccordionItem value="item-2">
    <AccordionTrigger>Section 2</AccordionTrigger>
    <AccordionContent>Content for section 2</AccordionContent>
  </AccordionItem>
</Accordion>;

Calendar & DatePicker

import { Calendar, DatePicker } from "@votekio/3d-ui";

// Calendar
<Calendar
  value={selectedDate}
  onChange={setSelectedDate}
  showNavigation
/>

// DatePicker
<DatePicker
  label="Select Date"
  value={date}
  onChange={setDate}
  placeholder="Pick a date"
/>

TimePicker, TimezonePicker & DateTimePicker

import { TimePicker, TimezonePicker, DateTimePicker } from "@votekio/3d-ui";

// TimePicker
<TimePicker
  label="Select Time"
  value={time}
  onChange={setTime}
  format="24h"
  showSeconds
/>

// TimezonePicker
<TimezonePicker
  label="Select Timezone"
  value={timezone}
  onChange={setTimezone}
  priorityTimezones={[
    { value: "America/New_York", label: "Eastern Time" },
    { value: "America/Los_Angeles", label: "Pacific Time" },
  ]}
/>

// DateTimePicker
<DateTimePicker
  label="Select Date & Time"
  value={dateTime}
  onChange={setDateTime}
  format="24h"
  showSeconds
/>

Grid

import { Grid, GridItem } from "@votekio/3d-ui";

<Grid cols={12} gap={4}>
  <GridItem colSpan={{ base: 12, md: 6, lg: 4 }}>
    <Card>Item 1</Card>
  </GridItem>
  <GridItem colSpan={{ base: 12, md: 6, lg: 4 }}>
    <Card>Item 2</Card>
  </GridItem>
  <GridItem colSpan={{ base: 12, md: 6, lg: 4 }}>
    <Card>Item 3</Card>
  </GridItem>
</Grid>;

FileUpload

import { FileUpload } from "@votekio/3d-ui";

<FileUpload
  label="Upload Files"
  value={files}
  onChange={setFiles}
  multiple
  accept="image/*"
  maxSize={5 * 1024 * 1024} // 5MB
  maxFiles={5}
/>;

Rating

import { Rating } from "@votekio/3d-ui";

<Rating
  value={rating}
  onChange={setRating}
  max={5}
  allowHalf
  color="primary"
  size="lg"
/>;

Carousel

import {
  Carousel,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
  CarouselDots,
} from "@votekio/3d-ui";

<Carousel
  autoPlay={3000}
  loop
  showNavigation
  showDots
  swipeable
  keyboardNavigation
>
  <CarouselItem>
    <Card>
      <CardContent>Slide 1</CardContent>
    </Card>
  </CarouselItem>
  <CarouselItem>
    <Card>
      <CardContent>Slide 2</CardContent>
    </Card>
  </CarouselItem>
  <CarouselItem>
    <Card>
      <CardContent>Slide 3</CardContent>
    </Card>
  </CarouselItem>
</Carousel>;

Video

import { Video } from "@votekio/3d-ui";

// Basic usage
<Video
  src="https://example.com/video.mp4"
  showControls
  customControls
  autoHideControls={3000}
/>;

// With chapters/markers
<Video
  src="https://example.com/video.mp4"
  chapters={[
    { startTime: 0, endTime: 30, label: "Intro", color: "rgb(59, 130, 246)" },
    { startTime: 30, endTime: 60, label: "Main", color: "rgb(34, 197, 94)" },
    { startTime: 60, endTime: -1, label: "End", color: "rgb(239, 68, 68)" },
  ]}
  onTimeUpdate={(current, total) => console.log(current, total)}
  onReady={(duration) => console.log("Duration:", duration)}
/>;

// HLS streaming (requires hls.js)
<Video src="https://example.com/stream.m3u8" showControls customControls />;

Form

import {
  Form,
  FormItem,
  FormLabel,
  FormMessage,
  FormField,
  TextField,
  Button,
} from "@votekio/3d-ui";

<Form onSubmit={handleSubmit}>
  <FormField name="email">
    <FormItem>
      <FormLabel>Email</FormLabel>
      <TextField type="email" placeholder="[email protected]" />
      <FormMessage />
    </FormItem>
  </FormField>
  <Button type="submit">Submit</Button>
</Form>;

Pagination

import { Pagination } from "@votekio/3d-ui";

<Pagination
  currentPage={1}
  totalPages={10}
  onPageChange={setPage}
  showFirstLast
  showPrevNext
/>;

Select

import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from "@votekio/3d-ui";

<Select value={value} onValueChange={setValue}>
  <SelectTrigger>
    <SelectValue placeholder="Select an option" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="option1">Option 1</SelectItem>
    <SelectItem value="option2">Option 2</SelectItem>
  </SelectContent>
</Select>;

DropdownMenu

import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
} from "@votekio/3d-ui";

<DropdownMenu>
  <DropdownMenuTrigger>
    <Button>Open Menu</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem>Profile</DropdownMenuItem>
    <DropdownMenuItem>Settings</DropdownMenuItem>
    <DropdownMenuItem>Logout</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>;

Charts

import { BarChart, LineChart, PieChart, AreaChart } from "@votekio/3d-ui";

// BarChart
<BarChart
  title="Sales Overview"
  data={[
    { label: "Jan", value: 120, color: "primary" },
    { label: "Feb", value: 190, color: "secondary" },
    { label: "Mar", value: 300, color: "accent" },
  ]}
  showGrid
  showLabels
/>

// LineChart
<LineChart
  title="User Growth"
  series={[
    {
      name: "Users",
      color: "primary",
      data: [
        { label: "Jan", value: 100 },
        { label: "Feb", value: 150 },
        { label: "Mar", value: 200 },
      ],
    },
  ]}
  showGrid
  showDots
  curve="smooth"
/>

// PieChart
<PieChart
  title="Market Share"
  data={[
    { label: "Desktop", value: 45, color: "primary" },
    { label: "Mobile", value: 30, color: "secondary" },
    { label: "Tablet", value: 15, color: "accent" },
  ]}
  showLabels
  showLegend
/>

// AreaChart
<AreaChart
  title="Revenue Trend"
  series={[
    {
      name: "Revenue",
      color: "primary",
      data: [
        { label: "Jan", value: 10000 },
        { label: "Feb", value: 15000 },
        { label: "Mar", value: 12000 },
      ],
    },
  ]}
  showGrid
  curve="smooth"
/>

ScatterChart

import { ScatterChart } from "@votekio/3d-ui";

<ScatterChart
  title="Sales vs Marketing"
  xAxisLabel="Marketing Spend"
  yAxisLabel="Sales"
  series={[
    {
      name: "Data",
      color: "primary",
      data: [
        { x: 1000, y: 5000 },
        { x: 2000, y: 8000 },
        { x: 3000, y: 12000 },
      ],
    },
  ]}
  showGrid
/>;

RadarChart

import { RadarChart } from "@votekio/3d-ui";

<RadarChart
  title="Performance Metrics"
  series={[
    {
      name: "Product A",
      color: "primary",
      data: [
        { label: "Speed", value: 80 },
        { label: "Quality", value: 90 },
        { label: "Price", value: 70 },
      ],
    },
  ]}
  showGrid
  showArea
/>;

ComposedChart

import { ComposedChart } from "@votekio/3d-ui";

<ComposedChart
  title="Revenue Analysis"
  data={[
    { label: "Jan", barValue: 12000, lineValue: 8000, areaValue: 4000 },
    { label: "Feb", barValue: 15000, lineValue: 9000, areaValue: 6000 },
  ]}
  showGrid
  barColor="primary"
  lineColor="secondary"
  areaColor="accent"
/>;

GaugeChart

import { GaugeChart } from "@votekio/3d-ui";

// Basic gauge
<GaugeChart
  title="CPU Usage"
  value={75}
  min={0}
  max={100}
  unit="%"
  color="primary"
/>

// Custom range
<GaugeChart
  title="Temperature"
  value={22}
  min={0}
  max={40}
  unit="°C"
  color="warning"
/>

// Full circle gauge
<GaugeChart
  title="Progress"
  value={270}
  min={0}
  max={360}
  type="full"
  color="success"
/>

🛠️ Development

# Install dependencies
npm install

# Start Storybook development server
npm run dev

# Build the library
npm run build

# Build Storybook for production
npm run build:storybook

🚀 Deployment

Deploy to Vercel

The project is configured to deploy Storybook to Vercel automatically.

Option 1: Deploy via Vercel CLI

# Install Vercel CLI
npm i -g vercel

# Deploy
vercel

Option 2: Deploy via Vercel Dashboard

  1. Push your code to GitHub/GitLab/Bitbucket
  2. Go to Vercel Dashboard
  3. Click "Add New Project"
  4. Import your repository
  5. Vercel will automatically detect the configuration from vercel.json
  6. Click "Deploy"

The vercel.json file is already configured with:

  • Build command: npm run build:storybook
  • Output directory: storybook-static
  • Framework: Static Site

Manual Build & Deploy

# Build Storybook
npm run build:storybook

# The output will be in storybook-static/
# You can deploy this folder to any static hosting service

Publish to npm

The library is configured to be published to npm.

Prerequisites

  1. Create an npm account at npmjs.com
  2. Login to npm via CLI:
    npm login

Build & Publish

# Build the library (this will also copy CSS files)
npm run build

# Verify the build output
ls dist/

# Publish to npm (this will run prepublishOnly script automatically)
npm publish

# For scoped packages, publish publicly:
npm publish --access public

Version Management

# Update version before publishing
npm version patch   # 0.1.0 -> 0.1.1
npm version minor   # 0.1.0 -> 0.2.0
npm version major   # 0.1.0 -> 1.0.0

# Then publish
npm publish --access public

What Gets Published

The following files are included in the npm package:

  • dist/ - Built JavaScript, TypeScript definitions, and CSS files
  • README.md - Documentation
  • package.json - Package metadata

The following are excluded (via .npmignore):

  • Source files (src/)
  • Storybook files
  • Development configs
  • Tests

After Publishing

Users can install and use the package:

npm install @votekio/3d-ui
import { Button } from "@votekio/3d-ui";
import "@votekio/3d-ui/styles/globals.css";

💝 Support

If this project has helped you in any way, or you'd like to support its continued development, please consider:

  • Starring this repository
  • 🐛 Reporting bugs or suggesting features
  • 💬 Sharing with others who might find it useful
  • Buying me a coffee to support development

Your support means the world to me! 🙏

📄 License

MIT © John Tran


Made with ❤️ by John Tran

☕ Buy Me a Coffee📖 Documentation🐛 Report Bug