Starting Point UI: Shadcn/ui-Style Tailwind Components

Add shadcn/ui-style components to any Tailwind project through semantic classes, theme variables, and optional vanilla JS.

Starting Point UI is an open-source Tailwind CSS v4+ component library that adds the shadcn/ui design system to React, Vue, Angular, Laravel, Rails, Django, and plain HTML.

Its semantic classes define the UI, and a small vanilla JavaScript module handles interactive components.

Features

  • WAI-ARIA patterns, keyboard navigation, and focus management for interactive controls.
  • shadcn/ui-compatible CSS variables for colors, radius, and typography.
  • Light and dark color schemes.
  • RTL behavior across the component library.
  • Component-level styling through Tailwind utilities and custom @utility rules.

UI Components Included

CategoryComponents
ActionsButton, Button Group
Forms and inputsCalendar, Checkbox, Combobox, Date Picker, Field, Forms, Input, Input Group, Label, Radio Group, Select, Slider, Switch, Textarea
Navigation and commandsBreadcrumb, Command, Context Menu, Dropdown, Pagination, Sidebar, Tabs
Overlays and disclosureAccordion, Collapsible, Dialog, Drawer, Popover, Sheet, Tooltip
Feedback and statusAlert, Badge, Empty, Progress, Shimmer, Skeleton, Toast
Content and dataAvatar, Bubble, Card, Item, Kbd, Marker, Message, Message Scroller, Table
Layout and scrollingCarousel, Resizable, Scroll Fade, Scrollbar, Separator

How to Use Starting Point UI

Install the Package

npm install starting-point-ui

Import the Styles

Add Starting Point UI after Tailwind in the main stylesheet:

@import "tailwindcss";
@import "starting-point-ui";

Add a Static Component

Static components need no JavaScript.

<button class="btn btn-primary" type="button">
  Save changes
</button>

Load JavaScript for Interactive Components

For a bundler:

import "starting-point-ui";

For a browser module:

<script
  src="https://cdn.jsdelivr.net/npm/starting-point-ui"
  type="module"
></script>

Next.js App Router Setup

Run the component JavaScript on the client after the DOM is ready:

"use client";
import { useEffect } from "react";
export function StartingPointUI() {
  useEffect(() => {
    import("starting-point-ui");
  }, []);
  return null;
}

Mount the loader from the root layout:

import { StartingPointUI } from "@/components/starting-point-ui";
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <StartingPointUI />
      </body>
    </html>
  );
}

Basic Usage: Dialog Component

<button
  id="settings-trigger"
  class="btn btn-outline"
  type="button"
>
  Open settings
</button>
<dialog
  id="settings-dialog"
  class="dialog"
  data-sp-toggle="#settings-trigger"
>
  <div class="dialog-panel">
    <div class="dialog-header">
      <h2 class="dialog-title">Account settings</h2>
      <p class="dialog-description">
        Update your account preferences.
      </p>
    </div>
    <div class="dialog-content">
      <div class="field">
        <label class="label" for="display-name">
          Display name
        </label>
        <input
          class="input"
          id="display-name"
          name="display-name"
        />
      </div>
    </div>
    <div class="dialog-footer">
      <button
        class="btn btn-outline"
        type="button"
        data-sp-dismiss
      >
        Cancel
      </button>
      <button
        class="btn"
        type="button"
        data-sp-dismiss
      >
        Save
      </button>
    </div>
  </div>
</dialog>

Styling and Theming

Starting Point UI uses the CSS variables from shadcn/ui themes. You can override theme values after the library import:

@import "tailwindcss";
@import "starting-point-ui";
:root {
  --primary: oklch(0.55 0.2 250);
  --primary-foreground: oklch(1 0 0);
  --ring: oklch(0.55 0.2 250);
}

Change an individual instance with normal Tailwind utilities:

<button class="btn rounded-full">
  Rounded Button
</button>

Restyle a component class throughout the project:

@utility btn {
  @apply rounded-full;
}

RTL

Set dir="rtl" on the root element or an individual container:

<html dir="rtl">

Inline Component Events

Experimental data-sp-on-* attributes run JavaScript when Starting Point UI component events fire:

<dialog
  class="dialog"
  data-sp-toggle="#settings-trigger"
  data-sp-on-shown="console.log('Dialog opened')"
>
  ...
</dialog>

The attribute receives event and el, and the global sp API is available inside the expression.

Inline event expressions use the JavaScript Function constructor. A strict Content Security Policy requires unsafe-eval in script-src for these attributes. Never interpolate untrusted data into a data-sp-on-* value.

Related Resources

gufodotdev

gufodotdev

Leave a Reply

Your email address will not be published. Required fields are marked *