# Progress 进度条

表达「某件事进行到什么程度」。线性用于页面顶部或卡片内的横向进度，环形用于按钮旁或数据面板里的紧凑指示。

## 代码演示

### 基础用法

`determinate` 配合 `value` 展示确定进度，点按钮可以把进度推进 20%。线性与环形可以绑同一个值。

```vue
<script setup lang="ts">
import { ref } from 'vue'

const value = ref(30)

function advance() {
  value.value = value.value >= 100 ? 0 : Math.min(100, value.value + 20)
}
</script>

<template>
  <div class="m-row-demo--stretch">
    <MProgress type="linear" variant="determinate" :value="value" />
    <div class="m-row-demo">
      <MButton variant="contained" color="primary" size="small" @click="advance">
        推进 20%
      </MButton>
      <MProgress type="circular" variant="determinate" :value="value" :size="36" />
    </div>
  </div>
</template>
```

### 三种变体

`determinate` 需要 `value`；`indeterminate` 表示时长未知，走循环动画；`buffer` 用于流媒体式的「已加载 / 已缓冲」双进度。

**演示说明：** 最后一个环形传了 `variant="buffer"`，组件会把它回退成 `indeterminate`。

```vue
<template>
  <div class="m-row-demo--stretch">
    <MProgress type="linear" variant="determinate" :value="60" />
    <MProgress type="linear" variant="indeterminate" />
    <MProgress type="linear" variant="buffer" :value="40" :value-buffer="72" />
    <div class="m-row-demo">
      <MProgress type="circular" variant="determinate" :value="60" />
      <MProgress type="circular" variant="indeterminate" />
      <MProgress type="circular" variant="buffer" />
    </div>
  </div>
</template>
```

### 环形尺寸与粗细

`size` 控制环形直径、`thickness` 控制描边宽度，两者只对 `circular` 生效。

```vue
<template>
  <div class="m-row-demo">
    <MProgress type="circular" variant="determinate" :value="25" :size="28" :thickness="3" />
    <MProgress type="circular" variant="determinate" :value="50" :size="40" :thickness="3.6" />
    <MProgress type="circular" variant="determinate" :value="75" :size="56" :thickness="5" />
    <MProgress type="circular" variant="indeterminate" :size="40" :thickness="4" />
  </div>
</template>
```

### 语义色

六种语义色与 `--m-*` 主题令牌对应，线性与环形同一套取值。

```vue
<script setup lang="ts">
const colors = ['primary', 'secondary', 'success', 'warning', 'error', 'info'] as const
</script>

<template>
  <div class="m-row-demo--stretch">
    <MProgress
      v-for="color in colors"
      :key="color"
      type="linear"
      variant="determinate"
      :value="65"
      :color="color" />
    <div class="m-row-demo">
      <MProgress
        v-for="color in colors"
        :key="color"
        type="circular"
        variant="determinate"
        :value="65"
        :size="36"
        :color="color" />
    </div>
  </div>
</template>
```

### 缓冲进度

`value` 是主进度、`valueBuffer` 是缓冲进度，两者都收敛在 0–100。

```vue
<script setup lang="ts">
import { ref } from 'vue'

const value = ref(20)
const valueBuffer = ref(45)

function loadBatch() {
  if (value.value >= 100) {
    value.value = 0
    valueBuffer.value = 30
    return
  }
  value.value = Math.min(100, value.value + 10)
  valueBuffer.value = Math.min(100, Math.max(valueBuffer.value, value.value) + 14)
}
</script>

<template>
  <div class="m-row-demo--stretch">
    <MProgress
      type="linear"
      variant="buffer"
      :value="value"
      :value-buffer="valueBuffer"
      color="info" />
    <div class="m-row-demo">
      <MButton variant="contained" color="info" size="small" @click="loadBatch">
        加载一批
      </MButton>
      <span>已加载 {{ value }}% · 已缓冲 {{ valueBuffer }}%</span>
    </div>
  </div>
</template>
```

## API

### Props

| 属性 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `type` | `'linear' \| 'circular'` | `'linear'` | 形态：线性进度条 / 环形进度 |
| `variant` | `'determinate' \| 'indeterminate' \| 'buffer'` | `'indeterminate'` | 变体；`buffer` 仅线性支持，环形下自动回退为 `indeterminate` |
| `color` | `'primary' \| 'secondary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `'primary'` | 语义色 |
| `value` | `number` | `0` | 进度值 0–100，`determinate` / `buffer` 生效，超出区间自动收敛 |
| `valueBuffer` | `number` | `0` | 缓冲进度 0–100，仅 `buffer` 变体生效 |
| `size` | `number` | `40` | 环形直径 px，仅 `circular` 生效 |
| `thickness` | `number` | `3.6` | 环形描边厚度 px，仅 `circular` 生效 |

### Events

无。

### Slots

无。

## 使用建议

::: tip 线性进度会撑满父容器宽度
线性形态的根元素是 `display: block; width: 100%` 的块，放在 flex 行里会自然占满剩余空间，不需要手动设宽。需要窄条时给它加一个限宽容器。
:::

::: warning 默认变体是不确定态
`variant` 的默认值是 `indeterminate`，不是 `determinate`。如果只想画一条静态进度条，必须显式写 `variant="determinate"` 并传 `value`，否则看到的是循环动画。
:::

::: warning `buffer` 在环形下无效
`type="circular"` 与 `variant="buffer"` 同时出现时，组件内部会把变体改写成 `indeterminate`（与 MUI 的 `CircularProgress` 一致，环形没有缓冲语义）。环形要用缓冲效果只能换回线性。
:::

::: tip 无障碍取值
`determinate` / `buffer` 会写入 `aria-valuenow`；`aria-valuemin` / `aria-valuemax` 只在 `linear` 下上报。
:::

## 相关组件

- [Button 按钮](/components/button)：提交类按钮配合进度条展示后台任务状态。
- [Toast 轻提示](/components/toast)：短任务用轻提示即可，不需要进度条。
