移动端导航顶部导航栏

顶部导航栏NavBar

页面顶部的标题栏,提供返回入口、页面标题与右侧操作区

导航 规格 1 · 顶部导航栏 NavBar 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/navbar.css">

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

演示

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

01 组件类型

标题居中titleAlign=center

左侧仅返回图标、右侧单个操作;标题在剩余空间居中并单行省略。

查看代码(演示页原文 · 10 行)
frameworks-mobile/NavBar.html · center
<section class="demo-block" data-demo="center">
<p class="demo-label">标题居中 · 常态(titleAlign=center / elevated=false)</p>
<header class="kole-m-navbar kole-m-navbar--center" id="nb-center" data-assert="navbar-center" role="banner">
  <button class="kole-m-navbar__back" type="button" aria-label="返回">‹</button>
  <h2 class="kole-m-navbar__title">订单详情</h2>
  <div class="kole-m-navbar__actions">
    <button class="kole-m-navbar__action" type="button">分享</button>
  </div>
</header>
</section>
标题左对齐titleAlign=left

标题紧跟返回入口,适合标题较长或需要强调层级关系的页面。

查看代码(演示页原文 · 10 行)
frameworks-mobile/NavBar.html · left
<section class="demo-block" data-demo="left">
<p class="demo-label">标题左对齐 + 操作禁用(titleAlign=left)</p>
<header class="kole-m-navbar kole-m-navbar--left" data-assert="navbar-left" role="banner">
  <button class="kole-m-navbar__back" type="button" aria-label="返回">返回</button>
  <h2 class="kole-m-navbar__title">超长标题在单行内省略,不换行也不撑开栏高</h2>
  <div class="kole-m-navbar__actions">
    <button class="kole-m-navbar__action" type="button" disabled aria-label="保存">保存</button>
  </div>
</header>
</section>

02 组件状态

滚动后投影elevated=true

页面滚动后加上 is-elevated:出现分隔线与投影,把导航栏与内容分层。

查看代码(演示页原文 · 17 行)
frameworks-mobile/NavBar.html · elevated
<section class="demo-block" data-demo="elevated">
<p class="demo-label">滚动后投影(elevated=true,点击下方按钮切换)</p>
<header class="kole-m-navbar kole-m-navbar--center" id="nb-elevated" data-assert="navbar-elevated" role="banner">
  <button class="kole-m-navbar__back" type="button" aria-label="返回">‹</button>
  <h2 class="kole-m-navbar__title">收货地址</h2>
  <div class="kole-m-navbar__actions">
    <button class="kole-m-navbar__action" type="button" id="toggle-elevated"
            data-behavior="click-toggles-class:#nb-elevated|is-elevated">切换投影</button>
  </div>
</header>

<div class="demo-body">
  返回入口与右侧操作的点击热区不小于 44×44;顶部内边距包含安全区,
  横屏与刘海屏不遮挡内容。
</div>
</div>
</section>

API

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

Props

名称类型默认值说明必传
titlestring''中间标题,单行省略(规格 §1.2)N
titleAlign'center' | 'left''center'变体 titleAlign:标题居中或紧跟返回(规格 §1.3)N
elevatedbooleanfalse滚动后出现分隔线与投影(规格 §1.4)N
backTextstring'‹'返回入口文案,可为箭头或文字(规格 §1.2)N

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

事件

名称参数说明
back—点击返回入口时触发

插槽

名称说明
actions右侧操作区,可放 1~2 个图标按钮或一个文字按钮(规格 §1.2)

CSS 变量

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

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

何时使用

  • 页面顶部的标题栏,提供返回入口、页面标题与右侧操作区
  • 固定于页面顶部,高度 44px + 顶部安全区
  • 标题超长时单行省略,不换行、不撑开栏高
  • 返回入口与右侧操作的点击热区不小于 44×44,视觉图标可小于该尺寸
  • 顶部内边距包含安全区,横屏与刘海屏不遮挡内容
  • 滚动后出现分隔线或投影

交互与触控

  • 返回入口与右侧操作的点击热区不小于 44×44,视觉图标可小于该尺寸
  • 标题超长时单行省略,不换行、不撑开栏高
  • 顶部内边距包含安全区,横屏与刘海屏不遮挡内容
  • 滚动后出现分隔线或投影

无障碍

  • 容器语义 role=banner(页内使用时也可用 role=navigation 并配 aria-label)
  • 标题节点具备 aria-label 或可见文本
  • 图标按钮具备 aria-label

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

组件何时用它而不是本组件
底部标签栏TabBar底部一级导航。顶栏负责「我在哪、怎么回」,标签栏负责切换主模块
动作面板ActionSheet顶栏右侧操作超过 2 个时,收进「更多」再打开动作面板

规格未定 / 禁止发明

类别条目
禁止发明多行标题的折叠规则
禁止发明返回行为的栈深度策略(是否回退到首页)
规格未定阴影出现的确切滚动阈值
规格未定右侧操作超过 2 个时的收敛方式

结构(anatomy)

字段说明
bar导航栏容器,固定于页面顶部,高度 44px + 顶部安全区
back左侧返回入口,可为返回箭头或文字
title中间标题,单行省略
actions右侧操作区,可放 1~2 个图标按钮或一个文字按钮
divider可选底部分隔线

变体维度与类名映射

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

维度取值对应类名 / 变量
titleAligncenter / left
center .kole-m-navbar--center
left .kole-m-navbar--left
elevatedfalse / true
false (由数据驱动,无专属类)
true .is-elevated

代表变体

变体标签
titleAlign=center · elevated=false标题居中 · 常态
titleAlign=left · elevated=false标题左对齐
titleAlign=center · elevated=true滚动后投影
titleAlign=left · elevated=true左对齐 + 操作禁用

用到的令牌

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

--kole-m-font-size-body --kole-m-font-size-label --kole-m-font-size-title --kole-m-navbar-height --kole-m-safe-top --kole-m-touch-target --kole-color-border --kole-color-brand --kole-color-brand-bg --kole-color-card-bg --kole-color-focus-ring --kole-color-text-body --kole-color-text-disabled --kole-color-text-title --kole-duration-base --kole-ease-standard --kole-font-family --kole-radius-base --kole-shadow-low --kole-space-4 --kole-space-8

6 端源码

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

frameworks-mobile/NavBar.css · 纯样式(CSS) · 112 行
frameworks-mobile/NavBar.css
/* Kole UI Mobile · NavBar 样式 — 对齐 .design_library/kole-ui-mobile/spec/移动端规格.md §1
   顶部导航栏:固定于页面顶部,高度 44px + 顶部安全区;返回/操作点击热区 ≥ 44×44。
   令牌:颜色/字体/圆角继承 PC(--kole-*),触控与安全区取移动端令牌(--kole-m-*)。 */

.kole-m-navbar {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: var(--kole-space-8);
  box-sizing: border-box;
  height: calc(var(--kole-m-navbar-height) + var(--kole-m-safe-top));
  padding-top: var(--kole-m-safe-top);
  padding-inline: var(--kole-space-8);
  background: var(--kole-color-card-bg);
  color: var(--kole-color-text-title);
  font-family: var(--kole-font-family);
  border-bottom: 1px solid transparent;
  transition: box-shadow var(--kole-duration-base) var(--kole-ease-standard),
              border-color var(--kole-duration-base) var(--kole-ease-standard);
}

/* 变体 elevated=true:滚动后出现分隔线与投影 */
.kole-m-navbar.is-elevated {
  border-bottom-color: var(--kole-color-border);
  box-shadow: var(--kole-shadow-low);
}

.kole-m-navbar__back {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--kole-space-4);
  min-width: var(--kole-m-touch-target);
  min-height: var(--kole-m-touch-target);
  margin-inline-start: calc(-1 * var(--kole-space-4));
  padding: 0 var(--kole-space-4);
  border: 0;
  border-radius: var(--kole-radius-base);
  background: transparent;
  color: var(--kole-color-text-body);
  font-family: inherit;
  font-size: var(--kole-m-font-size-body);
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
}

.kole-m-navbar__back:hover { color: var(--kole-color-brand); }
.kole-m-navbar__back:focus-visible {
  outline: 2px solid var(--kole-color-focus-ring);
  outline-offset: 2px;
}
.kole-m-navbar__back:active { background: var(--kole-color-brand-bg); }

.kole-m-navbar__title {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  font-size: var(--kole-m-font-size-title);
  font-weight: 500;
  line-height: 1.3;
  color: var(--kole-color-text-title);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 变体 titleAlign:center(标题居中,两侧等宽占位)/ left(标题紧跟返回) */
.kole-m-navbar--center .kole-m-navbar__title { text-align: center; }
.kole-m-navbar--left .kole-m-navbar__title {
  text-align: start;
  padding-inline-start: var(--kole-space-4);
}

.kole-m-navbar__actions {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--kole-space-4);
  min-width: var(--kole-m-touch-target);
}

.kole-m-navbar__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--kole-m-touch-target);
  min-height: var(--kole-m-touch-target);
  padding: 0 var(--kole-space-8);
  border: 0;
  border-radius: var(--kole-radius-base);
  background: transparent;
  color: var(--kole-color-brand);
  font-family: inherit;
  font-size: var(--kole-m-font-size-label);
  cursor: pointer;
  touch-action: manipulation;
}

.kole-m-navbar__action:focus-visible {
  outline: 2px solid var(--kole-color-focus-ring);
  outline-offset: 2px;
}
.kole-m-navbar__action:active { background: var(--kole-color-brand-bg); }
.kole-m-navbar__action:disabled,
.kole-m-navbar__action.is-disabled {
  color: var(--kole-color-text-disabled);
  cursor: not-allowed;
}
frameworks-mobile/NavBar.html · H5 原生(无框架) · 100 行
frameworks-mobile/NavBar.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 · NavBar(H5)</title>
<!-- 移动端令牌层:@import PC 令牌 + --kole-m-* 触控/安全区 -->
<link rel="stylesheet" href="../.design_library/kole-ui-mobile/colors_and_type.css">
<link rel="stylesheet" href="NavBar.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; background: var(--kole-color-page-bg); min-height: 100vh; }
  .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-body { padding: var(--kole-m-gutter); font-size: var(--kole-m-font-size-body); line-height: 1.7; }
</style>
</head>
<body>
<div class="demo">
  <section class="demo-block" data-demo="center">
  <p class="demo-label">标题居中 · 常态(titleAlign=center / elevated=false)</p>
  <header class="kole-m-navbar kole-m-navbar--center" id="nb-center" data-assert="navbar-center" role="banner">
    <button class="kole-m-navbar__back" type="button" aria-label="返回">‹</button>
    <h2 class="kole-m-navbar__title">订单详情</h2>
    <div class="kole-m-navbar__actions">
      <button class="kole-m-navbar__action" type="button">分享</button>
    </div>
  </header>
  </section>
  <section class="demo-block" data-demo="left">
  <p class="demo-label">标题左对齐 + 操作禁用(titleAlign=left)</p>
  <header class="kole-m-navbar kole-m-navbar--left" data-assert="navbar-left" role="banner">
    <button class="kole-m-navbar__back" type="button" aria-label="返回">返回</button>
    <h2 class="kole-m-navbar__title">超长标题在单行内省略,不换行也不撑开栏高</h2>
    <div class="kole-m-navbar__actions">
      <button class="kole-m-navbar__action" type="button" disabled aria-label="保存">保存</button>
    </div>
  </header>
  </section>
  <section class="demo-block" data-demo="elevated">
  <p class="demo-label">滚动后投影(elevated=true,点击下方按钮切换)</p>
  <header class="kole-m-navbar kole-m-navbar--center" id="nb-elevated" data-assert="navbar-elevated" role="banner">
    <button class="kole-m-navbar__back" type="button" aria-label="返回">‹</button>
    <h2 class="kole-m-navbar__title">收货地址</h2>
    <div class="kole-m-navbar__actions">
      <button class="kole-m-navbar__action" type="button" id="toggle-elevated"
              data-behavior="click-toggles-class:#nb-elevated|is-elevated">切换投影</button>
    </div>
  </header>

  <div class="demo-body">
    返回入口与右侧操作的点击热区不小于 44×44;顶部内边距包含安全区,
    横屏与刘海屏不遮挡内容。
  </div>
</div>
  </section>

<script>
  /* 演示页只做展示:投影态由 data-behavior 的点击切换驱动,业务侧由 elevated prop 控制 */
  (function () {
    var bar = document.getElementById('nb-elevated');
    var btn = document.getElementById('toggle-elevated');
    btn.addEventListener('click', function () {
      var on = bar.classList.toggle('is-elevated');
      btn.textContent = on ? '取消投影' : '切换投影';
    });
    document.querySelectorAll('.kole-m-navbar__back').forEach(function (b) {
      b.addEventListener('click', function () { btn.focus(); });
    });
  })();
</script>
  <script>
    /* ?demo=<id> → 只显示该演示块:文档站为每个演示单独起一个 375×640 预览帧。
       无参数时全部显示 —— 测试页与回归走无参数路径,行为不变。 */
    (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');
      /* 单块模式去掉 min-height:100vh —— 否则内容高度随帧高变化(帧高→vh→内容高)形成反馈环,
         自适应量到的永远是视口高度而不是内容高度。 */
      var demoBox = document.querySelector('.demo');
      if (demoBox) demoBox.style.minHeight = 'auto';
      /* 单块模式:帧内不再重复显示演示标题行(文档页已给出标题与说明) */
      blocks.forEach(function (b) {
        var label = b.querySelector('.demo-label');
        if (label && !b.hidden) label.hidden = true;
      });
    })();
  </script>
</body>
</html>
frameworks-mobile/NavBar.jsx · React · 31 行
frameworks-mobile/NavBar.jsx
import React from 'react';
import './NavBar.css';

/* 顶部导航栏(移动端)— 规格 §1;返回与操作热区 ≥ 44×44,顶部内边距含安全区 */
export default function NavBar({
  title = '',
  titleAlign = 'center',
  elevated = false,
  backText = '‹',
  onBack,
  actions = null,
}) {
  return (
    <header
      className={`kole-m-navbar kole-m-navbar--${titleAlign}` + (elevated ? ' is-elevated' : '')}
      role="banner"
    >
      <button
        className="kole-m-navbar__back"
        type="button"
        aria-label="返回"
        onClick={onBack}
      >
        {backText}
      </button>
      <h2 className="kole-m-navbar__title">{title}</h2>
      <div className="kole-m-navbar__actions">{actions}</div>
    </header>
  );
}
frameworks-mobile/NavBar.vue2.vue · Vue 2 · 30 行
frameworks-mobile/NavBar.vue2.vue
<template>
  <header
    class="kole-m-navbar"
    :class="['kole-m-navbar--' + titleAlign, { 'is-elevated': elevated }]"
    role="banner"
  >
    <button class="kole-m-navbar__back" type="button" aria-label="返回" @click="$emit('back')">
      {{ backText }}
    </button>
    <h2 class="kole-m-navbar__title">{{ title }}</h2>
    <div class="kole-m-navbar__actions">
      <slot name="actions"></slot>
    </div>
  </header>
</template>

<script>
export default {
  name: 'KoleMNavBar',
  props: {
    title: { type: String, default: '' },
    titleAlign: { type: String, default: 'center' },
    elevated: { type: Boolean, default: false },
    backText: { type: String, default: '‹' }
  }
};
</script>

<style src="./NavBar.css"></style>
frameworks-mobile/NavBar.vue3.vue · Vue 3 · 28 行
frameworks-mobile/NavBar.vue3.vue
<template>
  <header
    class="kole-m-navbar"
    :class="['kole-m-navbar--' + titleAlign, { 'is-elevated': elevated }]"
    role="banner"
  >
    <button class="kole-m-navbar__back" type="button" aria-label="返回" @click="emit('back')">
      {{ backText }}
    </button>
    <h2 class="kole-m-navbar__title">{{ title }}</h2>
    <div class="kole-m-navbar__actions">
      <slot name="actions" />
    </div>
  </header>
</template>

<script setup>
const props = defineProps({
  title: { type: String, default: '' },
  titleAlign: { type: String, default: 'center' },
  elevated: { type: Boolean, default: false },
  backText: { type: String, default: '‹' }
});
const emit = defineEmits(['back']);
</script>

<style src="./NavBar.css"></style>
frameworks-mobile/NavBar.uniapp.vue · uni-app(跨端:小程序 / App / H5) · 87 行
frameworks-mobile/NavBar.uniapp.vue
<template>
  <view class="kole-m-navbar" :class="['kole-m-navbar--' + titleAlign, elevated ? 'is-elevated' : '']">
    <view class="kole-m-navbar__back" role="button" aria-label="返回" @tap="emit('back')">
      <text class="kole-m-navbar__back-icon">{{ backText }}</text>
    </view>
    <text class="kole-m-navbar__title">{{ title }}</text>
    <view class="kole-m-navbar__actions">
      <slot name="actions"></slot>
    </view>
  </view>
</template>

<script setup>
/* uni-app 端 · 顶部导航栏(移动端)— 规格 §1
   与 frameworks-mobile/NavBar.jsx|.vue 同源同契约,差异是跨端运行时约束:
   - 结构用 uni 基础组件(view / text),不用 div/span(小程序无 DOM)
   - 不用 PointerEvent:手势与点击一律 @tap / @touchstart 系
   - 尺寸用 rpx(750rpx = 视口宽度,88rpx = 375pt 下的 44px 触控最小边长)
   令牌由宿主工程全局引入一次:@import "kole-ui/mobile/tokens.css"; */
const props = defineProps({
  title: { type: String, default: '' },
  titleAlign: { type: String, default: 'center' },
  elevated: { type: Boolean, default: false },
  backText: { type: String, default: '‹' }
});
const emit = defineEmits(['back']);
</script>

<style>
/* uni-app 端令牌覆盖:rpx 化触控尺寸(颜色/字体族仍取全局 --kole-* 令牌) */
.kole-m-navbar {
  --kole-m-navbar-height: 88rpx;
  --kole-m-touch-target: 88rpx;
  --kole-m-font-size-title: 34rpx;
  --kole-m-font-size-body: 32rpx;
  --kole-m-font-size-label: 28rpx;
  --kole-m-gutter: 32rpx;
  display: flex;
  align-items: center;
  /* 刘海屏安全区:小程序与 App 端由系统提供 safe-area-inset-* */
  padding-top: constant(safe-area-inset-top);
  padding-top: env(safe-area-inset-top);
  height: calc(var(--kole-m-navbar-height) + constant(safe-area-inset-top));
  height: calc(var(--kole-m-navbar-height) + env(safe-area-inset-top));
  box-sizing: content-box;
  padding-left: 16rpx;
  padding-right: 16rpx;
  background-color: var(--kole-color-card-bg);
  border-bottom: 1rpx solid transparent;
}

.kole-m-navbar.is-elevated {
  border-bottom-color: var(--kole-color-border);
}

.kole-m-navbar__back {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: var(--kole-m-touch-target);
  min-height: var(--kole-m-touch-target);
  color: var(--kole-color-text-body);
  font-size: var(--kole-m-font-size-body);
}

.kole-m-navbar__back-icon { line-height: 1; }

.kole-m-navbar__title {
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: var(--kole-m-font-size-title);
  color: var(--kole-color-text-title);
}

.kole-m-navbar--center .kole-m-navbar__title { text-align: center; }
.kole-m-navbar--left .kole-m-navbar__title { text-align: left; padding-left: 8rpx; }

.kole-m-navbar__actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  min-width: var(--kole-m-touch-target);
}
</style>

测试与回归

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

断言 14 条 · 全部通过 报告 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/navbar.json(点击展开原始 JSON)
{
  "schemaVersion": 1,
  "sourceKind": "authored-spec",
  "provenance": "authored-in-repo",
  "specFile": "spec/移动端规格.md",
  "specSection": "1 · 顶部导航栏 NavBar",
  "confidence": "high",
  "slug": "navbar",
  "name": "顶部导航栏 NavBar",
  "semanticTypeCandidates": [
    "navbar",
    "appbar",
    "header"
  ],
  "variantDimensions": [
    {
      "name": "titleAlign",
      "values": [
        "center",
        "left"
      ]
    },
    {
      "name": "elevated",
      "values": [
        "false",
        "true"
      ]
    }
  ],
  "representativeVariants": [
    {
      "titleAlign": "center",
      "elevated": "false",
      "label": "标题居中 · 常态"
    },
    {
      "titleAlign": "left",
      "elevated": "false",
      "label": "标题左对齐"
    },
    {
      "titleAlign": "center",
      "elevated": "true",
      "label": "滚动后投影"
    },
    {
      "titleAlign": "left",
      "elevated": "true",
      "label": "左对齐 + 操作禁用"
    }
  ],
  "anatomy": {
    "bar": "导航栏容器,固定于页面顶部,高度 44px + 顶部安全区",
    "back": "左侧返回入口,可为返回箭头或文字",
    "title": "中间标题,单行省略",
    "actions": "右侧操作区,可放 1~2 个图标按钮或一个文字按钮",
    "divider": "可选底部分隔线"
  },
  "structurePatterns": {
    "titleAlign": "center(标题居中,左侧仅图标)/ left(标题左对齐,紧跟返回)",
    "elevated": "false(无阴影)/ true(滚动后投影)"
  },
  "usageHints": [
    "页面顶部的标题栏,提供返回入口、页面标题与右侧操作区",
    "固定于页面顶部,高度 44px + 顶部安全区",
    "标题超长时单行省略,不换行、不撑开栏高",
    "返回入口与右侧操作的点击热区不小于 44×44,视觉图标可小于该尺寸",
    "顶部内边距包含安全区,横屏与刘海屏不遮挡内容",
    "滚动后出现分隔线或投影"
  ],
  "doNotInvent": [
    "多行标题的折叠规则",
    "返回行为的栈深度策略(是否回退到首页)"
  ],
  "unknowns": [
    "阴影出现的确切滚动阈值",
    "右侧操作超过 2 个时的收敛方式"
  ],
  "interaction": [
    "返回入口与右侧操作的点击热区不小于 44×44,视觉图标可小于该尺寸",
    "标题超长时单行省略,不换行、不撑开栏高",
    "顶部内边距包含安全区,横屏与刘海屏不遮挡内容",
    "滚动后出现分隔线或投影"
  ],
  "accessibility": [
    "容器语义 role=banner(页内使用时也可用 role=navigation 并配 aria-label)",
    "标题节点具备 aria-label 或可见文本",
    "图标按钮具备 aria-label"
  ],
  "api": {
    "source": "implementation",
    "note": "props / events / slots 为 6 端实现的公共接口(说明文字取自规格对应小节)。字段名与各端源码逐名核对:node tools/verify-mobile-docs.mjs",
    "props": [
      {
        "name": "title",
        "type": "string",
        "default": "''",
        "desc": "中间标题,单行省略(规格 §1.2)",
        "required": false
      },
      {
        "name": "titleAlign",
        "type": "'center' | 'left'",
        "default": "'center'",
        "desc": "变体 titleAlign:标题居中或紧跟返回(规格 §1.3)",
        "required": false
      },
      {
        "name": "elevated",
        "type": "boolean",
        "default": "false",
        "desc": "滚动后出现分隔线与投影(规格 §1.4)",
        "required": false
      },
      {
        "name": "backText",
        "type": "string",
        "default": "'‹'",
        "desc": "返回入口文案,可为箭头或文字(规格 §1.2)",
        "required": false
      }
    ],
    "events": [
      {
        "name": "back",
        "params": "—",
        "desc": "点击返回入口时触发"
      }
    ],
    "slots": [
      {
        "name": "actions",
        "desc": "右侧操作区,可放 1~2 个图标按钮或一个文字按钮(规格 §1.2)"
      }
    ],
    "requiredNote": "「必传」按严格定义:实现里**没有默认值**时才为 Y(本门禁逐条核对 props 与各端源码的默认值,防止契约与实现脱节)。"
  },
  "variantClasses": {
    "titleAlign": {
      "center": [
        ".kole-m-navbar--center"
      ],
      "left": [
        ".kole-m-navbar--left"
      ]
    },
    "elevated": {
      "false": [],
      "true": [
        ".is-elevated"
      ]
    }
  },
  "demos": [
    {
      "id": "center",
      "group": "01 组件类型",
      "title": "标题居中",
      "desc": "左侧仅返回图标、右侧单个操作;标题在剩余空间居中并单行省略。",
      "variant": "titleAlign=center"
    },
    {
      "id": "left",
      "group": "01 组件类型",
      "title": "标题左对齐",
      "desc": "标题紧跟返回入口,适合标题较长或需要强调层级关系的页面。",
      "variant": "titleAlign=left"
    },
    {
      "id": "elevated",
      "group": "02 组件状态",
      "title": "滚动后投影",
      "desc": "页面滚动后加上 is-elevated:出现分隔线与投影,把导航栏与内容分层。",
      "variant": "elevated=true"
    }
  ],
  "related": [
    {
      "slug": "tabbar",
      "why": "底部一级导航。顶栏负责「我在哪、怎么回」,标签栏负责切换主模块"
    },
    {
      "slug": "actionsheet",
      "why": "顶栏右侧操作超过 2 个时,收进「更多」再打开动作面板"
    }
  ]
}