feat: stash-ui 0.1.0(40 个组件 + 文档站 + 主题机制)

This commit is contained in:
stash
2026-10-28 20:44:18 +08:00
commit 52296b3368
153 changed files with 17129 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
import { Divider, Grid, Space, Tag } from '../../src'
import { Demo } from '../components/Demo'
import { PropsTable } from '../components/PropsTable'
import { Section } from '../components/Section'
import { DEMO_POSTERS } from '../data/demo'
const BLOCKS = [1, 2, 3, 4, 5, 6, 7, 8]
function Block({ index, tall = false }: { index: number; tall?: boolean }) {
return (
<div
style={{
display: 'grid',
placeItems: 'center',
height: tall ? 96 : 56,
borderRadius: 'var(--su-radius-sm)',
background: 'var(--su-gray-2)',
color: 'var(--su-text-muted)',
fontSize: 12,
}}
>
{index}
</div>
)
}
export function Layouts() {
return (
<Section
id="layouts"
title="网格与间距"
api="Grid / Space / Divider"
desc="页面布局只保留三件套:给卡片列表用的 Grid(列数与断点收在组件里),给元素间距用的 Space,以及分隔内容块的 Divider。"
>
<Demo
title="网格列数"
desc="窄屏自动退化:≤1100px 取一半(至少 2 列),≤720px 收成一列;也可以显式指定 tabletColumns / mobileColumns。"
layout="column"
code={`<Grid columns={4} gap="md">…</Grid>
<Grid columns={6} tabletColumns={3} mobileColumns={2} gap="sm">…</Grid>`}
>
<Grid columns={4} gap="md">
{BLOCKS.slice(0, 4).map((index) => (
<Block key={index} index={index} />
))}
</Grid>
<Grid columns={6} tabletColumns={3} mobileColumns={2} gap="sm">
{BLOCKS.map((index) => (
<Block key={index} index={index} />
))}
</Grid>
</Demo>
<Demo
title="列表语义"
desc="传 as='ul' 时用 li 做列表项,屏幕阅读器能读出条目数;纯展示容器用默认的 div。"
layout="column"
code={`<Grid as="ul" role="list" columns={4} gap="md">
{items.map((item) => <li key={item.id}>…</li>)}
</Grid>`}
>
<Grid as="ul" role="list" columns={4} gap="md">
{DEMO_POSTERS.map((poster) => (
<li key={poster.id} style={{ listStyle: 'none' }}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
gap: 'var(--su-space-2)',
padding: 'var(--su-space-3)',
border: '1px solid var(--su-border)',
borderRadius: 'var(--su-radius-md)',
}}
>
<span style={{ fontWeight: 500 }}>{poster.title}</span>
<Tag shape="pill" tone="neutral">
{poster.tag}
</Tag>
</div>
</li>
))}
</Grid>
</Demo>
<Demo
title="间距"
desc="Space 只是 flex + gap 的封装,方向、间距、对齐都用语义化的档位表达,避免每个页面各写一套像素值。"
layout="column"
code={`<Space gap="md">
<Tag>本地</Tag>
<span>docs</span>
</Space>
<Space direction="column" gap="sm" align="start">…</Space>`}
>
<Space gap="md">
<Tag>本地</Tag>
<span>docs</span>
<Tag tone="success" dot>
已连接
</Tag>
</Space>
<Space direction="column" gap="sm" align="start">
<span style={{ fontWeight: 500 }}>竖向排列</span>
<span style={{ color: 'var(--su-text-muted)' }}>适合标题 + 描述这类两行结构</span>
</Space>
</Demo>
<Demo
title="分隔线"
desc="横向分隔内容块,纵向分隔并排元素;虚线用于「弱分隔」,和实线区分层级。"
layout="column"
code={`<Divider />
<Divider variant="dashed" spacing="sm" />
<Space gap="sm"><span>左</span><Divider orientation="vertical" /><span>右</span></Space>`}
>
<Divider />
<Divider variant="dashed" spacing="sm" />
<Space gap="sm">
<span>左</span>
<Divider orientation="vertical" />
<span>右</span>
</Space>
</Demo>
<PropsTable
rows={[
{ name: 'columns', type: 'number', defaultValue: '4', desc: '宽屏列数' },
{ name: 'tabletColumns', type: 'number', defaultValue: 'columns / 2(至少 2)', desc: '≤1100px 列数' },
{ name: 'mobileColumns', type: 'number', defaultValue: '1', desc: '≤720px 列数' },
{ name: 'gap', type: "'sm' | 'md' | 'lg'", defaultValue: "'md'", desc: '间距档位' },
{ name: 'as', type: "'div' | 'ul'", defaultValue: "'div'", desc: '列表语义' },
]}
/>
</Section>
)
}