框架集成
将 HeroUI 集成到你的框架中
Next.js
1. 创建 Next.js 项目
npx heroui-cli@latest init -t app-t 会跳过模板选择步骤,但仍会提示你输入项目名称并选择包管理器 —— 直接传入这两项即可跳过所有提示:npx heroui-cli@latest init my-app -t app -p pnpm。然后进入新创建的文件夹并安装依赖(例如 pnpm install)。
2. 使用你的第一个 HeroUI 组件
示例:app/page.tsx
import {Button} from "@lenso/ui";
export default function HomePage() { return ( <main className="flex min-h-screen items-center justify-center"> <Button variant="tertiary">Hello HeroUI</Button> </main> );}HeroUI v3 无需 Provider。安装并导入样式后,组件即可直接使用。
3. 区域设置(可选)
为了与 Next.js 集成,请确保服务端的区域设置与客户端一致。
在根布局中,确定用户的首选语言,并在 <html> 元素上设置 lang 和 dir 属性。
// app/layout.tsximport {headers} from 'next/headers';import {isRTL} from '@lenso/ui';import {ClientProviders} from './provider';
export default async function RootLayout({children}) { // Get the user's preferred language from the Accept-Language header. // You could also get this from a database, URL param, etc. const acceptLanguage = (await headers()).get('accept-language'); const lang = acceptLanguage?.split(/[,;]/)[0] || 'en-US';
return ( <html lang={lang} dir={isRTL(lang) ? 'rtl' : 'ltr'}> <body> <ClientProviders lang={lang}> {children} </ClientProviders> </body> </html> );}创建 app/provider.tsx,其中应渲染一个 I18nProvider,用于设置 React Aria 所使用的区域设置。
// app/provider.tsx"use client";
import {I18nProvider} from '@lenso/ui';
export function ClientProviders({lang, children}) { return ( <I18nProvider locale={lang}> {children} </I18nProvider> );}如果你使用了带 nonce 的 内容安全策略(CSP),请在文档的 head 中添加 <meta property="csp-nonce"> 标签,并将其 content 属性设置为生成的 nonce 值。React Aria 会自动从该标签读取 nonce。
Vite
1. 创建 Vite 项目
npx heroui-cli@latest init -t vite-t 会跳过模板选择步骤,但仍会提示你输入项目名称并选择包管理器 —— 直接传入这两项即可跳过所有提示:npx heroui-cli@latest init my-app -t vite -p pnpm。然后进入新创建的文件夹并安装依赖(例如 pnpm install)。
2. 使用你的第一个 HeroUI 组件
示例:src/App.tsx
import {Button} from "@lenso/ui";
function App() { return ( <main className="flex min-h-screen items-center justify-center"> <Button variant="tertiary">Hello HeroUI</Button> </main> );}
export default App;HeroUI v3 无需 Provider。安装并导入样式后,组件即可直接使用。
React Router
1. 创建 React Router 项目
npx heroui-cli@latest init -t react-router-t 会跳过模板选择步骤,但仍会提示你输入项目名称并选择包管理器 —— 直接传入这两项即可跳过所有提示:npx heroui-cli@latest init my-app -t react-router -p pnpm。然后进入新创建的文件夹并安装依赖(例如 pnpm install)。
2. 使用你的第一个 HeroUI 组件
示例:app/routes/_index.tsx
import {Button} from "@lenso/ui";
export default function Index() { return ( <main className="flex min-h-screen items-center justify-center"> <Button variant="tertiary">Hello HeroUI</Button> </main> );}该模板在 app/root.tsx 中通过 import "./tailwind.css"; 加载样式。HeroUI v3 无需 Provider,安装并导入样式后,组件即可直接使用。
其他框架
@lenso/ui 的交互行为基于 React Aria 构建,因此必须在 React 中使用。但设计系统本身位于 @lenso/tokens —— 这是一个不依赖 React 的包,提供 HeroUI 的 BEM 类名和与框架无关的变体函数。你可以在 Vue、Svelte、Angular 或纯 HTML 中使用它。
这种方式只提供 HeroUI 的视觉样式,不包含交互行为。键盘导航、焦点管理和 ARIA 属性均由 @lenso/ui 中的 React Aria 提供,因此在你自己的组件中需要自行实现。
1. 安装样式包
npm i @lenso/tokens2. 导入样式
在主 CSS 文件中添加:
@import "tailwindcss";@import "@lenso/tokens";只有这种方式才能让 Tailwind 工具类与 HeroUI 类名一起使用。
预编译产物和 CDN 产物包含 HeroUI 的组件类名和主题令牌,但不包含 Tailwind 的工具类。如果你还需要使用 flex、gap-4 这类工具类,请选择 Tailwind CSS v4 方式。
3. 使用你的第一个 HeroUI 组件
你可以直接使用 BEM 类名,也可以通过变体函数生成类名以获得类型安全。
<script setup lang="ts">import {buttonVariants} from "@lenso/tokens";
const buttonClass = buttonVariants({variant: "primary"});</script>
<template> <button :class="buttonClass">Hello HeroUI</button>
<!-- 或者直接使用 BEM 类名 --> <button class="button button--primary">Hello HeroUI</button></template>所有组件都遵循相同的 BEM 约定:一个块级类名、用 -- 表示变体和尺寸的修饰符、用 __ 表示子元素。以 button 为例,变体为 .button--primary、--secondary、--tertiary、--ghost、--outline、--danger 和 --danger-soft;尺寸为 .button--sm、--md 和 --lg;.button--icon-only 和 .button--full-width 则是修饰符。
关于变体函数以及如何将 HeroUI 样式应用到任意元素,请参阅 组合。
4. 交互状态
HeroUI 的 CSS 同时匹配原生伪类和 data-* 属性,因此语义化的 HTML 元素无需任何 JavaScript 即可获得悬停、按下、聚焦和禁用样式:
/* button.css */.button { &:active, &[data-pressed="true"] { ... }
&:disabled, &[aria-disabled="true"] { ... }}浏览器无法自行推断的状态则需要你手动设置。常见的属性包括:
| 属性 | 用途 |
|---|---|
data-selected="true" | 菜单、列表框和标签页中的选中项 |
data-entering="true" / data-exiting="true" | 浮层的进入和退出动画 |
data-placement="top" | 弹出框和工具提示的箭头方向与偏移 |
data-invalid="true" | 表单字段的校验样式 |
data-slot="..." | 标记复合组件的子部件 |
button、chip、card、skeleton 等无状态组件可以直接以标记形式使用。而浮层和集合类组件(select、menu、popover、date picker)依赖你自行管理的状态 —— 建议这类组件继续使用 React,或查阅对应组件 CSS 文件中的 data-* 选择器以了解所需的属性。
5. 主题
深色模式由任意祖先元素上的 .dark 类名或 data-theme="dark" 属性控制:
<html class="dark">...</html>
<!-- 或 --><html data-theme="dark">...</html>通过重新定义 CSS 变量来覆盖主题:
:root { --accent: oklch(0.62 0.19 253); --radius: 0.5rem;}