diff --git a/AGENTS.md b/AGENTS.md
index 284c8dc6..4fe02350 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -92,6 +92,7 @@ GoodWidget/
- Treat public component names and theme targets as API surface (renaming is a breaking
change for integrators).
- Mirror the issue checklist in the PR body.
+- Render `` (from `@goodwidget/ui`) in every widget; see `docs/widget-author-instructions.md`.
- Preserve existing code comments when refactoring files unless explicitly asked to remove
them.
diff --git a/docs/widget-author-instructions.md b/docs/widget-author-instructions.md
index fdf109aa..60943d8c 100644
--- a/docs/widget-author-instructions.md
+++ b/docs/widget-author-instructions.md
@@ -298,6 +298,24 @@ inline. It becomes hard to review and hard to theme correctly.
---
+## Widget Version Label
+
+Every widget must show its own version, read from the widget package's `package.json`, as a
+small muted label in the bottom-right corner. Render the shared `WidgetVersion` primitive as the
+last child of the widget's root (inside `GoodWidgetProvider`) so it never overlaps content:
+
+```tsx
+import { WidgetVersion } from '@goodwidget/ui'
+import { version } from '../package.json'
+
+
+```
+
+The widget's `tsconfig.json` and `tsconfig.build.json` must use `"rootDir": "."` and include
+`package.json` so the import type-checks.
+
+---
+
## Review Checklist
Before requesting review:
@@ -310,6 +328,7 @@ Before requesting review:
- Light and dark states were checked when the component supports both.
- Mobile width was checked against the design reference.
- Storybook screenshots were refreshed when visual states changed.
+- The widget renders ``.
- Manual visual review was done against Figma/Stitch/reference screenshots.
If a design seems impossible to express through the current system, do not work around it by
diff --git a/packages/ai-credits-widget/src/AiCreditsWidget.tsx b/packages/ai-credits-widget/src/AiCreditsWidget.tsx
index fb46271a..c9b7f6d9 100644
--- a/packages/ai-credits-widget/src/AiCreditsWidget.tsx
+++ b/packages/ai-credits-widget/src/AiCreditsWidget.tsx
@@ -20,6 +20,8 @@ import {
createToast,
updateToast,
} from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { needsWalletConnection, useAiCreditsAdapter } from './adapter'
import { useAiCreditsHistory } from './useAiCreditsHistory'
import {
@@ -649,6 +651,7 @@ export function AiCreditsWidget({
showWalletControls={showWalletControls}
/>
+
)
diff --git a/packages/ai-credits-widget/tsconfig.build.json b/packages/ai-credits-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/ai-credits-widget/tsconfig.build.json
+++ b/packages/ai-credits-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/ai-credits-widget/tsconfig.json b/packages/ai-credits-widget/tsconfig.json
index 006b6f40..5f693f93 100644
--- a/packages/ai-credits-widget/tsconfig.json
+++ b/packages/ai-credits-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -10,5 +10,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/citizen-claim-widget/src/CitizenClaimWidget.tsx b/packages/citizen-claim-widget/src/CitizenClaimWidget.tsx
index ce73257e..89782d65 100644
--- a/packages/citizen-claim-widget/src/CitizenClaimWidget.tsx
+++ b/packages/citizen-claim-widget/src/CitizenClaimWidget.tsx
@@ -20,6 +20,8 @@ import {
YStack,
WidgetTabs,
} from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { SupportedChains } from '@goodsdks/citizen-sdk'
import { getChainDisplayName, useCitizenClaimAdapter } from './adapter'
import type {
@@ -687,6 +689,7 @@ export function CitizenClaimWidget({
onClaimError={onClaimError}
initialTab={initialTab}
/>
+
)
}
diff --git a/packages/citizen-claim-widget/tsconfig.build.json b/packages/citizen-claim-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/citizen-claim-widget/tsconfig.build.json
+++ b/packages/citizen-claim-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/citizen-claim-widget/tsconfig.json b/packages/citizen-claim-widget/tsconfig.json
index 006b6f40..5f693f93 100644
--- a/packages/citizen-claim-widget/tsconfig.json
+++ b/packages/citizen-claim-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -10,5 +10,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/claim-widget-theme-demo/src/ClaimWidget.tsx b/packages/claim-widget-theme-demo/src/ClaimWidget.tsx
index f6db42da..146bcd2f 100644
--- a/packages/claim-widget-theme-demo/src/ClaimWidget.tsx
+++ b/packages/claim-widget-theme-demo/src/ClaimWidget.tsx
@@ -19,6 +19,8 @@ import {
XStack,
YStack,
} from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
const ClaimCard = createComponent(Card, {
name: 'ClaimCard',
@@ -261,6 +263,7 @@ export function ClaimWidget({
defaultTheme={defaultTheme}
>
+
)
}
diff --git a/packages/claim-widget-theme-demo/tsconfig.build.json b/packages/claim-widget-theme-demo/tsconfig.build.json
index c2f740fe..87d73765 100644
--- a/packages/claim-widget-theme-demo/tsconfig.build.json
+++ b/packages/claim-widget-theme-demo/tsconfig.build.json
@@ -2,11 +2,11 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/ui": ["../ui/src/index.ts"],
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/claim-widget-theme-demo/tsconfig.json b/packages/claim-widget-theme-demo/tsconfig.json
index 66f66cf7..5ab7b0d2 100644
--- a/packages/claim-widget-theme-demo/tsconfig.json
+++ b/packages/claim-widget-theme-demo/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -11,5 +11,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/gooddata-widget/src/GoodDataWidget.tsx b/packages/gooddata-widget/src/GoodDataWidget.tsx
index 6c686812..3916fbc1 100644
--- a/packages/gooddata-widget/src/GoodDataWidget.tsx
+++ b/packages/gooddata-widget/src/GoodDataWidget.tsx
@@ -10,7 +10,8 @@
*/
import React from 'react'
import { BrowserRouter, Link, Route, Routes, useParams } from 'react-router-dom'
-import { Heading, Text, YStack } from '@goodwidget/ui'
+import { Heading, Text, WidgetVersion, YStack } from '@goodwidget/ui'
+import { version } from '../package.json'
import { getDashboard, listDashboards } from './dashboards/registry'
const CONTENT_MAX_WIDTH = 1120
@@ -103,6 +104,7 @@ export function GoodDataWidget({ basename }: GoodDataWidgetProps = {}) {
} />
+
)
diff --git a/packages/gooddata-widget/tsconfig.build.json b/packages/gooddata-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/gooddata-widget/tsconfig.build.json
+++ b/packages/gooddata-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/gooddata-widget/tsconfig.json b/packages/gooddata-widget/tsconfig.json
index 1821cb56..bcceced4 100644
--- a/packages/gooddata-widget/tsconfig.json
+++ b/packages/gooddata-widget/tsconfig.json
@@ -2,12 +2,12 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/embed": ["../embed/src/index.ts"],
"@goodwidget/ui": ["../ui/src/index.ts"],
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/goodreserve-widget/src/GoodReserveWidget.tsx b/packages/goodreserve-widget/src/GoodReserveWidget.tsx
index 52368652..748830f4 100644
--- a/packages/goodreserve-widget/src/GoodReserveWidget.tsx
+++ b/packages/goodreserve-widget/src/GoodReserveWidget.tsx
@@ -1,6 +1,8 @@
import React, { useEffect, useRef } from 'react'
import { GoodWidgetProvider } from '@goodwidget/core'
import { YStack } from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import type { EIP1193Provider } from '@goodwidget/core'
import { ReserveSwapView } from './ReserveSwapView'
import { useGoodReserveAdapter } from './useGoodReserveAdapter'
@@ -75,6 +77,7 @@ export function GoodReserveWidget({
mockState={mockState}
preferredChainId={preferredChainId}
/>
+
)
diff --git a/packages/goodreserve-widget/tsconfig.build.json b/packages/goodreserve-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/goodreserve-widget/tsconfig.build.json
+++ b/packages/goodreserve-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/goodreserve-widget/tsconfig.json b/packages/goodreserve-widget/tsconfig.json
index 66f66cf7..5ab7b0d2 100644
--- a/packages/goodreserve-widget/tsconfig.json
+++ b/packages/goodreserve-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -11,5 +11,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/governance-widget/src/GovernanceOnboardingWidget.tsx b/packages/governance-widget/src/GovernanceOnboardingWidget.tsx
index 4439c7a8..fc6a651e 100644
--- a/packages/governance-widget/src/GovernanceOnboardingWidget.tsx
+++ b/packages/governance-widget/src/GovernanceOnboardingWidget.tsx
@@ -1,5 +1,6 @@
import { useMemo } from 'react'
-import { PageWizardProvider } from '@goodwidget/ui'
+import { PageWizardProvider, WidgetVersion } from '@goodwidget/ui'
+import { version } from '../package.json'
import { GovernanceOnboardingFlow } from './onboarding/GovernanceOnboardingFlow'
import { DEFAULT_FINAL_ACTIONS, DEFAULT_TRANSACTION_STEPS, ONBOARDING_STEPS } from './onboarding/constants'
import { HOUSE_COPY } from './onboarding/copy'
@@ -63,6 +64,7 @@ export function GovernanceOnboardingWidget({
onFinalActionPress={onFinalActionPress}
dataTestId={dataTestId}
/>
+
)
}
diff --git a/packages/governance-widget/src/GovernanceWidget.tsx b/packages/governance-widget/src/GovernanceWidget.tsx
index 77318584..8abc6858 100644
--- a/packages/governance-widget/src/GovernanceWidget.tsx
+++ b/packages/governance-widget/src/GovernanceWidget.tsx
@@ -12,6 +12,8 @@ import {
XStack,
YStack,
} from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { useTheme } from 'tamagui'
import { AlignmentVotingProposalCard } from './AlignmentVotingProposalCard'
import { BalanceCard } from './BalanceCard'
@@ -759,6 +761,7 @@ export function GovernanceWidget({
) : (
)}
+
)
}
diff --git a/packages/governance-widget/tsconfig.build.json b/packages/governance-widget/tsconfig.build.json
index 5a24989c..7e89cd4c 100644
--- a/packages/governance-widget/tsconfig.build.json
+++ b/packages/governance-widget/tsconfig.build.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src"
+ "rootDir": "."
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/governance-widget/tsconfig.json b/packages/governance-widget/tsconfig.json
index c2f740fe..87d73765 100644
--- a/packages/governance-widget/tsconfig.json
+++ b/packages/governance-widget/tsconfig.json
@@ -2,11 +2,11 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/ui": ["../ui/src/index.ts"],
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/staking-migration-widget/src/StakingMigrationWidget.tsx b/packages/staking-migration-widget/src/StakingMigrationWidget.tsx
index 55e43e60..dc8600b3 100644
--- a/packages/staking-migration-widget/src/StakingMigrationWidget.tsx
+++ b/packages/staking-migration-widget/src/StakingMigrationWidget.tsx
@@ -2,6 +2,8 @@ import React, { useCallback, useMemo } from 'react'
import { GoodWidgetProvider } from '@goodwidget/core'
import type { EIP1193Provider } from '@goodwidget/core'
import { Text, ToastContainer, YStack } from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { MigrationProgressTimeline } from './MigrationProgressTimeline'
import { MigrationSummaryCard } from './MigrationSummaryCard'
import { MigrationSecondaryCard } from './migrationWidgetComponents'
@@ -155,6 +157,7 @@ export function StakingMigrationWidget({
adapterFactory={adapterFactory}
/>
+
)
}
diff --git a/packages/staking-migration-widget/tsconfig.build.json b/packages/staking-migration-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/staking-migration-widget/tsconfig.build.json
+++ b/packages/staking-migration-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/staking-migration-widget/tsconfig.json b/packages/staking-migration-widget/tsconfig.json
index 006b6f40..5f693f93 100644
--- a/packages/staking-migration-widget/tsconfig.json
+++ b/packages/staking-migration-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -10,5 +10,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/streaming-widget/src/StreamingWidget.tsx b/packages/streaming-widget/src/StreamingWidget.tsx
index fbc25e39..63c13bcf 100644
--- a/packages/streaming-widget/src/StreamingWidget.tsx
+++ b/packages/streaming-widget/src/StreamingWidget.tsx
@@ -2,6 +2,8 @@ import React from 'react'
import { GoodWidgetProvider } from '@goodwidget/core'
import type { EIP1193Provider } from '@goodwidget/core'
import { ToastContainer } from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { useStreamingAdapter } from './adapter'
import { StreamingWidgetView } from './components/StreamingWidgetView'
import type {
@@ -47,6 +49,7 @@ export function StreamingWidgetPreview({
initialStreamsFormOpen={initialStreamsFormOpen}
/>
+
)
}
@@ -68,6 +71,7 @@ export function StreamingWidget({
>
+
)
}
diff --git a/packages/streaming-widget/tsconfig.build.json b/packages/streaming-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/streaming-widget/tsconfig.build.json
+++ b/packages/streaming-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/streaming-widget/tsconfig.json b/packages/streaming-widget/tsconfig.json
index 006b6f40..5f693f93 100644
--- a/packages/streaming-widget/tsconfig.json
+++ b/packages/streaming-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/core/*": ["../core/src/*"],
@@ -10,5 +10,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/superfluid-campaign-widget/src/SuperfluidCampaignWidget.tsx b/packages/superfluid-campaign-widget/src/SuperfluidCampaignWidget.tsx
index 7218b043..8bb42208 100644
--- a/packages/superfluid-campaign-widget/src/SuperfluidCampaignWidget.tsx
+++ b/packages/superfluid-campaign-widget/src/SuperfluidCampaignWidget.tsx
@@ -3,6 +3,8 @@ import { GoodWidgetProvider, useWallet } from '@goodwidget/core'
import type { EIP1193Provider } from '@goodwidget/core'
import { CitizenClaimWidget } from '@goodwidget/citizen-claim-widget'
import { Card, Heading, Text, ToastContainer, YStack } from '@goodwidget/ui'
+import { version } from '../package.json'
+import { WidgetVersion } from '@goodwidget/ui'
import { CampaignHeader } from './components/CampaignHeader'
import { FaqAccordion } from './components/FaqAccordion'
import { LeaderboardSummary } from './components/LeaderboardSummary'
@@ -308,6 +310,7 @@ export function SuperfluidCampaignWidgetWithClient({
/>
+
)
}
diff --git a/packages/superfluid-campaign-widget/tsconfig.build.json b/packages/superfluid-campaign-widget/tsconfig.build.json
index 54871c40..60a46961 100644
--- a/packages/superfluid-campaign-widget/tsconfig.build.json
+++ b/packages/superfluid-campaign-widget/tsconfig.build.json
@@ -2,10 +2,10 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/superfluid-campaign-widget/tsconfig.json b/packages/superfluid-campaign-widget/tsconfig.json
index a720cb71..793b9eca 100644
--- a/packages/superfluid-campaign-widget/tsconfig.json
+++ b/packages/superfluid-campaign-widget/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
- "rootDir": "src",
+ "rootDir": ".",
"paths": {
"@goodwidget/core": ["../core/src/index.ts"],
"@goodwidget/ui": ["../ui/src/index.ts"],
@@ -10,5 +10,5 @@
"react-native": ["./node_modules/react-native-web"]
}
},
- "include": ["src"]
+ "include": ["src", "package.json"]
}
diff --git a/packages/ui/src/components/WidgetVersion.tsx b/packages/ui/src/components/WidgetVersion.tsx
new file mode 100644
index 00000000..e77456e8
--- /dev/null
+++ b/packages/ui/src/components/WidgetVersion.tsx
@@ -0,0 +1,24 @@
+import { YStack } from 'tamagui'
+import { Text } from './Text'
+
+export interface WidgetVersionProps {
+ /** Widget package version, taken from the widget's own package.json. */
+ version: string
+ /** Optional test id override. */
+ testId?: string
+}
+
+/**
+ * Small, muted version label rendered at the bottom-right corner of a widget.
+ * It sits in normal flow below the widget content (right-aligned) so it never
+ * overlaps or shifts the widget layout.
+ */
+export function WidgetVersion({ version, testId = 'widget-version' }: WidgetVersionProps) {
+ return (
+
+
+ {`v${version}`}
+
+
+ )
+}
diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts
index 4d1e88fb..d0671280 100644
--- a/packages/ui/src/index.ts
+++ b/packages/ui/src/index.ts
@@ -44,6 +44,8 @@ export { ScrollArea } from './components-test/ScrollArea'
// Typography
export { Heading } from './components/Heading'
export { Text } from './components/Text'
+export { WidgetVersion } from './components/WidgetVersion'
+export type { WidgetVersionProps } from './components/WidgetVersion'
export { Anchor } from './components/Anchor'
// Inputs
diff --git a/tests/widgets/ai-credits-widget/version.spec.ts b/tests/widgets/ai-credits-widget/version.spec.ts
new file mode 100644
index 00000000..8379a534
--- /dev/null
+++ b/tests/widgets/ai-credits-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/ai-credits-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('AiCreditsWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-aicreditswidget-runtime-fixtures--disconnected&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/citizen-claim-widget/version.spec.ts b/tests/widgets/citizen-claim-widget/version.spec.ts
new file mode 100644
index 00000000..aac6b1f9
--- /dev/null
+++ b/tests/widgets/citizen-claim-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/citizen-claim-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('CitizenClaimWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-citizenclaimwidget-runtime-fixtures--custodial-local-fixture&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/goodreserve-widget/version.spec.ts b/tests/widgets/goodreserve-widget/version.spec.ts
new file mode 100644
index 00000000..43dca4f9
--- /dev/null
+++ b/tests/widgets/goodreserve-widget/version.spec.ts
@@ -0,0 +1,11 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/goodreserve-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('GoodReserveWidget displays its package version', async ({ page }) => {
+ await page.goto('/iframe.html?id=widgets-goodreservewidget--interactive&viewMode=story')
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/governance-widget/version.spec.ts b/tests/widgets/governance-widget/version.spec.ts
new file mode 100644
index 00000000..a0f68e2d
--- /dev/null
+++ b/tests/widgets/governance-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/governance-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('GovernanceWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-governancewidget-runtime-fixtures--disconnected-dashboard&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/staking-migration-widget/version.spec.ts b/tests/widgets/staking-migration-widget/version.spec.ts
new file mode 100644
index 00000000..346f63f2
--- /dev/null
+++ b/tests/widgets/staking-migration-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/staking-migration-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('StakingMigrationWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-stakingmigrationwidget-runtime-fixtures--ready&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/streaming-widget/version.spec.ts b/tests/widgets/streaming-widget/version.spec.ts
new file mode 100644
index 00000000..62f0ea56
--- /dev/null
+++ b/tests/widgets/streaming-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(readFileSync('packages/streaming-widget/package.json', 'utf-8')) as {
+ version: string
+}
+
+test('StreamingWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-streamingwidget-runtime-fixtures--populated-state&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})
diff --git a/tests/widgets/superfluid-campaign-widget/version.spec.ts b/tests/widgets/superfluid-campaign-widget/version.spec.ts
new file mode 100644
index 00000000..77fd7323
--- /dev/null
+++ b/tests/widgets/superfluid-campaign-widget/version.spec.ts
@@ -0,0 +1,13 @@
+import { readFileSync } from 'node:fs'
+import { test, expect } from '@playwright/test'
+
+const { version } = JSON.parse(
+ readFileSync('packages/superfluid-campaign-widget/package.json', 'utf-8'),
+) as { version: string }
+
+test('SuperfluidCampaignWidget displays its package version', async ({ page }) => {
+ await page.goto(
+ '/iframe.html?id=qa-superfluidcampaignwidget-runtime-fixtures--no-wallet-content&viewMode=story',
+ )
+ await expect(page.getByTestId('widget-version')).toHaveText(`v${version}`, { timeout: 20_000 })
+})