Preview Updated 2026-05-10

NavMenu

Top horizontal navigation; each item can attach a rich panel (multi-column links + descriptions); 3 variants, hover / click triggers.

Basic usage

items is the top-level menu array. Each entry is either a simple link (href) or has a links[] sublist. The latter opens a rich panel on hover / click; each link can carry a description and icon. columns controls how many columns per row in the panel (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>
    </>
  );
}

Three variants

  • underline — thin underline beneath the active item (default, most restrained)
  • pill — active item turns into a filled pill
  • minimal — color change only, no shape indicator
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

triggerhover (default, opens on mouse hover) / click (opens on click; better for mobile or to avoid accidental triggers).

背景 视口
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>
    </>
  );
}

API

PropTypeDefaultDescription
itemsNavMenuItem[][]Top-level entries
activestringkey of the active item; drives underline / highlight
variant'underline' | 'pill' | 'minimal''underline'Visual mode
trigger'hover' | 'click''hover'Trigger for the rich panel

Type exports:

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;
}

Events: navigate(item) (React: onNavigate); fires only when a simple link is clicked (no links sublist).

反馈与讨论

NavMenu · Discussion

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