@shipshitdev/ui
v0.4.3
Published
A modern, accessible React component library built with TypeScript, Tailwind CSS v4, and Radix UI. Features primitives, composites, and patterns with full theme support and Storybook documentation.
Downloads
733
Maintainers
Readme
ShipShitDevUI
⚠️ Warning: This project is currently under active development and is not ready for production use. Many features are incomplete, and the codebase is subject to significant changes.
A modern React component library built with TypeScript, Tailwind CSS v4, Radix UI, and shadcn/ui patterns.
📖 View Storybook Documentation
Installation
bun add @shipshitdev/uiQuick Start
Get started in 3 simple steps:
1. Add Tailwind Preset
Add the preset to your tailwind.config.ts:
import type { Config } from 'tailwindcss';
export default {
presets: [require('@shipshitdev/ui/tailwind.preset')],
// Your other Tailwind config...
} satisfies Config;2. Import Theme CSS
Choose a theme and import it (this replaces the need for styles.css):
// Light theme (off-white) - includes theme variables
import '@shipshitdev/ui/themes/light';
// OR Dark theme (gray) - includes theme variables
import '@shipshitdev/ui/themes/dark';
// Note: Import only ONE theme file, not both styles.css and a theme fileNote for Tailwind v4: theme files include an @source directive so Tailwind scans the UI package and generates component utilities. If you skip the theme import, add an @source for @shipshitdev/ui/dist/**/*.{js,cjs} in your global CSS.
3. Use Components
import { Button, Card, CardHeader, CardContent } from '@shipshitdev/ui';
function App() {
return (
<Card>
<CardHeader>Welcome</CardHeader>
<CardContent>
<Button variant="primary">Click me</Button>
</CardContent>
</Card>
);
}That's it! Your components are ready to use and look great out of the box.
Theme Switching
You can switch themes programmatically:
import { setTheme, getTheme, initTheme } from '@shipshitdev/ui';
// Initialize theme on app load
initTheme();
// Switch themes
setTheme('dark'); // or 'light'
// Get current theme
const currentTheme = getTheme();Setup
1. Install dependencies
bun run pre:installThis command updates all dependencies to their latest versions and runs the build.
2. Development
Start the Storybook development server:
bun devThis launches Storybook at http://localhost:6006 where you can preview and develop components.
Scripts
| Command | Description |
| ------------------------- | -------------------------------------- |
| bun dev | Start Storybook development server |
| bun run build | Build the library for production |
| bun run build-storybook | Build Storybook for deployment |
| bun run build:lib | Build only the JS/TS bundle |
| bun run build:css | Build only the CSS bundle |
| bun run pre:install | Update dependencies and rebuild |
| bun run prepare:deploy | Format, lint, and build for deployment |
| bun run format:check | Check code formatting |
| bun run format:fix | Fix code formatting |
| bun run lint:check | Check for linting errors |
| bun run lint:fix | Fix linting errors |
| bun test | Run tests |
| bun run typecheck | Run TypeScript type checking |
Usage
import { Button, Card, CardHeader, CardContent } from '@shipshitdev/ui';
import '@shipshitdev/ui/styles.css';
function App() {
return (
<Card>
<CardHeader>Welcome</CardHeader>
<CardContent>
<Button variant="primary" size="md">
Click me
</Button>
</CardContent>
</Card>
);
}Customization
The library provides multiple ways to customize components to match your design system. All components accept a className prop that merges seamlessly with existing styles.
Method 1: CSS Variables (Global Theming)
The easiest way to customize colors globally is by overriding CSS variables. This affects all components using those color tokens.
Example: Customize Button Primary Color
/* In your global CSS file (e.g., globals.css, app.css) */
:root {
/* Change primary color to green */
--primary: 142 76% 36%;
--primary-foreground: 0 0% 100%;
/* Or use any color you want */
--primary: 262 83% 58%; /* Purple */
--primary: 0 72% 51%; /* Red */
--primary: 217 91% 60%; /* Blue */
}All buttons with variant="primary" will now use your custom color:
<Button variant="primary">My Custom Green Button</Button>Available CSS Variables:
:root {
/* Background & Text */
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
/* Primary Colors */
--primary: 199.1 89.1% 48.2%;
--primary-foreground: 210 40% 98%;
/* Secondary Colors */
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
/* Accent Colors */
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
/* Destructive (Error) Colors */
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
/* Muted Colors */
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
/* Borders & Inputs */
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 199.1 89.1% 48.2%;
/* Card Colors */
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
/* Popover Colors */
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
/* Border Radius */
--radius: 0.5rem;
}Method 2: Component-Specific Customization (className)
For one-off customizations, use the className prop to override styles:
<Button
variant="primary"
className="bg-purple-500 hover:bg-purple-600 text-white"
>
Custom Purple Button
</Button>
<Button
variant="outline"
className="border-2 border-pink-500 text-pink-600 hover:bg-pink-50"
>
Custom Pink Outline Button
</Button>Method 3: Create Custom Theme File
For a complete custom theme, create your own SCSS file:
For Tailwind CSS v4:
/* my-custom-theme.scss */
@use 'tailwindcss';
@use '@shipshitdev/ui/themes/dark.scss' as *;
:root {
--primary: 142 76% 36%; /* Your brand green */
--primary-foreground: 0 0% 100%;
--secondary: 210 20% 96%;
--secondary-foreground: 222.2 47.4% 11.2%;
/* ... define all your colors */
--radius: 0.75rem; /* Custom border radius */
}
@theme {
/* Map your custom variables to Tailwind */
--color-primary: hsl(var(--primary));
--color-primary-foreground: hsl(var(--primary-foreground));
--color-secondary: hsl(var(--secondary));
--color-secondary-foreground: hsl(var(--secondary-foreground));
/* ... map all your custom variables ... */
}
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}Then import it instead of the default theme:
import './my-custom-theme.scss';For Tailwind CSS v3 (legacy):
/* my-custom-theme.css */
@import 'tailwindcss';
:root {
--primary: 142 76% 36%; /* Your brand green */
--primary-foreground: 0 0% 100%;
--secondary: 210 20% 96%;
--secondary-foreground: 222.2 47.4% 11.2%;
/* ... define all your colors */
--radius: 0.75rem; /* Custom border radius */
}
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}Then import it:
import './my-custom-theme.css';Method 4: Tailwind Config Override
You can also extend colors in your tailwind.config.ts:
import type { Config } from 'tailwindcss';
export default {
presets: [require('@shipshitdev/ui/tailwind.preset')],
theme: {
extend: {
colors: {
// Override or extend colors
primary: {
DEFAULT: '#10b981', // Your custom green
foreground: '#ffffff',
},
},
},
},
} satisfies Config;Dark Mode Customization
Dark mode is supported via the dark class on your HTML element. Customize dark mode colors:
.dark {
--primary: 142 76% 50%; /* Lighter green for dark mode */
--background: 222.2 47.4% 11.2%;
--foreground: 210 40% 98%;
/* ... */
}Examples: Button Color Customization
Change all primary buttons to green:
:root {
--primary: 142 76% 36%;
--primary-foreground: 0 0% 100%;
}Change a single button:
<Button className="bg-green-500 hover:bg-green-600">Green Button</Button>Create a custom variant:
<Button
variant="outline"
className="border-green-500 text-green-600 hover:bg-green-50"
>
Green Outline
</Button>Components
Primitives
- Avatar - User avatar with image and fallback
- Badge - Status indicators and labels
- Button - Interactive buttons with variants and asChild support
- Card - Container component with header, content, and footer
- Checkbox - Accessible checkbox with Radix UI
- Input - Text input fields with icon support
- Label - Form labels
- Progress - Progress indicator
- RadioGroup - Radio button groups
- Select - Accessible dropdown select with Radix UI
- Separator - Visual separator
- Skeleton - Loading placeholder
- Slider - Range slider input
- Switch - Toggle switch
- Textarea - Multi-line text input
Composites
- Alert - Alert messages with variants
- Dialog - Modal dialogs
- DropdownMenu - Dropdown menus with submenus
- Popover - Popover overlays
- Table - Table components (Header, Body, Row, Cell, etc.)
- Tabs - Tab navigation
- Tooltip - Tooltip overlays
Patterns
- DataTable - Advanced data table with sorting, filtering, pagination, and action buttons
DataTable Usage
The DataTable component accepts arrays for columns and rows, making it easy to display dynamic data with action buttons:
import { DataTable } from '@shipshitdev/ui';
import { DropdownMenu, DropdownMenuItem } from '@shipshitdev/ui';
import type { ColumnDef } from '@tanstack/react-table';
interface User {
id: string;
name: string;
email: string;
role: string;
}
const columns: ColumnDef<User>[] = [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'email',
header: 'Email',
},
{
accessorKey: 'role',
header: 'Role',
},
{
id: 'actions',
cell: ({ row }) => {
const user = row.original;
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost">Actions</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={() => editUser(user.id)}>
Edit
</DropdownMenuItem>
<DropdownMenuItem onClick={() => deleteUser(user.id)}>
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
const users: User[] = [
{ id: '1', name: 'John Doe', email: '[email protected]', role: 'Admin' },
{ id: '2', name: 'Jane Smith', email: '[email protected]', role: 'User' },
];
function UsersTable() {
return (
<DataTable
columns={columns}
data={users}
searchable
searchPlaceholder="Search users..."
pagination
/>
);
}The DataTable supports:
- Array-based columns: Define columns as an array of
ColumnDefobjects - Array-based data: Pass your data as an array
- Action buttons: Add action columns with custom cell renderers
- Search: Built-in global search functionality
- Sorting: Click column headers to sort
- Pagination: Automatic pagination controls
- TypeScript: Full type safety with generics
Tech Stack
- React 19 - UI framework
- TypeScript 5.9 - Type safety
- Tailwind CSS 4 - Utility-first CSS
- Radix UI - Accessible component primitives
- TanStack Table - Powerful table functionality
- class-variance-authority - Variant management
- Vite 7 - Build tool
- Storybook 10 - Component development
- Bun - Package manager and runtime
Project Structure
src/
├── components/
│ ├── primitives/ # Base UI components
│ │ ├── Avatar/
│ │ ├── Badge/
│ │ ├── Button/
│ │ ├── Card/
│ │ ├── Checkbox/
│ │ ├── Input/
│ │ ├── Label/
│ │ ├── Progress/
│ │ ├── RadioGroup/
│ │ ├── Select/
│ │ ├── Separator/
│ │ ├── Skeleton/
│ │ ├── Slider/
│ │ ├── Switch/
│ │ └── Textarea/
│ ├── composites/ # Composed components
│ │ ├── Alert/
│ │ ├── Dialog/
│ │ ├── DropdownMenu/
│ │ ├── Popover/
│ │ ├── Table/
│ │ ├── Tabs/
│ │ └── Tooltip/
│ └── patterns/ # Complex patterns
│ └── DataTable/
├── styles/
│ └── globals.scss # Tailwind CSS entry point
├── utils/
│ └── cn.ts # Class name utility
└── index.ts # Public exportsStorybook
This project uses Storybook for component development and documentation. All components have corresponding .stories.tsx files that demonstrate their usage, variants, and interactive examples.
Viewing Storybook
- Local Development: Run
bun devto start Storybook athttp://localhost:6006 - Online: View the deployed Storybook at https://shipshitdev.github.io/ui/ (automatically deployed on push to main)
Storybook Features
- Interactive component playground
- All component variants and states
- Code examples for each component
- Auto-generated documentation
- Dark mode support
GitHub Pages Deployment
Storybook is automatically deployed to GitHub Pages on every push to the main branch via GitHub Actions. The workflow:
- Builds Storybook using
bun run build-storybook - Deploys the static build to the
gh-pagesbranch - Makes it available at https://shipshitdev.github.io/ui/
License
MIT
