From 6537f9fa9b6ce04ce4c7015215a95fe0e93e4ca3 Mon Sep 17 00:00:00 2001 From: Ejirosoft Date: Thu, 25 Jun 2026 13:39:09 +0000 Subject: [PATCH 1/2] feat: add Storybook stories for ConfirmModal, ProgressIndicator, and InsufficientBalanceWarning Adds *.stories.tsx coverage for the remaining UI primitives so every component in src/components/UI/ has a default plus meaningful variants: - ConfirmModal: default, no-description, destructive, and closed states - ProgressIndicator: pending, in-progress, completed, and error states - InsufficientBalanceWarning: testnet, mainnet, and large-shortfall states (wrapped in mocked Wallet/Toast context providers) Also ignores the Storybook build output (storybook-static/). The build-storybook step already runs in .github/workflows/storybook.yml and passes locally via `npm run build-storybook`. --- frontend/.gitignore | 3 ++ .../components/UI/ConfirmModal.stories.tsx | 43 ++++++++++++++++ .../UI/InsufficientBalanceWarning.stories.tsx | 49 ++++++++++++++++++ .../UI/ProgressIndicator.stories.tsx | 51 +++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 frontend/src/components/UI/ConfirmModal.stories.tsx create mode 100644 frontend/src/components/UI/InsufficientBalanceWarning.stories.tsx create mode 100644 frontend/src/components/UI/ProgressIndicator.stories.tsx diff --git a/frontend/.gitignore b/frontend/.gitignore index 68e2ea05..84bb21be 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -2,6 +2,9 @@ dist/ dist-ssr/ +# Storybook build output +storybook-static/ + # Vitest coverage coverage/ diff --git a/frontend/src/components/UI/ConfirmModal.stories.tsx b/frontend/src/components/UI/ConfirmModal.stories.tsx new file mode 100644 index 00000000..2c43485d --- /dev/null +++ b/frontend/src/components/UI/ConfirmModal.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { fn } from '@storybook/test' +import { ConfirmModal } from './ConfirmModal' + +const meta: Meta = { + title: 'UI/ConfirmModal', + component: ConfirmModal, + tags: ['autodocs'], + args: { + isOpen: true, + title: 'Confirm Transaction', + details: [ + { label: 'Amount', value: '100 XLM' }, + { label: 'Recipient', value: 'GABCD…WXYZ' }, + { label: 'Network Fee', value: '0.00001 XLM' }, + ], + onConfirm: fn(), + onCancel: fn(), + }, + parameters: { layout: 'fullscreen' }, +} +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + description: 'Please review the details before confirming.', + }, +} + +export const WithoutDescription: Story = {} + +export const DestructiveAction: Story = { + args: { + title: 'Delete Token', + description: 'This action cannot be undone.', + confirmLabel: 'Delete', + details: [{ label: 'Token', value: 'MTK — My Token' }], + }, +} + +export const Closed: Story = { args: { isOpen: false } } diff --git a/frontend/src/components/UI/InsufficientBalanceWarning.stories.tsx b/frontend/src/components/UI/InsufficientBalanceWarning.stories.tsx new file mode 100644 index 00000000..d38f2350 --- /dev/null +++ b/frontend/src/components/UI/InsufficientBalanceWarning.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { fn } from '@storybook/test' +import { InsufficientBalanceWarning } from './InsufficientBalanceWarning' +import { WalletContext } from '../../context/WalletContext' +import { ToastContext } from '../../context/ToastContext' + +const mockWalletValue = { + wallet: { address: 'GABCDEFGHIJKLMNOPQRSTUVWXYZ234567', isConnected: true, balance: '5.0000000' }, + isConnecting: false, + error: null, + isInstalled: true, + connect: fn(), + disconnect: fn(), + refreshBalance: fn(), +} + +const mockToastValue = { + toasts: [], + addToast: fn(), + removeToast: fn(), +} + +const meta: Meta = { + title: 'UI/InsufficientBalanceWarning', + component: InsufficientBalanceWarning, + tags: ['autodocs'], + decorators: [ + (Story) => ( + + + + + + ), + ], + args: { + shortfall: '0.5000000', + isTestnet: true, + }, +} +export default meta + +type Story = StoryObj + +export const Default: Story = {} + +export const Mainnet: Story = { args: { isTestnet: false } } + +export const LargeShortfall: Story = { args: { shortfall: '125.0000000' } } diff --git a/frontend/src/components/UI/ProgressIndicator.stories.tsx b/frontend/src/components/UI/ProgressIndicator.stories.tsx new file mode 100644 index 00000000..53a6de9a --- /dev/null +++ b/frontend/src/components/UI/ProgressIndicator.stories.tsx @@ -0,0 +1,51 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { ProgressIndicator } from './ProgressIndicator' + +const meta: Meta = { + title: 'UI/ProgressIndicator', + component: ProgressIndicator, + tags: ['autodocs'], +} +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + steps: [ + { label: 'Validate token details', status: 'pending' }, + { label: 'Submit transaction', status: 'pending' }, + { label: 'Confirm on network', status: 'pending' }, + ], + }, +} + +export const InProgress: Story = { + args: { + steps: [ + { label: 'Validate token details', status: 'completed' }, + { label: 'Submit transaction', status: 'in-progress' }, + { label: 'Confirm on network', status: 'pending' }, + ], + }, +} + +export const Completed: Story = { + args: { + steps: [ + { label: 'Validate token details', status: 'completed' }, + { label: 'Submit transaction', status: 'completed' }, + { label: 'Confirm on network', status: 'completed' }, + ], + }, +} + +export const WithError: Story = { + args: { + steps: [ + { label: 'Validate token details', status: 'completed' }, + { label: 'Submit transaction', status: 'error' }, + { label: 'Confirm on network', status: 'pending' }, + ], + }, +} From b7e255f7c51191b05ce2e087f50eec0ab1657287 Mon Sep 17 00:00:00 2001 From: Ejirosoft Date: Thu, 25 Jun 2026 13:47:45 +0000 Subject: [PATCH 2/2] fix: add esbuild as a direct devDependency for Storybook CI build The Storybook CI job installs with `npm install --legacy-peer-deps`, which skips peer dependencies. esbuild was only present as a peer dep, so esbuild-register (used to evaluate .storybook/main.ts) failed with "Cannot find module 'esbuild'" in CI. Declaring esbuild directly ensures it is hoisted to top-level node_modules during the workflow build. --- frontend/package-lock.json | 30 ++---------------------------- frontend/package.json | 1 + 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 3b0fd9ed..3eff148a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -42,6 +42,7 @@ "@vitest/coverage-v8": "^4.1.3", "@vitest/ui": "^4.1.3", "autoprefixer": "^10.4.16", + "esbuild": "^0.28.0", "eslint": "^9.0.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-jsx-a11y": "^6.10.2", @@ -2247,7 +2248,6 @@ "os": [ "aix" ], - "peer": true, "engines": { "node": ">=18" } @@ -2265,7 +2265,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -2283,7 +2282,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -2301,7 +2299,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=18" } @@ -2319,7 +2316,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -2337,7 +2333,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=18" } @@ -2355,7 +2350,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2373,7 +2367,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2391,7 +2384,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2409,7 +2401,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2427,7 +2418,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2445,7 +2435,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2463,7 +2452,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2481,7 +2469,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2499,7 +2486,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2517,7 +2503,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2535,7 +2520,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=18" } @@ -2553,7 +2537,6 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2571,7 +2554,6 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2589,7 +2571,6 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2607,7 +2588,6 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=18" } @@ -2625,7 +2605,6 @@ "os": [ "openharmony" ], - "peer": true, "engines": { "node": ">=18" } @@ -2643,7 +2622,6 @@ "os": [ "sunos" ], - "peer": true, "engines": { "node": ">=18" } @@ -2661,7 +2639,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -2679,7 +2656,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -2697,7 +2673,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=18" } @@ -7720,7 +7695,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -12780,7 +12754,7 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/frontend/package.json b/frontend/package.json index 2bc47e33..8cc24d79 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -61,6 +61,7 @@ "@vitest/coverage-v8": "^4.1.3", "@vitest/ui": "^4.1.3", "autoprefixer": "^10.4.16", + "esbuild": "^0.28.0", "eslint": "^9.0.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-jsx-a11y": "^6.10.2",