从 Vite starter 开始,或复制 Next.js 设置面板与破坏性确认对话框配方。
仓库提供一个紧凑的 Vite + React 19 + TypeScript starter,已经导入组件样式,并渲染 一个包含实时工作区预览、三张特性卡片、明暗主题切换与行动按钮的落地页。
pnpm dlx degit xingxingmofashu/ui/templates/starter my-app
cd my-app
pnpm install
pnpm devStarter 固定了一个已发布的组件包版本。克隆后需要新版本时,更新 package.json 中
的 @xingxingmofashu/ui。
关键文件:
src/index.css 导入 Tailwind CSS、组件样式与玻璃预设样式,并绘制页面背景。src/App.tsx 包含 Hero 文案、特性卡片、行动按钮与页脚。src/hero-preview.tsx 包含可交互的预览卡片。它的材质切换使用
GlassPresetScope,因此只影响该卡片;如果需要全局且持久化的预设,请用
GlassPresetProvider 包裹应用。src/use-theme.ts 负责持久化明暗主题。vite.config.ts 包含 Tailwind 与 React 插件。预览卡片使用了 Tabs、Switch、Progress、ToggleGroup、Button 与 Toast。
可以按产品需要替换其中的内容。
在现有的 Next.js 16 项目中安装组件包:
pnpm add @xingxingmofashu/ui在全局 CSS 文件中导入样式:
@import "tailwindcss";
@import "@xingxingmofashu/ui";从服务端组件渲染服务端安全的 Card:
import { Card } from "@xingxingmofashu/ui/components/card";
export default function Page() {
return (
<main className="mx-auto max-w-3xl p-8">
<Card title="Liquid glass" description="在服务端渲染。">
<p className="text-sm text-ui-ink/70">
需要交互时,在卡片内添加客户端组件。
</p>
</Card>
</main>
);
}在拥有状态或事件处理的文件顶部添加 "use client"。边界规则见
服务端渲染。
一个完整的设置面板,包含卡片、开关与保存操作。按钮和开关需要客户端状态,因此整个 面板是客户端组件。
"use client";
import { useState } from "react";
import { Button, Card, Switch } from "@xingxingmofashu/ui";
export function SettingsPanel() {
const [saved, setSaved] = useState(false);
return (
<Card
className="w-full max-w-lg"
title="通知"
description="选择工作区向你的收件箱发送哪些内容。"
footer={
<Button
size="sm"
label={saved ? "已保存" : "保存更改"}
onClick={() => setSaved(true)}
/>
}
>
<div className="flex flex-col gap-5">
<Switch
label="邮件通知"
description="队友发布更改时发送摘要。"
defaultChecked
/>
<Switch
label="每周摘要"
description="每周一早上给团队发邮件。"
/>
<Switch
label="@ 提及"
description="有人提到你的名字时通知你。"
defaultChecked
/>
</div>
</Card>
);
}AlertDialog 专为不可逆操作设计。确认与取消按钮会自动关闭对话框;用回调执行副作用。按 Escape 也会关闭对话框且不会调用任一回调,因此需要时请在 onOpenChange 中保护破坏性操作。
"use client";
import { Trash2 } from "lucide-react";
import { useState } from "react";
import { AlertDialog, Button } from "@xingxingmofashu/ui";
export function DeleteProject() {
const [open, setOpen] = useState(false);
return (
<>
<Button
label="删除项目"
leadingIcon={<Trash2 />}
onClick={() => setOpen(true)}
/>
<AlertDialog
open={open}
onOpenChange={setOpen}
title="删除项目?"
description="此操作无法撤销。所有文件与部署都会被移除。"
confirmLabel="删除项目"
cancelLabel="取消"
onConfirm={() => {
// 在这里调用删除接口。
}}
/>
</>
);
}当面板需要从边缘滑入时,使用 Drawer 而不是 Dialog。底部按钮不会自动关闭
抽屉,因此需要自行更新 open。
"use client";
import { Settings } from "lucide-react";
import { useState } from "react";
import { Button, Drawer, Switch } from "@xingxingmofashu/ui";
export function MobileSettings() {
const [open, setOpen] = useState(false);
return (
<>
<Button
label="设置"
leadingIcon={<Settings />}
onClick={() => setOpen(true)}
/>
<Drawer
open={open}
onOpenChange={setOpen}
title="设置"
description="更改仅应用于此设备。"
footer={
<>
<Button size="sm" label="取消" onClick={() => setOpen(false)} />
<Button size="sm" label="完成" onClick={() => setOpen(false)} />
</>
}
>
<Switch label="通知" defaultChecked />
</Drawer>
</>
);
}