开发预览 更新于 2026-05-10

NavMenu 主导航

顶部水平导航栏,每一项可挂富面板(多列链接 + 描述),3 种 variant、hover / click 触发。

基础用法

items 是顶层菜单数组,每项要么是简单链接(href),要么有 links[] 子列表。后者会在 hover / click 时打开富面板,每条 link 可带 descriptioniconcolumns 控制面板每行多少列(1 / 2 / 3)。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const active = ref('products');
const items: NavMenuItem[] = [
  {
    key: 'products',
    label: '产品',
    columns: 2,
    links: [
      { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
      { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
      { label: '图标', description: '16x16 sprite,CSS currentColor', href: '#' },
      { label: 'CLI', description: 'npx chufix add 拷贝源码到自己仓库', href: '#' },
    ],
  },
  {
    key: 'docs',
    label: '文档',
    columns: 1,
    links: [
      { label: '快速开始', href: '#' },
      { label: '主题', href: '#' },
      { label: '组件清单', href: '#' },
    ],
  },
  { key: 'pricing', label: '价格', href: '#' },
  { key: 'about', label: '关于', href: '#' },
];
</script>
<template>
  <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
    <CfNavMenu :items="items" :active="active" />
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfNavMenu } from '@chufix-design/vue';

const active = ref('products');
const items= [
  {
    key: 'products',
    label: '产品',
    columns: 2,
    links: [
      { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
      { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
      { label: '图标', description: '16x16 sprite,CSS currentColor', href: '#' },
      { label: 'CLI', description: 'npx chufix add 拷贝源码到自己仓库', href: '#' },
    ],
  },
  {
    key: 'docs',
    label: '文档',
    columns: 1,
    links: [
      { label: '快速开始', href: '#' },
      { label: '主题', href: '#' },
      { label: '组件清单', href: '#' },
    ],
  },
  { key: 'pricing', label: '价格', href: '#' },
  { key: 'about', label: '关于', href: '#' },
];
</script>
<template>
  <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
    <CfNavMenu :items="items" :active="active" />
  </div>
</template>
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [active, setActive] = useState('products');
  const items: NavMenuItem[] = [
    {
      key: 'products',
      label: '产品',
      columns: 2,
      links: [
        { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
        { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
        { label: '图标', description: '16x16 sprite,CSS currentColor', href: '#' },
        { label: 'CLI', description: 'npx chufix add 拷贝源码到自己仓库', href: '#' },
      ],
    },
    {
      key: 'docs',
      label: '文档',
      columns: 1,
      links: [
        { label: '快速开始', href: '#' },
        { label: '主题', href: '#' },
        { label: '组件清单', href: '#' },
      ],
    },
    { key: 'pricing', label: '价格', href: '#' },
    { key: 'about', label: '关于', href: '#' },
  ];
  return (
    <>
      <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
          <CfNavMenu items={items} active={active} />
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [active, setActive] = useState('products');
  const items= [
    {
      key: 'products',
      label: '产品',
      columns: 2,
      links: [
        { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
        { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
        { label: '图标', description: '16x16 sprite,CSS currentColor', href: '#' },
        { label: 'CLI', description: 'npx chufix add 拷贝源码到自己仓库', href: '#' },
      ],
    },
    {
      key: 'docs',
      label: '文档',
      columns: 1,
      links: [
        { label: '快速开始', href: '#' },
        { label: '主题', href: '#' },
        { label: '组件清单', href: '#' },
      ],
    },
    { key: 'pricing', label: '价格', href: '#' },
    { key: 'about', label: '关于', href: '#' },
  ];
  return (
    <>
      <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
          <CfNavMenu items={items} active={active} />
        </div>
    </>
  );
}

3 种 variant

  • underline —— 当前项底部细下划线(默认,最克制)
  • pill —— 当前项变成填充胶囊
  • minimal —— 仅文字颜色变化,无任何形状提示
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const a = ref('home');
const b = ref('home');
const c = ref('home');
const items: NavMenuItem[] = [
  { key: 'home', label: '首页', href: '#' },
  { key: 'docs', label: '文档', href: '#' },
  { key: 'about', label: '关于', href: '#' },
];
</script>
<template>
  <div class="demo-stack">
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="a" variant="underline" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="b" variant="pill" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="c" variant="minimal" />
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfNavMenu } from '@chufix-design/vue';

const a = ref('home');
const b = ref('home');
const c = ref('home');
const items= [
  { key: 'home', label: '首页', href: '#' },
  { key: 'docs', label: '文档', href: '#' },
  { key: 'about', label: '关于', href: '#' },
];
</script>
<template>
  <div class="demo-stack">
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="a" variant="underline" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="b" variant="pill" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="c" variant="minimal" />
      </div>
    </div>
  </div>
</template>
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState('home');
  const [b, setB] = useState('home');
  const [c, setC] = useState('home');
  const items: NavMenuItem[] = [
    { key: 'home', label: '首页', href: '#' },
    { key: 'docs', label: '文档', href: '#' },
    { key: 'about', label: '关于', href: '#' },
  ];
  return (
    <>
      <div className="demo-stack">
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={a} variant="underline" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={b} variant="pill" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={c} variant="minimal" />
            </div>
          </div>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState('home');
  const [b, setB] = useState('home');
  const [c, setC] = useState('home');
  const items= [
    { key: 'home', label: '首页', href: '#' },
    { key: 'docs', label: '文档', href: '#' },
    { key: 'about', label: '关于', href: '#' },
  ];
  return (
    <>
      <div className="demo-stack">
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={a} variant="underline" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={b} variant="pill" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={c} variant="minimal" />
            </div>
          </div>
        </div>
    </>
  );
}

触发方式

trigger —— hover(默认,鼠标悬停就打开)/ click(点击触发,更适合移动端或避免误触)。

背景 视口
src/App.vue
<script setup lang="ts">
import { ref } from 'vue';
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const a = ref('products');
const b = ref('products');
const items: NavMenuItem[] = [
  {
    key: 'products',
    label: '产品',
    columns: 1,
    links: [
      { label: '组件库', href: '#' },
      { label: 'Tokens', href: '#' },
      { label: '图标', href: '#' },
    ],
  },
  { key: 'docs', label: '文档', href: '#' },
];
</script>
<template>
  <div class="demo-stack">
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="a" trigger="hover" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="b" trigger="click" />
      </div>
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import { CfNavMenu } from '@chufix-design/vue';

const a = ref('products');
const b = ref('products');
const items= [
  {
    key: 'products',
    label: '产品',
    columns: 1,
    links: [
      { label: '组件库', href: '#' },
      { label: 'Tokens', href: '#' },
      { label: '图标', href: '#' },
    ],
  },
  { key: 'docs', label: '文档', href: '#' },
];
</script>
<template>
  <div class="demo-stack">
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="a" trigger="hover" />
      </div>
    </div>
    <div>
      <div style="background: var(--bg-1); padding: 8px 12px; border: 1px solid var(--line-1); border-radius: 8px;">
        <CfNavMenu :items="items" :active="b" trigger="click" />
      </div>
    </div>
  </div>
</template>
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState('products');
  const [b, setB] = useState('products');
  const items: NavMenuItem[] = [
    {
      key: 'products',
      label: '产品',
      columns: 1,
      links: [
        { label: '组件库', href: '#' },
        { label: 'Tokens', href: '#' },
        { label: '图标', href: '#' },
      ],
    },
    { key: 'docs', label: '文档', href: '#' },
  ];
  return (
    <>
      <div className="demo-stack">
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={a} trigger="hover" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={b} trigger="click" />
            </div>
          </div>
        </div>
    </>
  );
}
import { useState } from 'react';
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const [a, setA] = useState('products');
  const [b, setB] = useState('products');
  const items= [
    {
      key: 'products',
      label: '产品',
      columns: 1,
      links: [
        { label: '组件库', href: '#' },
        { label: 'Tokens', href: '#' },
        { label: '图标', href: '#' },
      ],
    },
    { key: 'docs', label: '文档', href: '#' },
  ];
  return (
    <>
      <div className="demo-stack">
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={a} trigger="hover" />
            </div>
          </div>
          <div>
            <div style={{ background: "var(--bg-1)", padding: "8px 12px", border: "1px solid var(--line-1)", borderRadius: 8 }}>
              <CfNavMenu items={items} active={b} trigger="click" />
            </div>
          </div>
        </div>
    </>
  );
}

columns 列数

columns 控制富面板每行多少列(1 / 2 / 3),每一项可以单独设置。链接较多时用 2-3 列横向展开,避免面板过高。

背景 视口

点击每个菜单项查看不同 columns 配置下的面板布局。

src/App.vue
<script setup lang="ts">
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const sharedLinks = [
  { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
  { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
  { label: '图标', description: '16x16 sprite', href: '#' },
  { label: 'CLI', description: 'npx chufix add', href: '#' },
  { label: '模板', description: '完整页面级骨架', href: '#' },
  { label: '示例', description: '可复制片段', href: '#' },
];

const items: NavMenuItem[] = [
  { key: 'one', label: 'columns=1', columns: 1, links: sharedLinks.slice(0, 3) },
  { key: 'two', label: 'columns=2', columns: 2, links: sharedLinks },
  { key: 'three', label: 'columns=3', columns: 3, links: sharedLinks },
];
</script>
<template>
  <CfNavMenu :items="items" active="two" trigger="click" />
  <p class="adm-hint">
    点击每个菜单项查看不同 <code>columns</code> 配置下的面板布局。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
<script setup>
import { CfNavMenu } from '@chufix-design/vue';

const sharedLinks = [
  { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
  { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
  { label: '图标', description: '16x16 sprite', href: '#' },
  { label: 'CLI', description: 'npx chufix add', href: '#' },
  { label: '模板', description: '完整页面级骨架', href: '#' },
  { label: '示例', description: '可复制片段', href: '#' },
];

const items= [
  { key: 'one', label: 'columns=1', columns: 1, links: sharedLinks.slice(0, 3) },
  { key: 'two', label: 'columns=2', columns: 2, links: sharedLinks },
  { key: 'three', label: 'columns=3', columns: 3, links: sharedLinks },
];
</script>
<template>
  <CfNavMenu :items="items" active="two" trigger="click" />
  <p class="adm-hint">
    点击每个菜单项查看不同 <code>columns</code> 配置下的面板布局。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const sharedLinks = [
    { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
    { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
    { label: '图标', description: '16x16 sprite', href: '#' },
    { label: 'CLI', description: 'npx chufix add', href: '#' },
    { label: '模板', description: '完整页面级骨架', href: '#' },
    { label: '示例', description: '可复制片段', href: '#' },
  ];

  const items: NavMenuItem[] = [
    { key: 'one', label: 'columns=1', columns: 1, links: sharedLinks.slice(0, 3) },
    { key: 'two', label: 'columns=2', columns: 2, links: sharedLinks },
    { key: 'three', label: 'columns=3', columns: 3, links: sharedLinks },
  ];
  return (
    <>
      <CfNavMenu items={items} active="two" trigger="click" />
        <p className="adm-hint">
          点击每个菜单项查看不同 <code>columns</code> 配置下的面板布局。
        </p>
    </>
  );
}
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const sharedLinks = [
    { label: '组件库', description: 'Vue 3 与 React 双框架同源', href: '#' },
    { label: 'Tokens', description: 'OKLCH 设计变量与三套主题', href: '#' },
    { label: '图标', description: '16x16 sprite', href: '#' },
    { label: 'CLI', description: 'npx chufix add', href: '#' },
    { label: '模板', description: '完整页面级骨架', href: '#' },
    { label: '示例', description: '可复制片段', href: '#' },
  ];

  const items= [
    { key: 'one', label: 'columns=1', columns: 1, links: sharedLinks.slice(0, 3) },
    { key: 'two', label: 'columns=2', columns: 2, links: sharedLinks },
    { key: 'three', label: 'columns=3', columns: 3, links: sharedLinks },
  ];
  return (
    <>
      <CfNavMenu items={items} active="two" trigger="click" />
        <p className="adm-hint">
          点击每个菜单项查看不同 <code>columns</code> 配置下的面板布局。
        </p>
    </>
  );
}

链接图标

link.icon 接收原始 SVG 字符串,组件通过 v-html 注入到链接前方。SVG 用 currentColor 描边会自动跟随面板文字色。

背景 视口

link.icon 接收原始 SVG 字符串(通过 v-html 注入)。 SVG 用 currentColor 描边会自动跟随面板文字色。

src/App.vue
<script setup lang="ts">
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const ICONS = {
  cube: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1l6 3.5v7L8 15l-6-3.5v-7z"/><path d="M2 4.5L8 8l6-3.5M8 8v7"/></svg>',
  palette: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1.5c-3.6 0-6.5 2.6-6.5 5.9 0 2 1.9 3 3.4 3 .8 0 1.4.5 1.4 1.4 0 .5-.2.9-.2 1.4 0 .8.7 1.4 1.9 1.4 3.6 0 6.5-2.6 6.5-5.9 0-3.6-2.9-7.2-6.5-7.2z"/><circle cx="4.5" cy="6" r="0.8" fill="currentColor"/><circle cx="6.5" cy="3.8" r="0.8" fill="currentColor"/><circle cx="10" cy="3.8" r="0.8" fill="currentColor"/><circle cx="12" cy="6.5" r="0.8" fill="currentColor"/></svg>',
  terminal: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1.5" y="3" width="13" height="10" rx="1"/><path d="M4 7l2 2-2 2M7.5 11h4"/></svg>',
  book: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3v10s2-1 6-1 6 1 6 1V3s-2-1-6-1-6 1-6 1z"/><path d="M8 2v11"/></svg>',
};

const items: NavMenuItem[] = [
  {
    key: 'resources',
    label: '资源',
    columns: 2,
    links: [
      { label: '组件库', description: 'Vue 3 与 React 同源', href: '#', icon: ICONS.cube },
      { label: 'Tokens',  description: 'OKLCH 三套主题',     href: '#', icon: ICONS.palette },
      { label: 'CLI',     description: 'npx chufix add',     href: '#', icon: ICONS.terminal },
      { label: '文档',     description: '完整指南与示例',     href: '#', icon: ICONS.book },
    ],
  },
];
</script>
<template>
  <CfNavMenu :items="items" active="resources" trigger="click" />
  <p class="adm-hint">
    <code>link.icon</code> 接收原始 SVG 字符串(通过 <code>v-html</code> 注入)。
    SVG 用 <code>currentColor</code> 描边会自动跟随面板文字色。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; line-height: 1.6; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
<script setup>
import { CfNavMenu } from '@chufix-design/vue';

const ICONS = {
  cube: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1l6 3.5v7L8 15l-6-3.5v-7z"/><path d="M2 4.5L8 8l6-3.5M8 8v7"/></svg>',
  palette: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1.5c-3.6 0-6.5 2.6-6.5 5.9 0 2 1.9 3 3.4 3 .8 0 1.4.5 1.4 1.4 0 .5-.2.9-.2 1.4 0 .8.7 1.4 1.9 1.4 3.6 0 6.5-2.6 6.5-5.9 0-3.6-2.9-7.2-6.5-7.2z"/><circle cx="4.5" cy="6" r="0.8" fill="currentColor"/><circle cx="6.5" cy="3.8" r="0.8" fill="currentColor"/><circle cx="10" cy="3.8" r="0.8" fill="currentColor"/><circle cx="12" cy="6.5" r="0.8" fill="currentColor"/></svg>',
  terminal: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1.5" y="3" width="13" height="10" rx="1"/><path d="M4 7l2 2-2 2M7.5 11h4"/></svg>',
  book: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3v10s2-1 6-1 6 1 6 1V3s-2-1-6-1-6 1-6 1z"/><path d="M8 2v11"/></svg>',
};

const items= [
  {
    key: 'resources',
    label: '资源',
    columns: 2,
    links: [
      { label: '组件库', description: 'Vue 3 与 React 同源', href: '#', icon: ICONS.cube },
      { label: 'Tokens',  description: 'OKLCH 三套主题',     href: '#', icon: ICONS.palette },
      { label: 'CLI',     description: 'npx chufix add',     href: '#', icon: ICONS.terminal },
      { label: '文档',     description: '完整指南与示例',     href: '#', icon: ICONS.book },
    ],
  },
];
</script>
<template>
  <CfNavMenu :items="items" active="resources" trigger="click" />
  <p class="adm-hint">
    <code>link.icon</code> 接收原始 SVG 字符串(通过 <code>v-html</code> 注入)。
    SVG 用 <code>currentColor</code> 描边会自动跟随面板文字色。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; line-height: 1.6; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const ICONS = {
    cube: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1l6 3.5v7L8 15l-6-3.5v-7z"/><path d="M2 4.5L8 8l6-3.5M8 8v7"/></svg>',
    palette: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1.5c-3.6 0-6.5 2.6-6.5 5.9 0 2 1.9 3 3.4 3 .8 0 1.4.5 1.4 1.4 0 .5-.2.9-.2 1.4 0 .8.7 1.4 1.9 1.4 3.6 0 6.5-2.6 6.5-5.9 0-3.6-2.9-7.2-6.5-7.2z"/><circle cx="4.5" cy="6" r="0.8" fill="currentColor"/><circle cx="6.5" cy="3.8" r="0.8" fill="currentColor"/><circle cx="10" cy="3.8" r="0.8" fill="currentColor"/><circle cx="12" cy="6.5" r="0.8" fill="currentColor"/></svg>',
    terminal: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1.5" y="3" width="13" height="10" rx="1"/><path d="M4 7l2 2-2 2M7.5 11h4"/></svg>',
    book: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3v10s2-1 6-1 6 1 6 1V3s-2-1-6-1-6 1-6 1z"/><path d="M8 2v11"/></svg>',
  };

  const items: NavMenuItem[] = [
    {
      key: 'resources',
      label: '资源',
      columns: 2,
      links: [
        { label: '组件库', description: 'Vue 3 与 React 同源', href: '#', icon: ICONS.cube },
        { label: 'Tokens',  description: 'OKLCH 三套主题',     href: '#', icon: ICONS.palette },
        { label: 'CLI',     description: 'npx chufix add',     href: '#', icon: ICONS.terminal },
        { label: '文档',     description: '完整指南与示例',     href: '#', icon: ICONS.book },
      ],
    },
  ];
  return (
    <>
      <CfNavMenu items={items} active="resources" trigger="click" />
        <p className="adm-hint">
          <code>link.icon</code> 接收原始 SVG 字符串(通过 <code>v-html</code> 注入)。
          SVG 用 <code>currentColor</code> 描边会自动跟随面板文字色。
        </p>
    </>
  );
}
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const ICONS = {
    cube: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1l6 3.5v7L8 15l-6-3.5v-7z"/><path d="M2 4.5L8 8l6-3.5M8 8v7"/></svg>',
    palette: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 1.5c-3.6 0-6.5 2.6-6.5 5.9 0 2 1.9 3 3.4 3 .8 0 1.4.5 1.4 1.4 0 .5-.2.9-.2 1.4 0 .8.7 1.4 1.9 1.4 3.6 0 6.5-2.6 6.5-5.9 0-3.6-2.9-7.2-6.5-7.2z"/><circle cx="4.5" cy="6" r="0.8" fill="currentColor"/><circle cx="6.5" cy="3.8" r="0.8" fill="currentColor"/><circle cx="10" cy="3.8" r="0.8" fill="currentColor"/><circle cx="12" cy="6.5" r="0.8" fill="currentColor"/></svg>',
    terminal: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="1.5" y="3" width="13" height="10" rx="1"/><path d="M4 7l2 2-2 2M7.5 11h4"/></svg>',
    book: '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 3v10s2-1 6-1 6 1 6 1V3s-2-1-6-1-6 1-6 1z"/><path d="M8 2v11"/></svg>',
  };

  const items= [
    {
      key: 'resources',
      label: '资源',
      columns: 2,
      links: [
        { label: '组件库', description: 'Vue 3 与 React 同源', href: '#', icon: ICONS.cube },
        { label: 'Tokens',  description: 'OKLCH 三套主题',     href: '#', icon: ICONS.palette },
        { label: 'CLI',     description: 'npx chufix add',     href: '#', icon: ICONS.terminal },
        { label: '文档',     description: '完整指南与示例',     href: '#', icon: ICONS.book },
      ],
    },
  ];
  return (
    <>
      <CfNavMenu items={items} active="resources" trigger="click" />
        <p className="adm-hint">
          <code>link.icon</code> 接收原始 SVG 字符串(通过 <code>v-html</code> 注入)。
          SVG 用 <code>currentColor</code> 描边会自动跟随面板文字色。
        </p>
    </>
  );
}

禁用项

item.disabled = true 灰显该项并阻止 hover / click 打开富面板。常用于”即将上线”或权限不足的菜单。

背景 视口

item.disabled = true 的项不响应 hover / click, 同时获得灰显样式与 aria-disabled

src/App.vue
<script setup lang="ts">
import { CfNavMenu, type NavMenuItem } from '@chufix-design/vue';

const items: NavMenuItem[] = [
  { key: 'home', label: '首页', href: '#' },
  {
    key: 'products',
    label: '产品',
    links: [
      { label: '组件库', href: '#' },
      { label: 'CLI', href: '#' },
    ],
  },
  { key: 'pricing', label: '价格', href: '#', disabled: true },
  { key: 'beta', label: 'Beta(即将上线)', href: '#', disabled: true },
];
</script>
<template>
  <CfNavMenu :items="items" active="home" />
  <p class="adm-hint">
    给 <code>item.disabled = true</code> 的项不响应 hover / click,
    同时获得灰显样式与 <code>aria-disabled</code>。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; line-height: 1.6; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
<script setup>
import { CfNavMenu } from '@chufix-design/vue';

const items= [
  { key: 'home', label: '首页', href: '#' },
  {
    key: 'products',
    label: '产品',
    links: [
      { label: '组件库', href: '#' },
      { label: 'CLI', href: '#' },
    ],
  },
  { key: 'pricing', label: '价格', href: '#', disabled: true },
  { key: 'beta', label: 'Beta(即将上线)', href: '#', disabled: true },
];
</script>
<template>
  <CfNavMenu :items="items" active="home" />
  <p class="adm-hint">
    给 <code>item.disabled = true</code> 的项不响应 hover / click,
    同时获得灰显样式与 <code>aria-disabled</code>。
  </p>
</template>
<style scoped>
.adm-hint { color: var(--fg-3); font-size: var(--t-12); margin-top: 12px; line-height: 1.6; }
code { font-family: var(--font-mono); color: var(--fg-2); }
</style>
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const items: NavMenuItem[] = [
    { key: 'home', label: '首页', href: '#' },
    {
      key: 'products',
      label: '产品',
      links: [
        { label: '组件库', href: '#' },
        { label: 'CLI', href: '#' },
      ],
    },
    { key: 'pricing', label: '价格', href: '#', disabled: true },
    { key: 'beta', label: 'Beta(即将上线)', href: '#', disabled: true },
  ];
  return (
    <>
      <CfNavMenu items={items} active="home" />
        <p className="adm-hint">
          给 <code>item.disabled = true</code> 的项不响应 hover / click,
          同时获得灰显样式与 <code>aria-disabled</code>。
        </p>
    </>
  );
}
import { CfNavMenu } from '@chufix-design/react';

export default function Demo() {
  const items= [
    { key: 'home', label: '首页', href: '#' },
    {
      key: 'products',
      label: '产品',
      links: [
        { label: '组件库', href: '#' },
        { label: 'CLI', href: '#' },
      ],
    },
    { key: 'pricing', label: '价格', href: '#', disabled: true },
    { key: 'beta', label: 'Beta(即将上线)', href: '#', disabled: true },
  ];
  return (
    <>
      <CfNavMenu items={items} active="home" />
        <p className="adm-hint">
          给 <code>item.disabled = true</code> 的项不响应 hover / click,
          同时获得灰显样式与 <code>aria-disabled</code>。
        </p>
    </>
  );
}

API

属性类型默认值说明
itemsNavMenuItem[][]顶级菜单条目
activestring当前活动项的 key,影响下划线 / 高亮
variant'underline' | 'pill' | 'minimal''underline'视觉模式
trigger'hover' | 'click''hover'富面板的触发方式

类型导出:

interface NavMenuItem {
  key: string;
  label: string;
  href?: string;
  links?: NavMenuLink[];
  columns?: 1 | 2 | 3;
  disabled?: boolean;
}
interface NavMenuLink {
  label: string;
  description?: string;
  href: string;
  icon?: VNode | ReactNode;
}

事件:navigate(item)(React 端:onNavigate),仅在简单链接被点击(无 links 子项)时触发。

反馈与讨论

NavMenu 主导航 的讨论

0
0 / 600
正在加载评论...