墨穗app.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v1.0.165 · 墨穗笔记
笔记

Notebase墨穗
静水流深,落墨成穗。

0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →

笔记

0
加载中...

工具

0

此页用于记录用户反馈问题后的每一次改进

关于

笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势

// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

如何用 shadcn/ui 构建生产级 Card 组件

2026-07-07编程开发

Card 组件可能是 Web 开发里最常见的 UI 模式了。你在房产列表 App、SaaS 分析仪表盘、电商商品页、后台管理面板里到处都能看到它们。但想要构建一个 hover 状态干净利落、支持暗色模式、可访问性好、并且各种屏幕尺寸下都能正常显示的 Card,可不仅仅是把内容包进一个 <div> 那么简单。你需要一个一致的组件结构、可靠的设计系统,以及经过深思熟虑的 Tailwind 模式。

在这篇文章里,我会带你用 shadcn/ui 和 Shadcn Space 里的 Base UI 原语,构建四种生产级的 Card 组件。每个 Card 都针对一个真实的、开发者日常会遇到的 UI 模式。

学完之后,你会得到:

  • 一个 预览卡(Preview Card),带有分组 hover 图片效果、覆盖箭头图标和房产详情布局
  • 一个 分析卡(Analytics Card),带有类型化的 metric 属性、条件徽章颜色和装饰性背景图片
  • 一个 统计卡(Statistics Card),带有响应式四列电商统计网格和图标徽章
  • 一个 电商产品变体卡(Ecommerce Product Variant Card),包含尺寸选择、心愿单切换、购物袋按钮和购买按钮上的涟漪动画

目录

  • 前置要求
  • 为什么用 shadcn/ui?
  • Shadcn Space 是什么?
  • 你要构建什么
  • 如何设置 CLI 注册表
  • 如何构建预览卡(card-02)
  • 如何构建分析卡(card-05)
  • 如何构建统计卡(card-06)
  • 如何构建电商产品变体卡(card-17)
  • 快速参考表
  • 关键概念总结
  • 结语
  • 资源

前置要求

开始之前,确保你已经准备好以下内容:

  • 安装了 Node.js 18 或更高版本
  • 有一个已搭建好的 Next.js 或 React 项目
  • 你的项目中已经初始化了 shadcn/ui(运行 npx shadcn@latest init)
  • Tailwind CSS 已配置好
  • 具备 React 和 TypeScript 的基础知识

如果你还没有初始化 shadcn/ui,请先在项目根目录运行 npx shadcn@latest init 并按提示操作,然后再继续。

为什么用 shadcn/ui?

shadcn/ui 是一套基于 Radix UI、Base UI 构建的可访问、开源 React 组件集合,并使用 Tailwind CSS 进行样式设计。它的工作方式与传统组件库不同。你不是安装一个包,而是通过 CLI 将组件源文件直接复制到你的项目中。这意味着你拥有每一行代码的所有权。你可以阅读它、编辑它,而且组件永远不会因为你无法控制的库更新而损坏。

一些关键优势:

  • 默认可访问:基于 Radix UI 和 Base UI 原语构建
  • 完全基于 Tailwind:没有外部 CSS 文件,没有特异性冲突
  • 零锁定:组件位于你的 components/ 文件夹中,而不是 node_modules 里
  • 随处可用:Next.js、Vite、Astro、Remix 和其他 React 框架

你将在本教程中使用的 Card、Badge、Button 和 Separator 组件都来自 shadcn/ui 的基础安装。

Shadcn Space 是什么?

Shadcn Space 是一个开源的注册表,提供了基于 shadcn/ui 构建的生产级组件和 UI 块。它在默认的 shadcn/ui 组件集基础上进行了扩展,增加了从常见模式到高度吸引人的布局的各种变体。

与默认的 shadcn/ui Card 组件的关键区别在于,Shadcn Space 的卡片是为特定的布局模式设计的。你开箱即用就能获得更多的结构。Shadcn Space 中的每个组件都同时支持 Radix UI 和 Base UI 原语。你还可以使用“复制提示”(Copy Prompt)功能。本教程使用的是 Base UI 版本。

安装方式与任何 shadcn/ui 组件相同,只需一个 CLI 命令,源文件就会放到你的项目中。你可以在 Shadcn 卡片组件库 中浏览完整的卡片集合。

你要构建什么

以下是你要构建的四张卡片及其具体功能的概览:

预览卡(card-02)

  • 大图,带有 hover 亮度和缩放动画
  • 仅在 hover 时显示的箭头图标
  • 物业名称和位置
  • 青绿色系的价格徽章
  • 带有床、浴室和面积图标的设施行

分析卡(card-05)

  • 类型化的 TypeScript 属性,带有内置的默认数据集
  • 两个由垂直分隔符分隔的指标列
  • 基于正/负趋势的条件徽章颜色
  • 固定在右下角的装饰性背景图片

统计卡(card-06)

  • 四列响应式网格,在移动设备上堆叠显示
  • 每个指标使用 Iconify Solar 图标集
  • 带有趋势方向图标的徽章
  • 最后一列的边框分隔线自动移除

电商产品变体卡(card-17)

  • 带有 3D 投影和 hover 缩放的产品图片
  • 支持暗色模式的心形心愿单切换
  • 带有高亮状态的尺寸选择器
  • 点击时填充的购物袋图标切换
  • 带有 CSS 涟漪动画的“立即购买”按钮
  • 带有序数后缀格式的动态交货日期

如何设置 CLI 注册表

在运行任何安装命令之前,你需要先在 components.json 文件中注册 Shadcn Space 注册表。打开项目根目录下的 components.json,添加 registries 字段:

{
  "registries": {
    "@shadcn-space": {
      "url": "https://shadcnspace.com/r/{name}.json"
    }
  }
}

这告诉 shadcn CLI 在哪里可以找到以 @shadcn-space/ 为前缀的组件。如果没有这一步,本教程中的所有安装命令都会失败。

添加注册表后,你的完整 components.json 应该看起来像这样:

{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "default",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  },
  "registries": {
    "@shadcn-space": {
      "url": "https://shadcnspace.com/r/{name}.json"
    }
  }
}

关于 CLI 如何与第三方注册表配合使用的完整指南,请访问 入门指南。你也可以观看 视频教程,如果你更喜欢跟着视频学习的话。

如何构建预览卡(card-02)

预览卡是做什么的

预览卡专为房产列表、酒店页面或任何需要大图配合下方支持性内容的设计而打造。当用户将鼠标悬停在卡片上时,图片会变暗并放大。一个箭头图标会出现在角落。图片下方会显示标题、位置、价格徽章和设施行。

如何安装预览卡

根据你的包管理器运行以下命令之一:

npm:

npx shadcn@latest add @shadcn-space/card-02

pnpm:

pnpm dlx shadcn@latest add @shadcn-space/card-02

Yarn:

yarn dlx shadcn@latest add @shadcn-space/card-02

Bun:

bunx --bun shadcn@latest add @shadcn-space/card-02

CLI 会将组件复制到你的项目中的以下位置:

components/
  shadcn-space/
    card/
      Card-02.tsx

组件代码

import { Badge } from "@/components/ui/badge";
import { Card } from "@/components/ui/card";
import { ArrowRight, Bath, BedDouble, Expand } from "lucide-react";

const PreviewCard = () => (
  <Card className="relative gap-0 py-0 rounded-2xl group hover:shadow-3xl duration-300">
    <div className="overflow-hidden rounded-t-2xl">
      <a href="#">
        <div className="w-full h-72">
          <img 
            src="https://images.shadcnspace.com/assets/card/property-cover-1.jpg" 
            alt="Serenity Residential Home" 
            width={440} 
            height={300} 
            className="w-full h-full object-cover rounded-t-2xl group-hover:brightness-50 group-hover:scale-125 transition duration-300 delay-75" 
          />
        </div>
      </a>
      <div className="absolute top-6 right-6 hidden p-4 bg-white rounded-full group-hover:block">
        <ArrowRight className="text-card-foreground" />
      </div>
    </div>
    <div className="p-6">
      <div className="flex justify-between gap-5 mb-6">
        <div>
          <a href="#">
            <h3 className="text-xl font-medium duration-300 group-hover:text-primary">
              Serenity Residential Home
            </h3>
          </a>
          <p className="text-base font-normal text-muted-foreground">
            15 S Aurora Ave, Miami
          </p>
        </div>
        <Badge className="px-5 py-4 text-base font-normal rounded-full bg-teal-500/10 text-teal-500">
          $570,000
        </Badge>
      </div>
      <div className="flex items-center gap-6">
        <div className="flex items-center gap-2">
          <BedDouble className="w-5 h-5 text-muted-foreground" />
          <span className="text-base text-muted-foreground">3 Beds</span>
        </div>
        <div className="flex items-center gap-2">
          <Bath className="w-5 h-5 text-muted-foreground" />
          <span className="text-base text-muted-foreground">2 Baths</span>
        </div>
        <div className="flex items-center gap-2">
          <Expand className="w-5 h-5 text-muted-foreground" />
          <span className="text-base text-muted-foreground">1,500 sqft</span>
        </div>
      </div>
    </div>
  </Card>
);

export default PreviewCard;

深入理解代码

让我带你拆解一下这个组件,看看每个部分是怎么工作的,以及为什么要这么写。

外层 Card 容器:我们用了 group 类,这是 Tailwind 的一个分组功能。它允许父元素上的 hover 状态影响子元素。比如当鼠标悬停在整个卡片上时,图片会变暗并缩放,箭头图标会显示,标题颜色也会变化。hover:shadow-3xl 提供了 hover 时的阴影效果,让卡片有“浮起来”的感觉。

图片区域:图片被包裹在一个 overflow-hidden 的 div 里,这是为了防止缩放后的图片溢出边界。group-hover:brightness-50 让图片变暗到 50% 亮度,group-hover:scale-125 让它放大到 125%。transition duration-300 delay-75 控制动画持续 300 毫秒,延迟 75 毫秒开始。这个延迟很重要——它让动画感觉更自然,而不是一上来就猛冲。

箭头图标:默认是 hidden,只有 hover 时才显示。absolute top-6 right-6 把它定位在图片区域的右上角。白色背景和圆角让它看起来像一个悬浮的按钮。这里有个小细节:图标容器用了 p-4,这意味着点击区域比图标本身大,提高了可用性。

内容区域:价格徽章用了 bg-teal-500/10 和 text-teal-500,这是一个半透明背景加实色文字的组合,看起来很现代。设施图标使用了 Lucide React 图标库的 BedDouble、Bath 和 Expand 图标。每个图标都配有文字说明,并且用 flex items-center gap-2 来对齐。

如何使用这个组件

在你的页面中引入并使用它:

import PreviewCard from "@/components/shadcn-space/card/Card-02";

export default function PropertyPage() {
  return (
    <div className="max-w-md mx-auto p-4">
      <PreviewCard />
    </div>
  );
}

实时预览

你可以在这里查看 预览卡的实时演示。

如何构建分析卡(card-05)

分析卡是做什么的

分析卡用于展示两个关键指标的对比,比如本月 vs 上月的收入或用户数。它包含类型化的 TypeScript 属性、条件徽章颜色、垂直分隔符,以及一个装饰性的背景图片。

如何安装分析卡

运行以下命令之一:

npm:

npx shadcn@latest add @shadcn-space/card-05

pnpm:

pnpm dlx shadcn@latest add @shadcn-space/card-05

Yarn:

yarn dlx shadcn@latest add @shadcn-space/card-05

Bun:

bunx --bun shadcn@latest add @shadcn-space/card-05

组件代码

import { Badge } from "@/components/ui/badge";
import { Card } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { ArrowDown, ArrowUp } from "lucide-react";

interface Metric {
  label: string;
  value: string;
  trend: number;
}

interface AnalyticsCardProps {
  metrics?: [Metric, Metric];
}

const defaultMetrics: [Metric, Metric] = [
  { label: "Revenue", value: "$45,231", trend: 20.1 },
  { label: "Subscribers", value: "+2350", trend: -4.5 },
];

const AnalyticsCard = ({ metrics = defaultMetrics }: AnalyticsCardProps) => {
  return (
    <Card className="p-6 relative overflow-hidden">
      <div className="flex items-center justify-between gap-8">
        {metrics.map((metric, index) => (
          <div key={index} className="flex items-center gap-8">
            <div className="space-y-1">
              <p className="text-sm text-muted-foreground">{metric.label}</p>
              <p className="text-2xl font-bold">{metric.value}</p>
              <Badge
                variant={metric.trend >= 0 ? "default" : "destructive"}
                className="gap-1"
              >
                {metric.trend >= 0 ? (
                  <ArrowUp className="w-3 h-3" />
                ) : (
                  <ArrowDown className="w-3 h-3" />
                )}
                {Math.abs(metric.trend)}%
              </Badge>
            </div>
            {index === 0 && <Separator orientation="vertical" className="h-20" />}
          </div>
        ))}
      </div>
      <img
        src="https://images.shadcnspace.com/assets/card/pattern-1.svg"
        alt=""
        className="absolute -bottom-6 -right-6 opacity-10 pointer-events-none"
        width={150}
        height={150}
      />
    </Card>
  );
};

export default AnalyticsCard;

深入理解代码

这个组件展示了 TypeScript 在 React 组件中的强大之处。我们来看看关键部分。

类型定义:Metric 接口定义了每个指标的结构:label(标签)、value(值)和 trend(趋势,一个正负数)。AnalyticsCardProps 接口定义了一个可选的 metrics 属性,它是一个包含两个 Metric 对象的元组。如果用户没有传入自定义数据,组件会使用 defaultMetrics。

条件徽章颜色:Badge 的 variant 属性根据 trend 的正负值动态设置为 "default" 或 "destructive"。在 shadcn/ui 的默认主题中,default 通常是绿色,destructive 是红色。这样用户一眼就能看出趋势是上升还是下降。

趋势箭头图标:我们根据 trend 的正负值条件渲染 ArrowUp 或 ArrowDown 图标。注意这里用了 Math.abs(metric.trend) 来显示绝对值,所以趋势值始终显示为正数,但箭头指示了方向。

垂直分隔符:Separator 组件只在第一个指标后面显示(index === 0)。orientation="vertical" 让它变成一条竖线,h-20 控制它的高度。这个分隔符在视觉上清晰地区分了两个指标。

装饰性背景图片:<img> 标签被定位在卡片的右下角(-bottom-6 -right-6),opacity-10 让它几乎透明,pointer-events-none 确保它不会干扰用户交互。这是一个很常见的设计技巧:用微弱的背景图案增加视觉层次感,而不分散注意力。

如何使用这个组件

import AnalyticsCard from "@/components/shadcn-space/card/Card-05";

export default function DashboardPage() {
  return (
    <div className="max-w-2xl mx-auto p-4">
      <AnalyticsCard />
      {/* 或者传入自定义数据 */}
      <AnalyticsCard 
        metrics={[
          { label: "Page Views", value: "12,847", trend: 8.3 },
          { label: "Bounce Rate", value: "32.1%", trend: -2.1 },
        ]} 
      />
    </div>
  );
}

实时预览

你可以在这里查看 分析卡的实时演示。

如何构建统计卡(card-06)

统计卡是做什么的

统计卡用于电商仪表盘,以网格形式展示多个关键指标,比如总收入、订单数、客户数和转化率。每个指标都有一个对应的图标、数值和趋势徽章。

如何安装统计卡

运行以下命令之一:

npm:

npx shadcn@latest add @shadcn-space/card-06

pnpm:

pnpm dlx shadcn@latest add @shadcn-space/card-06

Yarn:

yarn dlx shadcn@latest add @shadcn-space/card-06

Bun:

bunx --bun shadcn@latest add @shadcn-space/card-06

组件代码

import { Badge } from "@/components/ui/badge";
import { Card } from "@/components/ui/card";
import { ArrowUp, ArrowDown } from "lucide-react";

interface Stat {
  label: string;
  value: string;
  trend: number;
  icon: React.ReactNode;
}

interface StatisticsCardProps {
  stats?: Stat[];
}

const defaultStats: Stat[] = [
  {
    label: "Total Revenue",
    value: "$45,231",
    trend: 20.1,
    icon: (
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
        <path fill="currentColor" d="M11.5 1L18 10H5l6.5-9zm0 22L5 14h13l-6.5 9z"/>
      </svg>
    ),
  },
  {
    label: "Orders",
    value: "+1,234",
    trend: -4.5,
    icon: (
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
        <path fill="currentColor" d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 14l-5-5 1.41-1.41L12 14.17l6.59-6.59L20 9l-8 8z"/>
      </svg>
    ),
  },
  {
    label: "Customers",
    value: "+5,678",
    trend: 12.3,
    icon: (
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
        <path fill="currentColor" d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/>
      </svg>
    ),
  },
  {
    label: "Conversion Rate",
    value: "3.24%",
    trend: -1.2,
    icon: (
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
        <path fill="currentColor" d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/>
      </svg>
    ),
  },
];

const StatisticsCard = ({ stats = defaultStats }: StatisticsCardProps) => {
  return (
    <Card className="p-6">
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
        {stats.map((stat, index) => (
          <div key={index} className="flex flex-col gap-4">
            <div className="flex items-center justify-between">
              <div className="p-2 rounded-lg bg-muted">
                {stat.icon}
              </div>
              <Badge
                variant={stat.trend >= 0 ? "default" : "destructive"}
                className="gap-1"
              >
                {stat.trend >= 0 ? (
                  <ArrowUp className="w-3 h-3" />
                ) : (
                  <ArrowDown className="w-3 h-3" />
                )}
                {Math.abs(stat.trend)}%
              </Badge>
            </div>
            <div>
              <p className="text-sm text-muted-foreground">{stat.label}</p>
              <p className="text-2xl font-bold">{stat.value}</p>
            </div>
            {index < stats.length - 1 && (
              <div className="hidden lg:block border-r border-border h-full" />
            )}
          </div>
        ))}
      </div>
    </Card>
  );
};

export default StatisticsCard;

深入理解代码

这个组件的关键在于它的响应式网格布局和自动分隔符管理。

响应式网格:grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 实现了从单列到两列再到四列的平滑过渡。在手机上,每个指标占一整行;在平板尺寸上,变成两列;在大屏幕上,四列并排显示。

图标系统:这里使用了内联 SVG 图标,而不是外部图标库。这样做的好处是无需安装额外的依赖,而且 SVG 是“当前颜色”(currentColor)的,会自动继承父元素的文字颜色。如果你更喜欢使用 Iconify 或其他图标库,完全可以替换掉这些 SVG。

条件徽章:和之前的分析卡一样,我们根据 trend 的正负值动态设置徽章的变体和箭头方向。

自动分隔符移除:注意最后这部分代码:

{index < stats.length - 1 && (
  <div className="hidden lg:block border-r border-border h-full" />
)}

这确保了最后一个指标后面不会显示分隔线。hidden lg:block 意味着分隔线只在桌面端显示,在移动端会被隐藏,避免了在小屏幕上出现拥挤的竖线。

如何使用这个组件

import StatisticsCard from "@/components/shadcn-space/card/Card-06";

export default function DashboardPage() {
  return (
    <div className="max-w-4xl mx-auto p-4">
      <StatisticsCard />
    </div>
  );
}

实时预览

你可以在这里查看 统计卡的实时演示。

如何构建电商产品变体卡(card-17)

电商产品变体卡是做什么的

这是最复杂的一张卡片,专为电商产品详情页设计。它包含产品图片(带有 3D 投影和 hover 缩放)、心愿单切换按钮、尺寸选择器、购物袋图标和“立即购买”按钮(带有涟漪动画),以及动态计算的交货日期。

如何安装电商产品变体卡

运行以下命令之一:

npm:

npx shadcn@latest add @shadcn-space/c
相似推荐
uBlock Origin 开发版被 Chrome 商店拒绝:一场关于扩展单一用途政策的争议逆向工程实战:我如何绕过亚马逊Kindle网页端的DRM加密Heroku的丑陋秘密:云之王如何背离Rails并欺骗客户Firefox 成为最后一个支持 uBlock Origin 的主流浏览器:广告拦截的终局之战GitHub Codespaces 深度解读:云端开发环境如何重塑编码工作流认知负荷才是关键:软件设计的根本度量
编写使用方法
Markdown 格式 · Ctrl+Enter 确定
0 字新建笔记
欢迎回来
登录你的墨穗笔记账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属墨穗笔记
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

隐私提醒

取消
编辑工具
受控分享
为这篇笔记生成限时 / 带密码的临时链接
关闭