Mantine Spotlight 实战指南:为 React 应用打造 Overlay 命令中心 Mantine Spotlight 实战指南为 React 应用打造 Overlay 命令中心【免费下载链接】mantineA fully featured React components library项目地址: https://gitcode.com/GitHub_Trending/ma/mantineSpotlight 是 Mantine 提供的全屏覆盖式命令中心组件Overlay command center它基于 Modal 实现支持快捷键唤起、即时过滤、键盘导航可直接为应用注入类似 macOS Spotlight / VS Code 命令面板的交互体验。本文将基于 packages/mantine/spotlight 的源码完整讲解安装、用法、数据模型、状态管理、过滤机制与样式定制帮助你快速集成并深度定制。什么是 Mantine SpotlightSpotlight 是 Mantine 生态中的独立包README 将其定位为 Overlay command center for your application应用的全屏命令中心。它解决的问题很具体当应用功能越来越多用户难以通过菜单层级找到想要的操作时提供一个以键盘驱动的搜索面板输入关键词即可命中并触发任意动作。从源码结构看mantine/spotlight是一组可组合的复合组件compound components外加一个全局状态 store组件Spotlight、SpotlightRoot、SpotlightSearch、SpotlightActionsList、SpotlightAction、SpotlightActionsGroup、SpotlightEmpty、SpotlightFooter导出见 index.ts状态与动作spotlight、createSpotlight、createSpotlightStore、useSpotlight、openSpotlight、closeSpotlight、toggleSpotlight包依赖mantine/core、mantine/hooks、mantine/store见 package.json。安装与基础环境安装命令README 给出的安装方式如下README.md# With yarn yarn add mantine/spotlight mantine/core mantine/hooks # With npm npm install mantine/spotlight mantine/core mantine/hooks版本与依赖说明当前仓库中mantine/spotlight版本为 9.6.0peerDependencies要求mantine/core与mantine/hooks同为 9.6.0React 需为^19.2.0、react-dom 同理见 package.json安装时注意版本对齐它内部依赖mantine/store9.6.0用于状态管理见 package.json包同时提供 ESMesm/index.mjs、CJScjs/index.cjs与类型声明lib/index.d.ts并单独导出样式文件./styles.css与./styles.layer.css见 package.json使用 CSS Modules 构建需要你的构建工具链支持 CSS Modules 与 Mantine 的 PostCSS 配置仓库根目录的 postcss.config.cjs 即此类配置示例。基础用法声明式 actions 快捷键唤起Spotlight 提供两种主要集成方式声明式通过actions数组声明命令与命令式通过 store 的 open/close/toggle 控制开关。方式一声明式推荐以复合组件形式声明搜索框、动作列表、空态与页脚动作通过actions数组传入import { Spotlight } from mantine/spotlight; import { IconSearch, IconHome, IconUser } from tabler/icons-react; function App() { return ( Spotlight actions{[ { id: home, label: Go to home, description: Navigate to the home page, leftSection: IconHome size{18} /, onClick: () navigate(/) }, { id: profile, label: Open profile, description: View your profile, leftSection: IconUser size{18} /, onClick: () navigate(/profile) }, ]} nothingFoundNo results found Spotlight.Search placeholderSearch actions... / Spotlight.ActionsList / Spotlight.Empty / Spotlight.FooterPress Enter to select/Spotlight.Footer /Spotlight ); }Spotlight组件内部逻辑见 Spotlight.tsx大致为将query交给filter过滤再交给limitActions截断把每一项渲染为SpotlightAction若某项带group则包一层SpotlightActionsGroup。过滤后无结果且传了nothingFound时渲染SpotlightEmpty。方式二命令式通过Spotlight.open()/Spotlight.close()/Spotlight.toggle()或全局导出的openSpotlight/closeSpotlight/toggleSpotlight手动控制开关import { Button } from mantine/core; import { openSpotlight, Spotlight } from mantine/spotlight; function App() { return ( Button onClick{openSpotlight}Open spotlight/Button Spotlight actions{actions} nothingFoundNothing found / / ); }这些静态方法与全局函数都来自 store 层见 Spotlight.tsx 与 spotlight.store.ts。组件 API 全景Spotlight是一个复合组件其静态子组件与函数见 Spotlight.tsx 的Factory定义与 Spotlight.test.tsx 的测试断言静态成员对应组件/函数作用Spotlight.SearchSpotlightSearch搜索输入框负责过滤与键盘事件Spotlight.ActionsListSpotlightActionsList动作列表容器内部使用ScrollArea.AutosizeSpotlight.ActionSpotlightAction单个动作按钮Spotlight.ActionsGroupSpotlightActionsGroup动作分组带组标题Spotlight.EmptySpotlightEmpty无结果时的空态提示Spotlight.FooterSpotlightFooter底部区域如快捷键提示Spotlight.RootSpotlightRoot根容器基于 ModalSpotlight.open/close/togglestore 动作程序化开关Spotlight 主组件 Props定义见 Spotlight.tsx同时继承SpotlightRootPropsModal 相关 propsProp类型默认值说明actionsSpotlightActions[]必填动作数据见下文数据模型filterSpotlightFilterFunctiondefaultSpotlightFilter自定义过滤函数nothingFoundReact.ReactNode-无匹配结果时的提示内容highlightQuerybooleanfalse是否高亮动作 label 中的匹配文本limitnumberInfinity单次最多显示的动作数量searchPropsSpotlightSearchProps-透传给Spotlight.Search的 propsscrollAreaPropsPartialScrollAreaAutosizeProps-透传给列表内部ScrollArea的 propsquery/onQueryChangestring/ 回调-受控查询词来自 Rootshortcutstring \| string[] \| nullmod K唤起快捷键来自 RootSpotlightRoot Props继承自 Modal定义见 SpotlightRoot.tsxProp类型默认值说明storeSpotlightStore全局spotlightStore指定 store用于多实例场景clearQueryOnClosebooleantrue关闭时是否清空查询词closeOnActionTriggerbooleantrue触发动作后是否自动关闭shortcutstring \| string[] \| nullmod K快捷键传null可禁用tagsToIgnorestring[][input,textarea,select]焦点在这些标签内时忽略快捷键triggerOnContentEditablebooleanfalsecontentEditable 区域是否触发快捷键disabledbooleanfalse为 true 时不渲染 SpotlightonSpotlightOpen/onSpotlightClose回调-打开/关闭回调由useDidUpdate触发forceOpenedboolean-强制打开常用于测试maxHeightCSSmaxHeight400内容最大高度需配合scrollablescrollablebooleanfalse是否让动作列表可滚动此外还继承size默认 600、yOffset默认 80、zIndex默认getDefaultZIndex(max)、overlayProps默认{ backgroundOpacity: 0.35, blur: 7 }、transitionProps默认{ duration: 200, transition: pop }等 Modal props默认值汇总见 SpotlightRoot.tsx。SpotlightAction Props定义见 SpotlightAction.tsxProp类型默认值说明labelstring-动作标题参与默认过滤descriptionstring-动作描述参与默认过滤leftSection/rightSectionReact.ReactNode-左侧图标/右侧快捷键提示区块childrenReact.ReactNode-自定义内容覆盖默认 label/描述/区块dimmedSectionsbooleantrue左右区块是否使用弱化样式highlightQuerybooleanfalse是否高亮匹配文本highlightColorMantineColoryellow高亮颜色theme.colors键或任意 CSS 颜色closeSpotlightOnTriggerboolean-触发后是否关闭覆盖根组件的closeOnActionTriggerkeywordsstring \| string[]-隐藏关键词参与过滤但不展示如react,router,javascript数据模型ActionData 与 ActionsGroup类型定义见 Spotlight.tsxinterface SpotlightActionData extends SpotlightActionProps { id: string; // 唯一标识用作 React key group?: string; // 分组名存在时按组渲染 } interface SpotlightActionGroupData { group: string; actions: SpotlightActionData[]; } type SpotlightActions SpotlightActionData | SpotlightActionGroupData;两种组织方式示例const actions [ { id: home, label: Home, group: Navigation, onClick: () go(/) }, { group: Actions, actions: [ { id: new-file, label: New file, keywords: [create, document], onClick: createFile }, { id: save, label: Save, onClick: saveFile }, ], }, ];isActionsGroup通过group ! undefined Array.isArray(item.actions)判定条目是否为分组is-actions-group.ts渲染逻辑见 Spotlight.tsx。键盘交互与默认快捷键SpotlightRoot使用useHotkeys注册快捷键SpotlightRoot.tsxgetHotkeys会把字符串或数组转换为[hotkey, open]形式的快捷键项get-hotkeys.ts// 单个快捷键 Spotlight shortcutmod K ... / // 多个快捷键 Spotlight shortcut{[mod K, mod P]} ... / // 禁用快捷键 Spotlight shortcut{null} ... /SpotlightSearch处理输入框内的键盘导航SpotlightSearch.tsxArrowDownselectNextAction选中下一个动作ArrowUpselectPreviousAction选中上一个动作Enter/NumpadEntertriggerSelectedAction触发当前选中的动作支持 IME 输入法合成onCompositionStart/onCompositionEnd中文输入法候选状态下手势事件会被跳过避免误触发。选中与滚动逻辑在 store 层实现spotlight.store.tsselectAction通过#listId定位动作列表使用[data-action]收集动作按钮、[data-selected]标记当前项并调用scrollIntoView({ block: nearest })保证选中项可见triggerSelectedAction则对[data-selected]元素执行.click()。注意selectAction支持 Shadow DOM 递归查找元素spotlight.store.ts。过滤机制与自定义 filter默认过滤由defaultSpotlightFilter实现default-spotlight-filter.ts匹配规则查询词先trim().toLowerCase()归一化优先级矩阵label包含查询词的动作进入第一优先级description或keywords包含查询词的动作进入第二优先级结果先按优先级排序再按原顺序保留flatActionsToGroups会重新聚合成组分组内的动作仍按顺序排列组间顺序保持不变。keywords支持字符串如react,router,javascript或数组如[react, router, javascript]统一转为小写后参与匹配default-spotlight-filter.ts。自定义 filter 只需实现(query, actions) actions签名const fuzzyFilter: SpotlightFilterFunction (query, actions) { // 使用你自己的模糊匹配算法如 Fuse.js过滤 actions return fuzzySearch(query, actions); }; Spotlight filter{fuzzyFilter} actions{actions} /;过滤后的结果还会经过limitActions截断limit-actions.ts它按顺序累计动作数量达到limit后停止分组内部也会递归截断保证总显示数不超过limit。状态管理SpotlightStore 与多实例Spotlight 的状态基于mantine/store的createStoreSpotlightState包含opened、selected当前选中索引、listId动作列表 DOM id、query、empty空态标记、registeredActions已注册动作的 Setspotlight.store.ts。全局单例默认导出的spotlightStore与spotlight由createSpotlight()生成spotlight.store.tsopenSpotlight/closeSpotlight/toggleSpotlight直接操作该全局实例。全局单例适合大多数应用只有一个命令中心的场景。多实例与 createSpotlight需要多个独立命令中心时使用createSpotlight或createSpotlightStore创建独立 storeimport { createSpotlight, Spotlight } from mantine/spotlight; // 创建独立的 store 与命令 const [store, spotlight] createSpotlight(); function App() { return ( Spotlight store{store} actions{actions} / button onClick{spotlight.open}Open/button / ); }Store 关键动作open/close/toggle开关面板toggle 时重置选中索引见 spotlight.store.tssetQuery更新查询词异步重置选中到第一项并根据查询非空但已注册动作数为 0计算empty状态spotlight.store.tsclearSpotlightState关闭时按clearQueryOnClose决定是否清空查询词与空态spotlight.store.tsregisterAction注册/注销动作 id供空态判断使用spotlight.store.ts。样式定制样式 APIStyles APISpotlight的样式名SpotlightStylesNames包括 Modal 的全部样式名root、content、body、inner、overlay等外加search、actionsList、action、empty、footer、actionBody、actionLabel、actionDescription、actionSection、actionsGroupSpotlightRoot.tsx因此可以通过classNames/styles精确覆盖任意层级。测试中验证了完整的样式选择器列表包括root、action、actionBody、actionDescription、actionLabel、actionSection、actionsList、actionsGroup、body、content、inner、overlay、searchSpotlight.test.tsx。Spotlight actions{actions} classNames{{ search: my-search, action: my-action }} styles{{ actionLabel: { fontWeight: 600 } }} /关键 CSS 实现核心样式见 Spotlight.module.css.content通过 CSS 变量控制高度height: var(--spotlight-content-height, auto)、max-height: var(--spotlight-max-height)scrollable时由 Root 注入--spotlight-max-heightSpotlightRoot.tsx.actionsList使用--spotlight-actions-list-padding: 4px作为滚动条偏移量并设置max-height: calc(100vh - 15rem).action[data-selected]使用主题主色var(--mantine-primary-color-filled)高亮选中项描述文本通过--action-description-color/--action-description-opacity变量做降级显示.actionsGroup通过--spotlight-labelCSS 变量渲染组标题content: var(--spotlight-label)组标题由 SpotlightActionsGroup.tsx 注入并转义引号深色/浅色模式分别通过mixin where-light/mixin where-dark适配边框与 hover 背景色。无障碍与测试要点每个动作渲染为UnstyledButton带data-action属性tabIndex{-1}由 store 通过data-selected属性管理选中态SpotlightAction.tsx搜索框基于 MantineInput构建键盘事件完整支持方向键与回车导航测试用例覆盖了系统 props 与样式 API 选择器、静态成员暴露、无动作时不渲染列表容器仅渲染nothingFound、triggerSelectedAction在listId为空时不抛异常Spotlight.test.tsx需要打开面板做测试时可组合forceOpened、withinPortal{false}与transitionProps{{ duration: 0 }}见测试的defaultPropsSpotlight.test.tsx。典型使用场景全局命令面板注册所有页面跳转、创建/保存等高频操作mod K唤起配合keywords提供语义别名导航替代方案通过group将导航操作设置分组展示减少鼠标点击层级多实例业务场景例如页面内搜索mod K与主题切换mod T分别使用createSpotlight创建的独立 store自定义过滤引擎替换filter接入模糊匹配或拼音检索提升中文/复杂关键词的命中体验快捷键提示可视化利用rightSection显示每个动作的快捷键如⌘N配合底部Spotlight.Footer给出操作指引。总结Mantine Spotlight 用约十个文件实现了一个功能完整的命令中心数据驱动渲染actions数组、可插拔过滤filterlimitActions、事件驱动状态mantine/store、复合组件组合Spotlight.*静态成员与完整样式 API。通过本文的 Props 表格、源码路径与数据模型说明你可以快速集成默认行为也可以在需要时替换过滤逻辑、扩展多实例或精细定制样式。【免费下载链接】mantineA fully featured React components library项目地址: https://gitcode.com/GitHub_Trending/ma/mantine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考