UI Components

Building beautiful interfaces with Shadcn/UI, Tailwind CSS, and custom components in ShipKit

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

  1. 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"
    
  2. Use TypeScript

    interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
      variant?: "default" | "destructive" | "outline"
      size?: "default" | "sm" | "lg"
    }
    
  3. Implement Proper Loading States

    <Button disabled={isLoading}>
      {isLoading ? (
        <>
          <Loading className="mr-2 h-4 w-4" />
          Please wait
        </>
      ) : (
        "Click me"
      )}
    </Button>
    
  4. Handle Errors Gracefully

    <Form onSubmit={async (data) => {
      try {
        await submitData(data)
      } catch (error) {
        toast({
          title: "Error",
          description: "Something went wrong",
          variant: "destructive"
        })
      }
    }}>
    

Performance

  1. Lazy Loading

    const HeavyComponent = dynamic(() => import("@/components/heavy-component"), {
      loading: () => <Loading />,
      ssr: false
    })
    
  2. Memoization

    const MemoizedComponent = memo(({ data }) => {
      return <div>{/* Complex rendering */}</div>
    })
    
  3. Virtualization

    <DataTable
      data={largeDataset}
      virtualization={{
        enabled: true,
        rowHeight: 40
      }}
    />
    

Accessibility

  1. ARIA Labels

    <Button
      aria-label="Close dialog"
      onClick={closeDialog}
    >
      <XIcon className="h-4 w-4" />
    </Button>
    
  2. Keyboard Navigation

    <NavigationMenu>
      <NavigationMenuList>
        <NavigationMenuItem>
          <NavigationMenuTrigger>
            Item 1
          </NavigationMenuTrigger>
          <NavigationMenuContent>
            <NavigationMenuLink
              href="/item-1"
              onKeyDown={handleKeyDown}
            >
              Subitem 1
            </NavigationMenuLink>
          </NavigationMenuContent>
        </NavigationMenuItem>
      </NavigationMenuList>
    </NavigationMenu>
    
  3. 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

  1. 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
    )}>
    
  2. Theme Variables

    // tailwind.config.ts
    export default {
      theme: {
        extend: {
          colors: {
            brand: {
              50: "rgb(var(--brand-50) / <alpha-value>)",
              // ... other shades
            }
          }
        }
      }
    }
    
  3. 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