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' | 按钮尺寸 |
fullWidth | boolean | false | 是否占满容器宽度 |
isDisabled | boolean | false | 是否禁用 |
isPending | boolean | false | 是否处于加载状态 |
isIconOnly | boolean | false | 是否仅包含图标 |
onPress | (e: PressEvent) => void | - | 按下时的回调 |
children | React.ReactNode | (values: ButtonRenderProps) => React.ReactNode | - | 按钮内容或 render prop |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, ButtonRenderProps> | - | 使用自定义 render 函数覆盖默认 DOM 元素 |
Render Props
使用 render prop 模式时,提供以下值:
| Prop | 类型 | 描述 |
|---|---|---|
isPending | boolean | 是否处于加载状态 |
isPressed | boolean | 是否正在按下 |
isHovered | boolean | 是否悬停 |
isFocused | boolean | 是否聚焦 |
isFocusVisible | boolean | 是否显示焦点指示器 |
isDisabled | boolean | 是否禁用 |
相关案例
See upstream Button showcases. Product showcases are not part of the local component runtime.