# Badge 徽标

数字/状态徽标，通常用于消息计数或新内容提示。

## 基础用法

<DemoBlock title="数字徽标">
  <oas-badge value="5">
    <oas-tag>通知</oas-tag>
  </oas-badge>
  <oas-badge value="88">
    <oas-tag>未读消息</oas-tag>
  </oas-badge>
</DemoBlock>

## 上限显示

超过 `max` 时显示 `max+`。

<DemoBlock title="上限显示">
  <oas-badge value="120" max="99">
    <oas-tag>评论</oas-tag>
  </oas-badge>
</DemoBlock>

## 小圆点

<DemoBlock title="状态点">
  <oas-badge dot>
    <oas-tag>在线状态</oas-tag>
  </oas-badge>
</DemoBlock>

## 零值

默认隐藏 0，设置 `showZero` 时显示。

<DemoBlock title="零值控制">
  <oas-badge value="0">
    <oas-tag>默认隐藏 0</oas-tag>
  </oas-badge>
  <oas-badge value="0" showZero>
    <oas-tag>显示 0</oas-tag>
  </oas-badge>
</DemoBlock>

## 独立徽标

不包裹任何子内容时，徽标从「贴右上角」回落为静态行内展示（不塌陷），可独立放在文本流或菜单行里。

<DemoBlock title="独立徽标">
  <span>新消息 <oas-badge value="3"></oas-badge></span>
  <span>待办事项 <oas-badge value="12" color="success"></oas-badge></span>
  <span>系统运行中 <oas-badge dot color="green"></oas-badge></span>
</DemoBlock>

## 图标徽标

`icon` 传入图标名（查表时自定义注册优先、内置图标集兜底），徽标内渲染小图标（如状态角标放 √ / !）。与 `value` / `dot` 互斥：`icon` 优先显示图标，不渲染数字/圆点；非法图标名静默回落数字逻辑。

<DemoBlock title="图标徽标">
  <oas-badge icon="check" color="success" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>已完成</oas-tag>
  </oas-badge>
  <oas-badge icon="warning" color="warning" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>需注意</oas-tag>
  </oas-badge>
  <oas-badge icon="error" color="danger">
    <oas-tag>已失败</oas-tag>
  </oas-badge>
</DemoBlock>

## 徽标颜色

`color` 支持四种语义色（`primary` / `success` / `warning` / `danger`）、任意 CSS 色值、以及 11 个预设名（`magenta` / `red` / `volcano` / `orange` / `gold` / `lime` / `green` / `cyan` / `blue` / `geekblue` / `purple`，映射 `--oas-preset-*` token，dark 自动调亮）。count / dot / ribbon 三种模式统一生效；实心文字色：语义色 / 预设名走固定 `text-on-*` token，仅任意 CSS 色值按底色亮度取黑/白保证可读。

<DemoBlock title="count 语义色">
  <oas-badge value="5" color="primary" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>primary</oas-tag>
  </oas-badge>
  <oas-badge value="5" color="success" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>success</oas-tag>
  </oas-badge>
  <oas-badge value="5" color="warning" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>warning</oas-tag>
  </oas-badge>
  <oas-badge value="5" color="danger">
    <oas-tag>danger</oas-tag>
  </oas-badge>
</DemoBlock>

<DemoBlock title="count 预设色">
  <oas-badge value="3" color="magenta" style="margin-inline-end: var(--oas-space-3)">
    <oas-tag>magenta</oas-tag>
  </oas-badge>
  <oas-badge value="3" color="geekblue" style="margin-inline-end: var(--oas-space-3)">
    <oas-tag>geekblue</oas-tag>
  </oas-badge>
  <oas-badge value="3" color="gold" style="margin-inline-end: var(--oas-space-3)">
    <oas-tag>gold</oas-tag>
  </oas-badge>
  <oas-badge value="3" color="cyan">
    <oas-tag>cyan</oas-tag>
  </oas-badge>
</DemoBlock>

<DemoBlock title="count / dot 自定义色">
  <oas-badge value="8" color="#7c3aed" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>#7c3aed 紫色</oas-tag>
  </oas-badge>
  <oas-badge dot color="#e11d48" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>dot #e11d48</oas-tag>
  </oas-badge>
  <oas-badge dot color="purple">
    <oas-tag>dot purple</oas-tag>
  </oas-badge>
</DemoBlock>

## 描边形态

`variant="outline"` 切换为描边徽标：背景透明、边框与文字走 color 语义色（`solid` 实心为默认，非法值回落）。适合叠加在图片/彩色底上的场景；与 `bordered` 白描边可叠加。

<DemoBlock title="outline 描边形态">
  <oas-badge value="5" variant="outline" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>outline 默认</oas-tag>
  </oas-badge>
  <oas-badge value="5" variant="outline" color="success" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>outline success</oas-tag>
  </oas-badge>
  <oas-badge dot variant="outline" color="warning" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>outline dot</oas-tag>
  </oas-badge>
  <oas-badge value="5" variant="outline" color="#7c3aed" bordered>
    <oas-tag>outline 自定义色 + bordered</oas-tag>
  </oas-badge>
</DemoBlock>

## 偏移

`offset="x,y"`（px 数字）在角标定位基础上额外平移，x 正向右、y 正向下（屏幕坐标，与角标朝向无关）；非法值（非数字、缺坐标）静默忽略。与 `corner` 可叠加：先定角再平移。

<DemoBlock title="offset 偏移">
  <oas-badge value="5" offset="10,5" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>向右下偏移</oas-tag>
  </oas-badge>
  <oas-badge value="5" offset="0,8">
    <oas-tag>向下偏移</oas-tag>
  </oas-badge>
</DemoBlock>

## 四角定位

`corner` 把角标定位到宿主四角之一：`top-right`（默认）/ `top-left` / `bottom-right` / `bottom-left`；非法值静默回落 `top-right`。`offset` 是在 `corner` 结果上的精确微调（先定角、再平移，可叠加）。

<DemoBlock title="四角定位">
  <oas-badge value="5" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>top-right 默认</oas-tag>
  </oas-badge>
  <oas-badge value="5" corner="top-left" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>top-left</oas-tag>
  </oas-badge>
  <oas-badge value="5" corner="bottom-right" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>bottom-right</oas-tag>
  </oas-badge>
  <oas-badge value="5" corner="bottom-left">
    <oas-tag>bottom-left</oas-tag>
  </oas-badge>
</DemoBlock>

<DemoBlock title="corner + offset 叠加">
  <oas-badge value="5" corner="bottom-left" offset="4,4" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>bottom-left 向右下微调</oas-tag>
  </oas-badge>
  <oas-badge value="5" corner="top-left" offset="0,6">
    <oas-tag>top-left 向下微调</oas-tag>
  </oas-badge>
</DemoBlock>

## 圆形内收

包裹圆形内容（如头像）时加 `overlap`，角标向圆内收进圆边：平移幅度从 50% 收到约 29%（1-√2/2 几何内收）。仅影响角标模式。

<DemoBlock title="overlap 圆形内收">
  <oas-badge value="5" overlap style="margin-inline-end: var(--oas-space-5)">
    <oas-avatar size="48">张</oas-avatar>
  </oas-badge>
  <oas-badge dot overlap color="success" style="margin-inline-end: var(--oas-space-5)">
    <oas-avatar size="48">李</oas-avatar>
  </oas-badge>
  <oas-badge value="99" max="99" overlap corner="bottom-right">
    <oas-avatar size="48">王</oas-avatar>
  </oas-badge>
</DemoBlock>

## 白描边

`bordered` 给徽标加 2px 背景色描边（`box-shadow: 0 0 0 2px var(--oas-color-bg)`），从头像/图片等复杂背景中分离出来；仅视觉叠加、不改定位，与 `corner` / `offset` / `overlap` 联动正常。

<DemoBlock title="bordered 白描边">
  <oas-badge value="5" bordered style="margin-inline-end: var(--oas-space-5)">
    <oas-avatar size="48">张</oas-avatar>
  </oas-badge>
  <oas-badge dot bordered color="success" style="margin-inline-end: var(--oas-space-5)">
    <oas-avatar size="48">李</oas-avatar>
  </oas-badge>
  <oas-badge value="3" bordered corner="bottom-right" offset="2,2">
    <oas-avatar size="48">王</oas-avatar>
  </oas-badge>
</DemoBlock>

## 状态点

`status` 渲染「状态点 + `text` 文字」的行内独立元素（非角标定位），与 ribbon / dot / count 模式互斥（设置时优先渲染状态点）。`processing` 圆点带脉冲动画（`prefers-reduced-motion` 下停用）。

<DemoBlock title="状态点">
  <oas-badge status="success" text="已发布" style="margin-inline-end: var(--oas-space-4)"></oas-badge>
  <oas-badge status="processing" text="处理中" style="margin-inline-end: var(--oas-space-4)"></oas-badge>
  <oas-badge status="default" text="默认" style="margin-inline-end: var(--oas-space-4)"></oas-badge>
  <oas-badge status="error" text="错误" style="margin-inline-end: var(--oas-space-4)"></oas-badge>
  <oas-badge status="warning" text="警告"></oas-badge>
</DemoBlock>

## 尺寸档位

`size` 提供三档：`small`（小档，数字徽标高约 13px、dot 6px）/ `medium`（默认，约 16px、dot 8px）/ `large`（大档，约 20px、dot 10px）；非法值静默回落 `medium`。

<DemoBlock title="尺寸档位 small / medium / large">
  <oas-badge value="5" size="small" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>small</oas-tag>
  </oas-badge>
  <oas-badge value="99" max="99" size="small" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>small 99+</oas-tag>
  </oas-badge>
  <oas-badge dot size="small" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>small dot</oas-tag>
  </oas-badge>
  <oas-badge value="5" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>medium 默认</oas-tag>
  </oas-badge>
  <oas-badge value="5" size="medium" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>medium 显式</oas-tag>
  </oas-badge>
  <oas-badge value="5" size="large" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>large</oas-tag>
  </oas-badge>
  <oas-badge value="99" max="99" size="large" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>large 99+</oas-tag>
  </oas-badge>
  <oas-badge dot size="large">
    <oas-tag>large dot</oas-tag>
  </oas-badge>
</DemoBlock>

## 吸引动画

`attention="pulse"` 让徽标外圈周期性脉冲扩散（脉冲颜色可用 `--oas-badge-pulse-color` 自定义，默认跟随徽章底色）；`attention="bounce"` 让徽标轻微上下弹跳。仅作用于 count / dot / standalone 徽标（缎带不受影响），`prefers-reduced-motion` 下自动停用。

<DemoBlock title="pulse 脉冲">
  <oas-badge value="5" attention="pulse" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>pulse 脉冲</oas-tag>
  </oas-badge>
  <oas-badge dot attention="pulse" color="success" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>dot pulse</oas-tag>
  </oas-badge>
  <oas-badge
    value="3"
    attention="pulse"
    color="purple"
    style="--oas-badge-pulse-color: var(--oas-color-warning)"
  >
    <oas-tag>自定义脉冲色</oas-tag>
  </oas-badge>
</DemoBlock>

<DemoBlock title="bounce 弹跳">
  <oas-badge value="5" attention="bounce" style="margin-inline-end: var(--oas-space-5)">
    <oas-tag>bounce 弹跳</oas-tag>
  </oas-badge>
  <oas-badge dot attention="bounce" color="warning">
    <oas-tag>dot bounce</oas-tag>
  </oas-badge>
</DemoBlock>

## 原生提示

给徽标宿主加原生 `title` 属性即可获得悬停原生提示，无需任何 JS。

<DemoBlock title="原生提示">
  <oas-badge value="3" title="3 条未读消息">
    <oas-tag>未读消息</oas-tag>
  </oas-badge>
</DemoBlock>

## 动态增减

`value` 变化即时反映；宿主可在点击按钮时为徽标添加动画 class 实现过渡反馈（本例通过 `::part(badge)` 做缩放/透明度小动画）。

数字徽标内置 `role="status"` + `aria-live="polite"` + `aria-atomic="true"`：数字（含 max 截断显示值）变化时通过 `aria-label` 向屏幕阅读器播报，文案走 locale（如「5 条未读通知」），无需额外 JS。

<DemoBlock title="动态增减">
  <oas-badge id="badge-dyn" value="5">
    <oas-tag>动态计数</oas-tag>
  </oas-badge>
  <oas-button id="badge-dec" size="small" aria-label="减少">−</oas-button>
  <oas-button id="badge-inc" size="small" type="primary" aria-label="增加">＋</oas-button>
</DemoBlock>

<script setup>
import { onMounted } from 'vue'
onMounted(() => {
  const badge = document.getElementById('badge-dyn')
  const bump = () => {
    badge.classList.remove('bump')
    void badge.offsetWidth
    badge.classList.add('bump')
  }
  document.getElementById('badge-inc')?.addEventListener('click', () => {
    badge.setAttribute('value', String(Number(badge.getAttribute('value') || 0) + 1))
    bump()
  })
  document.getElementById('badge-dec')?.addEventListener('click', () => {
    badge.setAttribute('value', String(Math.max(0, Number(badge.getAttribute('value') || 0) - 1)))
    bump()
  })
})
</script>

<style>
oas-badge#badge-dyn.bump::part(badge) {
  animation: oas-badge-dyn-bump 220ms var(--oas-ease-out);
}
@keyframes oas-badge-dyn-bump {
  0%,
  100% {
    transform: translate(50%, -50%) scale(1);
    opacity: 1;
  }
  45% {
    transform: translate(50%, -50%) scale(1.22);
    opacity: 0.72;
  }
}
</style>

## 缎带角标

`ribbon` 布尔属性或 `mode="ribbon"` 开启缎带角标。文本经 `text` 属性提供，默认位于右端（`placement="end"`），可用 `placement="start"` 切到左端。

<DemoBlock title="普通缎带">
  <oas-badge ribbon text="HOT" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>默认缎带（右上角）</p></oas-card>
  </oas-badge>
  <oas-badge mode="ribbon" text="限量" placement="start">
    <oas-card><p>mode="ribbon"（左上角）</p></oas-card>
  </oas-badge>
</DemoBlock>

## 缎带位置

`ribbon-position` 控制缎带的纵向位置：`hang`（默认，挂沿下）/ `edge`（贴顶边）/ `cross`（骑跨顶边，压住卡片顶边框，包裹感最强）。三种位置与 `placement`（start / end 横向）正交，两侧均生效。

<DemoBlock title="缎带位置">
  <oas-badge ribbon text="HANG" ribbon-position="hang" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>hang（默认，挂沿下）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="EDGE" ribbon-position="edge" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>edge（贴顶边）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="CROSS" ribbon-position="cross">
    <oas-card><p>cross（骑跨顶边）</p></oas-card>
  </oas-badge>
</DemoBlock>

<DemoBlock title="缎带位置（placement=start 左侧）">
  <oas-badge ribbon text="HANG" ribbon-position="hang" placement="start" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>hang（挂沿下）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="EDGE" ribbon-position="edge" placement="start" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>edge（贴顶边）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="CROSS" ribbon-position="cross" placement="start">
    <oas-card><p>cross（骑跨顶边）</p></oas-card>
  </oas-badge>
</DemoBlock>

## 缎带形态

`ribbon-form` 切换缎带形态：`fold`（默认，直条 + 折叠）/ `diagonal`（45° 对角斜带，条身探出卡外，宿主需 `overflow: hidden` 裁切）/ `triangle`（角落纯三角形，内容为小图标或 `slot="ribbon"`）/ `bookmark`（顶边垂挂 + 底部燕尾缺口）/ `side`（侧边竖挂）/ `seal`（圆形锯齿印章，文字居中）/ `banner`（顶部横贯横幅，两端折角）/ `flag`（侧燕尾横旗，横条 + 内端燕尾 V 缺口，外端贴卡片边线不探出，缺口始终朝卡片内侧端）。非法值静默回落 `fold`。`ribbon-direction` 控制 `bookmark` 的燕尾尖头方向（`down` 默认顶边垂挂 / `left` 贴右缘尖头朝左 / `right` 贴左缘尖头朝右，物理方向 RTL 不翻转），仅 bookmark 生效；`ribbon-vertical` 控制侧挂（left/right）的纵向位置（`center` 默认垂直居中 / `top` 贴顶边 / `bottom` 贴底边）。`ribbon-size` 给 diagonal 提供 `sm`（默认）/ `md` / `lg` 三档（档位只改带宽/字号/钉点默认值，宿主 `--oas-badge-diagonal-*` 自定义属性优先级更高）。`ribbon-position` 纵向三选仅作用于 `fold` 形态，其余形态有各自的纵向定位。`offset` 给所有缎带形态做任意位置微调（`offset="x,y"` px 平移，支持负值）。`rolled` 布尔修饰给探出外端加卷边（端部大圆角 + 内侧渐暗模拟卷起圆柱），可叠加 `fold` / `flag` / `rounded` / `zigzag` / `arrow`（`banner` 保留自身双端折角、不叠卷边；`diagonal` / `triangle` / `bookmark` / `side` / `seal` 静默忽略）。

<DemoBlock title="缎带形态">
  <oas-badge ribbon text="HOT" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>fold</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal</p></oas-card>
  </oas-badge>
  <oas-badge ribbon ribbon-form="triangle" style="margin-inline-end: var(--oas-space-4)">
    <oas-icon slot="ribbon" name="star" size="18"></oas-icon>
    <oas-card><p>triangle</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>bookmark</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" ribbon-direction="left" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 180px"><p>bookmark direction=left（尖头朝左）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" ribbon-direction="right">
    <oas-card style="width: 180px"><p>bookmark direction=right（尖头朝右）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" ribbon-direction="left" ribbon-vertical="top" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 180px"><p>bookmark left + vertical=top</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" ribbon-direction="right" ribbon-vertical="bottom" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 180px"><p>bookmark right + vertical=bottom</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="side" placement="start" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>side</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="奖" ribbon-form="seal" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>seal</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="限时特惠" ribbon-form="banner" placement="start">
    <oas-card><p>banner</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="flag" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>flag（侧燕尾横旗）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="rounded" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>rounded（圆头）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="zigzag" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>zigzag（锯齿）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="arrow" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>arrow（箭头）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" rolled style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>fold + rolled 卷边</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="50% OFF" ribbon-form="diagonal" ribbon-size="lg" style="overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 240px"><p>diagonal + ribbon-size=lg</p></oas-card>
  </oas-badge>
</DemoBlock>

`ribbon-size` 给 diagonal 提供三档（`sm` 默认 / `md` 中等 / `lg` 宽幅大字），档位只改带宽、字号与带中心钉点的默认值；宿主可直接覆盖 `--oas-badge-diagonal-height` / `--oas-badge-diagonal-font` / `--oas-badge-diagonal-pin` / `--oas-badge-diagonal-text-inset` 自定义属性，其优先级高于档位。

<DemoBlock title="diagonal 尺寸档位 sm / md / lg">
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>ribbon-size=sm（默认）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="大促" ribbon-form="diagonal" ribbon-size="md" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>ribbon-size=md</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="50% OFF" ribbon-form="diagonal" ribbon-size="lg" style="overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 200px"><p>ribbon-size=lg</p></oas-card>
  </oas-badge>
</DemoBlock>

`offset` 给所有缎带形态提供任意位置微调：`offset="x,y"` 在形态自身锚点基础上做 px 平移（x 正向右、y 正向下，支持负值），与 `placement` / `ribbon-position` / `ribbon-vertical` 等正交叠加。

<DemoBlock title="缎带 offset 任意位置微调">
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" ribbon-direction="left" offset="0,20" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 180px"><p>bookmark left + offset=0,20</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" offset="0,-8" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>fold + offset=0,-8</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="限时" ribbon-form="diagonal" offset="-30,0" style="overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal + offset=-30,0</p></oas-card>
  </oas-badge>
</DemoBlock>

`ribbon-anchor` 统一缎带锚点，锚点集合按形态语义适配（形态与位置绑定）：

- **diagonal / triangle**：仅四角
- **fold / side / banner / seal / bookmark / flag**（及其余形态）：8 位置全支持（4 边中 + 4 角）
锚点预置贴边/贴角（底部锚点时折叠角自动翻转），任意位置再用 `offset` 微调兜底。

<DemoBlock title="缎带锚点：斜形态四角">
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" ribbon-anchor="top-left" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal top-left</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" ribbon-anchor="top-right" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal top-right</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" ribbon-anchor="bottom-left" style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal bottom-left</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" ribbon-anchor="bottom-right" style="overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>diagonal bottom-right</p></oas-card>
  </oas-badge>
</DemoBlock>

<DemoBlock title="缎带锚点：fold 位置（贴左/右，上下可调）">
  <oas-badge ribbon text="HOT" ribbon-anchor="left" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 160px"><p>fold left（边中）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-anchor="right" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 160px"><p>fold right（边中）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-anchor="bottom-left" style="margin-inline-end: var(--oas-space-4)">
    <oas-card style="width: 160px"><p>fold bottom-left（折叠角翻转）</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-anchor="bottom-right">
    <oas-card style="width: 160px"><p>fold bottom-right（折叠角翻转）</p></oas-card>
  </oas-badge>
</DemoBlock>

## premium 金属质感

`premium` 给缎带叠加金色金属质感：多段亮金→暗金渐变底 + 深金细描边（clip-path 形态沿轮廓描边），文字色固定近黑 `#1a1a1a`。与 `color` 正交叠加，优先级 `premium` > `color` > 语义色默认；与 `ribbon-form` 各形态均可组合，dark 主题自动适配（走 `--oas-preset-gold` token 联动）。

<DemoBlock title="premium 金属质感">
  <oas-badge ribbon text="HOT" premium style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>premium fold</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="限量" premium color="success" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>premium 覆盖 color</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="NEW" ribbon-form="bookmark" premium style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>premium bookmark</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="奖" ribbon-form="seal" premium style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>premium seal</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="HOT" ribbon-form="diagonal" premium style="margin-inline-end: var(--oas-space-4); overflow: hidden; border-radius: var(--oas-radius-lg)">
    <oas-card style="width: 160px"><p>premium diagonal</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="限时" ribbon-form="banner" premium placement="start">
    <oas-card><p>premium banner</p></oas-card>
  </oas-badge>
</DemoBlock>

## 彩色缎带

`color` 支持 `primary` / `success` / `warning` / `danger` 四种语义色，与主题 light/dark 联动；同样支持预设名与任意色值（走 `--oas-preset-*` token / 原色值注入）。

<DemoBlock title="彩色缎带">
  <oas-badge ribbon text="推荐" color="primary" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>primary</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="免费" color="success" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>success</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="即将结束" color="warning" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>warning</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="已售罄" color="danger">
    <oas-card><p>danger</p></oas-card>
  </oas-badge>
</DemoBlock>

<DemoBlock title="缎带预设色与自定义色">
  <oas-badge ribbon text="限时" color="geekblue" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>geekblue</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="特惠" color="#7c3aed">
    <oas-card><p>#7c3aed</p></oas-card>
  </oas-badge>
</DemoBlock>

## 自定义缎带内容

除 `text` 属性外，也可用 `slot="ribbon"` 传入任意自定义内容（有插槽内容时优先）。

<DemoBlock title="自定义内容">
  <oas-badge ribbon>
    <span slot="ribbon">新品 8 折起</span>
    <oas-card><p>slot="ribbon" 自定义内容</p></oas-card>
  </oas-badge>
</DemoBlock>

## 与数字/圆点徽标对比

同一 `oas-badge` 可做 count 或 ribbon 两种用途：count 徽标固定在右上角的小圆点/数字，dot 是无文本状态点，ribbon 则横跨卡片上沿的缎带；status 是独立行内的「状态点 + 文字」。

<DemoBlock title="count / dot / ribbon 对比">
  <oas-badge value="5" style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>count 数字徽标</p></oas-card>
  </oas-badge>
  <oas-badge dot style="margin-inline-end: var(--oas-space-4)">
    <oas-card><p>dot 状态点</p></oas-card>
  </oas-badge>
  <oas-badge ribbon text="上新">
    <oas-card><p>ribbon 缎带</p></oas-card>
  </oas-badge>
</DemoBlock>

## 徽标形态

`shape` 控制徽标形态：`round`（默认，圆角，基类即默认不写 class）/ `square`（直角）/ `pill`（胶囊，完全圆端）。数值徽标与 `dot` 圆点通用：`square` 让圆点变直角方点，`pill` 圆点保持正圆；非法值静默回落 `round`。

<DemoBlock title="shape 形态：round / square / pill">
  <oas-badge value="5" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>round 默认</oas-tag>
  </oas-badge>
  <oas-badge value="5" shape="square" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>square</oas-tag>
  </oas-badge>
  <oas-badge value="5" shape="pill" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>pill</oas-tag>
  </oas-badge>
  <oas-badge dot style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>dot round</oas-tag>
  </oas-badge>
  <oas-badge dot shape="square" style="margin-inline-end: var(--oas-space-4)">
    <oas-tag>dot square</oas-tag>
  </oas-badge>
  <oas-badge dot shape="pill">
    <oas-tag>dot pill</oas-tag>
  </oas-badge>
</DemoBlock>

## 加载徽标（组合 oas-spin）

徽标本体不内建 spinner 属性——把 `oas-spin` 放进默认插槽即可表达「徽标内含加载圈」：角标/圆点/状态点仍由 `oas-badge` 提供，加载指示器的形态（`variant`）与尺寸（`size`）由 `oas-spin` 独立控制，两者按需自由组合。

<DemoBlock title="角标 + 加载圈（组合 oas-spin）">
  <oas-badge dot color="primary" style="margin-inline-end: var(--oas-space-5)">
    <oas-spin size="small"></oas-spin>
  </oas-badge>
  <oas-badge value="3" style="margin-inline-end: var(--oas-space-5)">
    <oas-spin size="medium"></oas-spin>
  </oas-badge>
  <oas-badge dot overlap color="success" style="margin-inline-end: var(--oas-space-5)">
    <oas-spin size="large"></oas-spin>
  </oas-badge>
  <oas-badge dot variant="outline" color="warning" style="margin-inline-end: var(--oas-space-5)">
    <oas-spin size="medium" variant="dot"></oas-spin>
  </oas-badge>
  <oas-badge value="2" bordered>
    <oas-spin size="large" tip="同步中"></oas-spin>
  </oas-badge>
</DemoBlock>

## API

### oas-badge

#### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `attention` | 吸引动画：`pulse`（外圈脉冲扩散，脉冲色走 `--oas-badge-pulse-color` 自定义属性、默认跟随徽章底色）/ `bounce`（轻微上下弹跳）；仅作用于 count / dot / standalone 徽标（缎带不受影响），`prefers-reduced-motion` 下自动停用 | `BadgeAttention` | — |
| `bordered` | 白描边：布尔属性，徽标加 2px 背景色描边（box-shadow: 0 0 0 2px var(--oas-color-bg)），从头像/图片背景分离；仅视觉叠加不改定位（与 corner/offset/overlap 联动正常） | `boolean` | — |
| `color` | 徽标颜色：4 语义色（`primary` / `success` / `warning` / `danger`）、任意 CSS 色值、或 11 个预设名（`magenta` / `red` / `volcano` / `orange` / `gold` / `lime` / `green` / `cyan` / `blue` / `geekblue` / `purple`，映射 `--oas-preset-*` token，dark 自动调亮）。count / dot / ribbon 三种模式统一生效；实心文字色：语义色 / 预设名走固定 `text-on-*` token，仅任意 CSS 色值按底色亮度取黑/白保证可读 | `BadgeColor \| BadgePresetColor` | — |
| `corner` | 角标四角定位：`top-right`（默认）/ `top-left` / `bottom-right` / `bottom-left`，仅影响 count / dot 角标（ribbon 用 `placement`）；`offset` 在其结果上做屏幕坐标 px 微调（x 正向右、y 正向下，与 corner 朝向无关），先定角再平移可叠加；非法值静默回落 `top-right` | `BadgeCorner` | `top-right` |
| `dot` | 小圆点模式 | `boolean` | — |
| `icon` | 徽标内图标：内置图标名（如 check / warning），渲染内联 SVG（1em 跟随徽标字号、装饰性对读屏隐藏）；与 value/dot 互斥（icon 优先） | `string` | — |
| `max` | 上限 | `string` | — |
| `mode` | 模式：`count`（默认，数字/圆点徽标）或 `ribbon`（缎带角标，等价 `ribbon` 属性） | `BadgeMode` | `count` |
| `offset` | 位置微调：`"x,y"`（px 数字，支持负值），在角标/缎带定位基础上额外平移（x 正向右、y 正向下）；与 `corner` / `placement` / `ribbon-vertical` 可叠加（先定位再平移）；非法值（非数字、缺坐标）静默忽略 | `string` | — |
| `overlap` | 圆形内收：包裹圆形内容（如头像）时角标向圆内收进圆边（平移幅度从 50% 收到约 29%，1-√2/2 几何内收）；仅影响角标模式 | `boolean` | — |
| `placement` | 缎带位置：`start`（行首）/ `end`（行尾，默认） | `BadgePlacement` | `end` |
| `premium` | 金属质感：金色多段渐变底 + 深金细描边（clip-path 形态沿轮廓描边），文字色固定近黑 `#1a1a1a`；与 `color` 正交叠加，优先级 `premium` > `color` > 语义色默认；与 `ribbon-form` 各形态可组合，dark 主题自动适配（走 `--oas-preset-gold` token） | `boolean` | — |
| `ribbon` | 缎带角标模式（布尔，等价 `mode="ribbon"`） | `boolean` | — |
| `ribbon-anchor` | 缎带统一锚点，锚点集合按形态语义适配：`fold`（left/right 边中 + 四角，横条贴左/右、纵向上下可调）、`diagonal`/`triangle`（四角）、`side`（left/right 边中 + 四角）、`banner`（top/bottom）、`seal`（8 位置全支持）、`bookmark`（四角 + 四边中）；锚点预置贴边/贴角（底部锚点时折叠角自动翻转），任意位置用 `offset` 微调兜底；未设置时回落 placement/ribbon-position/ribbon-direction/ribbon-vertical 兼容别名，非法值或该形态不支持的锚点静默回落 | `BadgeRibbonAnchor` | — |
| `ribbon-direction` | bookmark 燕尾尖头方向：`down`（默认，顶边垂挂，尖头朝下）/ `left`（贴右缘，尖头朝左）/ `right`（贴左缘，尖头朝右）；物理方向语义（RTL 下不翻转）；仅 `ribbon-form="bookmark"` 生效，非法值静默回落 `down` | `BadgeRibbonDirection` | `down` |
| `ribbon-form` | 缎带形态：`fold`（默认，直条 + 折叠）/ `diagonal`（45° 对角斜带，条身探出卡外，宿主需 `overflow: hidden` 裁切）/ `triangle`（角落纯三角形，内容为小图标或 `slot="ribbon"`）/ `bookmark`（顶边垂挂 + 底部燕尾缺口）/ `side`（侧边竖挂）/ `seal`（圆形锯齿印章，文字居中）/ `banner`（顶部横贯横幅，两端折角）/ `flag`（侧燕尾横旗，横条 + 燕尾 V 缺口，缺口始终朝卡片内侧端：徽标在右缺口在左、在左缺口在右）/ `rounded`（圆头端）/ `zigzag`（锯齿端）/ `arrow`（箭头端）；`ribbon-position` 纵向三选仅作用于 `fold`，其余形态有各自纵向定位，非法值静默回落 `fold` | `BadgeRibbonForm` | `fold` |
| `ribbon-position` | 缎带纵向位置：`hang`（默认，挂沿下）/ `edge`（贴顶边）/ `cross`（骑跨顶边，压住卡片顶边框，包裹感最强）；与 `placement`（start/end 横向）正交，仅作用于 `ribbon-form="fold"` 形态，非法值静默回落 `hang` | `BadgeRibbonPosition` | `hang` |
| `ribbon-size` | diagonal 斜带尺寸档位：`small`（默认，30px 带宽 / xs 字号）/ `medium`（33px / sm 字号，钉点 35px）/ `large`（36px / md 字号，钉点 45px，宽幅大字场景）；`sm`/`md`/`lg` 为等价别名；档位只改 `--oas-badge-diagonal-*` 的 fallback 默认值，宿主自定义属性优先级更高；仅 `ribbon-form="diagonal"` 生效，非法值静默回落 `small` | `BadgeRibbonSize` | `small` |
| `ribbon-vertical` | bookmark 侧挂（`ribbon-direction="left"` / `"right"`）的纵向位置：`center`（默认，垂直居中）/ `top`（贴顶边）/ `bottom`（贴底边）；仅侧挂生效，非法值静默回落 `center` | `BadgeRibbonVertical` | `center` |
| `rolled` | 端部卷边：布尔修饰，给卡片内侧端做卷边效果（内侧端大圆角 + 渐暗渐变模拟卷起圆柱，外端顶卡片边线不再探出；纯 CSS）；可叠加 `fold` / `flag` / `rounded` / `zigzag` / `arrow`（`banner` 保留自身双端折角、不叠卷边；`diagonal` / `triangle` / `bookmark` / `side` / `seal` 静默忽略） | `boolean` | — |
| `shape` | 徽标形态 `round`（默认）/ `square` / `pill`，数值与 dot 通用 | `string` | — |
| `showZero` | value=0 时是否显示 | `boolean` | — |
| `size` | 尺寸档位：small（小档，数字徽标高约 13px、dot 6px）/ medium（默认，约 16px）/ large（大档，约 20px、dot 10px）；非法值静默回落 medium | `BadgeSize` | `medium` |
| `status` | 状态点形态：`success` / `processing` / `default` / `error` / `warning`，渲染「状态点 + `text` 文字」的行内独立元素，与 ribbon / dot / count 模式互斥（设置时优先渲染）；`processing` 圆点带脉冲动画（`prefers-reduced-motion` 下停用） | `BadgeStatus` | — |
| `text` | 缎带或状态点文字；`slot="ribbon"` 有内容时以插槽为准 | `string` | — |
| `value` | 数字 | `string` | — |
| `variant` | 形态：solid（默认，实心）或 outline（描边：背景透明、边框与文字走 color 语义色）；非法值静默回落 solid | `BadgeVariant` | — |

#### 插槽

| 名称 | 说明 |
| --- | --- |
| 默认 | 被包裹内容（卡片、按钮等）；无内容时徽标回落为独立行内展示 |
| `ribbon` | 缎带自定义内容 |

#### CSS 变量

| CSS 变量 | 说明 | 默认值 |
| --- | --- | --- |
| `--oas-badge-bg` | — | `var(--oas-color-danger)` |
| `--oas-badge-diagonal-font` | — | `var(--oas-font-size-xs)` |
| `--oas-badge-diagonal-height` | — | `30px` |
| `--oas-badge-diagonal-pin` | — | `25px` |
| `--oas-badge-diagonal-text-inset` | — | `0px` |
| `--oas-badge-on-color` | — | `var(--oas-color-text-on-danger)` |
| `--oas-badge-outline` | outline 描边形态的边框与文字色（`color` 为语义色/预设名时组件注入 `-text` 安全档；缺省回落徽标底色） | `var(--oas-badge-bg, var(--oas-color-danger))` |
| `--oas-badge-pos` | — | `translate(50%, -50%)` |
| `--oas-badge-pulse-color` | — | `var(--oas-badge-bg, var(--oas-color-danger))` |
| `--oas-diag-pin` | — | `var(--oas-badge-diagonal-pin, 25px)` |
| `--oas-ribbon-anchor-x` | — | `0px` |
| `--oas-ribbon-anchor-y` | — | `0px` |
| `--oas-ribbon-offset-x` | — | `0px` |
| `--oas-ribbon-offset-y` | — | `0px` |
| `--oas-status-color` | — | `var(--oas-color-text-secondary)` |
