@data-slot/navigation-menu

中文文档
1.1.3发布于 2026/11/05MITTypeScriptESM + CJS构建来源已验证近 30 天下载 2万

香草JavaScript的无头导航菜单(mega菜单)组件. 无障碍而无作相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.

中文使用文档
文档目录14 节
  1. 安装
  2. 快速启动
  3. API 密码
  4. 初始化
  5. 槽数
  6. 数据属性
  7. 选项
  8. 内容安装和服务器渲染
  9. 主计长
  10. 活动
  11. 样式
  12. 键盘导航
  13. 行为
  14. 许可证

@ data- slot/ 导航菜单

香草JavaScript的无头导航菜单(mega菜单)组件. 无障碍而无作相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.

安装

npm install @data-slot/navigation-menu

快速启动

<nav data-slot="navigation-menu">
  <ul data-slot="navigation-menu-list">
    <li data-slot="navigation-menu-item" data-value="products">
      <button data-slot="navigation-menu-trigger">Products</button>
      <div data-slot="navigation-menu-content">
        <a href="/product-a">Product A</a>
        <a href="/product-b">Product B</a>
      </div>
    </li>
    <li data-slot="navigation-menu-item" data-value="company">
      <button data-slot="navigation-menu-trigger">Company</button>
      <div data-slot="navigation-menu-content">
        <a href="/about">About</a>
        <a href="/careers">Careers</a>
      </div>
    </li>
    <li data-slot="navigation-menu-indicator" role="presentation" aria-hidden="true"></li>
  </ul>
  <div data-slot="navigation-menu-portal">
    <div data-slot="navigation-menu-positioner">
      <div data-slot="navigation-menu-popup">
        <div data-slot="navigation-menu-viewport"></div>
      </div>
    </div>
  </div>
</nav>

<script type="module">
  import { create } from "@data-slot/navigation-menu";
  
  const controllers = create();
</script>

只有作者的最小标记 navigation-menu-viewport 还行 运行时间 在菜单打开时生成弹出堆栈,并在关闭时恢复原来的DOM.

API 密码

初始化

create(scope?)

自动发现并绑定范围中的所有导航菜单例(默认为 document) (中文(简体) ).

import { create } from "@data-slot/navigation-menu";

const controllers = create(); // Returns NavigationMenuController[]

createNavigationMenu(root, options?)

为特定元素创建控制器.

import { createNavigationMenu } from "@data-slot/navigation-menu";

const menu = createNavigationMenu(element, {
  delayOpen: 0,
  delayClose: 0,
  onValueChange: (value) => console.log(value),
});

槽数

运行时间槽

  • navigation-menu - 管理活动面板和打开状态的根导航元素.
  • navigation-menu-list - 包含导航项目的必要顶级列表;用于发现顶级悬浮和聚焦目标.
  • navigation-menu-item - 航行入境集装箱;至少需要一件物品。 使用 data-value 以识别带有内容面板的条目.
  • navigation-menu-trigger - 打开其相关内容面板的项目中的按钮.
  • navigation-menu-content - 项目内的内容面板,当项目活动时显示.
  • navigation-menu-indicator - 可选动画亮点,紧随顶级悬浮/聚焦目标,在面板打开时仍固定在主动触发器上.
  • navigation-menu-portal - 门户包装器移到 document.body 当菜单打开时.
  • navigation-menu-positioner - 弹出式定位包,接收已解析的侧/对齐属性和大小变量.
  • navigation-menu-popup - 动画弹出外壳在取景口周围.
  • navigation-menu-viewport - 可选剪辑取景口,该取景口设有活动内容面板.
  • navigation-menu-viewport-positioner - 折旧的别名 navigation-menu-positioner。 。 。 .

生成槽

  • navigation-menu-bridge - 运行时创建的悬浮安全屏蔽,既能保持菜单的开放,又能跨越缺口到其内容.
  • navigation-menu-safe-triangle - 运行时创建调试多边形,在调试启用时可视化悬浮安全走廊.

标记

<nav data-slot="navigation-menu">
  <ul data-slot="navigation-menu-list">
    <li data-slot="navigation-menu-item" data-value="unique-id">
      <button data-slot="navigation-menu-trigger">Label</button>
      <div data-slot="navigation-menu-content">
        <!-- Links, content -->
      </div>
    </li>
    <!-- Optional hover indicator -->
    <li data-slot="navigation-menu-indicator" role="presentation" aria-hidden="true"></li>
  </ul>
  <div data-slot="navigation-menu-portal">
    <div data-slot="navigation-menu-positioner">
      <div data-slot="navigation-menu-popup">
        <div data-slot="navigation-menu-viewport"></div>
      </div>
    </div>
  </div>
</nav>

如果你只写 navigation-menu-viewport,运行时间合成缺失 navigation-menu-portal, (中文(简体) ), navigation-menu-positioner,以及 navigation-menu-popup 菜单打开时的包装符 .

数据属性

也可以通过根元素上的数据属性来设定选项. 联合来文的选择优先.

属性类型默认说明
data-delay-open编号0悬浮开始前的延迟( 毫秒)
data-delay-close编号0关闭鼠标休假前的延迟( 毫秒)
data-open-on-focus布尔false聚焦触发是否打开其内容
data-mount-strategy"lazy" | "eager""lazy"切除不活动面板或保持其连接和隐藏
data-side字符串"bottom"侧: "top", (中文(简体) ), "right", (中文(简体) ), "bottom", (中文(简体) ), "left"
data-align字符串"start"视图端口对齐 : "start", (中文(简体) ), "center",或 "end"
data-side-offset编号0从触发到取景口的距离( px)
data-align-offset编号0交叉轴对齐相抵 (px)
data-position-method字符串"absolute"定位战略: "absolute" 或者说 "fixed"
data-safe-triangle布尔false启用悬空安全三角切换保护
data-debug-safe-triangle布尔false显示红色悬浮安全三角调试覆盖

布尔属性: 存在或 "true" 没错, "false" =虚假,缺席=默认.

放置属性( A)data-side, (中文(简体) ), data-align, (中文(简体) ), data-side-offset, (中文(简体) ), data-align-offset控制( ) 相对于活动触发器的视图端口位置 :

  • start - 用触发左边缘对齐视图左边缘( 默认)
  • center - 以触发器为中心取景口
  • end - 对接右侧取景口和右侧取景口

可设定为:

  1. navigation-menu-content (最高优先,每组)
  2. navigation-menu-item
  3. navigation-menu root (最低优先级, 全球默认)

navigation-menu-positioner 是犬形弹出定位槽。 内容 data-side 编号 : data-align 是镜像输出值,不用作放置输入. navigation-menu-viewport-positioner 仍被接受为遗产的别名.

<!-- Faster hover response with focus auto-open opt-in -->
<nav data-slot="navigation-menu" data-delay-open="100" data-open-on-focus="true">
  ...
</nav>

<!-- Center-align a narrow submenu under its trigger -->
<li data-slot="navigation-menu-item" data-value="company" data-align="center">
  <button data-slot="navigation-menu-trigger">Company</button>
  <div data-slot="navigation-menu-content">
    <a href="/about">About</a>
    <a href="/careers">Careers</a>
  </div>
</li>

输出属性

表面属性
根号data-state="open|closed", (中文(简体) ), data-open, (中文(简体) ), data-closed
定位器data-state="open|closed", (中文(简体) ), data-open, (中文(简体) ), data-closed, (中文(简体) ), data-side, (中文(简体) ), data-align, (中文(简体) ), data-instant
弹出data-state="open|closed", (中文(简体) ), data-open, (中文(简体) ), data-closed, (中文(简体) ), data-side, (中文(简体) ), data-align, (中文(简体) ), data-starting-style, (中文(简体) ), data-ending-style, (中文(简体) ), data-instant
视图data-state="open|closed", (中文(简体) ), data-open, (中文(简体) ), data-closed, (中文(简体) ), data-side, (中文(简体) ), data-align, (中文(简体) ), data-starting-style, (中文(简体) ), data-ending-style, (中文(简体) ), data-instant
内容data-state="active|inactive", (中文(简体) ), data-open, (中文(简体) ), data-closed, (中文(简体) ), data-side, (中文(简体) ), data-align, (中文(简体) ), data-starting-style, (中文(简体) ), data-ending-style, (中文(简体) ), data-activation-direction="left|right"

data-activation-direction 仅在打开顶级面板之间切换时被放出. 完全接近是故意非方向性的.

选项

选项类型默认说明
delayOpennumber0悬浮开始前的延迟( 毫秒)
delayClosenumber0关闭鼠标休假前的延迟( 毫秒)
openOnFocusbooleanfalse聚焦触发是否打开其内容
mountStrategy"lazy" | "eager""lazy"切除不活动面板或保持其连接和隐藏
side"top" | "right" | "bottom" | "left""bottom"相对于触发的视图端
align"start" | "center" | "end""start"在横轴上查看端口对齐
sideOffsetnumber0从触发到取景口的距离( px)
alignOffsetnumber0交叉轴对齐相抵 (px)
positionMethod"absolute" | "fixed""absolute"共享弹出位置的定位策略
safeTrianglebooleanfalse启用悬空安全三角切换保护
onValueChange(value: string | null) => voidundefined活动项目更改时召回
debugSafeTrianglebooleanfalse显示红色悬浮安全三角调试覆盖

内容安装和服务器渲染

默认情况下,导航菜单会从页面的 DOM 中删除其已关闭的面板. 这个 初始化后保留大菜单较小的页面。 菜单按钮和 这些面板以外的链接留在页面中.

打开一个面板将相同的内容放回页面中. 其状态和活动 听众被保存下来。 当切换面板时,在 前一个完成它的退出动画。 上次动画之后 面板被删除.

关闭菜单等待面板及其周围弹出完成 出道动画. 在出局动画期间重新打开一个面板,保留在页面上.

大多数应用程序可以不作任何修改地使用此默认值.

如果您的代码需要在封闭面板内找到或更新链接—— 例如, 使用 querySelector——使用 eager 在 DOM 中保留面板的模式 :

createNavigationMenu(root, { mountStrategy: "eager" });

您还可以添加 data-mount-strategy="eager" 转到导航菜单根。 A 类 JavaScript 选项优先于 HTML 属性.

默认 lazy 模式, DOM 查询不会找到关闭的面板或链接. 在初始化导航菜单和 稍后使用这个参考.

没有 JavaScript 的服务器渲染和页面

懒散的升起 没有 减少发送给浏览器的 HTML 。 面板内容是 仍然包含在您的 HTML; 导航菜单从 DOM 中删除已关闭的面板 在JavaScript初始化后.

在 JavaScript 负载或它从未运行之前, 确保必要的导航工作有效 . 您可以在初始化之前将链接保留在可见位置, 或者提供单独的倒置 如果您的面板开始隐藏, 则导航 。 也没有 lazy 也没有 eager 模式提供 自动回落.

主计长

方法/财产说明
open(value)打开特定项目
close()关闭菜单
value目前活动项目值( 只读) string | null(中文(简体) )
destroy()清理所有事件听众

主计长销毁

destroy() 永久处理控制器并隐藏任何打开的表面,而不包含 产生额外的变化事件。 重复销毁是安全的 旧控制器变成无操作器。 在同一根上创建新控制器以重新组合 .

活动

境外事件

通过自定义事件聆听更改 :

element.addEventListener("navigation-menu:change", (e) => {
  console.log("Active item:", e.detail.value);
});

入境事件

通过事件控制导航菜单 :

活动细节说明
navigation-menu:set{ value: string | null }设置活动项目或关闭菜单
// Open a specific item
element.dispatchEvent(
  new CustomEvent("navigation-menu:set", { detail: { value: "products" } })
);

// Close the menu
element.dispatchEvent(
  new CustomEvent("navigation-menu:set", { detail: { value: null } })
);

样式

navigation-menu-portal 移动到 document.body 并打开。 如果创建了弹出式插槽 它们被重新使用。 否则,就不见了 portal 编号 : positioner 编号 : popup 包装器是 在打开和关闭时生成.

运行时几何由 navigation-menu-positioner数字 : position, (中文(简体) ), top, (中文(简体) ), left, (中文(简体) ), width, (中文(简体) ), 财务报告和审定财务报表 height 被写入内并重置在关闭处. navigation-menu-popup 是犬科动物 动画外壳. 活跃 navigation-menu-content 面板挂在内部 navigation-menu-viewport 并打开。 非活动面板退出后被拆卸 默认动画; 急切的面板返回原标记位置 .

使用 positionMethod: "fixed" 或者说 data-position-method="fixed" 当菜单需要视图端口时 锚地,如内粘相头.

基本结构

/* Hidden by default */
[data-slot="navigation-menu-content"] {
  display: none;
}

[data-slot="navigation-menu-content"][data-open] {
  display: block;
}

/* Positioner owns placement geometry */
[data-slot="navigation-menu-positioner"],
[data-slot="navigation-menu-viewport-positioner"] {
  top: 0;
  left: 0;
  transition: top 0.3s, left 0.3s;
}

/* Skip initial position animation */
[data-slot="navigation-menu-positioner"][data-instant],
[data-slot="navigation-menu-viewport-positioner"][data-instant] {
  transition: none;
}

/* Popup owns the main shell animation */
[data-slot="navigation-menu-popup"] {
  transform-origin: var(--transform-origin);
  width: var(--popup-width);
  height: var(--popup-height);
  transition: transform 0.3s, width 0.3s, height 0.3s, opacity 0.15s;
}

[data-slot="navigation-menu-popup"][data-starting-style],
[data-slot="navigation-menu-popup"][data-ending-style] {
  opacity: 0;
}

/* Viewport keeps backward-compatible sizing aliases */
[data-slot="navigation-menu-viewport"] {
  width: var(--viewport-width);
  height: var(--viewport-height);
}

/* Skip animation on initial open */
[data-slot="navigation-menu-viewport"][data-instant] {
  transition: none;
}

/* Indicator positioning */
[data-slot="navigation-menu-indicator"] {
  position: absolute;
  left: var(--indicator-left);
  width: var(--indicator-width);
  transition: left 0.2s, width 0.2s;
}

data-instant 用于初始开放阶段和同步驱动锚地跟踪更新 (例如,当一个粘性触发器在菜单打开时移动). 切换时可以清除, 关闭, 或者在跟踪更新后解决。 使用它来跳过这些重新定位的转换,而无需 压制出站动画.

动画

使用 data-starting-style 编号 : data-ending-style 打开 navigation-menu-popup 完全弹出 打开/关闭动画 navigation-menu-content 用于面板存在. 方向面板切换应关闭密钥 data-activation-direction="left|right" 内容. 活动面板保持正常流;挂载的不活动/出行面板绝对定位 以运行时间表示,这样它们不会在激活时影响弹出测量.

对于出局动画,请避免CSS即刻强制加码内容 data-state (例如 display: none 在非活性面板上),因为这绕过存在生命周期.

[data-slot="navigation-menu-popup"][data-starting-style],
[data-slot="navigation-menu-popup"][data-ending-style] {
  opacity: 0;
  transform: scale(0.96);
}

[data-slot="navigation-menu-content"][data-starting-style],
[data-slot="navigation-menu-content"][data-ending-style] {
  opacity: 0;
}

[data-slot="navigation-menu-content"][data-starting-style][data-activation-direction="right"] {
  transform: translateX(2rem);
}

[data-slot="navigation-menu-content"][data-starting-style][data-activation-direction="left"] {
  transform: translateX(-2rem);
}

[data-slot="navigation-menu-content"][data-ending-style][data-activation-direction="right"] {
  transform: translateX(-2rem);
}

[data-slot="navigation-menu-content"][data-ending-style][data-activation-direction="left"] {
  transform: translateX(2rem);
}

遗产 data-motion 财务报告和审定财务报表 --motion-direction 在面板切换后向后仍会释放 兼容性。 包括根层和内容层 data-motion 输出,但 data-activation-direction 是犬形方向钩.

--popup-width 编号 : --popup-height 是弹出壳大小的Vars。 菜单打开后,他们就留下来 在固定像素值下, CSS 可以直接将面板到平面板的大小变化 px 目标. 初始打开时同步写入测量大小; shell 不需要 auto 重置时 打开.

CSS 变量

变量元素说明
--popup-width弹出打开时弹出宽度; CSS 可以在像素值之间对 shell 宽度进行动画化
--popup-height弹出打开时弹出高度; CSS 可以在像素值之间对 shell 高度进行动画化
--positioner-width定位器活动面板的测量宽度
--positioner-height定位器活动面板的测量高度
--available-width定位器活动触发器和视图边缘之间的可用宽度
--available-height定位器活动触发器和视图边缘之间的可用高度
--transform-origin弹出/取景口/内容/位置锁定像素源以触发( S)side + 键 align),范围为每个元素的坐标空间
--viewport-width视图活动面板宽度的遗留别名
--viewport-height视图活动面板高度的后遗症别名
--indicator-left指标从列表中向左偏移
--indicator-width指标悬浮起子的宽度
--indicator-top指标从列表中乘以顶
--indicator-height指标悬浮起落器高度
--motion-direction视图遗留切换方向输出 : 1 (权利)或 -1 (左边)

折旧兼容性

  • navigation-menu-viewport-positioner 是一个被折旧的别名,用于 navigation-menu-positioner。 。 。 .
  • --viewport-width, (中文(简体) ), --viewport-height根/内容 data-motion,以及 --motion-direction 将在下一次主要释放中进行折旧并计划清除.
  • 内容已包装 navigation-menu-portal 编号 : navigation-menu-positioner 贝壳是只恢复相容的,也计划在下个主放出时被移除.

键盘导航

在顶级项目内

密钥行动
ArrowLeft将焦点移动到上一个顶级项目( 子菜单触发器或纯链接)
ArrowRight将焦点移动到下一个顶级项目( submenu 触发器或纯链接)
Tab按 DOM 顺序将焦点移动到下一个顶级项目
Shift+Tab以反向 DOM 顺序将焦点移动到上一个顶级项目
ArrowDown将焦点移动到内容面板( 仅在焦点项目有子菜单内容时)
Home将焦点移动到第一个顶级项目
End将焦点移动到上一个顶级项目
Escape关闭菜单

顶级子菜单触发器和平面链接仍保留在天然标签顺序中.

在内容小组内

密钥行动
ArrowDown 编号 : ArrowRight移动到下一个可聚焦元素
ArrowUp 编号 : ArrowLeft移动到上一个元素( 启动时返回触发)
Tab从上一个内容项中, 移动焦点到下个顶级 Nav项; 如果没有, 移动到 nav root 之后的下个可焦点项
Shift+Tab从第一个内容项目, 将焦点移回自有触发器
Escape关闭菜单并返回焦点以触发

行为

  • 缓冲: 打开 delayOpen 毫秒后关闭 delayClose 分钟
  • 点击: 锁定菜单打开直至明确动作为止(单击同一触发器,单击另一个触发器,点击外部,或 Escape); 盘旋在锁定时不切换/关闭
  • 焦点: 默认不自动打开; 设置 openOnFocus 编号 : data-open-on-focus="true" 选择加入
  • 触发打开焦点数字 :
    • 指针点击/tap 保持对触发器的关注
    • 键盘激活/程序点击将焦点移入菜单内容(第一个可聚焦项目,或内容面板倒置)
  • 指标: 当没有子菜单打开时, 普通顶级链接参与指标定位; 打开子菜单状态优先
  • 切换: 项目之间的即时过渡(无延迟)

许可证

麻省理工学院

版本与发布记录

@data-slot/navigation-menu 共发布 164 个版本,首次发布于 2026/01/09;过去 12 个月发布了 164 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.3latest2026/11/056 天前
1.1.22026/10/1428 天前
1.1.12026/10/051 个月前
1.1.02026/10/021 个月前
1.0.22026/09/271 个月前
1.0.12026/09/261 个月前

关于 @data-slot/navigation-menu 的常见问题

@data-slot/navigation-menu 是什么?

香草JavaScript的无头导航菜单(mega菜单)组件. 无障碍而无作相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相相.

如何安装 @data-slot/navigation-menu?

在项目目录运行 npm install @data-slot/navigation-menu,或使用 pnpm add / yarn add / bun add。

@data-slot/navigation-menu 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@data-slot/navigation-menu 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@data-slot/navigation-menu 可以商用吗?

@data-slot/navigation-menu 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@data-slot/navigation-menu 的下载量有多少?

根据 npm 官方下载统计,@data-slot/navigation-menu 在 2026/10/12 – 2026/11/10 这 30 天内被下载 19,684 次,日均约 656 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@data-slot/navigation-menu 还在维护吗?

最新版本 1.1.3 发布于 2026/11/05(6 天前);至今共发布 164 个版本,其中过去 12 个月发布了 164 个;首次发布于 2026/01/09。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。