移动端导航单元格

单元格Cell

列表的基本单元:一行里承载「标题 + 说明 + 值 + 箭头」,可整行点击进入下级

数据展示 规格 7 · 单元格 Cell 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/cell.css">

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

演示

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

01 组件类型

基础用法link=true / arrow=true

标题 + 右侧值 + 箭头,最常见的可点单元格。

查看代码(演示页原文 · 11 行)
frameworks-mobile/Cell.html · basic
<section class="demo-block" data-demo="basic">
  <p class="demo-label">基础用法(link + arrow:整行可点,带箭头)</p>
  <div class="demo-box">
    <button class="kole-m-cell kole-m-cell--link" type="button" id="cell-link"
            data-assert="cell-basic" data-behavior="click-sets-attr:#cell-link|data-clicked|true">
      <span class="kole-m-cell__main"><span class="kole-m-cell__title">收货地址</span></span>
      <span class="kole-m-cell__value">杭州市余杭区</span>
      <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
    </button>
  </div>
</section>
带副标题desc

两行文字(主 + 副),副标题单行省略。

查看代码(演示页原文 · 12 行)
frameworks-mobile/Cell.html · desc
<section class="demo-block" data-demo="desc">
  <p class="demo-label">带副标题(两行文字,副标题单行省略)</p>
  <div class="demo-box">
    <div class="kole-m-cell" data-assert="cell-desc">
      <span class="kole-m-cell__main">
        <span class="kole-m-cell__title">订单编号</span>
        <span class="kole-m-cell__desc">20260920-001 · 2026-09-20 09:12 创建</span>
      </span>
      <span class="kole-m-cell__value">已发货</span>
    </div>
  </div>
</section>
自定义右侧slots.default

右侧放开关、标签等非文字内容(此处用标签示意)。

查看代码(演示页原文 · 9 行)
frameworks-mobile/Cell.html · custom
<section class="demo-block" data-demo="custom">
  <p class="demo-label">自定义右侧(右侧放标签等非文字内容)</p>
  <div class="demo-box">
    <div class="kole-m-cell" data-assert="cell-custom">
      <span class="kole-m-cell__main"><span class="kole-m-cell__title">发票抬头</span></span>
      <span class="demo-tag">已开票</span>
    </div>
  </div>
</section>

02 组件状态

分组列表borderless

一组单元格共享分隔线;组内最后一条用 borderless 收尾。

查看代码(演示页原文 · 15 行)
frameworks-mobile/Cell.html · group
<section class="demo-block" data-demo="group">
  <p class="demo-label">分组列表(组内共享分隔线,最后一条 borderless 收尾)</p>
  <div class="demo-box">
    <button class="kole-m-cell kole-m-cell--link" type="button" data-assert="cell-group-1">
      <span class="kole-m-cell__main"><span class="kole-m-cell__title">支付方式</span></span>
      <span class="kole-m-cell__value">微信支付</span>
      <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
    </button>
    <button class="kole-m-cell kole-m-cell--link kole-m-cell--borderless" type="button" data-assert="cell-group-2">
      <span class="kole-m-cell__main"><span class="kole-m-cell__title">配送方式</span></span>
      <span class="kole-m-cell__value">顺丰标快</span>
      <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
    </button>
  </div>
</section>
禁用disabled=true

置灰且不响应点击(无权限项的常见表达)。

查看代码(演示页原文 · 12 行)
frameworks-mobile/Cell.html · disabled
<section class="demo-block" data-demo="disabled">
  <p class="demo-label">禁用(无权限项:置灰且不响应)</p>
  <div class="demo-box">
    <div class="kole-m-cell is-disabled" data-assert="cell-disabled" aria-disabled="true">
      <span class="kole-m-cell__main">
        <span class="kole-m-cell__title">企业认证</span>
        <span class="kole-m-cell__desc">需要管理员权限</span>
      </span>
      <span class="kole-m-cell__value">暂无权限</span>
    </div>
  </div>
</section>

API

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

Props

名称类型默认值说明必传
titlestring''主标题,单行省略(规格 §7.2)N
descstring''可选副标题,单行省略(规格 §7.2)N
valuestring''右侧值或状态文字(规格 §7.2)N
arrowbooleanfalse变体 arrow:显示右箭头表示可进入(规格 §7.3)N
linkbooleanfalse变体 link:整行可点(规格 §7.3)N
borderlessbooleanfalse关掉底部 1px 分隔线(规格 §7.5)N
disabledbooleanfalse置灰且不响应(规格 §7.4)N

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

事件

名称参数说明
click—可点单元格(link=true)点击时触发

插槽

名称说明
default右侧自定义内容,替代 value(规格 §7.2)
icon可选左侧图标(规格 §7.2)

CSS 变量

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

名称默认值说明
本组件没有组件级 CSS 变量

何时使用

  • 列表的基本单元:一行里承载「标题 + 说明 + 值 + 箭头」,可整行点击进入下级
  • 可点单元格整行都是热区,高度不小于 56px
  • 按下反馈是整行背景变化,不是只有文字变色
  • 单元格之间默认有 1px 分隔线,可用 borderless 关掉

交互与触控

  • 可点单元格整行都是热区,高度不小于 56px
  • 按下反馈是整行背景变化,不是只有文字变色
  • 单元格之间默认有 1px 分隔线,可用 borderless 关掉

无障碍

  • 可点单元格用原生 button;纯展示单元格用 div
  • 值区只作展示时不要放进可聚焦元素

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

组件何时用它而不是本组件
滑动单元格SwipeCell行内还需要滑动操作时用滑动单元格;只进入下级用普通单元格
动作面板ActionSheet点击单元格后需要提供多个动作时用动作面板;单一跳转保留单元格语义

规格未定 / 禁止发明

类别条目
禁止发明多行标题的折叠规则
禁止发明单元格内多列布局的栅格规则
规格未定副标题最多显示几行
规格未定右侧值超长时的截断策略

结构(anatomy)

字段说明
cell根元素,一行两类内容(左侧主区 / 右侧值区)
title主标题,单行省略
desc可选副标题,单行省略
value右侧值或状态文字
arrow可选右箭头,表示可进入
icon可选左侧图标

变体维度与类名映射

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

维度取值对应类名 / 变量
arrowfalse / true
false (由数据驱动,无专属类)
true .kole-m-cell__arrow
linkfalse / true
false (由数据驱动,无专属类)
true .kole-m-cell--link

代表变体

变体标签
arrow=true · link=true可点单元格(带箭头)
arrow=false · link=false纯展示单元格
arrow=false · link=true可点无箭头
arrow=true · link=false有箭头但不可点

用到的令牌

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

--kole-m-action-height --kole-m-font-size-body --kole-m-font-size-label --kole-m-gutter --kole-color-border --kole-color-card-bg --kole-color-focus-ring --kole-color-table-header-bg --kole-color-text-body --kole-color-text-disabled --kole-color-text-placeholder --kole-color-text-secondary --kole-color-text-title --kole-space-12 --kole-space-8

6 端源码

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

frameworks-mobile/Cell.css · 纯样式(CSS) · 72 行
frameworks-mobile/Cell.css
/* Kole UI Mobile · Cell 样式 — 对齐移动端规格 §7
   单元格:一行承载「标题 + 说明 + 值 + 箭头」,整行热区(高度 ≥ 56px),
   按下反馈是整行背景变化;行间默认 1px 分隔线,可用 borderless 关掉。 */

.kole-m-cell {
  display: flex;
  align-items: center;
  gap: var(--kole-space-8);
  box-sizing: border-box;
  width: 100%;
  min-height: var(--kole-m-action-height);
  padding: var(--kole-space-12) var(--kole-m-gutter);
  border: 0;
  border-bottom: 1px solid var(--kole-color-border);
  background: var(--kole-color-card-bg);
  color: var(--kole-color-text-body);
  font-family: inherit;
  font-size: var(--kole-m-font-size-body);
  line-height: 1.4;
  text-align: start;
}

/* 组内最后一条:关掉分隔线 */
.kole-m-cell--borderless { border-bottom-color: transparent; }

/* 变体 link:整行可点,按下反馈是整行背景变化 */
.kole-m-cell--link { cursor: pointer; touch-action: manipulation; }
.kole-m-cell--link:active { background: var(--kole-color-table-header-bg); }

.kole-m-cell:disabled,
.kole-m-cell.is-disabled {
  color: var(--kole-color-text-disabled);
  cursor: not-allowed;
}
.kole-m-cell:disabled:active { background: var(--kole-color-card-bg); }

.kole-m-cell__icon { flex: 0 0 auto; display: inline-flex; color: var(--kole-color-text-secondary); }

.kole-m-cell__main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }

.kole-m-cell__title {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--kole-color-text-title);
}

.kole-m-cell__desc {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--kole-m-font-size-label);
  color: var(--kole-color-text-secondary);
}

.kole-m-cell__value {
  flex: 0 0 auto;
  max-width: 45%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--kole-m-font-size-label);
  color: var(--kole-color-text-secondary);
}

.kole-m-cell__arrow { flex: 0 0 auto; display: inline-flex; color: var(--kole-color-text-placeholder); }

.kole-m-cell:focus-visible {
  outline: 2px solid var(--kole-color-focus-ring);
  outline-offset: -2px;
}
frameworks-mobile/Cell.html · H5 原生(无框架) · 118 行
frameworks-mobile/Cell.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 · Cell(H5)</title>
<link rel="stylesheet" href="../.design_library/kole-ui-mobile/colors_and_type.css">
<link rel="stylesheet" href="Cell.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 { background: var(--kole-color-card-bg); border-block: 1px solid var(--kole-color-border); }
  .demo-tag { display: inline-flex; align-items: center; height: 22px; padding: 0 8px; border-radius: 11px;
    background: var(--kole-color-brand-bg); color: var(--kole-color-brand); font-size: var(--kole-m-font-size-caption); }
  .demo-block[hidden] { display: none; }
</style>
</head>
<body>
<div class="demo">
  <section class="demo-block" data-demo="basic">
    <p class="demo-label">基础用法(link + arrow:整行可点,带箭头)</p>
    <div class="demo-box">
      <button class="kole-m-cell kole-m-cell--link" type="button" id="cell-link"
              data-assert="cell-basic" data-behavior="click-sets-attr:#cell-link|data-clicked|true">
        <span class="kole-m-cell__main"><span class="kole-m-cell__title">收货地址</span></span>
        <span class="kole-m-cell__value">杭州市余杭区</span>
        <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
      </button>
    </div>
  </section>

  <section class="demo-block" data-demo="desc">
    <p class="demo-label">带副标题(两行文字,副标题单行省略)</p>
    <div class="demo-box">
      <div class="kole-m-cell" data-assert="cell-desc">
        <span class="kole-m-cell__main">
          <span class="kole-m-cell__title">订单编号</span>
          <span class="kole-m-cell__desc">20260920-001 · 2026-09-20 09:12 创建</span>
        </span>
        <span class="kole-m-cell__value">已发货</span>
      </div>
    </div>
  </section>

  <section class="demo-block" data-demo="custom">
    <p class="demo-label">自定义右侧(右侧放标签等非文字内容)</p>
    <div class="demo-box">
      <div class="kole-m-cell" data-assert="cell-custom">
        <span class="kole-m-cell__main"><span class="kole-m-cell__title">发票抬头</span></span>
        <span class="demo-tag">已开票</span>
      </div>
    </div>
  </section>

  <section class="demo-block" data-demo="group">
    <p class="demo-label">分组列表(组内共享分隔线,最后一条 borderless 收尾)</p>
    <div class="demo-box">
      <button class="kole-m-cell kole-m-cell--link" type="button" data-assert="cell-group-1">
        <span class="kole-m-cell__main"><span class="kole-m-cell__title">支付方式</span></span>
        <span class="kole-m-cell__value">微信支付</span>
        <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
      </button>
      <button class="kole-m-cell kole-m-cell--link kole-m-cell--borderless" type="button" data-assert="cell-group-2">
        <span class="kole-m-cell__main"><span class="kole-m-cell__title">配送方式</span></span>
        <span class="kole-m-cell__value">顺丰标快</span>
        <span class="kole-m-cell__arrow" aria-hidden="true">›</span>
      </button>
    </div>
  </section>

  <section class="demo-block" data-demo="disabled">
    <p class="demo-label">禁用(无权限项:置灰且不响应)</p>
    <div class="demo-box">
      <div class="kole-m-cell is-disabled" data-assert="cell-disabled" aria-disabled="true">
        <span class="kole-m-cell__main">
          <span class="kole-m-cell__title">企业认证</span>
          <span class="kole-m-cell__desc">需要管理员权限</span>
        </span>
        <span class="kole-m-cell__value">暂无权限</span>
      </div>
    </div>
  </section>
</div>
<script>
  /* 演示页脚本:可点单元格被点击后打个标记(真实业务里是路由跳转) */
  (function () {
    var cell = document.getElementById('cell-link');
    if (!cell) return;
    cell.addEventListener('click', function () {
      cell.setAttribute('data-clicked', '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/Cell.jsx · React · 61 行
frameworks-mobile/Cell.jsx
import React from 'react';
import './Cell.css';

/* 单元格(移动端)— 规格 §7;link=true 时用原生 button(整行热区、可键盘聚焦) */
export default function Cell({
  title = '',
  desc = '',
  value = '',
  arrow = false,
  link = false,
  borderless = false,
  disabled = false,
  onClick,
  children = null,
  icon = null,
}) {
  const cls =
    'kole-m-cell' +
    (link ? ' kole-m-cell--link' : '') +
    (borderless ? ' kole-m-cell--borderless' : '') +
    (disabled ? ' is-disabled' : '');

  const inner = (
    <>
      {icon ? <span className="kole-m-cell__icon">{icon}</span> : null}
      <span className="kole-m-cell__main">
        <span className="kole-m-cell__title">{title}</span>
        {desc ? <span className="kole-m-cell__desc">{desc}</span> : null}
      </span>
      {children || (value ? <span className="kole-m-cell__value">{value}</span> : null)}
      {arrow ? (
        <span className="kole-m-cell__arrow" aria-hidden="true">
          ›
        </span>
      ) : null}
    </>
  );

  /* 可点单元格用原生 button(规格 §7.6);纯展示用 div */
  if (link) {
    return (
      <button
        className={cls}
        type="button"
        disabled={disabled}
        onClick={() => {
          if (disabled) return;
          if (onClick) onClick();
        }}
      >
        {inner}
      </button>
    );
  }
  return (
    <div className={cls} aria-disabled={disabled ? 'true' : undefined}>
      {inner}
    </div>
  );
}
frameworks-mobile/Cell.vue2.vue · Vue 2 · 57 行
frameworks-mobile/Cell.vue2.vue
<template>
  <button
    v-if="link"
    class="kole-m-cell"
    :class="cellClass"
    type="button"
    :disabled="disabled"
    @click="$emit('click')"
  >
    <span class="kole-m-cell__main">
      <span class="kole-m-cell__title">{{ title }}</span>
      <span v-if="desc" class="kole-m-cell__desc">{{ desc }}</span>
    </span>
    <slot>
      <span v-if="value" class="kole-m-cell__value">{{ value }}</span>
    </slot>
    <span v-if="arrow" class="kole-m-cell__arrow" aria-hidden="true">›</span>
  </button>

  <div v-else class="kole-m-cell" :class="cellClass" :aria-disabled="disabled ? 'true' : null">
    <span class="kole-m-cell__main">
      <span class="kole-m-cell__title">{{ title }}</span>
      <span v-if="desc" class="kole-m-cell__desc">{{ desc }}</span>
    </span>
    <slot>
      <span v-if="value" class="kole-m-cell__value">{{ value }}</span>
    </slot>
    <span v-if="arrow" class="kole-m-cell__arrow" aria-hidden="true">›</span>
  </div>
</template>

<script>
export default {
  name: 'KoleMCell',
  props: {
    title: { type: String, default: '' },
    desc: { type: String, default: '' },
    value: { type: String, default: '' },
    arrow: { type: Boolean, default: false },
    link: { type: Boolean, default: false },
    borderless: { type: Boolean, default: false },
    disabled: { type: Boolean, default: false }
  },
  computed: {
    cellClass: function () {
      return [
        this.link ? 'kole-m-cell--link' : '',
        this.borderless ? 'kole-m-cell--borderless' : '',
        this.disabled ? 'is-disabled' : ''
      ].filter(Boolean);
    }
  }
};
</script>

<style src="./Cell.css"></style>
frameworks-mobile/Cell.vue3.vue · Vue 3 · 54 行
frameworks-mobile/Cell.vue3.vue
<template>
  <button
    v-if="link"
    class="kole-m-cell"
    :class="cellClass"
    type="button"
    :disabled="disabled"
    @click="emit('click')"
  >
    <span class="kole-m-cell__main">
      <span class="kole-m-cell__title">{{ title }}</span>
      <span v-if="desc" class="kole-m-cell__desc">{{ desc }}</span>
    </span>
    <slot>
      <span v-if="value" class="kole-m-cell__value">{{ value }}</span>
    </slot>
    <span v-if="arrow" class="kole-m-cell__arrow" aria-hidden="true">›</span>
  </button>

  <div v-else class="kole-m-cell" :class="cellClass" :aria-disabled="disabled ? 'true' : null">
    <span class="kole-m-cell__main">
      <span class="kole-m-cell__title">{{ title }}</span>
      <span v-if="desc" class="kole-m-cell__desc">{{ desc }}</span>
    </span>
    <slot>
      <span v-if="value" class="kole-m-cell__value">{{ value }}</span>
    </slot>
    <span v-if="arrow" class="kole-m-cell__arrow" aria-hidden="true">›</span>
  </div>
</template>

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

const props = defineProps({
  title: { type: String, default: '' },
  desc: { type: String, default: '' },
  value: { type: String, default: '' },
  arrow: { type: Boolean, default: false },
  link: { type: Boolean, default: false },
  borderless: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false }
});
const emit = defineEmits(['click']);

const cellClass = computed(() => [
  props.link ? 'kole-m-cell--link' : '',
  props.borderless ? 'kole-m-cell--borderless' : '',
  props.disabled ? 'is-disabled' : ''
].filter(Boolean));
</script>

<style src="./Cell.css"></style>
frameworks-mobile/Cell.uniapp.vue · uni-app(跨端:小程序 / App / H5) · 105 行
frameworks-mobile/Cell.uniapp.vue
<template>
  <view
    class="kole-m-cell"
    :class="cellClass"
    :role="link ? 'button' : ''"
    :aria-disabled="disabled ? 'true' : 'false'"
    @tap="onTap"
  >
    <view class="kole-m-cell__main">
      <text class="kole-m-cell__title">{{ title }}</text>
      <text v-if="desc" class="kole-m-cell__desc">{{ desc }}</text>
    </view>
    <slot>
      <text v-if="value" class="kole-m-cell__value">{{ value }}</text>
    </slot>
    <text v-if="arrow" class="kole-m-cell__arrow">›</text>
  </view>
</template>

<script setup>
/* uni-app 端 · 单元格(移动端)— 规格 §7
   跨端差异:用 view/text;可点单元格的语义靠 role="button"(小程序无 <button> 语义差异,
   但 role 在 H5 产物里生效),点击用 @tap;尺寸用 rpx(88rpx = 44px @375pt)。 */
import { computed } from 'vue';

const props = defineProps({
  title: { type: String, default: '' },
  desc: { type: String, default: '' },
  value: { type: String, default: '' },
  arrow: { type: Boolean, default: false },
  link: { type: Boolean, default: false },
  borderless: { type: Boolean, default: false },
  disabled: { type: Boolean, default: false }
});
const emit = defineEmits(['click']);

const cellClass = computed(() => [
  props.link ? 'kole-m-cell--link' : '',
  props.borderless ? 'kole-m-cell--borderless' : '',
  props.disabled ? 'is-disabled' : ''
].filter(Boolean));

function onTap() {
  if (!props.link || props.disabled) return;
  emit('click');
}
</script>

<style>
.kole-m-cell {
  --kole-m-action-height: 112rpx;
  --kole-m-touch-target: 88rpx;
  --kole-m-font-size-body: 32rpx;
  --kole-m-font-size-label: 28rpx;
  --kole-m-gutter: 32rpx;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  width: 100%;
  min-height: var(--kole-m-action-height);
  padding: 24rpx var(--kole-m-gutter);
  border-bottom: 1rpx solid var(--kole-color-border);
  background-color: var(--kole-color-card-bg);
  color: var(--kole-color-text-body);
  font-size: var(--kole-m-font-size-body);
}

.kole-m-cell--borderless { border-bottom-color: transparent; }
.kole-m-cell--link:active { background-color: var(--kole-color-table-header-bg); }
.kole-m-cell.is-disabled { color: var(--kole-color-text-disabled); }

.kole-m-cell__main { flex: 1; display: flex; flex-direction: column; }

.kole-m-cell__title {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--kole-color-text-title);
}

.kole-m-cell__desc {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--kole-m-font-size-label);
  color: var(--kole-color-text-secondary);
}

.kole-m-cell__value {
  flex-shrink: 0;
  max-width: 45%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--kole-m-font-size-label);
  color: var(--kole-color-text-secondary);
}

.kole-m-cell__arrow {
  flex-shrink: 0;
  padding-left: 8rpx;
  color: var(--kole-color-text-placeholder);
}
</style>

测试与回归

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

断言 17 条 · 全部通过 报告 2026-09-20 16:50:33

复现命令
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/cell.json(点击展开原始 JSON)
{
  "schemaVersion": 1,
  "sourceKind": "authored-spec",
  "provenance": "authored-in-repo",
  "specFile": "spec/移动端规格.md",
  "confidence": "high",
  "specSection": "7 · 单元格 Cell",
  "slug": "cell",
  "name": "单元格 Cell",
  "semanticTypeCandidates": [
    "cell",
    "list-item"
  ],
  "variantDimensions": [
    {
      "name": "arrow",
      "values": [
        "false",
        "true"
      ]
    },
    {
      "name": "link",
      "values": [
        "false",
        "true"
      ]
    }
  ],
  "representativeVariants": [
    {
      "arrow": "true",
      "link": "true",
      "label": "可点单元格(带箭头)"
    },
    {
      "arrow": "false",
      "link": "false",
      "label": "纯展示单元格"
    },
    {
      "arrow": "false",
      "link": "true",
      "label": "可点无箭头"
    },
    {
      "arrow": "true",
      "link": "false",
      "label": "有箭头但不可点"
    }
  ],
  "anatomy": {
    "cell": "根元素,一行两类内容(左侧主区 / 右侧值区)",
    "title": "主标题,单行省略",
    "desc": "可选副标题,单行省略",
    "value": "右侧值或状态文字",
    "arrow": "可选右箭头,表示可进入",
    "icon": "可选左侧图标"
  },
  "structurePatterns": {
    "arrow": "false / true",
    "link": "false(纯展示)/ true(整行可点)"
  },
  "usageHints": [
    "列表的基本单元:一行里承载「标题 + 说明 + 值 + 箭头」,可整行点击进入下级",
    "可点单元格整行都是热区,高度不小于 56px",
    "按下反馈是整行背景变化,不是只有文字变色",
    "单元格之间默认有 1px 分隔线,可用 borderless 关掉"
  ],
  "doNotInvent": [
    "多行标题的折叠规则",
    "单元格内多列布局的栅格规则"
  ],
  "unknowns": [
    "副标题最多显示几行",
    "右侧值超长时的截断策略"
  ],
  "interaction": [
    "可点单元格整行都是热区,高度不小于 56px",
    "按下反馈是整行背景变化,不是只有文字变色",
    "单元格之间默认有 1px 分隔线,可用 borderless 关掉"
  ],
  "accessibility": [
    "可点单元格用原生 button;纯展示单元格用 div",
    "值区只作展示时不要放进可聚焦元素"
  ],
  "api": {
    "source": "implementation",
    "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs",
    "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。",
    "props": [
      {
        "name": "title",
        "type": "string",
        "default": "''",
        "desc": "主标题,单行省略(规格 §7.2)",
        "required": false
      },
      {
        "name": "desc",
        "type": "string",
        "default": "''",
        "desc": "可选副标题,单行省略(规格 §7.2)",
        "required": false
      },
      {
        "name": "value",
        "type": "string",
        "default": "''",
        "desc": "右侧值或状态文字(规格 §7.2)",
        "required": false
      },
      {
        "name": "arrow",
        "type": "boolean",
        "default": "false",
        "desc": "变体 arrow:显示右箭头表示可进入(规格 §7.3)",
        "required": false
      },
      {
        "name": "link",
        "type": "boolean",
        "default": "false",
        "desc": "变体 link:整行可点(规格 §7.3)",
        "required": false
      },
      {
        "name": "borderless",
        "type": "boolean",
        "default": "false",
        "desc": "关掉底部 1px 分隔线(规格 §7.5)",
        "required": false
      },
      {
        "name": "disabled",
        "type": "boolean",
        "default": "false",
        "desc": "置灰且不响应(规格 §7.4)",
        "required": false
      }
    ],
    "events": [
      {
        "name": "click",
        "params": "—",
        "desc": "可点单元格(link=true)点击时触发"
      }
    ],
    "slots": [
      {
        "name": "default",
        "desc": "右侧自定义内容,替代 value(规格 §7.2)"
      },
      {
        "name": "icon",
        "desc": "可选左侧图标(规格 §7.2)"
      }
    ]
  },
  "variantClasses": {
    "arrow": {
      "false": [],
      "true": [
        ".kole-m-cell__arrow"
      ]
    },
    "link": {
      "false": [],
      "true": [
        ".kole-m-cell--link"
      ]
    }
  },
  "demos": [
    {
      "id": "basic",
      "group": "01 组件类型",
      "title": "基础用法",
      "desc": "标题 + 右侧值 + 箭头,最常见的可点单元格。",
      "variant": "link=true / arrow=true"
    },
    {
      "id": "desc",
      "group": "01 组件类型",
      "title": "带副标题",
      "desc": "两行文字(主 + 副),副标题单行省略。",
      "variant": "desc"
    },
    {
      "id": "custom",
      "group": "01 组件类型",
      "title": "自定义右侧",
      "desc": "右侧放开关、标签等非文字内容(此处用标签示意)。",
      "variant": "slots.default"
    },
    {
      "id": "group",
      "group": "02 组件状态",
      "title": "分组列表",
      "desc": "一组单元格共享分隔线;组内最后一条用 borderless 收尾。",
      "variant": "borderless"
    },
    {
      "id": "disabled",
      "group": "02 组件状态",
      "title": "禁用",
      "desc": "置灰且不响应点击(无权限项的常见表达)。",
      "variant": "disabled=true"
    }
  ],
  "related": [
    {
      "slug": "swipecell",
      "why": "行内还需要滑动操作时用滑动单元格;只进入下级用普通单元格"
    },
    {
      "slug": "actionsheet",
      "why": "点击单元格后需要提供多个动作时用动作面板;单一跳转保留单元格语义"
    }
  ]
}