UI Components
ShipKit provides a comprehensive UI component library built on top of Shadcn/UI and Tailwind CSS . Our components are designed for accessibility, performance, and developer experience.
Core Components
Interactive Elements
import { Button } from "@/components/ui/button"
import { ButtonExtended } from "@/components/ui/button-extended"
import { RainbowButton } from "@/components/ui/rainbow-button"
import { ShinyButton } from "@/components/ui/shiny-button"
import { ShimmerButton } from "@/components/ui/shimmer-button"
// Basic button with variants
<Button variant="default">Click me</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
// Extended button with additional features
<ButtonExtended loading={true}>Loading...</ButtonExtended>
// Animated buttons
<RainbowButton>Rainbow Effect</RainbowButton>
<ShinyButton>Shiny Effect</ShinyButton>
<ShimmerButton>Shimmer Effect</ShimmerButton>
Form Components
import { Form } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { InputHover } from "@/components/ui/input-hover"
import { InputOTP } from "@/components/ui/input-otp"
import { Textarea } from "@/components/ui/textarea"
import { Select } from "@/components/ui/select"
import { Checkbox } from "@/components/ui/checkbox"
import { RadioGroup } from "@/components/ui/radio-group"
import { Switch } from "@/components/ui/switch"
import { Slider } from "@/components/ui/slider"
import { TimeInput } from "@/components/ui/time-input"
import { DateRangePicker } from "@/components/ui/date-range-picker"
// Form with validation
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
})
<Form {...form}>
<Input type="text" placeholder="Enter text" />
<InputHover placeholder="Hover effect input" />
<InputOTP value="123456" />
<Textarea placeholder="Enter long text" />
<Select>
<SelectTrigger>
<SelectValue placeholder="Select option" />
</SelectTrigger>
<SelectContent>
<SelectItem value="1">Option 1</SelectItem>
<SelectItem value="2">Option 2</SelectItem>
</SelectContent>
</Select>
<Checkbox>Remember me</Checkbox>
<RadioGroup>
<RadioGroupItem value="1">Option 1</RadioGroupItem>
<RadioGroupItem value="2">Option 2</RadioGroupItem>
</RadioGroup>
<Switch />
<Slider defaultValue={[50]} max={100} step={1} />
<TimeInput />
<DateRangePicker />
</Form>
Navigation Components
import { NavigationMenu } from "@/components/ui/navigation-menu"
import { Menubar } from "@/components/ui/menubar"
import { DropdownMenu } from "@/components/ui/dropdown-menu"
import { ContextMenu } from "@/components/ui/context-menu"
import { Breadcrumb } from "@/components/ui/breadcrumb"
import { BreadcrumbNav } from "@/components/ui/breadcrumb-nav"
import { SidebarNav } from "@/components/ui/sidebar-nav"
import { NavLink } from "@/components/ui/nav-link"
import { Pagination } from "@/components/ui/pagination"
// Navigation menu
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Item 1</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Subitem 1</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
// Breadcrumb navigation
<BreadcrumbNav items={[
{ title: "Home", href: "/" },
{ title: "Features", href: "/features" }
]} />
// Sidebar navigation
<SidebarNav items={[
{ title: "Dashboard", href: "/dashboard" },
{ title: "Settings", href: "/settings" }
]} />
Data Display
import { Table, DataTable } from "@/components/ui/data-table"
import { Card } from "@/components/ui/card"
import { Card3D } from "@/components/ui/card-3d"
import { CardSpotlight } from "@/components/ui/card-spotlight"
import { NeonGradientCard } from "@/components/ui/neon-gradient-card"
import { ProfileCard } from "@/components/ui/profile-card"
import { Chart } from "@/components/ui/chart"
import { Progress } from "@/components/ui/progress"
import { NumberTicker } from "@/components/ui/number-ticker"
// Data table with sorting and filtering
<DataTable
columns={columns}
data={data}
searchKey="name"
pagination
/>
// Interactive cards
<Card3D>
<CardContent>3D hover effect</CardContent>
</Card3D>
<CardSpotlight>
<CardContent>Spotlight hover effect</CardContent>
</CardSpotlight>
// Charts and data visualization
<Chart
type="line"
data={chartData}
options={chartOptions}
/>
// Progress indicators
<Progress value={75} />
<NumberTicker value={1234} />
Dialog and Overlays
import { Dialog } from "@/components/ui/dialog"
import { Sheet } from "@/components/ui/sheet"
import { Drawer } from "@/components/ui/drawer"
import { HoverCard } from "@/components/ui/hover-card"
import { Popover } from "@/components/ui/popover"
import { Tooltip } from "@/components/ui/tooltip"
import { ResponsiveDialog } from "@/components/ui/responsive-dialog"
import { FeedbackDialog } from "@/components/ui/feedback-dialog"
// Dialog
<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Dialog content goes here</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
// Responsive dialog that switches to drawer on mobile
<ResponsiveDialog>
<DialogContent>Responsive content</DialogContent>
</ResponsiveDialog>
// Feedback dialog with form
<FeedbackDialog>
<Button>Send Feedback</Button>
</FeedbackDialog>
Loading States
import { Loading } from "@/components/ui/loading"
import { Skeleton } from "@/components/ui/skeleton"
import { LoaderAtoms } from "@/components/ui/loaders/loader-atoms"
import { LoaderLines } from "@/components/ui/loaders/loader-lines"
import { LoaderTetris } from "@/components/ui/loaders/loader-tetris"
import { LoaderBouncingShapes } from "@/components/ui/loaders/loader-bouncing-shapes"
// Simple loading spinner
<Loading />
// Content placeholder
<Skeleton className="h-12 w-12 rounded-full" />
// Animated loaders
<LoaderAtoms />
<LoaderLines />
<LoaderTetris />
<LoaderBouncingShapes />
Visual Effects
import { Sparkles } from "@/components/ui/sparkles"
import { SparklesText } from "@/components/ui/sparkles-text"
import { ShootingStars } from "@/components/ui/shooting-stars"
import { Meteors } from "@/components/ui/meteors"
import { Particles } from "@/components/ui/particles"
import { Vortex } from "@/components/ui/vortex"
import { WavyLine } from "@/components/ui/wavy-line"
import { BorderBeam } from "@/components/ui/border-beam"
import { Spotlight } from "@/components/ui/spotlight"
import { DotPattern } from "@/components/ui/dot-pattern"
import { RetroGrid } from "@/components/ui/retro-grid"
import { CanvasRevealEffect } from "@/components/ui/canvas-reveal-effect"
// Text effects
<SparklesText>Sparkly Text</SparklesText>
// Background effects
<ShootingStars />
<Meteors />
<Particles />
<Vortex />
// Border and spotlight effects
<BorderBeam />
<Spotlight />
// Pattern backgrounds
<DotPattern />
<RetroGrid />
// Canvas effects
<CanvasRevealEffect />
Extended Components
import { MultiSelect } from "@/components/ui/expansions/multi-select"
import { DatePicker } from "@/components/ui/expansions/date-picker"
import { AutosizeTextarea } from "@/components/ui/expansions/autosize-textarea"
import { FloatingLabelInput } from "@/components/ui/expansions/floating-label-input"
import { DualRangeSlider } from "@/components/ui/expansions/dual-range-slider"
import { InfiniteScroll } from "@/components/ui/expansions/infinite-scroll"
import { ProgressWithValue } from "@/components/ui/expansions/progress-with-value"
import { ResponsiveModal } from "@/components/ui/expansions/responsive-modal"
import { HeadingWithAnchor } from "@/components/ui/expansions/heading-with-anchor"
// Enhanced select with multiple selection
<MultiSelect
options={options}
value={selected}
onChange={setSelected}
/>
// Enhanced date picker
<DatePicker
selected={date}
onChange={setDate}
/>
// Auto-resizing textarea
<AutosizeTextarea
placeholder="Type something..."
maxRows={5}
/>
// Input with floating label
<FloatingLabelInput
label="Email"
type="email"
/>
// Dual range slider
<DualRangeSlider
min={0}
max={100}
onChange={handleChange}
/>
// Infinite scroll container
<InfiniteScroll
items={items}
loadMore={loadMoreItems}
hasMore={hasMoreItems}
/>
Component Registry
To add new Shadcn components:
# Add a single component
pnpm ui:add button
# Add multiple components
pnpm ui:add button card input
# Configure component options
pnpm ui:add table --template=data-table
Best Practices
Component Usage
Import from UI Directory
// ✅ Import from UI directory
import { Button } from "@/components/ui/button"
// ❌ Don't import from node_modules
import { Button } from "@shadcn/ui"
Use TypeScript
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: "default" | "destructive" | "outline"
size?: "default" | "sm" | "lg"
}
Implement Proper Loading States
<Button disabled={isLoading}>
{isLoading ? (
<>
<Loading className="mr-2 h-4 w-4" />
Please wait
</>
) : (
"Click me"
)}
</Button>
Handle Errors Gracefully
<Form onSubmit={async (data) => {
try {
await submitData(data)
} catch (error) {
toast({
title: "Error",
description: "Something went wrong",
variant: "destructive"
})
}
}}>
Performance
Lazy Loading
const HeavyComponent = dynamic(() => import("@/components/heavy-component"), {
loading: () => <Loading />,
ssr: false
})
Memoization
const MemoizedComponent = memo(({ data }) => {
return <div>{/* Complex rendering */}</div>
})
Virtualization
<DataTable
data={largeDataset}
virtualization={{
enabled: true,
rowHeight: 40
}}
/>
Accessibility
ARIA Labels
<Button
aria-label="Close dialog"
onClick={closeDialog}
>
<XIcon className="h-4 w-4" />
</Button>
Keyboard Navigation
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>
Item 1
</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink
href="/item-1"
onKeyDown={handleKeyDown}
>
Subitem 1
</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
Focus Management
const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(
({ children, ...props }, ref) => {
const closeRef = useRef<HTMLButtonElement>(null)
useEffect(() => {
closeRef.current?.focus()
}, [])
return (
<div ref={ref} role="dialog" aria-modal="true" {...props}>
{children}
<button ref={closeRef}>Close</button>
</div>
)
}
)
Styling
Use Tailwind Classes
<div className={cn(
"rounded-lg border bg-card p-4 text-card-foreground shadow-sm",
"hover:bg-accent hover:text-accent-foreground",
"dark:bg-card-dark dark:text-card-dark-foreground",
className
)}>
Theme Variables
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
brand: {
50: "rgb(var(--brand-50) / <alpha-value>)",
// ... other shades
}
}
}
}
}
Responsive Design
<div className="
grid
grid-cols-1
gap-4
sm:grid-cols-2
md:grid-cols-3
lg:grid-cols-4
">
Notes
All components are server-side rendering compatible
Components support dark mode through Tailwind classes
Visual effects are optimized for performance
Documentation is auto-generated from source
Components are tested for accessibility compliance
Regular updates from Shadcn/UI are incorporated