pangolin-components
v1.0.1
Published
A fully-customisable React component library built on shadcn/ui, Radix UI, and Tailwind CSS — with a CLI for selective component installation.
Maintainers
Readme
pangolin-components
A fully-customisable React component library built on shadcn/ui, Radix UI, and Tailwind CSS — with a CLI for selective component installation.
Non-Commercial Open Source — Free for non-commercial use. Contact for commercial licensing.
Features
- 43 production-ready components from shadcn/ui
- Accessible by default (Radix UI primitives + ARIA)
- Fully typed TypeScript
- Dark mode support via CSS variables
- CLI to copy component source into your project
- Storybook documentation
- Jest unit tests + Playwright e2e tests
Documentation
Full interactive docs: https://johannesmerwe.github.io/pangolin-components
Installation
npm install pangolin-componentsPeer dependencies
npm install react react-dom tailwindcssSetup
1. Configure Tailwind
Add the pangolin preset to your tailwind.config.js:
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [require('pangolin-components/tailwind')],
content: [
'./src/**/*.{ts,tsx}',
'./node_modules/pangolin-components/dist/**/*.{js,cjs}',
],
}2. Import the global styles
In your app entry file (e.g. main.tsx, _app.tsx, layout.tsx):
import 'pangolin-components/styles.css'3. Use components
import { Button, Dialog, DialogTrigger, DialogContent, DialogTitle } from 'pangolin-components'
export default function App() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogTitle>Hello, Pangolin!</DialogTitle>
</DialogContent>
</Dialog>
)
}CLI — Add component source to your project
The CLI copies component source files from the package directly into your project, so you can customise them freely.
# Add a single component
npx pangolin add button
# Add multiple components
npx pangolin add button dialog input
# Add all components interactively
npx pangolin add
# Add all components at once
npx pangolin add --all
# Specify output directory (default: ./src/components/ui)
npx pangolin add button --output ./components/ui
# Overwrite existing files
npx pangolin add button --overwriteAfter adding a component with the CLI, import it from your local copy instead of the package.
Components
| Component | Description | Docs | |---|---|---| | Accordion | Vertically stacked sections that expand/collapse to reveal content | Docs | | Alert | Displays a callout for important messages, warnings, or errors | Docs | | Alert Dialog | A modal dialog that interrupts the user with important content requiring a decision | Docs | | Aspect Ratio | Displays content within a desired ratio, maintaining consistent proportions | Docs | | Avatar | An image element with a fallback for representing the user | Docs | | Badge | Displays a small status indicator or label on top of or near other elements | Docs | | Breadcrumb | Shows the current page's location within a navigational hierarchy | Docs | | Button | Triggers an action or event, such as submitting a form or opening a dialog | Docs | | Calendar | A date field component that allows users to enter and edit date values | Docs | | Card | Displays content in a contained, bordered box with a header, body, and footer | Docs | | Carousel | A slideshow component for cycling through content items with controls | Docs | | Chart | Composable chart components built on top of Recharts | Docs | | Checkbox | A control that allows the user to toggle between checked and unchecked states | Docs | | Collapsible | An interactive component that expands/collapses a panel | Docs | | Command | A fast, composable command menu and keyboard shortcut interface | Docs | | Context Menu | Displays a menu to the user — such as a set of actions — triggered by a right-click | Docs | | Dialog | A window overlaid on the page, rendering content that requires user interaction | Docs | | Drawer | A panel that slides in from the edge of the screen, built on Vaul | Docs | | Dropdown Menu | Displays a menu when the user interacts with a trigger button | Docs | | Form | Building accessible forms with validation, powered by React Hook Form and Zod | Docs | | Hover Card | Shows a preview card when the user hovers over a trigger element | Docs | | Input | A text input field for capturing user data | Docs | | Label | Renders an accessible label associated with a form control | Docs | | Menubar | A visually persistent menu common in desktop applications | Docs | | Navigation Menu | A collection of links for navigating websites, with keyboard support | Docs | | Popover | Displays rich content in a portal, triggered by a button | Docs | | Progress | Displays an indicator showing the completion progress of a task | Docs | | Radio Group | A set of checkable buttons where only one can be checked at a time | Docs | | Resizable | Accessible resizable panel groups and layouts via react-resizable-panels | Docs | | Scroll Area | Augments native scroll functionality for custom, cross-browser styling | Docs | | Select | Displays a list of options for the user to pick from — triggered by a button | Docs | | Separator | Visually or semantically separates content | Docs | | Sheet | Extends the Dialog component to display content that complements the main content | Docs | | Skeleton | A placeholder preview that approximates the layout of the content being loaded | Docs | | Slider | An input where the user selects a value from within a given range | Docs | | Sonner | An opinionated toast component built on Sonner | Docs | | Switch | A control that allows the user to toggle between on and off states | Docs | | Table | A responsive table component with full accessibility support | Docs | | Tabs | A set of layered sections of content, known as tab panels | Docs | | Textarea | A multi-line text input control | Docs | | Toast | A succinct message that is displayed temporarily, with action support | Docs | | Toggle | A two-state button that can be either on or off | Docs | | Toggle Group | A set of two-state buttons that can be toggled on or off | Docs | | Tooltip | A popup that displays information related to an element when it receives focus or is hovered | Docs |
Dark Mode
All components respect the CSS variables defined in the global styles. Toggle dark mode by adding the .dark class to your <html> element:
document.documentElement.classList.toggle('dark')Or use next-themes for Next.js:
npm install next-themes// app/layout.tsx (Next.js App Router)
import { ThemeProvider } from 'next-themes'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
</body>
</html>
)
}Development
# Install dependencies
npm install
# Start Storybook
npm run storybook
# Run unit tests
npm test
# Run e2e tests (requires Storybook running on :6006)
npm run test:e2e
# Build the library
npm run build
# Build the CLI
npm run build:cli
# Type-check
npm run typecheckLicense
PolyForm Noncommercial License 1.0.0 — free for non-commercial use.
For commercial use, contact via GitHub.
Third-party components (shadcn/ui, Radix UI, Tailwind CSS) are MIT licensed — see LICENSE.
