From e613b54d9491e009acfd009b7ffbec7821c5f87a Mon Sep 17 00:00:00 2001 From: kairi Date: Mon, 27 Apr 2026 07:01:59 +0900 Subject: [PATCH] feat: add `default_state` option to popup actions (#2010) Co-authored-by: Aaron --- .../src/core/utils/__tests__/manifest.test.ts | 69 +++++++++++++++++++ packages/wxt/src/core/utils/manifest.ts | 3 + packages/wxt/src/types.ts | 6 ++ 3 files changed, 78 insertions(+) diff --git a/packages/wxt/src/core/utils/__tests__/manifest.test.ts b/packages/wxt/src/core/utils/__tests__/manifest.test.ts index 250c8b45..a629f26d 100644 --- a/packages/wxt/src/core/utils/__tests__/manifest.test.ts +++ b/packages/wxt/src/core/utils/__tests__/manifest.test.ts @@ -18,6 +18,7 @@ import { ContentScriptEntrypoint, Entrypoint, OutputAsset, + TargetManifestVersion, } from '../../../types'; import { wxt } from '../../wxt'; import { mock } from 'vitest-mock-extended'; @@ -198,6 +199,74 @@ describe('Manifest Utils', () => { expect((actual.action as any).theme_icons).toEqual(themeIcons); }); + describe('default_state', () => { + it.each<{ + browser: string; + manifestVersion: TargetManifestVersion; + type: 'browser_action' | 'action' | 'page_action'; + shouldExist: boolean; + }>([ + { + browser: 'chrome', + manifestVersion: 2, + type: 'browser_action', + shouldExist: false, + }, + { + browser: 'chrome', + manifestVersion: 3, + type: 'action', + shouldExist: true, + }, + { + browser: 'firefox', + manifestVersion: 2, + type: 'browser_action', + shouldExist: false, + }, + { + browser: 'firefox', + manifestVersion: 3, + type: 'action', + shouldExist: true, + }, + ])( + 'should configure default_state: $defaultState based on the $browser and mv$manifestVersion', + async ({ browser, manifestVersion, type, shouldExist }) => { + const popup = fakePopupEntrypoint({ + options: { + // @ts-expect-error: Force this to be undefined when null + actionType: manifestVersion === 3 ? null : type, + defaultState: 'enabled', + }, + outputDir: outDir, + skipped: false, + }); + const buildOutput = fakeBuildOutput(); + setFakeWxt({ + config: { + browser, + manifestVersion, + outDir, + }, + }); + + const { manifest: actual } = await generateManifest( + [popup], + buildOutput, + ); + + if (shouldExist) { + expect(actual[type]).toMatchObject({ + default_state: 'enabled', + }); + } else { + expect(actual[type].default_state).toBeUndefined(); + } + }, + ); + }); + it('should include default_area for Firefox in mv2', async () => { const popup = fakePopupEntrypoint({ options: { diff --git a/packages/wxt/src/core/utils/manifest.ts b/packages/wxt/src/core/utils/manifest.ts index 134c36c1..a36a164f 100644 --- a/packages/wxt/src/core/utils/manifest.ts +++ b/packages/wxt/src/core/utils/manifest.ts @@ -294,6 +294,9 @@ function addEntrypoints( options.default_icon = popup.options.defaultIcon; if (popup.options.defaultTitle) options.default_title = popup.options.defaultTitle; + if (popup.options.defaultState && wxt.config.manifestVersion === 3) + // @ts-expect-error: Not typed by @wxt-dev/browser, but supported by Chrome + options.default_state = popup.options.defaultState; if (popup.options.browserStyle) // @ts-expect-error: Not typed by @wxt-dev/browser, but supported by Firefox options.browser_style = popup.options.browserStyle; diff --git a/packages/wxt/src/types.ts b/packages/wxt/src/types.ts index 051a2ad6..06282c57 100644 --- a/packages/wxt/src/types.ts +++ b/packages/wxt/src/types.ts @@ -758,6 +758,12 @@ export interface PopupEntrypointOptions extends BaseEntrypointOptions { mv2Key?: PerBrowserOption<'browser_action' | 'page_action'>; defaultIcon?: Record; defaultTitle?: PerBrowserOption; + /** + * Chrome only. Controls the initial enabled/disabled state of the action. + * + * @see https://developer.chrome.com/docs/extensions/reference/api/action#enabled_state + */ + defaultState?: PerBrowserOption<'enabled' | 'disabled'>; browserStyle?: PerBrowserOption; /** * Firefox only. Defines the part of the browser in which the button is