shadcn-vue

repository·dev·Indexed 27 days ago

https://github.com/unovue/shadcn-vue

A set of customizable and extensible UI components for Vue and Nuxt developers, serving as a port of shadcn/ui. Powered by headless libraries like Reka UI, it includes a CLI for scaffolding projects via `shadcn-vue create` and initializing existing ones via `shadcn-vue init`. It offers multiple visual styles (Vega, Nova, Maia, Lyra, Mira) and a dedicated Nuxt module called `shadcn-nuxt`.

Tokens
138.8K
Snippets
421
Records
735
Agent score
93%

What's inside shadcn-vue

  1. Overview of shadcn-vue with Tailwind v4

    dev

    shadcn-vue now supports Tailwind v4. Key updates include:

    • CLI Support: The CLI can initialize projects directly with Tailwind v4.
    • Theme Support: Full support for the @theme directive and @theme inline option.
    • Component Updates: All components are updated for Tailwind v4, featuring a data-slot attribute on every primitive for easier styling.
    • Styling Improvements: Component styles have been cleaned up, and HSL colors are now converted to OKLCH.
    • Deprecations:
      • The toast component is being deprecated in favor of sonner.
      • The default style is being deprecated; new projects will use the new-york style.
    • Behavioral Changes: Buttons now use the default cursor.

    Note: This is a non-breaking update. Existing apps using Tailwind v3 will continue to work. New components added to a v3 project will remain in v3 until the project is upgraded.

  2. Build forms with VeeValidate and Zod

    dev

    The Form component is an abstraction over vee-validate. While the <Form /> component is available, it is recommended to use the useForm composable from vee-validate because it provides automatic type safety for form values.

    Note: The Form component is no longer actively being developed. For future implementations, it is recommended to use the <Field /> component directly.

  3. Use shadcn MCP Tools for Registry Operations

    dev

    The MCP server provides several tools for interacting with component registries.

    Note: MCP tools are specifically for registry operations (search, view, install). For project configuration tasks like checking aliases, framework, or Tailwind version, use the CLI command npx shadcn-vue@latest info instead, as there is no MCP equivalent for configuration inspection.

  4. Understand the shadcn-vue approach

    dev

    shadcn-vue is not a traditional NPM component library. Instead, it is a code distribution platform and a method for building your own component library. Unlike standard libraries where you import pre-packaged components, shadcn-vue provides you with the actual component source code. This allows for:

    • Full Customization: You can edit the component code directly to fit your design system instead of using workarounds or wrappers.
    • Transparency: You have full visibility into how every component is constructed.
    • Predictable Composition: Components share a common, composable interface, making them predictable for developers and AI models.
    • AI-Readiness: Because the code is open and follows a consistent pattern, LLMs can easily read, understand, and generate or improve components within your project.
  5. Understand the Sidebar component structure

    dev

    The Sidebar component is built using a composition pattern. It consists of the following sub-components:

    • SidebarProvider: Manages the collapsible state and context.
    • Sidebar: The main container.
    • SidebarHeader: Sticky top section.
    • SidebarFooter: Sticky bottom section.
    • SidebarContent: The scrollable area for content.
    • SidebarGroup: A logical section within SidebarContent.
    • SidebarTrigger: The component used to toggle the sidebar visibility.
    • SidebarRail: A component for interaction/visuals (often used for resizing or visual cues).
  6. Understand the shadcn-vue styling architecture

    dev

    Styles in this repository are implemented using a token-based system. A 'style' is defined in a single CSS file (e.g., apps/v4/registry/styles/style-{name}.css) that maps cn-* placeholder tokens to expanded Tailwind utility classes. These tokens are authored in the base component set (e.g., apps/v4/registry/bases/reka/ui/**).

    How styles are applied:

    1. Build Time: The buildStyles() script transforms base components by replacing cn-* tokens with their actual Tailwind expansions. This produces build artifacts in apps/v4/styles/reka-{name}/ui/** and registry JSON files in apps/v4/public/r/styles/reka-{name}/*.json for CLI installation.
    2. Runtime: The assets/css/main.css file imports style files under layer(base). Applying a class like .style-{name} to a DOM element allows it to render that specific style live (used by the customizer preview).
  7. Understand the shadcn-vue Skill capabilities

    dev

    The shadcn-vue skill provides AI assistants with several layers of project knowledge:

    • Project Context: Automatically retrieves configuration via shadcn-vue info --json (framework, Tailwind version, aliases, base library like reka, icon library, and installed components).
    • CLI Command Reference: Knowledge of all commands including init, add, search, view, docs, diff, info, and build, including flags and presets.
    • Theming and Customization: Guidance on CSS variables, OKLCH colors, dark mode, custom colors, border radius, and component variants for both Tailwind v3 and v4.
    • Registry Authoring: Instructions for building and publishing custom registries using the registry.json format.
    • MCP Server: Tools for AI assistants to search, browse, and install components directly from registries.
  8. Understand shadcn-vue Theming Architecture

    dev

    shadcn-vue uses a three-layer system for theming:

    1. CSS Variables: Defined in :root (light mode) and .dark (dark mode).
    2. Tailwind Utilities: Tailwind maps these variables to utility classes like bg-primary or text-muted-foreground.
    3. Components: Components consume these Tailwind utilities. Changing a CSS variable automatically updates all components referencing it.

    Colors use the OKLCH format: --variable: oklch(lightness chroma hue) (e.g., --primary: oklch(0.205 0 0)).

  9. Configure Field orientation and responsiveness

    dev

    The Field component supports three orientation modes via the orientation prop:

    • vertical (default): Stacks label, control, and helper text vertically.
    • horizontal: Aligns the label and control side-by-side. Use FieldContent to keep descriptions aligned when using this mode.
    • responsive: Automatically switches layouts based on container size.

    Note for Responsive Layouts: If using Tailwind CSS v3, you must install @tailwindcss/container-queries. To enable responsive switching, apply @container/field-group classes to the FieldGroup component.

    <Field orientation="horizontal">
      <FieldLabel for="remember">Remember me</FieldLabel>
      <Switch id="remember" />
    </Field>
    
    <template>
      <FieldGroup class="@container/field-group flex flex-col gap-6">
        <Field><!-- Fields --></Field>
      </FieldGroup>
    </template>
  10. Use the MessageScroller component

    dev

    The MessageScroller is a headless scroll container designed for chat transcripts. It manages complex scrolling behaviors like anchoring turns, following streamed replies, and preserving position when history is prepended.

    Note: The MessageScrollerProvider must have a constrained height (or a height-bounded parent) so the viewport can scroll.

    Composition Structure:

    MessageScrollerProvider
    └── MessageScroller
        ├── MessageScrollerViewport
        │   └── MessageScrollerContent
        │       └── MessageScrollerItem
        └── MessageScrollerButton
    <script setup lang="ts">
    import {
      MessageScroller,
      MessageScrollerButton,
      MessageScrollerContent,
      MessageScrollerItem,
      MessageScrollerProvider,
      MessageScrollerViewport,
    } from '@/components/ui/message-scroller'
    </script>
    
    <template>
      <MessageScrollerProvider auto-scroll default-scroll-position="last-anchor">
        <MessageScroller>
          <MessageScrollerViewport>
            <MessageScrollerContent>
              <MessageScrollerItem
                v-for="message in messages"
                :key="message.id"
                :message-id="message.id"
                :scroll-anchor="message.role === 'user'"
              >
                <!-- Message / Bubble / Marker goes here -->
              </MessageScrollerItem>
            </MessageScrollerContent>
          </MessageScrollerViewport>
          <MessageScrollerButton direction="end" />
        </MessageScroller>
      </MessageScrollerProvider>
    </template>