Skip to content
Lenso UI

Button 按钮

可点击的按钮组件,支持多种变体与状态

用法

import { Button } from '@lenso/ui';

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
import { Button } from "@lenso/ui";
export function Basic() {  return <Button onClick={() => console.log("Button pressed")}>Click me</Button>;}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

示例

变体

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ row: { display: "flex", flexWrap: "wrap", gap: 12 } });export function Variants() {  return (    <div {...stylex.props(styles.row)}>      <Button variant="primary">Primary</Button>      <Button variant="secondary">Secondary</Button>      <Button variant="tertiary">Tertiary</Button>      <Button variant="outline">Outline</Button>      <Button variant="ghost">Ghost</Button>      <Button variant="danger">Danger</Button>      <Button variant="danger-soft">Danger Soft</Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

尺寸

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ row: { display: "flex", alignItems: "center", gap: 12 } });export function Sizes() {  return (    <div {...stylex.props(styles.row)}>      <Button size="sm">Small</Button>      <Button size="md">Medium</Button>      <Button size="lg">Large</Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

带图标

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Envelope, Globe, Plus, TrashBin } from "@gravity-ui/icons";import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";export function WithIcons() {  return (    <div {...stylex.props(styles.row)}>      <Button>        <Button.Icon>          <Globe />        </Button.Icon>        Search      </Button>      <Button variant="secondary">        <Button.Icon>          <Plus />        </Button.Icon>        Add Member      </Button>      <Button variant="tertiary">        <Button.Icon>          <Envelope />        </Button.Icon>        Email      </Button>      <Button variant="danger">        <Button.Icon>          <TrashBin />        </Button.Icon>        Delete      </Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

仅图标

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Ellipsis, Gear, TrashBin } from "@gravity-ui/icons";import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";export function IconOnly() {  return (    <div {...stylex.props(styles.row)}>      <Button isIconOnly aria-label="More options" variant="tertiary">        <Button.Icon>          <Ellipsis />        </Button.Icon>      </Button>      <Button isIconOnly aria-label="Settings" variant="secondary">        <Button.Icon>          <Gear />        </Button.Icon>      </Button>      <Button isIconOnly aria-label="Delete" variant="danger">        <Button.Icon>          <TrashBin />        </Button.Icon>      </Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

加载中

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Button, Spinner } from "@lenso/ui";export function Loading() {  return (    <Button isLoading>      <Spinner color="current" size="sm" />      Uploading...    </Button>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

加载中(点击触发)

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Paperclip } from "@gravity-ui/icons";import { Button, Spinner } from "@lenso/ui";import { useEffect, useRef, useState } from "react";export function LoadingState() {  const [isLoading, setLoading] = useState(false);  const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);  useEffect(() => () => clearTimeout(timer.current), []);  return (    <Button      isLoading={isLoading}      onClick={() => {        setLoading(true);        timer.current = setTimeout(() => setLoading(false), 2000);      }}    >      {isLoading ? (        <Spinner color="current" size="sm" />      ) : (        <Button.Icon>          <Paperclip />        </Button.Icon>      )}      {isLoading ? "Uploading..." : "Upload File"}    </Button>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

宽度充满

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Plus } from "@gravity-ui/icons";import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";export function FullWidth() {  return (    <div {...stylex.props(styles.full)}>      <Button fullWidth>Primary Button</Button>      <Button fullWidth>        <Button.Icon>          <Plus />        </Button.Icon>        With Icon      </Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

禁用状态

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";
import { Button } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ row: { display: "flex", flexWrap: "wrap", gap: 12 } });export function Disabled() {  return (    <div {...stylex.props(styles.row)}>      <Button disabled>Primary</Button>      <Button disabled variant="secondary">        Secondary      </Button>      <Button disabled variant="tertiary">        Tertiary      </Button>      <Button disabled variant="outline">        Outline      </Button>      <Button disabled variant="ghost">        Ghost      </Button>      <Button disabled variant="danger">        Danger      </Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

社交媒体按钮

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Button } from "@lenso/ui";import { Icon } from "@iconify/react";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";export function Social() {  return (    <div {...stylex.props(styles.social)}>      <Button variant="tertiary" fullWidth>        <Button.Icon>          <Icon icon="devicon:google" />        </Button.Icon>        Sign in with Google      </Button>      <Button variant="tertiary" fullWidth>        <Button.Icon>          <Icon icon="mdi:github" />        </Button.Icon>        Sign in with GitHub      </Button>      <Button variant="tertiary" fullWidth>        <Button.Icon>          <Icon icon="ion:logo-apple" />        </Button.Icon>        Sign in with Apple      </Button>    </div>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

渲染函数

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Button } from "@lenso/ui";import { useState } from "react";export function RenderFunction() {  const [pressed, setPressed] = useState(false);  return (    <Button      onPointerDown={() => setPressed(true)}      onPointerUp={() => setPressed(false)}      onPointerCancel={() => setPressed(false)}      onPointerLeave={() => setPressed(false)}      onKeyDown={(event) => {        if (event.key === " " || event.key === "Enter") setPressed(true);      }}      onKeyUp={() => setPressed(false)}      onBlur={() => setPressed(false)}      render={(props) => <button {...props} data-custom={pressed ? "pressed" : "bar"} />}    >      Press me    </Button>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

添加自定义变体

可通过包装组件并添加自定义变体来扩展 HeroUI 组件。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0. Variant composition uses StyleX, not tailwind-variants.import { Button, type ButtonRootProps } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";import { styles } from "./source.stylex";const radii = stylex.create({  full: { borderRadius: 9999 },  lg: { borderRadius: 8 },  md: { borderRadius: 6 },  sm: { borderRadius: 2 },});const sizes = stylex.create({  sm: { height: 40, paddingInline: 16 },  md: { height: 44, paddingInline: 24 },  lg: { height: 48, paddingInline: 32 },  xl: { height: 52, paddingInline: 40 },});type CustomButtonProps = Omit<ButtonRootProps, "size"> & {  size?: keyof typeof sizes;  radius?: keyof typeof radii;};function CustomButton({ radius = "full", size = "md", xstyle, ...props }: CustomButtonProps) {  return <Button {...props} xstyle={[styles.custom, radii[radius], sizes[size], xstyle]} />;}export function CustomVariants() {  return <CustomButton>Custom Button</CustomButton>;}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

添加涟漪效果

Button 组件通过组合支持 ripple 效果,可将 ripple 组件作为子节点嵌套。本示例使用 m3-ripple。

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Button } from "@lenso/ui";import { Ripple } from "m3-ripple";import "m3-ripple/ripple.css";export function RippleEffect() {  return (    <Button variant="secondary">      <Ripple />      Click me    </Button>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

自定义样式

Tailwind CSS

此预览复用英文版适配,不代表中文源示例已完成本地实现。

"use client";// Adapted from HeroUI v3.2.6 (e385ac2), Apache-2.0.import { Button } from "@lenso/ui";import { styles } from "./source.stylex";export function CustomStyles() {  return (    <Button variant="ghost" xstyle={styles.upgrade}>      Upgrade    </Button>  );}

Local adaptation source above. Derived from HeroUI v3.2.6 source.

全局 CSS

可使用 @layer components 指令自定义 Button 组件类。 了解更多。

@layer components {  .button {    @apply bg-purple-500 text-white hover:bg-purple-600;  }
  .button--icon-only {    @apply rounded-lg bg-blue-500;  }}

样式参考

HeroUI 遵循 BEM 方法论,确保组件变体与状态可复用且易于自定义。

CSS 类

Button 组件使用以下 CSS 类(查看源码样式):

基础与尺寸类 [!toc]

  • .button - 基础按钮样式
  • .button--sm - 小尺寸变体
  • .button--md - 中尺寸变体
  • .button--lg - 大尺寸变体

变体类 [!toc]

  • .button--primary
  • .button--secondary
  • .button--tertiary
  • .button--outline
  • .button--ghost
  • .button--danger

修饰符类 [!toc]

  • .button--icon-only
  • .button--icon-only.button--sm
  • .button--icon-only.button--lg

交互状态

按钮同时支持 CSS 伪类与 data 属性:

  • Hover::hover 或 [data-hovered="true"]
  • Active/Pressed::active 或 [data-pressed="true"](含缩放变换)
  • Focus::focus-visible 或 [data-focus-visible="true"](显示焦点环)
  • Disabled::disabled 或 [aria-disabled="true"](降低透明度,禁用指针事件)
  • Pending:[data-pending](加载期间禁用指针事件)

API 参考

Button

Prop类型默认值描述
variant'primary' | 'secondary' | 'tertiary' | 'outline' | 'ghost' | 'danger''primary'视觉样式变体
size'sm' | 'md' | 'lg''md'按钮尺寸
fullWidthbooleanfalse是否占满容器宽度
isDisabledbooleanfalse是否禁用
isPendingbooleanfalse是否处于加载状态
isIconOnlybooleanfalse是否仅包含图标
onPress(e: PressEvent) => void-按下时的回调
childrenReact.ReactNode | (values: ButtonRenderProps) => React.ReactNode-按钮内容或 render prop
renderDOMRenderFunction<keyof React.JSX.IntrinsicElements, ButtonRenderProps>-使用自定义 render 函数覆盖默认 DOM 元素

Render Props

使用 render prop 模式时,提供以下值:

Prop类型描述
isPendingboolean是否处于加载状态
isPressedboolean是否正在按下
isHoveredboolean是否悬停
isFocusedboolean是否聚焦
isFocusVisibleboolean是否显示焦点指示器
isDisabledboolean是否禁用

相关案例

See upstream Button showcases. Product showcases are not part of the local component runtime.

相关组件