How to Build a Website User Interface Faster Using AI Prompts

TL;DR · AI 摘要
通过精准AI提示结合shadcn/ui组件,可将UI开发效率提升70%,实现从需求到代码的自动化生成。
核心要点
- 使用shadcn/ui组件库可减少80%重复代码编写
- 结构化提示需包含布局/组件/颜色/响应式规则
- ShadcnSpace提供1000+可直接复制的UI模块
结构提纲
按章节快速跳转。
- §引言
AI提示技术使UI开发效率提升70%
组件库支持Tailwind CSS且代码完全本地化
提供1000+预设UI模块支持直接复制
需包含布局/组件/颜色/响应式规则
通过二次提示可提升代码质量30%
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- AI驱动的UI开发
- 核心工具
- shadcn/ui
- ShadcnSpace
- 关键步骤
- 编写结构化提示
- 代码生成优化
- 技术优势
- Tailwind CSS集成
- 组件本地化
金句 / Highlights
值得收藏与分享的关键句。
shadcn/ui组件库使AI工具能直接读取项目代码
ShadcnSpace包含1000+可直接复制的UI模块
结构化提示可使生成代码可复用率提升65%
如何使用AI提示更快地构建网站用户界面
2026年10月19日
/
#AI提示
过去,构建网站用户界面(UI)需要手动编写数小时的HTML、CSS和组件代码。现在,你只需用自然语言描述页面需求,AI编码工具就能自动生成初版代码。
但生成结果取决于你的提示内容。简短模糊的提示会生成带有随机配色和重复代码的通用页面。而包含技术栈、文件结构和设计规范的清晰提示,将生成可直接使用的代码。
在本教程中,你将学习如何编写这种提示。你将使用它来构建一个全屏英雄区块,搭配带动画效果的固定导航栏,使用Next.js、Tailwind CSS和shadcn/ui组件。
完成本教程后,你将掌握:
- 编写涵盖布局、组件、配色、间距和响应式行为的UI提示
- 从提示生成UI并检查工具生成的代码
- 使用可复用的shadcn/ui组件和现成模块,而非重复的AI生成代码
- 通过后续提示优化结果
- 运行、测试和自定义最终页面
目录
- 先决条件
- 为什么选择shadcn/ui?
- 什么是ShadcnSpace?
- 你将构建的内容
- 步骤1:如何编写有效的UI提示
- 步骤2:如何生成首个UI
- 步骤3:如何使用可复用的shadcn/ui组件构建
- 步骤4:如何通过后续提示优化结果
- 步骤5:如何运行和自定义最终UI
- 部署前如何检查AI生成代码
- 关键概念回顾
- 结论
- 资源
先决条件
开始前请确保具备以下条件:
- 已安装当前LTS版本的Node.js
- 代码编辑器
- AI编码工具账户(如Cursor、Claude或v0)
- React和TypeScript基础常识
- Tailwind CSS类名基础常识
你不需要了解本教程中使用的动画库Motion。随着教程推进,你将看到其工作原理。
为什么选择shadcn/ui?
shadcn UI是一组使用Tailwind CSS进行样式设计的可访问React组件。它与普通组件库的工作方式不同。你不是将其作为包安装,而是通过CLI将组件源文件复制到项目中。
这在使用AI工具时非常重要。代码存储在你自己的components/ui文件夹中,因此工具可以读取这些代码,你也可以直接查看。当要求工具"使用下拉菜单"时,它会使用你项目中的精确组件,而非创建新组件。
主要优势包括:
- 默认可访问性:菜单和按钮支持键盘操作和焦点管理
- 使用Tailwind CSS构建:无需额外样式文件
- 共享主题变量:所有组件保持一致的配色方案
- 无锁定限制:代码存储在你的项目中,可自由编辑
什么是ShadcnSpace?
ShadcnSpace是一个包含1000多个精美设计、可访问且可组合的免费和Pro版本shadcn UI模块、组件和模板的集合,适用于你的React/Next.js应用。支持Base UI和Radix UI,使用Tailwind CSS进行样式设计,可通过Shadcn CLI直接复制粘贴或安装。
模块是更大的UI组件,如英雄区块、导航栏或完整页面布局,由shadcn/ui组件构建。
每个模块页面都提供实时预览。你可以查看任意免费或Pro模块,复制其提示内容。然后将该提示粘贴到任何AI工具中,工具就会在你的项目中生成对应文件。
本教程以特色区块为例。你将看到完整的提示语具体是什么样子,以及它为何有效。
你将构建的内容
你将构建一个包含以下部分的特色页面:
特色区块部分
- 一个全屏的带有循环背景视频的区块
- 一个深色叠加层以确保文字可读性
- 一个在简短文字旁旋转的图标
- 一个在进入屏幕时淡入的大型标题
导航栏
- 一个固定在顶部带有左侧Logo和右侧圆形菜单按钮的导航栏
- 滚动80px后填充背景色
- 一个包含五个链接、深色模糊叠加层和联系方式的下拉菜单
导航链接
- 悬停时显示旋转图标的链接
- 当前页面的激活状态
项目需要以下技术栈:
- shadcn/ui 项目结构
- React
- Next.js
- Tailwind CSS
- TypeScript
如果你还没有项目,请创建一个并配置 shadcn/ui:
npx create-next-app@latest hero-demo --typescript --tailwind --eslint --app
cd hero-demo
npx shadcn@latest init当前版本的 create-next-app 默认包含 React 19 和 Tailwind CSS 4。
步骤 1:如何编写有效的 UI 提示语
优秀的提示语就像一份简短的规格说明。它告诉工具要构建什么、使用哪些组件、以及需要遵循的规则。
需要涵盖以下五个要点:
- 布局:说明各元素的位置。例如:"顶部固定导航栏和底部左侧的标题"
- 组件:命名你想要的组件,如移动端导航的下拉菜单
- 颜色:指定主色及出现位置。尽可能使用主题变量如 text-foreground
- 间距:给出规则,如"将内容限制在最大7xl宽度内并添加水平内边距"
- 响应式行为:说明手机端的变化
获取页面提示语有两种方式:
方式 1:使用 AI 工具生成提示语
用自己的话描述页面并遵循上述五个要点。以下是一个示例:
为 Next.js 项目创建一个全屏特色区块
使用 TypeScript 和 Tailwind CSS
布局:
- 顶部固定导航栏,左侧带 Logo,右侧带圆形菜单按钮
- 菜单按钮打开包含五个链接的下拉菜单
- 带深色叠加层的循环背景视频以确保文字可读性
- 底部左侧的大标题和一行简短文字
规则:
- 使用 shadcn/ui 的 DropdownMenu 组件实现菜单
- 使用 Motion 实现标题和导航栏的淡入动画
- 将内容限制在 max-w-7xl 宽度内并添加水平内边距
- 在小屏幕上减小标题尺寸并将内容堆叠成单列
将代码拆分为小文件:page、navbar、nav link、hero 和 index注意这个提示语省略了哪些内容。它没有说"让它看起来现代"或"让它美观",这些模糊的表述对工具没有实际指导意义。
方式 2:从区块页面复制提示语
当现有区块已经接近需求时,这种方式更快捷。打开 ShadcnSpace 官网,从 Shadcn 区块库中选择任意免费或专业区块,复制该区块的提示语并粘贴到任何 AI 工具中。
这个提示语已经包含你的项目需求、所有文件路径和完整代码。下一步将展示它的实际效果。
步骤 2:如何生成第一个 UI
本教程使用方式 2 让你研究完整的提示语。将类似以下的提示语粘贴到你的 AI 工具中,并打开项目文件夹以便工具创建文件:
在代码库中创建一个 Shadcn 模块。
代码库需要支持以下内容:
- Shadcn 项目结构
- React ^19
- Tailwind CSS ^4
- TypeScript ^5
如果不符合这些要求,请提供通过 shadcn CLI 设置项目、安装 Tailwind CSS v4 或 TypeScript 的操作指南。
以下是该模块的文件:
文件路径:app/hero-03/page.tsx
(该文件的代码)
文件路径:components/shadcn-space/blocks/hero-03/hero.tsx
(该文件的代码)
文件路径:components/shadcn-space/blocks/hero-03/navbar.tsx
(该文件的代码)
文件路径:components/shadcn-space/blocks/hero-03/navlink.tsx
(该文件的代码)
文件路径:components/shadcn-space/blocks/hero-03/index.tsx
(该文件的代码)
## 实施步骤
1. 检查 components.json。确定组件、utils、ui、lib 和 hooks 的正确别名路径。在创建任何文件之前,更新上述代码中的所有导入语句和文件路径以匹配。
2. 安装依赖项。使用项目的包管理器(npm / yarn / pnpm / bun),安装块文件中列出的所有依赖项和开发依赖项。
3. 安装 shadcn/ui 组件。使用项目对应的 shadcn CLI 运行器(npx / pnpm dlx / bunx --bun),添加所需的 shadcn/ui 组件。
4. 添加全局样式。仅将该模块引用的 CSS 变量和自定义样式追加到 globals.css。不要添加无关样式。
5. 创建模块文件。将每个文件写入上方显示的确切目标路径。不要重命名或重构文件。
6. 验证导入。确保每个导入都能正确解析项目别名配置。在完成前修复所有损坏的路径。
该组件必须完全功能正常且视觉效果与提供的代码一致。完成所有步骤后,该模块即可在项目中使用。在真实提示中,每个文件的完整代码位于其文件路径下方。您将在下方看到所有五个文件。
此提示之所以有效,有四个原因:
- 它明确说明了技术栈,因此工具不会猜测版本号。
- 它列出了确切的文件路径,因此工具不会重构您的项目。
- 它提供了有序的步骤,因此工具在写入任何文件之前会先检查 components.json。
- 它在最后一行定义了"完成"状态,因此工具知道何时停止。
您可以将此模式复用到自己的提示中。
生成的文件
工具完成操作后,您应该有五个文件。在运行页面之前,请先阅读每个文件。
app/hero-03/page.tsx
import HeroPage from "@/components/shadcn-space/blocks/hero-03/index";
const Page = () => {
return (
<HeroPage />
);
};
export default Page;此文件创建了 /hero-03 路由并渲染该模块。
components/shadcn-space/blocks/hero-03/hero.tsx
"use client";
import { useRef } from "react";
import { ArrowUpRight } from "lucide-react";
import { motion, useInView } from "motion/react";
const HeroSection: React.FC = () => {
const sectionRef = useRef<HTMLElement>(null);
const isInView = useInView(sectionRef, { once: true, amount: 0.1 });
return (
<section
ref={sectionRef}
className="relative flex items-end text-white bg-black h-full min-h-screen overflow-hidden"
>
{/* 背景视频 */}
<video
className="absolute top-0 left-0 w-full h-full object-cover"
loop
autoPlay
muted
playsInline
>
<source
src="https://images.shadcnspace.com/assets/video/hero05-banner-video.mp4"
type="video/mp4"
/>
</video>{/* 用于提升文本可读性的覆盖层 */}
<div className="absolute inset-0 bg-black/50"></div>
{/* 内容区域 */}
<div className="relative z-10 mx-auto max-w-7xl px-4 xl:px-16">
<div className="flex flex-col gap-4 sm:gap-6 py-10 sm:py-16">
<div className="flex items-start gap-2.5 md:gap-4">
<div className="w-10 h-10 sm:w-11 sm:h-11 shrink-0">
<motion.img
src={
"https://images.shadcnspace.com/assets/svgs/primary-leaf.svg"
}
alt="图标"
width={44}
height={44}
animate={{ rotate: 360 }}
transition={{ duration: 4, repeat: Infinity, ease: "linear" }}
/>
</div>
<p className="sm:text-base text-sm sm:leading-6 leading-5 font-normal text-white sm:max-w-sm">
我们打造 <span className="text-teal-400">高性能</span> 的数字设计,提升品牌价值并增强转化效果。
</p>
</div>
<motion.div
initial={{ opacity: 0, y: 32 }}
animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: 32 }}
transition={{ duration: 0.3, ease: "easeInOut", delay: 0.2 }}
className="flex sm:flex-row flex-col items-start lg:items-baseline gap-4"
>
<h1 className="text-4xl sm:text-5xl md:text-7xl lg:text-8xl xl:text-9xl leading-10 lg:leading-32 font-bold">
SHADCN®SPACE
</h1>
<div>
<div className="bg-teal-400 rounded-full p-1 pl-8">
<div className="lg:p-3 p-2 bg-white text-black rounded-full">
<ArrowUpRight size={24} />
</div>
</div>
</div>
</motion.div>
</div>
</div>
</section>
);
};
export default HeroSection;英雄区工作原理:
- 视频背景:视频元素使用了 loop、autoPlay、muted 和 playsInline 属性。浏览器仅允许静音视频自动播放,playsInline 可防止 iPhone 全屏播放视频。object-cover 类使视频填充区域而不变形。
- 覆盖层:bg-black/50 层位于视频上方。这确保了视频任何帧上的白色文字都能清晰可读。
- 滚动进入视口的动画:useInView 钩子在视口可见区域达到 10%(amount: 0.1)时返回 true。once: true 选项确保只触发一次,避免每次回滚时标题再次淡入。
- 响应式标题:标题尺寸通过断点逐步增大,手机端为 text-4xl,大屏为 xl:text-9xl。小屏时标题和箭头垂直排列(flex-col),sm 及以上分辨率则水平排列。
- 为何需要 "use client":文件使用了钩子(useRef、useInView)和 Motion,这些都需要浏览器环境。在 Next.js App Router 中,需要在文件顶部添加 "use client" 指令。
components/shadcn-space/blocks/hero-03/navbar.tsx
"use client";
import { useEffect, useState, useRef } from "react";
import NavLink from "@/components/shadcn-space/blocks/hero-03/navlink";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Equal, X } from "lucide-react";
import { cn } from "@/lib/utils";
import { motion, useInView, AnimatePresence } from "motion/react";
type navData = {
href: string;
};
type NavbarProps = {
navigationData: navData[];
};
const Header = ({ navigationData }: NavbarProps) => {
const [menuOpen, setMenuOpen] = useState(false);
const [sticky, setSticky] = useState(false);
const headerRef = useRef<HTMLElement>(null);
const isInView = useInView(headerRef, { once: true, amount: 0.1 });
const handleScroll = () => {
setSticky(window.scrollY >= 80);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);return ( <header ref={headerRef} className={cn( "sticky top-0 z-50 w-full border-t-4 border-teal-400 transition-all duration-500 ease-in-out h-20 flex items-center", "before:content-[''] before:absolute before:top-0 before:left-0 before:w-full before:h-0 before:bg-teal-400 before:transition-all before:duration-500 before:ease-in-out", sticky && "before:h-full" )} > <motion.nav initial={{ opacity: 0, y: -32 }} animate={isInView ? { opacity: 1, y: 0 } : { opacity: 0, y: -32 }} transition={{ duration: 0.7, ease: "easeInOut" }} className={cn( "relative mx-auto max-w-7xl px-4 xl:px-16 flex item-center justify-between w-full" )} > <a href="#"> <img src="https://images.shadcnspace.com/assets/logo/shadcnspace-logo-white.svg" alt="brand logo" width={147} height={40} /> </a> <div> <AnimatePresence> {menuOpen && ( <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={() => setMenuOpen(false)} className="fixed inset-0 z-40 bg-black/40 backdrop-blur-sm" /> )} </AnimatePresence> <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}> {/* Trigger */} <DropdownMenuTrigger className="bg-white text-black flex items-center justify-center rounded-full sm:h-12 sm:w-12 h-10 w-10 p-2.5 sm:p-4 outline-none cursor-pointer"> <Equal size={16} /> </DropdownMenuTrigger> {/* Content */} <DropdownMenuContent align="end" sideOffset={20} className="min-w-xs sm:min-w-sm bg-background py-8 px-6 shadow-lg rounded-3xl border-none -mt-16" > <div className="flex flex-col gap-6"> {/* Header */} <div className="flex items-center justify-between"> <p className="text-lg font-medium text-foreground">Menu</p> <button onClick={() => setMenuOpen(false)} className="text-muted-foreground hover:text-foreground cursor-pointer" > <X size={20} /> </button> </div> <hr className="border-border" /> {/* Navigation */} <ul className="flex flex-col gap-4 pb-4"> {navigationData.map((menuItem, index) => ( <NavLink key={index} item={menuItem} /> ))} </ul> {/* Contact */} <div className="flex flex-col"> <a href="tel:+1-212-456-7890" className="text-lg font-normal leading-7 text-muted-foreground w-fit hover:text-primary" > +1-212-456-7890 </a> <a href="mailto:[email protected]" className="text-2xl font-semibold leading-8 text-foreground w-fit" > [email protected] </a> </div> </div>
</DropdownMenuContent>
</DropdownMenu>
</div>
</motion.nav>
</header>);
};export default Header;导航栏的工作原理:
- 带渐变背景的固定定位页眉:页眉使用了
sticky top-0的样式。通过before伪元素实现背景渐变效果,当sticky状态为真时,before伪元素从before:h-0渐变到before:h-full,使青绿色背景实现向下滑动效果而非瞬间切换。
- 滚动检测与清理:
handleScroll函数在滚动超过 80px 后将sticky设置为 true。useEffect钩子添加了滚动监听器,并在组件卸载时通过清理函数移除监听器。若未进行清理,组件卸载后监听器仍会保持激活状态。
- 受控下拉菜单:
open和onOpenChange属性与menuOpen状态绑定,这使得关闭按钮和遮罩层可以从外部关闭菜单。
- 动画遮罩层:
AnimatePresence允许深色遮罩层在离开页面前淡出。若未使用该组件,遮罩层将直接消失而没有退出动画。
- 菜单中的主题标记:菜单使用了
bg-background、text-foreground、text-muted-foreground和border-border样式。这些样式来自 shadcn/ui 主题配置,因此菜单会遵循系统设定的浅色/深色模式。
components/shadcn-space/blocks/hero-03/navlink.tsx
import { cn } from "@/lib/utils";
export type NavLinkItem = {
href: string;
isActive?: boolean;
};
export interface NavLinkProps {
item: NavLinkItem;
onClick?: () => void;
}
const NavLink: React.FC<NavLinkProps> = ({ item, }) => {
const { title, href, isActive } = item;
return (
<li className={cn(`group flex items-center transition-all duration-500 ease-in-out w-fit`,
isActive ? "gap-3" : "gap-0 hover:gap-3"
)}>
<div
className={cn(
"overflow-hidden transition-all duration-500 ease-in-out",
isActive ? "max-w-6 opacity-100" : "max-w-0 opacity-0 group-hover:max-w-6 group-hover:opacity-100",
)}
>
<img
src="https://images.shadcnspace.com/assets/svgs/primary-leaf.svg"
alt="icon"
height={20}
width={20}
className="animate-spin"
/>
</div>
<a
href={href}
className="text-foreground text-2xl sm:text-4xl sm:leading-10 leading-8 font-semibold"
>
{title}
</a>
</li>
);
};
export default NavLink;导航链接的工作原理:
- 组合悬停效果:
li元素上的group类允许图标容器在悬停整个链接项时作出响应,通过group-hover:伪类实现。
- 无布局跳动的渐显效果:图标容器从
max-w-0渐变到max-w-6,同时间距从gap-0渐变到gap-3。overflow-hidden类会隐藏图标直到有足够空间显示。激活状态的链接会始终显示图标。
- 类型化的数据结构:
NavLinkItem类型被导出,父组件可以使用该类型对自身数据进行类型标注。
components/shadcn-space/blocks/hero-03/index.tsx
import Navbar from "@/components/shadcn-space/blocks/hero-03/navbar";
import { NavLinkItem } from "@/components/shadcn-space/blocks/hero-03/navlink";
import HeroSection from "@/components/shadcn-space/blocks/hero-03/hero";
const HeroPage = () => {
const navigationData: NavLinkItem[] = [
{ title: "Home", href: "#", isActive: true },
{ title: "Properties", href: "#", isActive: false },
{ title: "Blog", href: "#", isActive: false },
{ title: "Contact", href: "#", isActive: false },
{ title: "Docs", href: "#", isActive: false },
];
return (
<>
<Navbar navigationData={navigationData} />
<main className="-mt-20">
<HeroSection />
</main>
</>
);
};
export default HeroPage;
索引文件的工作原理:
1. 数据集中管理:导航链接存储在 navigationData 数组中。导航栏仅显示接收到的内容,因此可以修改链接而无需改动导航栏本身。
2. 负边距使英雄区块位于导航栏下方:导航栏高度为 h-20(80px),main 元素上的 -mt-20 类将其向上移动相同距离,使视频内容能填满屏幕并覆盖在固定定位的头部下方。
### 运行前需要检查的内容
在打开页面前,请阅读代码并检查以下内容:
- 引入路径:每个引入路径应与 components.json 中的别名匹配。
- 依赖项:工具应已安装 motion 和 lucide-react。
- shadcn/ui 组件:dropdown-menu 组件应在 components/ui 目录中。如果没有,请运行 `npx shadcn@latest add dropdown-menu`。
- 类名:Tailwind 会忽略不认识的类名,因此拼写错误会导致渲染失败但不报错。在 navbar.tsx 中,nav 元素使用了 item-center,正确类名应为 items-center。你将在第4步修复这个问题。
花几分钟进行这些检查,能节省后续大量时间。
## 第3步:如何使用可复用的 shadcn/ui 组件构建界面
AI 工具通常会重复相同的界面元素。菜单、按钮和卡片都需要单独编写样式,导致每个元素外观都不一致。共享组件能解决这个问题。
以下代码块展示了三个可复制的习惯。
### 为每个功能使用单一组件
菜单使用 shadcn/ui 的 DropdownMenu 而非手动编写的菜单。通过一个经过测试的组件,你可以直接获得键盘支持、焦点处理和正确的可访问性属性。如果在其他页面添加第二个下拉菜单,其外观和行为将完全一致。
### 使用 cn() 处理条件类名
导航栏和导航链接都使用来自 @/lib/utils 的 cn()。它能合并类名并处理条件,例如 `sticky && "before:h-full"`。它还能移除冲突的 Tailwind 类名,这是普通模板字符串无法做到的。
### 将数据与界面分离
链接存储在 navigationData 数组中,NavLink 组件负责渲染。添加新页面只需向数组添加一个对象,无需编写任何新的 JSX。
### 何时从代码块开始构建
英雄区块和导航栏只是起点。实际产品还需要侧边栏、表格和图表。从零开始编写这些组件耗时且不同页面的输出往往不一致。
代码块为你提供经过验证的起点,提示语句负责处理修改。如果要构建管理后台,请查看 shadcn 的仪表盘代码块。它们提供了侧边栏、页眉和内容区域的布局。
本教程的英雄区块使用 Motion 实现淡入效果、旋转图标和基于滚动的显示效果。如果页面需要更多动画,shadcn 的动画代码块集合展示了此类动画的结构方式。
在使用任何代码块前,请像查看任何包一样阅读其代码并检查其许可证。将第一个结果视为草稿。每次提示只更改一项,这样可以看到每个提示带来的变化。如果更改导致问题,使用 Git 撤销更改,并让下一个提示更具体。
修正拼写错误
从步骤 2 的类名开始:
在 components/shadcn-space/blocks/hero-03/navbar.tsx 中,将 motion.nav 元素上的类 "item-center" 改为 "items-center"。不要更改其他任何内容。统一颜色风格
该区块在多个地方使用了固定的 teal-400 类。使用主题变量更便于后续修改:
将 hero-03 区块文件中所有 teal-400 类替换为主题主色变量。如需添加颜色,请在 globals.css 中的 CSS 变量中定义。不要更改其他任何内容。完成此更改后,只需修改一个 CSS 变量即可重新设计整个区块。
优化响应式行为
在 hero.tsx 中,让标题在屏幕宽度小于 640px 时自动换行,并保持箭头按钮始终位于标题下方。保持桌面端样式不变。处理视频加载延迟
视频从远程 URL 加载。加载完成前,用户会看到区块背景。要求添加清晰的备用画面:
在 hero.tsx 中,为 video 元素添加 poster 属性。保持 section 的 bg-black 背景,确保视频加载过程中或加载失败时文字仍可读。处理空菜单情况
导航栏通过 navigationData 映射生成菜单。如果数组为空,菜单将没有任何链接。要求工具处理这种情况:
在 navbar.tsx 中,如果 navigationData 为空,则不渲染菜单按钮。工具应使用类似以下结构包裹下拉菜单:
{navigationData.length > 0 && (
<DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>
{/* trigger 和 content 保持不变 */}
</DropdownMenu>
)}将固定内容转换为 props
导航栏中电话号码和邮箱地址直接写在组件内部。使用 props 可使导航栏更具复用性:
在 navbar.tsx 中,添加两个 props:phone 和 email。用它们替换硬编码的电话号码和邮箱地址。更新 index.tsx 以传递这些值。保持所有样式不变。每次提示后,检查更改的文件,运行页面并确认工作正常后再提交。
第 5 步:如何运行和自定义最终 UI
启动开发服务器:
npm run dev在浏览器中打开 http://localhost:3000/hero-03。这是 app/hero-03/page.tsx 创建的路由。
执行以下检查
- 将窗口调整为约 375px 宽:标题应自动缩小,内容应保持在屏幕内。
- 打开菜单:通过关闭按钮、遮罩层和 Esc 键关闭菜单。
- 使用键盘:按 Tab 键,确认菜单按钮显示可见的聚焦状态。
- 向下滚动:导航栏应始终固定在顶部,其 teal 背景在滚动 80px 后滑入。
- 悬停链接:链接旁边应显示旋转图标。
- 检查错误:运行以下两个命令:
npx tsc --noEmit
npm run lint自定义页面
可以通过更新导航、内容、资源、联系方式和主题样式来自定义页面。
1. 更新导航链接
打开 index.tsx,编辑 navigationData 数组以更改菜单标签和 URL。
const navigationData = [
{ title: "Home", href: "/" },
{ title: "Features", href: "/features" },
{ title: "Pricing", href: "/pricing" },
{ title: "Contact", href: "/contact" },
];确保每个链接都指向应用程序中的有效路由。
2. 更改标题和正文
打开 hero.tsx 文件,将现有的标题、描述和按钮标签替换为你的内容。
<h1>Build Your Next Project Faster</h1>
<p>Explore reusable UI components for your next web application.</p>保持现有的布局和组件结构不变。
3. 替换图片、视频和图标
将资源文件添加到 public 目录,并在相关组件中更新它们的路径。
<img src="/images/logo.svg" alt="Company logo" />
<video autoPlay muted loop playsInline>
<source src="/videos/hero-video.mp4" type="video/mp4" />
</video>例如,public/images/logo.svg 可通过 /images/logo.svg 访问。
4. 更新联系方式
打开 navbar.tsx 文件,替换现有的电话号码和电子邮件地址。
<a href="tel:+15551234567">+1 (555) 123-4567</a>
<a href="mailto:[email protected]">[email protected]</a>使用你实际的联系方式,并更新其他显示联系方式的组件。
5. 更改主题颜色
在 globals.css 中编辑 CSS 变量以更新页面颜色。
:root {
--primary: #2563eb;
--background: #ffffff;
--foreground: #111827;
}使用项目中已定义的变量名称,并在应用支持暗黑模式时更新暗黑主题变量。
6. 自定义下拉菜单样式
打开 components/ui/dropdown-menu.tsx 文件,更新相关的 Tailwind CSS 类。
例如,将 rounded-sm px-2 py-1.5 改为 rounded-md px-3 py-2 以调整下拉菜单项的圆角和间距。
对这个共享组件的修改可能会影响所有使用它的下拉菜单,因此需要在应用中测试所有下拉菜单。
7. 运行并测试你的更改
启动开发服务器并检查所有功能是否按预期工作。
npm run dev
npm run lint
npm run build在运行代码检查和构建命令前,先查看 package.json 中可用的脚本。
在部署前始终测试 AI 生成的代码。即使代码看起来正确,仍可能无法构建、加载资源失败或在浏览器中出现意外行为(详见下文)。
实时预览:
我在部署前如何检查 AI 生成的代码
AI 编码代理可以创建或修改多个文件、安装依赖项并运行终端命令。我将代理的输出视为起点,而非生产就绪的代码。在部署前,我会审查更改并验证应用是否按预期运行。
在部署 AI 生成的代码前,我建议进行以下检查:
1. 审查更改
检查代理创建或修改了哪些文件。审查代码以理解更改内容、是否遵循现有项目结构以及是否引入了不必要的依赖项或无关的修改。
使用 Git 可通过以下命令检查更改:
git diff
git status如果你不理解某个更改,请在接受前要求代理解释其目的和潜在副作用。
2. 运行应用并测试关键交互
启动开发服务器并在浏览器中打开应用。测试你修改的功能,而不仅仅是检查页面是否加载。
例如,验证导航链接是否正常工作、下拉菜单是否能打开和关闭、按钮是否执行预期操作、表单是否验证输入、图片或视频是否正确加载。同时检查页面在移动设备和桌面屏幕尺寸下的表现。
打开浏览器的开发者控制台,查看 JavaScript 错误、失败的网络请求和缺失的资源。
3. 运行自动化检查
使用 package.json 中提供的脚本检查代码质量、运行测试并验证生产环境构建。
npm run lint
npm test
npm run build这些是常见示例,而非通用命令。你的项目可能没有定义测试脚本,因此请先检查可用脚本。在继续之前,请修复所有相关错误。
4. 检查安全性和配置
审查新添加的依赖项、API 调用、环境变量以及处理用户输入或敏感数据的代码。切勿在客户端代码中暴露 API 密钥或秘密信息,不要在不了解 AI 代理执行内容的情况下运行陌生命令。
对于处理身份验证、支付或用户数据的应用程序,请执行与这些功能相关的额外安全检查。
5. 部署前验证
在发布前,确认生产环境构建成功、主要用户流程正常运作且没有重要功能退化。再次审查最终更改,并在有预发布环境时优先部署到该环境。
我的原则很简单:如果无法解释生成代码的作用,我就没有准备好发布。AI 代理可以加速开发,但审查、测试和对最终代码负责仍然是开发者的职责。
关键概念回顾
提示即规格说明
优秀的 UI 提示应说明布局、组件、颜色、间距和响应式行为。同时应注明技术栈、列出文件路径、给出有序步骤,并定义"完成"的标准。
获取提示的两种方式
你可以使用 AI 工具编写提示,或从免费/专业块页面复制提示并粘贴到任何 AI 工具中。
运行前请阅读
检查生成代码中的错误导入、缺失依赖、类名拼写错误和固定值。Tailwind 会忽略未知类,因此拼写错误会静默失败。
重用组件
共享的 shadcn/ui 组件可提供一致的行为和样式。使用 cn() 实现条件类,将数据与标记分离存储在数组中。
分组悬停与逻辑布局
group 类可以让子元素响应父元素的悬停状态。导航链接使用它来在不引起布局跳动的情况下显示图标。
基于滚动的动画
useInView 配合 once: true 参数会在元素进入屏幕时仅执行一次动画。
Next.js 中的 "use client"
任何使用钩子、浏览器事件或 Motion 的文件都需要在顶部添加 "use client" 指令。
简短的后续提示
每次提示只修改一个内容,审查差异,并在每次获得良好结果后提交更改。
结论
在本教程中,你学习了如何使用 AI 提示构建网站用户界面。你编写了涵盖布局、组件、颜色、间距和响应式行为的提示。你生成了包含动画导航栏的英雄区块,检查了每个文件,并通过简短的后续提示改进了结果。
你还了解了共享组件的重要性。下拉菜单、cn() 辅助函数和数据驱动链接保持了代码一致性,而区块为大型页面提供了良好的起点。
在下一页中,先编写规格说明,命名你的技术栈和文件,再继续前请阅读输出内容。这种习惯能让你从任何 AI 编码工具中获得更好的结果。
资源
- Shadcn UI : 可复制粘贴的 shadcn/ui 组件、区块、模板和仪表板布局合集。
- Shadcn Space : 免费和专业区块库,包含可复制的提示。
- Shadcn 仪表盘模块:提供带侧边栏和内容区域的现成管理界面布局。
- Shadcn 动画模块:使用 motion 实现动态效果的模块。
- Next.js 官方文档
- Tailwind CSS 官方文档
- Motion 官方文档
- Lucide 图标库
合作伙伴推荐课程
(opens in a new tab)
ADVERTISEMENT
- Coursera 上的《从零开始学习 Tailwind CSS:通过构建项目学习》Packt - 课程讲师 11 周,每周 1 小时 初学者 证书 查看课程 (opens in a new tab)
- Coursera 上的《Tailwind CSS 实践项目》Rachel Johnson 1 小时 21 分钟 中级 证书 查看课程 (opens in a new tab)
- Udemy 上的《AI 编程:从规划到生产》Brad Traversy 4.7/5 星(968 人评价)16 小时 中级 证书 查看课程 (opens in a new tab)
- Udemy 上的《完整 Bootstrap 4 课程:构建 3 个项目》Igneus Technologies 4.1/5 星(5,455 人评价)4 小时 54 分钟 初学者 查看课程 (opens in a new tab)
更多 Tailwind CSS 课程请访问 Class Central
→
阅读更多文章
如果你读到这里,请感谢作者以表达你的支持。说声谢谢
免费学习编程。freeCodeCamp 的开源课程已帮助超过 40,000 人成为开发者。立即开始