Skip to content
Lenso UI

设计原则

指导 HeroUI v3 设计和开发的核心原则

HeroUI v3 遵循 10 项核心原则,注重清晰度、无障碍、可定制性以及开发者体验。

核心原则

1. 语义意图优于视觉风格

使用语义命名(primary、secondary、tertiary),而非视觉描述(solid、flat、bordered)。灵感来自 Uber 的 Base 设计系统,变体遵循清晰的层次结构:

语义意图层次结构
// ✅ Semantic variants communicate hierarchy<Button variant="primary">Save</Button><Button variant="secondary">Edit</Button><Button variant="tertiary">Cancel</Button>
变体用途使用方式
Primary推进流程的主要操作每种场景 1 个
Secondary备选操作可使用多个
Tertiary次要操作(取消、跳过)谨慎使用
Danger破坏性操作需要时使用

2. 无障碍是基础

基于 React Aria Components 构建,符合 WCAG 2.1 AA 标准。内置自动 ARIA 属性、键盘导航与屏幕阅读器支持。

import { Tabs, TabList, Tab, TabPanel } from '@lenso/ui';
<Tabs defaultSelectedKey="profile">  <TabList aria-label="Settings">    <Tab id="profile">Profile</Tab>    <Tab id="security">Security</Tab>  </TabList>  <TabPanel id="profile">Content</TabPanel>  <TabPanel id="security">Content</TabPanel></Tabs>

3. 组合优于配置

复合组件允许你按需重新组合、自定义或省略其中的各个部分。可以使用点号语法、命名导出,或两者混合使用。

// Compose parts to build exactly what you needimport {  Accordion,  AccordionItem,  AccordionHeading,  AccordionTrigger,  AccordionIndicator,  AccordionPanel,  AccordionBody} from '@lenso/ui';
<Accordion>  <AccordionItem id="1">    <AccordionHeading>      <AccordionTrigger>        Question Text        <AccordionIndicator />      </AccordionTrigger>    </AccordionHeading>    <AccordionPanel>      <AccordionBody>Answer content</AccordionBody>    </AccordionPanel>  </AccordionItem></Accordion>

4. 渐进式呈现

从简单开始,仅在需要时才增加复杂度。组件只需最少的 props 即可工作,并能随需求增长而扩展。

// Level 1: Minimal<Button>Click me</Button>
// Level 2: Enhanced<Button variant="primary" size="lg">  <Icon icon="gravity-ui:check" className="mr-2" />  Submit</Button>
// Level 3: Advanced<Button variant="primary" isDisabled={isLoading}>  {isLoading ? <><Spinner size="sm" className="mr-2" /> Loading...</> : 'Submit'}</Button>

5. 可预测的行为

所有组件遵循一致的模式:尺寸(sm、md、lg)、变体、className 支持以及 data 属性。相同的 API,相同的行为。

// All components follow the same patterns<Button size="lg" variant="primary" className="custom" data-pressed="true" /><Chip size="lg" variant="success" className="custom" /><Avatar size="lg" className="custom" />
// Compound components support both named exports and dot notationimport { Alert, AlertIcon, CardHeader, AccordionTrigger } from '@lenso/ui';
// Named exports<Alert>  <AlertIcon /></Alert>
// Dot notation<Alert>  <Alert.Icon /></Alert>

6. 类型安全优先

完整的 TypeScript 支持,包括 IntelliSense、自动补全与编译时错误检测。可为自定义组件扩展类型。

import type { ButtonProps } from '@lenso/ui';
// Type-safe props and event handlers<Button  variant="primary"  // Autocomplete: primary | secondary | tertiary | danger | ghost  size="md"          // Type checked: sm | md | lg  onPress={(e) => {  // e is properly typed as PressEvent    console.log(e.target);  }}/>
// Extend types for custom componentsinterface CustomButtonProps extends Omit<ButtonProps, 'variant'> {  intent: 'save' | 'cancel' | 'delete';}

7. 样式与逻辑分离

样式(@lenso/tokens)与逻辑(@lenso/ui)相互分离,可与任何框架或纯 HTML 一同使用。参见 Tailwind Play 示例。

<!-- Use with plain HTML --><button class="button button--primary">Click me</button>

或与 React 一同使用:

// Apply styles to any componentimport { buttonVariants } from '@lenso/tokens';
<Link className={buttonVariants({ variant: "primary" })} href="/home">  Home</Link>

8. 卓越的开发者体验

清晰的 API、富含信息的错误提示、IntelliSense、对 AI 友好的 Markdown 文档,以及用于可视化测试的 Storybook。

9. 完全可定制

开箱即用的精美默认样式。使用 CSS 变量或 BEM 类即可彻底改变整体外观。每一个插槽都可定制。

/* Theme-wide changes with variables */:root {  --accent: oklch(0.7 0.25 260);  --radius: 0.375rem;  --spacing: 0.5rem;}
/* Component-specific customization */@layer components {  .button {    @apply uppercase tracking-wider;  }  .button--primary {    @apply bg-gradient-to-r from-purple-500 to-pink-500;  }}

10. 开放且可扩展

可以包装、扩展或自定义组件以满足你的需求。可以使用变体函数、直接应用 BEM 类,或创建自定义的包装组件。

使用变体函数应用样式:

import { Link } from '@lenso/ui';import { linkVariants } from '@lenso/tokens';import NextLink from 'next/link';
// Use variant functions to style framework-specific componentsconst slots = linkVariants({ underline: "hover" });
<NextLink className={slots.base()} href="/about">  About Page  <Link.Icon className={slots.icon()} /></NextLink>

直接应用 BEM 类:

import Link from 'next/link';
// Apply HeroUI's BEM classes directly to any element<Link className="button button--primary" href="/dashboard">  Dashboard</Link>

创建自定义包装组件:

// Custom wrapper componentconst CTAButton = ({  intent = 'primary-cta',  children,  ref,  ...props}: CTAButtonProps) => {  const variantMap = {    'primary-cta': 'primary',    'secondary-cta': 'secondary',    'minimal': 'ghost'  };
  return (    <Button ref={ref} variant={variantMap[intent]} {...props}>      {children}    </Button>  );};

使用 Tailwind Variants 扩展:

import { Button } from '@lenso/ui';import { buttonVariants, tv } from '@lenso/tokens';
// Extend button styles with custom variantsconst myButtonVariants = tv({  extend: buttonVariants,  variants: {    variant: {      'primary-cta': 'bg-gradient-to-r from-blue-500 to-purple-600 text-white shadow-lg',      'secondary-cta': 'border-2 border-blue-500 text-blue-500 hover:bg-blue-50',    }  }});
// Use the custom variantsfunction CustomButton({ variant, className, ...props }) {  return <Button className={myButtonVariants({ variant, className })} {...props} />;}
// Usage<CustomButton variant="primary-cta">Get Started</CustomButton><CustomButton variant="secondary-cta">Learn More</CustomButton>

与 HeroUI v2 的对比

维度HeroUI v2HeroUI v3
动画Framer MotionCSS + GPU 加速
组件模式带有大量 props 的单一组件复合组件
变体基于视觉(solid、bordered、flat)基于语义(primary、secondary、tertiary)
样式部分支持 Tailwind v4完整支持 Tailwind v4
无障碍优秀(基于 React Aria)优秀(基于 React Aria)
打包体积较大(整体打包)较小(支持 tree-shaking)
自定义难度中等(基于 props)简单(复合组件 + 原生 CSS)