| name | add-widget |
| description | NaiveTab 浏览器扩展的 Widget 开发指南。当用户要在 newtab-naivetab 项目中新增 Widget 组件、添加新功能组件时使用。涵盖需要修改的完整文件清单、配置规范、类型注册等,防止遗漏关键步骤。 |
NaiveTab Add Widget
新增 Widget 需按顺序完成以下步骤。完整模板参考见 reference.md。
完整注册点索引见 REGISTRY-MAP.md,新增时对照检查。
必须修改的 6 个文件
Step 1 — src/common/widget-constants.ts:代码列表与分组
WidgetCodes 不再手动维护联合类型,而是从 WIDGET_CODE_LIST 用 typeof 自动推导。 只需在列表数组中追加 code 即可。
WidgetConfigByCode 类型映射也在 src/common/widget-constants.ts 中(Step 6 处说明)。本 Step 处理以下三项:
1-A:添加到 WIDGET_CODE_LIST
export const WIDGET_CODE_LIST = [
'myWidget',
] as const
1-B:(可选)若新 Widget 与其他 Widget 共用同一个 setting pane,需维护 WIDGET_SETTING_PANE_MAP
export const WIDGET_SETTING_PANE_MAP: Partial<Record<WidgetCodes, settingPanes>> = {
myWidget: 'clockDate',
}
未在此 Map 中的 Widget,右键菜单会默认用自身 code 查找 pane(myWidget → pane myWidget)。
1-C:添加到 WIDGET_GROUPS 对应分组(用于组件库抽屉和专注设置按分类展示)
export const WIDGET_GROUPS: Array<{
labelKey: string
codes: WidgetCodes[]
}> = [
{
labelKey: 'widgetGroup.timeAndDate',
codes: ['clockDigital', ... , 'myWidget'],
},
]
必须添加否则不会显示在组件库列表中。
Step 2 — 新建 src/newtab/widgets/myWidget/config.ts
export const WIDGET_CODE = 'myWidget'
export const WIDGET_CONFIG = {
enabled: false,
layout: { xOffsetKey: 'left', xOffsetValue: 50, xTranslateValue: -50,
yOffsetKey: 'top', yOffsetValue: 50, yTranslateValue: -50 },
fontColor: ['rgba(255,255,255,1)', 'rgba(0,0,0,1)'],
}
export type TWidgetConfig = typeof WIDGET_CONFIG
Step 3 — 新建 src/newtab/widgets/myWidget/index.vue
- 用
WidgetWrap 作为根容器,直接子元素必须有 myWidget__container 的 class
- 样式块外层 selector 为
#myWidget,容器需 position: absolute
- 用
getStyleField(WIDGET_CODE, 'fieldName') 读取配置(自动处理颜色双数组/单位换算)
- 用
getIsWidgetRender(WIDGET_CODE) + watch 控制定时任务生命周期
Step 4 — 新建 src/newtab/widgets/myWidget/index.ts
import Index from './index.vue'
import { WIDGET_CODE, WIDGET_CONFIG } from './config'
import { WIDGET_ICON_META } from '@/logic/constants/icons'
export default {
code: WIDGET_CODE,
component: Index,
config: WIDGET_CONFIG,
iconName: WIDGET_ICON_META[WIDGET_CODE].iconName,
iconSize: WIDGET_ICON_META[WIDGET_CODE].widgetSize,
widgetLabel: 'setting.myWidget',
}
Step 5 — src/logic/constants/icons.ts ⚠️ 需修改两处,缺一不可
5-A:在 ICONS 对象中定义图标常量(图标来自 Iconify,需验证图标名存在):
export const ICONS = {
myWidget: 'mdi:some-valid-icon',
}
5-B:在 WIDGET_ICON_META 中引用(使用 ICONS.myWidget,禁止硬编码字符串):
export const WIDGET_ICON_META: Record<WidgetCodes, WidgetIconMeta> = {
myWidget: { iconName: ICONS.myWidget, widgetSize: 30 },
}
❌ 错误示范:iconName: 'mdi:some-icon'(硬编码字符串绕过了 ICONS 常量,难以统一维护)
设置面板中引用图标也必须使用 ICONS.xxx,新增专属 setting 面板时还需在 SETTING_ICON_META 中注册。
Step 6 — src/common/widget-constants.ts 类型映射
myWidget: import('@/newtab/widgets/myWidget/config').TWidgetConfig
只需追加一行 key-value,不再需要单独的 import 语句。
Step 7 — i18n:src/locales/zh-CN.json 和 en-US.json
"setting": {
"myWidget": "我的组件"
}
可选:添加专属设置面板
自 v2.0.0 起,所有设置面板统一管理在 src/setting/ 目录下。新增专属设置面板步骤:
步骤 1 — 新建面板文件
新建目录 src/setting/panes/myWidget/,并创建 index.vue:
<template>
<SettingFormWrap>
<!-- 在这里使用原子组件(ColorField, FontField, SliderField, etc.)构建表单 -->
<SwitchField
v-model="localConfig.myWidget.enabled"
/>
<ColorField
v-model="localConfig.myWidget.fontColor"
:label="$t('common.color')"
/>
<!-- ... 更多表单项 -->
</SettingFormWrap>
</template>
<script setup lang="ts">
import { SettingFormWrap } from '@/setting/components/SettingFormWrap'
import { SwitchField, ColorField } from '@/setting/fields'
import { localConfig } from '@/logic/config/state'
</script>
所有表单项必须使用 src/setting/fields 中提供的原子组件。
步骤 2 — 注册设置面板
在 src/setting/registry.ts 中注册:
在 SETTING_GROUPS 对应的分组(通常是 widget)的 items 数组添加配置项:
{ code: 'myWidget', labelKey: 'setting.myWidget' },
步骤 3 — 添加设置图标元数据
在 src/logic/constants/icons.ts 的 SETTING_ICON_META 中注册:
export const SETTING_ICON_META: Record<settingPanes, SettingIconMeta> = {
myWidget: { iconName: ICONS.myWidget, settingSize: 20 },
}
所有图标必须通过 ICONS 常量引用,禁止硬编码字符串。
步骤 4 — 建立 Widget 与 Setting Pane 的映射
在 src/common/widget-constants.ts 的 WIDGET_SETTING_PANE_MAP 中添加:
export const WIDGET_SETTING_PANE_MAP: Partial<Record<WidgetCodes, settingPanes>> = {
myWidget: 'myWidget',
}
无需手动修改(自动处理)
| 文件 | 机制 |
|---|
src/logic/config/defaults.ts | import.meta.glob('**/config.ts') 自动扫描收集 |
src/logic/config/state.ts | 遍历 WIDGET_CODE_LIST 动态创建 storage |
src/logic/config/sync/ | 遍历 defaultConfig 处理云同步/导入导出 |
src/newtab/Content.vue | 遍历 widgetsList 动态渲染 |
src/newtab/draft/DraftDrawer.vue | 遍历 widgetsList 展示组件库 |
src/newtab/widgets/registry.ts | import.meta.glob 自动扫描 widget index.ts 元信息 |