# 水平堆叠

## 使用方法

`Stack` 把子项排成一行或者一列，间距始终一致。子项之间的距离交给 `gap` 属性，不用自己算。

```ts
import { HStack } from '@astryx-vue/core/Stack'
```

`HStack` 就是把 `Stack` 的方向定成了横向，属性还是那一套，不用每次再写 `direction`。`gap` 取间距刻度上的一档，一行里的间距只靠它：不要给子元素加外边距。

`hAlign` 管这一行里的横向位置，可选 `start`、`center`、`end`、`between`、`around`、`evenly`。`vAlign` 管子项之间在纵向怎么对，`align` 是它的简写。一行放不下的时候用 `wrap` 让它换行，而不是溢出。

```vue
<script setup lang="ts">
import { Badge } from '@astryx-vue/core/Badge'
import { HStack } from '@astryx-vue/core/Stack'
</script>

<template>
  <HStack :gap="2">
    <Badge label="React" />
    <Badge label="TypeScript" />
    <Badge label="Node.js" />
  </HStack>
</template>
```

### 结构

- **堆叠容器**: 沿一条 flex 轴排列内容的布局容器。
- **项**: 可选的 StackItem，用来控制堆叠里的一项。
- **内容**: Stack 或 StackItem 画出的、由使用方提供的内容。

## 最佳实践

| 指引 | 实践 |
| --- | --- |
| 推荐 | 用 `gap` 属性控制项目间距，而不是给子元素手动添加外边距，间距更容易保持一致。 |
| 推荐 | 希望某个项目拉伸并填满剩余空间时，给它包一层 `size="fill"` 的 `StackItem`，其余项目仍保持固有尺寸。 |
| 避免 | 为了换行而嵌套堆叠布局，优先给 `Stack` 设置 `wrap="wrap"` 让项目自动换行，结构会更扁平。 |

## 示例

### 基础

子项横向排成一行，间距一致，垂直方向居中对齐。兄弟元素要并排摆时就用 HStack。

```vue
<script setup lang="ts">
import { Badge } from '@astryx-vue/core/Badge'
import { HStack } from '@astryx-vue/core/Stack'
</script>

<template>
  <HStack :gap="2">
    <Badge label="React" />
    <Badge label="TypeScript" />
    <Badge label="Node.js" />
  </HStack>
</template>
```

## 属性

`HStack` 支持 `Stack` 的全部属性，只有 `direction` 不开放，它固定是 `horizontal`。

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `align` | `StackCrossAlignment` | — | 纵向对齐的简写，属性和 `Stack` 上读起来一样。效果同 `vAlign`。 |
| `as` | `string \| Component` | `'div'` | 根元素或者根组件。 |
| `gap` | `SpacingStep` | — | 相邻子项之间的间距，取间距刻度。 |
| `height` | `number \| string` | — | 这一行的高度。写数字按像素，写字符串原样使用。 |
| `hAlign` | `StackMainAlignment` | — | 子项在横向主轴上的位置：`start`、`center`、`end`、`between`、`around`、`evenly`。 |
| `isScrollable` | `boolean` | `false` | 内容超出时允许滚动。 |
| `justify` | `StackMainAlignment` | — | 主轴对齐的另一个名字，对应 CSS 的 `justify-content`。 |
| `maxWidth` | `number \| string` | — | 这一行的最大宽度。 |
| `minHeight` | `number \| string` | — | 这一行的最小高度。 |
| `padding` | `SpacingStep` | — | 四周内边距，取间距刻度。 |
| `paddingBlock` | `SpacingStep` | — | 纵向内边距，会盖掉这一条轴上的 `padding`。 |
| `paddingBlockEnd` | `SpacingStep` | — | 只改下边内边距，会盖掉 `paddingBlock` 和 `padding` 在这一条边上的值。 |
| `paddingBlockStart` | `SpacingStep` | — | 只改上边内边距，会盖掉 `paddingBlock` 和 `padding` 在这一条边上的值。 |
| `paddingInline` | `SpacingStep` | — | 横向内边距，会盖掉这一条轴上的 `padding`。 |
| `paddingInlineEnd` | `SpacingStep` | — | 只改行内结束边（从左往右时是右边）的内边距，会盖掉 `paddingInline` 和 `padding` 在这一条边上的值。 |
| `paddingInlineStart` | `SpacingStep` | — | 只改行内起始边（从左往右时是左边）的内边距，会盖掉 `paddingInline` 和 `padding` 在这一条边上的值。 |
| `vAlign` | `StackCrossAlignment` | — | 子项在纵向交叉轴上的对齐：`start`、`center`、`end`、`stretch`。 |
| `width` | `number \| string` | — | 这一行的宽度。写数字按像素，写字符串原样使用。 |
| `wrap` | `StackWrap` | `'nowrap'` | 要不要换行：`nowrap`、`wrap` 或 `wrap-reverse`。 |

这几个辅助类型和 `Stack` 共用：

```ts
type SpacingStep = 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10
type StackMainAlignment = 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly'
type StackCrossAlignment = 'start' | 'center' | 'end' | 'stretch'
type StackWrap = 'nowrap' | 'wrap' | 'wrap-reverse'
type StackSizeValue = number | string
type StackElement = Component | string
```

## 插槽

- `default`：这一行里的子项。

## 原生属性

根元素会接收 HTML 属性、`aria-*` 属性、`data-*` 属性、`class` 和 `style`。`class` 会和组件自己的类合并，`style` 会和它自己写的尺寸、间距合并。
