移动端导航标签

标签Tag

用简短的文字标注状态、分类或属性;可关闭的标签用于已选项

数据展示 规格 10 · 标签 Tag 6 端实现 触摸优先

引入(H5 原生;其余 5 端见「快速开始」)
<!-- ① 令牌:PC 令牌 + 移动端 --kole-m-* 合成单文件,引一次 -->
<link rel="stylesheet" href="kole-ui/mobile/tokens.css">

<!-- ② 本组件样式(全量则用 kole-ui/mobile/components/index.css) -->
<link rel="stylesheet" href="kole-ui/mobile/components/mobile-tag.css">

<!-- ③ 结构照抄下方任一演示块(类名与 6 端实现一致) -->

演示

每个演示都是真实渲染:预览帧加载 frameworks-mobile/Tag.html?demo=<id>(只显示该演示块),代码是该演示块在演示页里的原文,可复制。全部演示同屏可看 演示页 ↗。

01 组件类型

基础用法tone=default

默认语气的标签,用于普通分类标注;纯展示标签不加交互角色。

查看代码(演示页原文 · 11 行)
frameworks-mobile/Tag.html · basic
<section class="demo-block" data-demo="basic">
  <p class="demo-label">基础用法(tone=default:默认语气,用于普通分类标注)</p>
  <div class="demo-box">
    <span class="kole-m-tag kole-m-tag--default" data-assert="tag-basic">
      <span class="kole-m-tag__label">全部订单</span>
    </span>
    <span class="kole-m-tag kole-m-tag--default">
      <span class="kole-m-tag__label">待发货</span>
    </span>
  </div>
</section>
五种语气tone=primary|success|warning|danger

primary / success / warning / danger 的底色与字色同族,浅底深字在亮暗两态都达标。

查看代码(演示页原文 · 17 行)
frameworks-mobile/Tag.html · tone
<section class="demo-block" data-demo="tone">
  <p class="demo-label">五种语气(tone=primary / success / warning / danger:底色与字色同族)</p>
  <div class="demo-box">
    <span class="kole-m-tag kole-m-tag--primary" data-assert="tag-tone">
      <span class="kole-m-tag__label">进行中</span>
    </span>
    <span class="kole-m-tag kole-m-tag--success">
      <span class="kole-m-tag__label">已完成</span>
    </span>
    <span class="kole-m-tag kole-m-tag--warning">
      <span class="kole-m-tag__label">待付款</span>
    </span>
    <span class="kole-m-tag kole-m-tag--danger">
      <span class="kole-m-tag__label">已取消</span>
    </span>
  </div>
</section>
可关闭closable=true

关闭按钮是原生 button(热区 24×24)并带 aria-label,读屏能区分是哪一枚标签。

查看代码(演示页原文 · 15 行)
frameworks-mobile/Tag.html · closable
<section class="demo-block" data-demo="closable">
  <p class="demo-label">可关闭(closable=true:关闭按钮是原生 button,热区 24×24,点后打标记)</p>
  <div class="demo-box">
    <span class="kole-m-tag kole-m-tag--primary" id="tag-closable" data-assert="tag-closable">
      <span class="kole-m-tag__label">已勾选</span>
      <button class="kole-m-tag__close" type="button" aria-label="移除标签:已勾选"
              data-behavior="click-sets-attr:#tag-closable|data-closed|true">✕</button>
    </span>
    <span class="kole-m-tag kole-m-tag--default" id="tag-closable-2">
      <span class="kole-m-tag__label">已发货</span>
      <button class="kole-m-tag__close" type="button" aria-label="移除标签:已发货"
              data-behavior="click-sets-attr:#tag-closable-2|data-closed|true">✕</button>
    </span>
  </div>
</section>

02 组件状态

小尺寸size=small

size=small 更矮更紧,适合表格行内或列表右侧这类空间受限的位置。

查看代码(演示页原文 · 14 行)
frameworks-mobile/Tag.html · small
<section class="demo-block" data-demo="small">
  <p class="demo-label">小尺寸(size=small:更矮更紧,用于表格行内或列表右侧)</p>
  <div class="demo-box">
    <span class="kole-m-tag kole-m-tag--small kole-m-tag--success" data-assert="tag-small">
      <span class="kole-m-tag__label">正常</span>
    </span>
    <span class="kole-m-tag kole-m-tag--small kole-m-tag--warning">
      <span class="kole-m-tag__label">超时</span>
    </span>
    <span class="kole-m-tag kole-m-tag--small kole-m-tag--default">
      <span class="kole-m-tag__label">草稿</span>
    </span>
  </div>
</section>
禁用状态 disabled

置灰且关闭按钮不响应,用于无权限项;禁用态文字用 disabled 色(WCAG 对禁用控件豁免)。

查看代码(演示页原文 · 12 行)
frameworks-mobile/Tag.html · disabled
<section class="demo-block" data-demo="disabled">
  <p class="demo-label">禁用(状态 disabled:置灰且关闭按钮不响应,多用于无权限项)</p>
  <div class="demo-box">
    <span class="kole-m-tag kole-m-tag--default is-disabled" data-assert="tag-disabled" aria-disabled="true">
      <span class="kole-m-tag__label">不可编辑</span>
      <button class="kole-m-tag__close" type="button" aria-label="移除标签:不可编辑" disabled>✕</button>
    </span>
    <span class="kole-m-tag kole-m-tag--primary is-disabled" aria-disabled="true">
      <span class="kole-m-tag__label">已归档</span>
    </span>
  </div>
</section>

API

props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs

Props

名称类型默认值说明必传
tone'default' | 'primary' | 'success' | 'warning' | 'danger''default'变体 tone:五种语气,底色与字色同族(规格 §10.3)N
size'default' | 'small''default'变体 size:small 更矮更紧,用于表格行内或列表右侧(规格 §10.3)N
closablebooleanfalse变体 closable:显示关闭按钮(规格 §10.3)N
disabledbooleanfalse状态 disabled:置灰且不可关闭(规格 §10.4)N

「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。

事件

名称参数说明
close—点击关闭按钮时触发;是否真的移除标签由宿主决定(规格 §10.5)

插槽

名称说明
default标签文字(规格 §10.2 label)

CSS 变量

组件级变量(在组件样式表里定义)。业务侧可在自己的作用域内覆盖,不必改组件源码。

名称默认值说明
--kole-m-tag-height24px标签高度(小尺寸 20px)
--kole-m-tag-hit-slack6px关闭按钮向外的额外热区
--kole-m-tag-height20px组件内部默认值,可在业务侧覆盖

何时使用

  • 用简短的文字标注状态、分类或属性;可关闭的标签用于已选项
  • 关闭按钮热区不小于 24×24(小尺寸标签内用负外边距扩展热区)
  • 关闭动作只触发一次事件,是否真的移除由宿主决定
  • 关闭按钮为原生 button 并带 aria-label(如「移除标签:已发货」)
  • 纯展示标签不加交互角色

交互与触控

  • 关闭按钮热区不小于 24×24(小尺寸标签内用负外边距扩展热区)
  • 关闭动作只触发一次事件,是否真的移除由宿主决定

无障碍

  • 关闭按钮为原生 button 并带 aria-label(如「移除标签:已发货」)
  • 纯展示标签不加交互角色

从「该用哪一个」的角度区分;PC 端的对应实现见 PC 文档站。

组件何时用它而不是本组件
徽标Badge徽标只承载计数与红点,标签承载文字语义;需要计数时用徽标而不是把数字写进标签
单元格Cell列表行右侧的状态标记用标签;整行可点时用单元格的 value,不必再叠标签
分割线Divider同一组标签之间的分隔靠间距,不要用分割线把标签切开

规格未定 / 禁止发明

类别条目
禁止发明标签的动态增删动画
禁止发明超长标签的换行规则
规格未定同一行最多放几个标签
规格未定关闭后是否保留占位

结构(anatomy)

字段说明
tag根元素,圆角胶囊
label标签文字
close可选关闭按钮

变体维度与类名映射

类名映射由构建脚本从契约 variantClasses 生成,并被 verify:mobile-docs 逐条对照组件 CSS 校验(类/变量必须真实存在)。

维度取值对应类名 / 变量
tonedefault / primary / success / warning / danger
default .kole-m-tag--default
primary .kole-m-tag--primary
success .kole-m-tag--success
warning .kole-m-tag--warning
danger .kole-m-tag--danger
sizedefault / small
default (由数据驱动,无专属类)
small .kole-m-tag--small
closablefalse / true
false (由数据驱动,无专属类)
true .kole-m-tag__close

代表变体

变体标签
tone=default · size=default · closable=false基础标签
tone=success · size=default · closable=false成功语气
tone=primary · size=default · closable=true可关闭标签
tone=warning · size=small · closable=false小尺寸标签

用到的令牌

构建时从本组件样式表扫描得出。蓝色为移动端自有令牌,绿色为继承的 PC 令牌(改一处两端生效)。

--kole-m-font-size-caption --kole-color-brand --kole-color-brand-bg --kole-color-disabled-bg --kole-color-error --kole-color-focus-ring --kole-color-success --kole-color-table-header-bg --kole-color-tag-green-bg --kole-color-text-disabled --kole-color-text-secondary --kole-color-warning --kole-font-family --kole-space-4 --kole-space-8 --kole-m-tag-height --kole-m-tag-hit-slack

6 端源码

同一组件的六份实现(生产环境的类名与结构一致,差异只在技术栈写法与单位)。点开查看,右侧可复制。

frameworks-mobile/Tag.css · 纯样式(CSS) · 76 行
frameworks-mobile/Tag.css
/* Kole UI Mobile · Tag 样式 — 对齐移动端规格 §10
   标签:圆角胶囊,浅底 + 同族深色文字(对比度亮色 5.35:1 起、暗色 ≥4.5:1);
   closable 的关闭按钮是原生 button,热区 24×24(不足处用负外边距扩展)。 */

.kole-m-tag {
  --kole-m-tag-height: 24px;      /* 标签高度(小尺寸 20px) */
  --kole-m-tag-hit-slack: 6px;    /* 关闭按钮向外的额外热区 */
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  gap: var(--kole-space-4);
  max-width: 100%;
  height: var(--kole-m-tag-height);
  padding: 0 var(--kole-space-8);
  border-radius: calc(var(--kole-m-tag-height) / 2);
  background: var(--kole-color-brand-bg);
  color: var(--kole-color-brand);
  font-family: var(--kole-font-family);
  font-size: var(--kole-m-font-size-caption);
  line-height: 1;
  white-space: nowrap;
}

.kole-m-tag__label {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 变体 size=small:更矮更紧,用于表格行内或列表右侧 */
.kole-m-tag--small {
  --kole-m-tag-height: 20px;
  padding: 0 var(--kole-space-4);
}

/* 变体 tone:五种语气,底色与字色同族(浅底 + 深字,对比度已实测) */
.kole-m-tag--primary { background: var(--kole-color-brand-bg); color: var(--kole-color-brand); }
.kole-m-tag--success { background: var(--kole-color-tag-green-bg); color: var(--kole-color-success); }
.kole-m-tag--warning { background: var(--kole-color-table-header-bg); color: var(--kole-color-warning); }
.kole-m-tag--danger { background: var(--kole-color-table-header-bg); color: var(--kole-color-error); }
.kole-m-tag--default { background: var(--kole-color-disabled-bg); color: var(--kole-color-text-secondary); }

/* 状态 disabled:置灰且不可关闭 */
.kole-m-tag.is-disabled {
  background: var(--kole-color-disabled-bg);
  color: var(--kole-color-text-disabled);
  pointer-events: none;
}

/* 关闭按钮:原生 button,24×24 热区(视觉尺寸小,靠 padding 撑开) */
.kole-m-tag__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 24px;
  height: 24px;
  margin-inline: calc(-1 * var(--kole-m-tag-hit-slack)) calc(-1 * var(--kole-space-4));
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: none;
  color: inherit;
  font-family: inherit;
  font-size: var(--kole-m-font-size-caption);
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}

.kole-m-tag__close:focus-visible {
  outline: 2px solid var(--kole-color-focus-ring);
  outline-offset: -2px;
}

.kole-m-tag__close:active { background: var(--kole-color-table-header-bg); }
frameworks-mobile/Tag.html · H5 原生(无框架) · 129 行
frameworks-mobile/Tag.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Kole UI Mobile · Tag(H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui-mobile/colors_and_type.css">
<link rel="stylesheet" href="Tag.css">
<style>
  body { margin: 0; background: var(--kole-color-page-bg); font-family: var(--kole-font-family); color: var(--kole-color-text-body); }
  .demo { max-width: 375px; margin: 0 auto; padding: var(--kole-m-gutter) 0; }
  .demo-label { margin: 0; padding: var(--kole-space-12) var(--kole-m-gutter) var(--kole-space-8);
    font-size: var(--kole-m-font-size-label); color: var(--kole-color-text-secondary); }
  .demo-box { display: flex; flex-wrap: wrap; align-items: center; gap: var(--kole-space-8);
    padding: var(--kole-space-16) var(--kole-m-gutter); background: var(--kole-color-card-bg);
    border-block: 1px solid var(--kole-color-border); }
  .demo-block[hidden] { display: none; }
</style>
</head>
<body>
<div class="demo">
  <section class="demo-block" data-demo="basic">
    <p class="demo-label">基础用法(tone=default:默认语气,用于普通分类标注)</p>
    <div class="demo-box">
      <span class="kole-m-tag kole-m-tag--default" data-assert="tag-basic">
        <span class="kole-m-tag__label">全部订单</span>
      </span>
      <span class="kole-m-tag kole-m-tag--default">
        <span class="kole-m-tag__label">待发货</span>
      </span>
    </div>
  </section>

  <section class="demo-block" data-demo="tone">
    <p class="demo-label">五种语气(tone=primary / success / warning / danger:底色与字色同族)</p>
    <div class="demo-box">
      <span class="kole-m-tag kole-m-tag--primary" data-assert="tag-tone">
        <span class="kole-m-tag__label">进行中</span>
      </span>
      <span class="kole-m-tag kole-m-tag--success">
        <span class="kole-m-tag__label">已完成</span>
      </span>
      <span class="kole-m-tag kole-m-tag--warning">
        <span class="kole-m-tag__label">待付款</span>
      </span>
      <span class="kole-m-tag kole-m-tag--danger">
        <span class="kole-m-tag__label">已取消</span>
      </span>
    </div>
  </section>

  <section class="demo-block" data-demo="closable">
    <p class="demo-label">可关闭(closable=true:关闭按钮是原生 button,热区 24×24,点后打标记)</p>
    <div class="demo-box">
      <span class="kole-m-tag kole-m-tag--primary" id="tag-closable" data-assert="tag-closable">
        <span class="kole-m-tag__label">已勾选</span>
        <button class="kole-m-tag__close" type="button" aria-label="移除标签:已勾选"
                data-behavior="click-sets-attr:#tag-closable|data-closed|true">✕</button>
      </span>
      <span class="kole-m-tag kole-m-tag--default" id="tag-closable-2">
        <span class="kole-m-tag__label">已发货</span>
        <button class="kole-m-tag__close" type="button" aria-label="移除标签:已发货"
                data-behavior="click-sets-attr:#tag-closable-2|data-closed|true">✕</button>
      </span>
    </div>
  </section>

  <section class="demo-block" data-demo="small">
    <p class="demo-label">小尺寸(size=small:更矮更紧,用于表格行内或列表右侧)</p>
    <div class="demo-box">
      <span class="kole-m-tag kole-m-tag--small kole-m-tag--success" data-assert="tag-small">
        <span class="kole-m-tag__label">正常</span>
      </span>
      <span class="kole-m-tag kole-m-tag--small kole-m-tag--warning">
        <span class="kole-m-tag__label">超时</span>
      </span>
      <span class="kole-m-tag kole-m-tag--small kole-m-tag--default">
        <span class="kole-m-tag__label">草稿</span>
      </span>
    </div>
  </section>

  <section class="demo-block" data-demo="disabled">
    <p class="demo-label">禁用(状态 disabled:置灰且关闭按钮不响应,多用于无权限项)</p>
    <div class="demo-box">
      <span class="kole-m-tag kole-m-tag--default is-disabled" data-assert="tag-disabled" aria-disabled="true">
        <span class="kole-m-tag__label">不可编辑</span>
        <button class="kole-m-tag__close" type="button" aria-label="移除标签:不可编辑" disabled>✕</button>
      </span>
      <span class="kole-m-tag kole-m-tag--primary is-disabled" aria-disabled="true">
        <span class="kole-m-tag__label">已归档</span>
      </span>
    </div>
  </section>
</div>
<script>
  /* 演示页交互:关闭按钮只打标记(真实业务里是否移除该项由宿主决定)。 */
  (function () {
    document.querySelectorAll('.kole-m-tag__close').forEach(function (btn) {
      btn.addEventListener('click', function () {
        var tag = btn.closest('.kole-m-tag');
        if (tag) tag.setAttribute('data-closed', 'true');
      });
    });
  })();
</script>
<script>
  /* ?demo=<id> → 只显示该演示块(文档站按块预览用;无参数时全部显示,测试与回归走无参数路径) */
  (function () {
    var id = new URLSearchParams(location.search).get('demo');
    if (!id) return;
    var blocks = Array.prototype.slice.call(document.querySelectorAll('.demo-block'));
    var hit = false;
    blocks.forEach(function (b) {
      var on = b.getAttribute('data-demo') === id;
      if (on) hit = true;
      b.hidden = !on;
    });
    if (!hit) { blocks.forEach(function (b) { b.hidden = false; }); return; }
    document.body.classList.add('demo-single');
    blocks.forEach(function (b) {
      var label = b.querySelector('.demo-label');
      if (label && !b.hidden) label.hidden = true;
    });
  })();
</script>
</body>
</html>
frameworks-mobile/Tag.jsx · React · 43 行
frameworks-mobile/Tag.jsx
import React from 'react';
import './Tag.css';

/* 标签(移动端)— 规格 §10;closable 的关闭按钮是原生 button(带 aria-label),
   关闭动作只回调,是否真的移除标签由宿主决定。 */
export default function Tag({
  tone = 'default',
  size = 'default',
  closable = false,
  disabled = false,
  onClose,
  children = null,
}) {
  const cls =
    'kole-m-tag' +
    ` kole-m-tag--${tone}` +
    (size === 'small' ? ' kole-m-tag--small' : '') +
    (disabled ? ' is-disabled' : '');

  /* 关闭按钮的读屏名称要带上标签文字,否则一串「✕」无法区分(规格 §10.6) */
  const label = typeof children === 'string' ? children : '';

  return (
    <span className={cls} aria-disabled={disabled ? 'true' : undefined}>
      <span className="kole-m-tag__label">{children}</span>
      {closable ? (
        <button
          className="kole-m-tag__close"
          type="button"
          disabled={disabled}
          aria-label={`移除标签:${label}`}
          onClick={() => {
            if (disabled) return;
            if (onClose) onClose();
          }}
        >
          ✕
        </button>
      ) : null}
    </span>
  );
}
frameworks-mobile/Tag.vue2.vue · Vue 2 · 53 行
frameworks-mobile/Tag.vue2.vue
<template>
  <span class="kole-m-tag" :class="tagClass" :aria-disabled="disabled ? 'true' : null">
    <span class="kole-m-tag__label"><slot></slot></span>
    <button
      v-if="closable"
      class="kole-m-tag__close"
      type="button"
      :disabled="disabled"
      :aria-label="closeLabel"
      @click="onCloseClick"
    >✕</button>
  </span>
</template>

<script>
export default {
  name: 'KoleMTag',
  props: {
    tone: { type: String, default: 'default' },
    size: { type: String, default: 'default' },
    closable: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false }
  },
  computed: {
    tagClass: function () {
      return [
        'kole-m-tag--' + this.tone,
        this.size === 'small' ? 'kole-m-tag--small' : '',
        this.disabled ? 'is-disabled' : ''
      ].filter(Boolean);
    },
    /* 关闭按钮的读屏名称带上标签文字,否则一串「✕」无法区分(规格 §10.6) */
    closeLabel: function () {
      var nodes = (this.$slots && this.$slots.default) || [];
      var text = nodes
        .map(function (n) {
          return n.children && typeof n.children === 'string' ? n.children : '';
        })
        .join('');
      return '移除标签:' + text;
    }
  },
  methods: {
    onCloseClick: function () {
      if (this.disabled) return;
      this.$emit('close');
    }
  }
};
</script>

<style src="./Tag.css"></style>
frameworks-mobile/Tag.vue3.vue · Vue 3 · 47 行
frameworks-mobile/Tag.vue3.vue
<template>
  <span class="kole-m-tag" :class="tagClass" :aria-disabled="disabled ? 'true' : null">
    <span class="kole-m-tag__label"><slot></slot></span>
    <button
      v-if="closable"
      class="kole-m-tag__close"
      type="button"
      :disabled="disabled"
      :aria-label="closeLabel"
      @click="onCloseClick"
    >✕</button>
  </span>
</template>

<script setup>
import { computed, useSlots } from 'vue';

const props = defineProps({
  tone: { type: String, default: 'default' },
  size: { type: String, default: 'default' },
  closable: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false }
});
const emit = defineEmits(['close']);

const slots = useSlots();
const tagClass = computed(() => [
  `kole-m-tag--${props.tone}`,
  props.size === 'small' ? 'kole-m-tag--small' : '',
  props.disabled ? 'is-disabled' : ''
].filter(Boolean));

/* 关闭按钮的读屏名称带上标签文字,否则一串「✕」无法区分(规格 §10.6) */
const closeLabel = computed(() => {
  const nodes = slots.default ? slots.default() : [];
  const text = nodes.map((n) => (typeof n.children === 'string' ? n.children : '')).join('');
  return '移除标签:' + text;
});

function onCloseClick() {
  if (props.disabled) return;
  emit('close');
}
</script>

<style src="./Tag.css"></style>
frameworks-mobile/Tag.uniapp.vue · uni-app(跨端:小程序 / App / H5) · 103 行
frameworks-mobile/Tag.uniapp.vue
<template>
  <view class="kole-m-tag" :class="tagClass" :aria-disabled="disabled ? 'true' : 'false'">
    <text class="kole-m-tag__label"><slot></slot></text>
    <view
      v-if="closable"
      class="kole-m-tag__close"
      :role="disabled ? '' : 'button'"
      :aria-label="closeLabel"
      @tap="onCloseTap"
    ><text>✕</text></view>
  </view>
</template>

<script setup>
/* uni-app 端 · 标签(移动端)— 规格 §10
   跨端差异:用 view / text;关闭按钮用 view + role="button" + aria-label(小程序无 <button>
   的行内语义,role 在 H5 产物里生效),点击用 @tap;尺寸用 rpx(48rpx = 24px @375pt)。 */
import { computed, useSlots } from 'vue';

const props = defineProps({
  tone: { type: String, default: 'default' },
  size: { type: String, default: 'default' },
  closable: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false }
});
const emit = defineEmits(['close']);

const slots = useSlots();
const tagClass = computed(() => [
  `kole-m-tag--${props.tone}`,
  props.size === 'small' ? 'kole-m-tag--small' : '',
  props.disabled ? 'is-disabled' : ''
].filter(Boolean));

/* 关闭按钮的读屏名称带上标签文字,否则一串「✕」无法区分(规格 §10.6) */
const closeLabel = computed(() => {
  const nodes = slots.default ? slots.default() : [];
  const text = nodes.map((n) => (typeof n.children === 'string' ? n.children : '')).join('');
  return '移除标签:' + text;
});

function onCloseTap() {
  if (props.disabled) return;
  emit('close');
}
</script>

<style>
.kole-m-tag {
  --kole-m-tag-height: 48rpx;
  --kole-m-tag-hit-slack: 12rpx;
  --kole-m-font-size-caption: 22rpx;
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  height: var(--kole-m-tag-height);
  padding: 0 16rpx;
  border-radius: 24rpx;
  background-color: var(--kole-color-brand-bg);
  color: var(--kole-color-brand);
  font-size: var(--kole-m-font-size-caption);
  line-height: 1;
}

.kole-m-tag__label {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.kole-m-tag--small {
  --kole-m-tag-height: 40rpx;
  padding: 0 8rpx;
}

.kole-m-tag--primary { background-color: var(--kole-color-brand-bg); color: var(--kole-color-brand); }
.kole-m-tag--success { background-color: var(--kole-color-tag-green-bg); color: var(--kole-color-success); }
.kole-m-tag--warning { background-color: var(--kole-color-table-header-bg); color: var(--kole-color-warning); }
.kole-m-tag--danger { background-color: var(--kole-color-table-header-bg); color: var(--kole-color-error); }
.kole-m-tag--default { background-color: var(--kole-color-disabled-bg); color: var(--kole-color-text-secondary); }

.kole-m-tag.is-disabled {
  background-color: var(--kole-color-disabled-bg);
  color: var(--kole-color-text-disabled);
}

.kole-m-tag__close {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48rpx;
  height: 48rpx;
  margin-right: -8rpx;
  margin-left: -4rpx;
  border-radius: 50%;
  color: inherit;
  font-size: var(--kole-m-font-size-caption);
  line-height: 1;
}
</style>

测试与回归

断言在真实的 375×640 设备帧里跑(引擎与 PC 侧共用 tests/_runtime.js,触控行为动词来自移动端 tests/mobile/_behaviors.js)。

断言 17 条 · 全部通过 报告 2026-09-22 23:01:05

复现命令
node site/dev-server.js &
REG_BASE=http://127.0.0.1:3311 node tools/run-mobile-regression.mjs   # 全量 5 个组件
npm run verify:mobile-docs                                           # 本页内容完整性 + API 与源码一致性

设计契约

components/mobile-tag.json(点击展开原始 JSON)
{
  "schemaVersion": 1,
  "sourceKind": "authored-spec",
  "provenance": "authored-in-repo",
  "specFile": "spec/移动端规格.md",
  "confidence": "high",
  "specSection": "10 · 标签 Tag",
  "slug": "mobile-tag",
  "name": "标签 Tag",
  "semanticTypeCandidates": [
    "tag",
    "chip",
    "label"
  ],
  "variantDimensions": [
    {
      "name": "tone",
      "values": [
        "default",
        "primary",
        "success",
        "warning",
        "danger"
      ]
    },
    {
      "name": "size",
      "values": [
        "default",
        "small"
      ]
    },
    {
      "name": "closable",
      "values": [
        "false",
        "true"
      ]
    }
  ],
  "representativeVariants": [
    {
      "tone": "default",
      "size": "default",
      "closable": "false",
      "label": "基础标签"
    },
    {
      "tone": "success",
      "size": "default",
      "closable": "false",
      "label": "成功语气"
    },
    {
      "tone": "primary",
      "size": "default",
      "closable": "true",
      "label": "可关闭标签"
    },
    {
      "tone": "warning",
      "size": "small",
      "closable": "false",
      "label": "小尺寸标签"
    }
  ],
  "anatomy": {
    "tag": "根元素,圆角胶囊",
    "label": "标签文字",
    "close": "可选关闭按钮"
  },
  "structurePatterns": {
    "tone": "default / primary / success / warning / danger",
    "size": "default / small",
    "closable": "false / true"
  },
  "usageHints": [
    "用简短的文字标注状态、分类或属性;可关闭的标签用于已选项",
    "关闭按钮热区不小于 24×24(小尺寸标签内用负外边距扩展热区)",
    "关闭动作只触发一次事件,是否真的移除由宿主决定",
    "关闭按钮为原生 button 并带 aria-label(如「移除标签:已发货」)",
    "纯展示标签不加交互角色"
  ],
  "doNotInvent": [
    "标签的动态增删动画",
    "超长标签的换行规则"
  ],
  "unknowns": [
    "同一行最多放几个标签",
    "关闭后是否保留占位"
  ],
  "interaction": [
    "关闭按钮热区不小于 24×24(小尺寸标签内用负外边距扩展热区)",
    "关闭动作只触发一次事件,是否真的移除由宿主决定"
  ],
  "accessibility": [
    "关闭按钮为原生 button 并带 aria-label(如「移除标签:已发货」)",
    "纯展示标签不加交互角色"
  ],
  "api": {
    "source": "implementation",
    "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs",
    "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。",
    "props": [
      {
        "name": "tone",
        "type": "'default' | 'primary' | 'success' | 'warning' | 'danger'",
        "default": "'default'",
        "desc": "变体 tone:五种语气,底色与字色同族(规格 §10.3)",
        "required": false
      },
      {
        "name": "size",
        "type": "'default' | 'small'",
        "default": "'default'",
        "desc": "变体 size:small 更矮更紧,用于表格行内或列表右侧(规格 §10.3)",
        "required": false
      },
      {
        "name": "closable",
        "type": "boolean",
        "default": "false",
        "desc": "变体 closable:显示关闭按钮(规格 §10.3)",
        "required": false
      },
      {
        "name": "disabled",
        "type": "boolean",
        "default": "false",
        "desc": "状态 disabled:置灰且不可关闭(规格 §10.4)",
        "required": false
      }
    ],
    "events": [
      {
        "name": "close",
        "params": "—",
        "desc": "点击关闭按钮时触发;是否真的移除标签由宿主决定(规格 §10.5)"
      }
    ],
    "slots": [
      {
        "name": "default",
        "desc": "标签文字(规格 §10.2 label)"
      }
    ]
  },
  "variantClasses": {
    "tone": {
      "default": [
        ".kole-m-tag--default"
      ],
      "primary": [
        ".kole-m-tag--primary"
      ],
      "success": [
        ".kole-m-tag--success"
      ],
      "warning": [
        ".kole-m-tag--warning"
      ],
      "danger": [
        ".kole-m-tag--danger"
      ]
    },
    "size": {
      "default": [],
      "small": [
        ".kole-m-tag--small"
      ]
    },
    "closable": {
      "false": [],
      "true": [
        ".kole-m-tag__close"
      ]
    }
  },
  "demos": [
    {
      "id": "basic",
      "group": "01 组件类型",
      "title": "基础用法",
      "desc": "默认语气的标签,用于普通分类标注;纯展示标签不加交互角色。",
      "variant": "tone=default"
    },
    {
      "id": "tone",
      "group": "01 组件类型",
      "title": "五种语气",
      "desc": "primary / success / warning / danger 的底色与字色同族,浅底深字在亮暗两态都达标。",
      "variant": "tone=primary|success|warning|danger"
    },
    {
      "id": "closable",
      "group": "01 组件类型",
      "title": "可关闭",
      "desc": "关闭按钮是原生 button(热区 24×24)并带 aria-label,读屏能区分是哪一枚标签。",
      "variant": "closable=true"
    },
    {
      "id": "small",
      "group": "02 组件状态",
      "title": "小尺寸",
      "desc": "size=small 更矮更紧,适合表格行内或列表右侧这类空间受限的位置。",
      "variant": "size=small"
    },
    {
      "id": "disabled",
      "group": "02 组件状态",
      "title": "禁用",
      "desc": "置灰且关闭按钮不响应,用于无权限项;禁用态文字用 disabled 色(WCAG 对禁用控件豁免)。",
      "variant": "状态 disabled"
    }
  ],
  "related": [
    {
      "slug": "mobile-badge",
      "why": "徽标只承载计数与红点,标签承载文字语义;需要计数时用徽标而不是把数字写进标签"
    },
    {
      "slug": "cell",
      "why": "列表行右侧的状态标记用标签;整行可点时用单元格的 value,不必再叠标签"
    },
    {
      "slug": "mobile-divider",
      "why": "同一组标签之间的分隔靠间距,不要用分割线把标签切开"
    }
  ]
}