npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cimom/vben-core-shadcn-ui

v5.6.8

Published

Shadcn UI 组件是一个基于 Vue 3 的 UI 组件库,提供了丰富的基础组件和高级组件,采用了现代化的设计风格,支持主题定制和响应式设计。

Readme

Shadcn UI 组件

Shadcn UI 组件是一个基于 Vue 3 的 UI 组件库,提供了丰富的基础组件和高级组件,采用了现代化的设计风格,支持主题定制和响应式设计。

安装

npm install @cimom/vben-core-ui-kit-shadcn-ui

组件列表

Shadcn UI 组件库包含以下组件:

基础组件

  • Avatar: 头像组件
  • Button: 按钮组件
  • Checkbox: 复选框组件
  • Icon: 图标组件
  • Input: 输入框组件
  • InputPassword: 密码输入框组件
  • PinInput: PIN 码输入组件
  • Select: 选择器组件
  • Spinner: 加载中组件
  • Tooltip: 文字提示组件

导航组件

  • BackTop: 回到顶部组件
  • Breadcrumb: 面包屑导航组件
  • ContextMenu: 上下文菜单组件
  • DropdownMenu: 下拉菜单组件
  • HoverCard: 悬停卡片组件
  • Popover: 弹出框组件
  • Scrollbar: 滚动条组件
  • Segmented: 分段控制器组件

其他组件

  • CountToAnimator: 数字动画组件
  • ExpandableArrow: 可展开箭头组件
  • FullScreen: 全屏组件
  • Logo: Logo 组件
  • RenderContent: 内容渲染组件
  • SpineText: 脊柱文本组件

基础组件使用

Button 按钮

<script setup lang="ts">
import { VbenButton } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div class="space-x-2">
    <VbenButton>默认按钮</VbenButton>
    <VbenButton variant="primary">主要按钮</VbenButton>
    <VbenButton variant="destructive">危险按钮</VbenButton>
    <VbenButton variant="outline">轮廓按钮</VbenButton>
    <VbenButton variant="ghost">幽灵按钮</VbenButton>
    <VbenButton variant="link">链接按钮</VbenButton>
  </div>

  <div class="mt-4 space-x-2">
    <VbenButton size="sm">小型按钮</VbenButton>
    <VbenButton>默认大小</VbenButton>
    <VbenButton size="lg">大型按钮</VbenButton>
  </div>

  <div class="mt-4 space-x-2">
    <VbenButton loading>加载中</VbenButton>
    <VbenButton disabled>禁用按钮</VbenButton>
    <VbenButton icon="Search">带图标</VbenButton>
  </div>
</template>

Avatar 头像

<script setup lang="ts">
import { VbenAvatar } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div class="flex space-x-4">
    <VbenAvatar src="/path/to/avatar.jpg" alt="用户头像" />
    <VbenAvatar>JD</VbenAvatar>
    <VbenAvatar icon="User" />
  </div>

  <div class="mt-4 flex space-x-4">
    <VbenAvatar size="sm" src="/path/to/avatar.jpg" />
    <VbenAvatar src="/path/to/avatar.jpg" />
    <VbenAvatar size="lg" src="/path/to/avatar.jpg" />
  </div>
</template>

Input 输入框

<script setup lang="ts">
import {
  VbenInput,
  VbenInputPassword,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const username = ref('');
const password = ref('');
</script>

<template>
  <div class="space-y-4">
    <div>
      <label class="mb-1 block">用户名</label>
      <VbenInput v-model="username" placeholder="请输入用户名" />
    </div>

    <div>
      <label class="mb-1 block">密码</label>
      <VbenInputPassword v-model="password" placeholder="请输入密码" />
    </div>
  </div>
</template>

PinInput 验证码输入

<script setup lang="ts">
import { VbenPinInput } from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const pinValue = ref('');
</script>

<template>
  <div>
    <label class="mb-2 block">验证码</label>
    <VbenPinInput
      v-model="pinValue"
      :length="6"
      @complete="(value) => console.log('验证码输入完成:', value)"
    />
  </div>
</template>

Select 选择器

<script setup lang="ts">
import { VbenSelect } from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const selectedValue = ref('');
const options = [
  { label: '选项1', value: '1' },
  { label: '选项2', value: '2' },
  { label: '选项3', value: '3' },
];
</script>

<template>
  <div>
    <label class="mb-1 block">选择项</label>
    <VbenSelect
      v-model="selectedValue"
      :options="options"
      placeholder="请选择"
    />
  </div>
</template>

导航组件使用

Breadcrumb 面包屑

<script setup lang="ts">
import {
  VbenBreadcrumb,
  VbenBreadcrumbItem,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <VbenBreadcrumb>
    <VbenBreadcrumbItem>首页</VbenBreadcrumbItem>
    <VbenBreadcrumbItem>用户管理</VbenBreadcrumbItem>
    <VbenBreadcrumbItem>用户详情</VbenBreadcrumbItem>
  </VbenBreadcrumb>
</template>

DropdownMenu 下拉菜单

<script setup lang="ts">
import {
  VbenDropdownMenu,
  VbenDropdownMenuTrigger,
  VbenDropdownMenuContent,
  VbenDropdownMenuItem,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <VbenDropdownMenu>
    <VbenDropdownMenuTrigger>
      <button class="rounded border px-4 py-2">点击打开菜单</button>
    </VbenDropdownMenuTrigger>

    <VbenDropdownMenuContent>
      <VbenDropdownMenuItem @select="() => console.log('选项1')">
        选项1
      </VbenDropdownMenuItem>
      <VbenDropdownMenuItem @select="() => console.log('选项2')">
        选项2
      </VbenDropdownMenuItem>
      <VbenDropdownMenuItem @select="() => console.log('选项3')">
        选项3
      </VbenDropdownMenuItem>
    </VbenDropdownMenuContent>
  </VbenDropdownMenu>
</template>

Scrollbar 滚动条

<script setup lang="ts">
import { VbenScrollbar } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div class="h-60 w-full">
    <VbenScrollbar>
      <div class="p-4">
        <p v-for="i in 20" :key="i" class="mb-4">
          这是一段示例文本,用于演示滚动条组件。 {{ i }}
        </p>
      </div>
    </VbenScrollbar>
  </div>
</template>

BackTop 回到顶部

<script setup lang="ts">
import { VbenBackTop } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div>
    <!-- 页面内容 -->

    <VbenBackTop :visibilityHeight="100" />
  </div>
</template>

其他组件使用

CountToAnimator 数字动画

<script setup lang="ts">
import { VbenCountToAnimator } from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const value = ref(0);

// 模拟数据变化
setTimeout(() => {
  value.value = 1000;
}, 1000);
</script>

<template>
  <div>
    <h3>数字动画:</h3>
    <VbenCountToAnimator
      :value="value"
      :duration="1000"
      :decimals="0"
      prefix="¥"
    />
  </div>
</template>

FullScreen 全屏

<script setup lang="ts">
import { VbenFullScreen } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div>
    <VbenFullScreen>
      <template #default="{ toggle, isFullscreen }">
        <button @click="toggle">
          {{ isFullscreen ? '退出全屏' : '进入全屏' }}
        </button>
      </template>
    </VbenFullScreen>
  </div>
</template>

Tooltip 文字提示

<script setup lang="ts">
import { VbenTooltip } from '@cimom/vben-core-ui-kit-shadcn-ui';
</script>

<template>
  <div class="p-10">
    <VbenTooltip content="这是一个提示文本">
      <button class="rounded border px-4 py-2">鼠标悬停查看提示</button>
    </VbenTooltip>
  </div>
</template>

组件属性

Button 属性

| 属性名 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | variant | 'default' \| 'primary' \| 'destructive' \| 'outline' \| 'ghost' \| 'link' | 'default' | 按钮样式变体 | | size | 'sm' \| 'default' \| 'lg' | 'default' | 按钮大小 | | loading | boolean | false | 是否显示加载状态 | | disabled | boolean | false | 是否禁用 | | icon | string \| Component | - | 按钮图标 | | iconPlacement | 'left' \| 'right' | 'left' | 图标位置 |

Avatar 属性

| 属性名 | 类型 | 默认值 | 说明 | | ------ | --------------------------- | ----------- | ---------------- | | src | string | - | 头像图片地址 | | alt | string | - | 头像图片替代文本 | | size | 'sm' \| 'default' \| 'lg' | 'default' | 头像大小 | | icon | string \| Component | - | 头像图标 | | shape | 'circle' \| 'square' | 'circle' | 头像形状 |

Input 属性

| 属性名 | 类型 | 默认值 | 说明 | | ----------- | --------------------------- | ----------- | ---------- | | modelValue | string | '' | 输入框值 | | placeholder | string | - | 占位文本 | | disabled | boolean | false | 是否禁用 | | readonly | boolean | false | 是否只读 | | clearable | boolean | false | 是否可清空 | | size | 'sm' \| 'default' \| 'lg' | 'default' | 输入框大小 | | prefix | string | - | 前缀内容 | | suffix | string | - | 后缀内容 |

Select 属性

| 属性名 | 类型 | 默认值 | 说明 | | ----------- | --------------------------- | ------- | ---------- | | modelValue | string \| number \| Array | - | 选择器值 | | options | Array | [] | 选项数据 | | placeholder | string | - | 占位文本 | | disabled | boolean | false | 是否禁用 | | clearable | boolean | false | 是否可清空 | | multiple | boolean | false | 是否多选 | | filterable | boolean | false | 是否可搜索 |

示例

登录表单

<template>
  <div class="mx-auto w-96 rounded border p-6 shadow-md">
    <h2 class="mb-6 text-center text-2xl font-bold">用户登录</h2>

    <form @submit.prevent="handleSubmit">
      <div class="mb-4">
        <label class="mb-1 block">用户名</label>
        <VbenInput
          v-model="form.username"
          placeholder="请输入用户名"
          :disabled="loading"
        />
      </div>

      <div class="mb-6">
        <label class="mb-1 block">密码</label>
        <VbenInputPassword
          v-model="form.password"
          placeholder="请输入密码"
          :disabled="loading"
        />
      </div>

      <div class="mb-6 flex items-center">
        <VbenCheckbox v-model="form.remember" :disabled="loading">
          记住我
        </VbenCheckbox>

        <a href="#" class="ml-auto text-sm text-blue-500">忘记密码?</a>
      </div>

      <VbenButton
        variant="primary"
        class="w-full"
        :loading="loading"
        @click="handleSubmit"
      >
        登录
      </VbenButton>
    </form>
  </div>
</template>

<script setup lang="ts">
import {
  VbenButton,
  VbenInput,
  VbenInputPassword,
  VbenCheckbox,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const form = ref({
  username: '',
  password: '',
  remember: false,
});

const loading = ref(false);

const handleSubmit = async () => {
  if (!form.value.username || !form.value.password) {
    alert('请输入用户名和密码');
    return;
  }

  loading.value = true;

  try {
    // 模拟登录请求
    await new Promise((resolve) => setTimeout(resolve, 1500));
    console.log('登录成功', form.value);
    // 登录成功后的处理...
  } catch (error) {
    console.error('登录失败', error);
  } finally {
    loading.value = false;
  }
};
</script>

数据展示卡片

<template>
  <div class="grid grid-cols-1 gap-6 md:grid-cols-3">
    <div
      v-for="(card, index) in cards"
      :key="index"
      class="rounded-lg border p-6 shadow-sm"
    >
      <div class="mb-4 flex items-center justify-between">
        <h3 class="text-lg font-medium">{{ card.title }}</h3>
        <VbenIcon :name="card.icon" class="text-gray-400" />
      </div>

      <div class="mb-2">
        <VbenCountToAnimator
          :value="card.value"
          :duration="1500"
          :decimals="card.decimals"
          :prefix="card.prefix"
          class="text-2xl font-bold"
        />
      </div>

      <div class="flex items-center text-sm">
        <span
          :class="[card.trend > 0 ? 'text-green-500' : 'text-red-500', 'mr-1']"
        >
          {{ card.trend > 0 ? '+' : '' }}{{ card.trend }}%
        </span>
        <span class="text-gray-500">较上周</span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  VbenIcon,
  VbenCountToAnimator,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref } from 'vue';

const cards = ref([
  {
    title: '总销售额',
    value: 126500,
    decimals: 2,
    prefix: '¥',
    trend: 12.5,
    icon: 'TrendingUp',
  },
  {
    title: '访问量',
    value: 8846,
    decimals: 0,
    prefix: '',
    trend: -2.3,
    icon: 'Users',
  },
  {
    title: '订单数',
    value: 1293,
    decimals: 0,
    prefix: '',
    trend: 8.7,
    icon: 'ShoppingCart',
  },
]);
</script>

交互式表格

<template>
  <div class="rounded-lg border p-6 shadow-sm">
    <div class="mb-4 flex items-center justify-between">
      <h2 class="text-xl font-bold">用户列表</h2>

      <div class="flex space-x-2">
        <VbenInput
          v-model="searchQuery"
          placeholder="搜索用户"
          suffix="Search"
          class="w-64"
        />

        <VbenButton variant="primary" icon="Plus"> 添加用户 </VbenButton>
      </div>
    </div>

    <div class="overflow-x-auto">
      <table class="w-full border-collapse">
        <thead>
          <tr class="bg-gray-50">
            <th class="p-3 text-left">用户名</th>
            <th class="p-3 text-left">邮箱</th>
            <th class="p-3 text-left">角色</th>
            <th class="p-3 text-left">状态</th>
            <th class="p-3 text-left">操作</th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="(user, index) in filteredUsers"
            :key="index"
            class="border-t hover:bg-gray-50"
          >
            <td class="p-3">
              <div class="flex items-center">
                <VbenAvatar :src="user.avatar" size="sm" class="mr-2" />
                {{ user.username }}
              </div>
            </td>
            <td class="p-3">{{ user.email }}</td>
            <td class="p-3">{{ user.role }}</td>
            <td class="p-3">
              <span
                :class="[
                  user.status === 'active'
                    ? 'bg-green-100 text-green-800'
                    : 'bg-gray-100 text-gray-800',
                  'rounded px-2 py-1 text-xs',
                ]"
              >
                {{ user.status === 'active' ? '活跃' : '禁用' }}
              </span>
            </td>
            <td class="p-3">
              <div class="flex space-x-2">
                <VbenTooltip content="编辑">
                  <button class="text-blue-500 hover:text-blue-700">
                    <VbenIcon name="Edit" size="sm" />
                  </button>
                </VbenTooltip>

                <VbenTooltip content="删除">
                  <button class="text-red-500 hover:text-red-700">
                    <VbenIcon name="Trash" size="sm" />
                  </button>
                </VbenTooltip>
              </div>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
</template>

<script setup lang="ts">
import {
  VbenButton,
  VbenInput,
  VbenAvatar,
  VbenIcon,
  VbenTooltip,
} from '@cimom/vben-core-ui-kit-shadcn-ui';
import { ref, computed } from 'vue';

const searchQuery = ref('');

const users = ref([
  {
    username: 'admin',
    email: '[email protected]',
    role: '管理员',
    status: 'active',
    avatar: 'https://via.placeholder.com/40',
  },
  {
    username: 'user1',
    email: '[email protected]',
    role: '编辑',
    status: 'active',
    avatar: 'https://via.placeholder.com/40',
  },
  {
    username: 'user2',
    email: '[email protected]',
    role: '访客',
    status: 'inactive',
    avatar: 'https://via.placeholder.com/40',
  },
]);

const filteredUsers = computed(() => {
  if (!searchQuery.value) return users.value;

  const query = searchQuery.value.toLowerCase();
  return users.value.filter(
    (user) =>
      user.username.toLowerCase().includes(query) ||
      user.email.toLowerCase().includes(query) ||
      user.role.toLowerCase().includes(query),
  );
});
</script>