Files
CNWei cc35400f67 feat(ui): 新增 TextButton / ToggleRow,Table 支持紧凑档
- TextButton:文字按钮(tone 主色/危险、可选图标、disabled),
  用于表格行内操作,hover 只加下划线
- ToggleRow:左标签 + 右开关的开关行,支持 hint 与 switchLabel
- Table:新增 size='md' | 'sm',sm 把行内边距收到 space-2
- 展示页:按钮补「文字按钮」、开关补「开关行」、表格补「紧凑档」;
  COMPONENTS.md 契约 3.46 / 3.47 与 README 清单同步
2026-11-01 21:59:13 +08:00

185 lines
8.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react'
import { Button, Icon, IconButton, Space, TextButton } from '../../src'
import { Demo } from '../components/Demo'
import { PropsTable } from '../components/PropsTable'
import { Section } from '../components/Section'
export function Buttons() {
const [loading, setLoading] = useState(false)
const loadOnce = () => {
setLoading(true)
window.setTimeout(() => setLoading(false), 1200)
}
return (
<Section
id="buttons"
title="按钮"
api="Button / IconButton"
desc="五种语义、两种尺寸、两种形状;图标按钮是圆形的,只放一个图标,所以无障碍名称必填。交互对齐参考站:hover 用 opacity .8(主色/危险),过渡 .3s ease-in-out。"
>
<Demo
title="语义变体"
desc="一个页面里主要操作只出现一次 primary,其余用 secondary / outline / ghost。"
code={`<Button>保存</Button>
<Button variant="secondary">取消</Button>
<Button variant="outline">更多</Button>
<Button variant="ghost">详情</Button>
<Button variant="danger">删除</Button>`}
>
<Button>保存</Button>
<Button variant="secondary">取消</Button>
<Button variant="outline">更多</Button>
<Button variant="ghost">详情</Button>
<Button variant="danger">删除</Button>
</Demo>
<Demo
title="形状"
desc="rounded(默认,6px 圆角)用于工具型操作;pill 用于登录、筛选这类主操作——参考站的全部分类筛选和登录按钮都是胶囊。"
code={`<Button shape="pill">登录</Button>
<Button shape="pill" variant="secondary">全部</Button>
<Button shape="pill" variant="ghost">重置</Button>`}
>
<Button shape="pill">登录</Button>
<Button shape="pill" variant="secondary">
全部
</Button>
<Button shape="pill" variant="ghost">
重置
</Button>
</Demo>
<Demo
title="尺寸"
desc="sm 用于卡片内的次级操作,md 用于页面级操作;两档高度分别是 32 / 36。"
code={`<Button size="sm">小号</Button>
<Button size="md">中号</Button>`}
>
<Button size="sm">小号按钮</Button>
<Button size="md">中号按钮</Button>
</Demo>
<Demo
title="状态"
desc="loading 会自动禁用点击;disabled 换成浅底弱文字(参考站的做法),不做整体降透明度。"
code={`<Button loading={loading} onClick={loadOnce}>提交</Button>
<Button disabled>不可用</Button>`}
>
<Button loading={loading} onClick={loadOnce}>
点我加载
</Button>
<Button disabled>不可用</Button>
<Button variant="secondary" disabled>
不可用(次要)
</Button>
</Demo>
<Demo
title="带图标与整行"
desc="图标放在文字左侧;block 让按钮占满容器宽度(表单底部常用)。"
layout="column"
code={`<Button icon={<Icon name="refresh_3_line" />}>重新扫描</Button>
<Button shape="pill" icon={<Icon name="arrow_right_up_line" />}>打开接口</Button>`}
>
<Space gap="md" wrap>
<Button icon={<Icon name="refresh_3_line" />}>重新扫描</Button>
<Button shape="pill" variant="secondary" icon={<Icon name="arrow_right_up_line" />}>
打开接口
</Button>
</Space>
<Button block icon={<Icon name="link_line" />}>
占满一行的按钮
</Button>
</Demo>
<Demo
title="图标按钮"
desc="xs / sm / md 是 28 / 36 / 44 的圆形,图标字号 16 / 20 / 24;ghost 用于顶栏,soft 用于需要一点底色的场景。"
code={`<IconButton label="搜索" icon={<Icon name="search_3_line" />} />
<IconButton label="更多" icon={<Icon name="more_3_line" />} variant="soft" />
<IconButton label="关闭" icon={<Icon name="close_line" />} size="xs" />
<IconButton label="刷新中" icon={<Icon name="refresh_3_line" />} spinning variant="soft" />`}
>
<IconButton label="搜索" icon={<Icon name="search_3_line" />} />
<IconButton label="用户" icon={<Icon name="user_3_line" />} />
<IconButton label="更多" icon={<Icon name="more_3_line" />} variant="soft" />
<IconButton label="小号" icon={<Icon name="close_line" />} size="xs" />
<IconButton label="大号" icon={<Icon name="share_3_line" />} size="md" variant="soft" />
<IconButton label="刷新中" icon={<Icon name="refresh_3_line" />} spinning variant="soft" />
</Demo>
<Demo
title="尺寸与进行中"
desc="sm 32 / md 36 / lg 44;spinning 让图标原地旋转(刷新类动作),loading 则换成转圈。"
code={`<Button size="lg">大按钮</Button>
<Button spinning icon={<Icon name="refresh_3_line" />}>重新扫描</Button>`}
>
<Space gap="md" wrap>
<Button size="sm">小号 32</Button>
<Button size="md">默认 36</Button>
<Button size="lg">大号 44</Button>
<Button variant="secondary" spinning icon={<Icon name="refresh_3_line" />}>
重新扫描
</Button>
</Space>
</Demo>
<Demo
title="文字按钮"
desc="看起来像链接、行为像按钮,用在表格行内操作这类不需要外框的地方;需要底色或独立操作时仍用 Button。"
layout="column"
code={`<TextButton icon={<Icon name="add_line" />}>新建子分组</TextButton>
<TextButton icon={<Icon name="edit_4_line" />}>编辑</TextButton>
<TextButton tone="danger" icon={<Icon name="delete_2_line" />}>删除</TextButton>
<TextButton disabled>禁用</TextButton>`}
>
<Space gap="lg" wrap>
<TextButton icon={<Icon name="add_line" />}>新建子分组</TextButton>
<TextButton icon={<Icon name="edit_4_line" />}>编辑</TextButton>
<TextButton tone="danger" icon={<Icon name="delete_2_line" />}>
删除
</TextButton>
<TextButton disabled icon={<Icon name="edit_4_line" />}>
禁用
</TextButton>
</Space>
</Demo>
<PropsTable
rows={[
{ name: 'variant', type: "'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'", defaultValue: "'primary'", desc: '语义变体' },
{ name: 'size', type: "'sm' | 'md' | 'lg'", defaultValue: "'md'", desc: '32 / 36 / 44px 高' },
{ name: 'spinning', type: 'boolean', defaultValue: 'false', desc: '图标原地旋转(不换转圈)' },
{ name: 'shape', type: "'rounded' | 'pill'", defaultValue: "'rounded'", desc: '6px 圆角 / 胶囊' },
{ name: 'block', type: 'boolean', defaultValue: 'false', desc: '占满一行' },
{ name: 'loading', type: 'boolean', defaultValue: 'false', desc: '加载中,自动禁用' },
{ name: 'icon', type: 'ReactNode', desc: '文字左侧图标' },
{ name: '…rest', type: 'ButtonHTMLAttributes', desc: '透传原生属性(type 默认 button)' },
]}
/>
<PropsTable
rows={[
{ name: 'label', type: 'string', required: true, desc: '无障碍名称,同时作为 title' },
{ name: 'icon', type: 'ReactNode', required: true, desc: '按钮里的图标' },
{ name: 'variant', type: "'ghost' | 'soft'", defaultValue: "'ghost'", desc: '是否有底色' },
{ name: 'size', type: "'xs' | 'sm' | 'md'", defaultValue: "'sm'", desc: '28 / 36 / 44px 圆形' },
{ name: 'spinning', type: 'boolean', defaultValue: 'false', desc: '图标旋转' },
]}
/>
<PropsTable
rows={[
{ name: 'icon', type: 'ReactNode', desc: '前置图标' },
{ name: 'tone', type: "'primary' | 'danger'", defaultValue: "'primary'", desc: '颜色语义' },
{ name: 'disabled', type: 'boolean', defaultValue: 'false', desc: '禁用态' },
{ name: 'onClick', type: '() => void', desc: '点击回调' },
{ name: 'title / label', type: 'string', desc: '悬停提示 / 无障碍名称' },
]}
/>
</Section>
)
}