@votekio/3d-ui
v0.1.8
Published
A 3D-styled UI component library built with TailwindCSS
Maintainers
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.
🌐 Live Demo • 📦 npm • 📖 GitHub • ☕ Buy Me a Coffee
👨💻 Author
John Tran
- 📧 Email: [email protected]
- 🌐 GitHub: @rintran720
- ☕ Support: Buy Me a Coffee
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-uiSetup 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 themetheme-ocean/data-theme="ocean"- Cyan/tealtheme-sunset/data-theme="sunset"- Orange/pinktheme-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
vercelOption 2: Deploy via Vercel Dashboard
- Push your code to GitHub/GitLab/Bitbucket
- Go to Vercel Dashboard
- Click "Add New Project"
- Import your repository
- Vercel will automatically detect the configuration from
vercel.json - 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 servicePublish to npm
The library is configured to be published to npm.
Prerequisites
- Create an npm account at npmjs.com
- 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 publicVersion 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 publicWhat Gets Published
The following files are included in the npm package:
dist/- Built JavaScript, TypeScript definitions, and CSS filesREADME.md- Documentationpackage.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-uiimport { 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
