Skip to content
Lenso UI

框架集成

将 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/tokens

2. 导入样式

在主 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;}

下一步

  • 快速入门 — 最快上手的方式
  • 主题 — 自定义颜色和设计令牌
  • 组合 — 变体函数与多态样式
  • 组件 — 探索所有可用的组件