From de7f36b22e524fe76e561253b766d39ef901d527 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 05:21:19 +0100 Subject: [PATCH 01/32] docs: add stories for CopyButton component --- .../src/CopyButton/index.stories.tsx | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 packages/component-library/src/CopyButton/index.stories.tsx diff --git a/packages/component-library/src/CopyButton/index.stories.tsx b/packages/component-library/src/CopyButton/index.stories.tsx new file mode 100644 index 0000000000..a175099d1e --- /dev/null +++ b/packages/component-library/src/CopyButton/index.stories.tsx @@ -0,0 +1,65 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { CopyButton as CopyButtonComponent } from "./index.jsx"; + +const meta = { + component: CopyButtonComponent, + argTypes: { + text: { + control: "text", + description: "The text to copy to clipboard", + table: { + category: "Content", + }, + }, + iconOnly: { + control: "boolean", + description: "Show only the copy icon without text", + table: { + category: "Display", + }, + }, + children: { + control: "text", + description: "Custom button text (defaults to 'Copy')", + table: { + category: "Content", + }, + }, + isDisabled: { + control: "boolean", + table: { + category: "State", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +export const Default = { + args: { + text: "This text will be copied to clipboard", + }, +} satisfies StoryObj; + +export const IconOnly = { + args: { + text: "Icon only copy button", + iconOnly: true, + }, +} satisfies StoryObj; + +export const CodeSnippet = { + args: { + text: "npm install @pythnetwork/component-library", + children: "Copy Command", + }, +} satisfies StoryObj; + +export const Disabled = { + args: { + text: "This cannot be copied", + isDisabled: true, + }, +} satisfies StoryObj; From 7696c78cebfb145c109a8bdfb719795691983466 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 05:51:12 +0100 Subject: [PATCH 02/32] fix: remove horizontal scrollbar from story canvas --- .../component-library/.storybook/preview.tsx | 4 +++- .../.storybook/storybook.module.scss | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/component-library/.storybook/preview.tsx b/packages/component-library/.storybook/preview.tsx index 760f997c96..4061ed7ec0 100644 --- a/packages/component-library/.storybook/preview.tsx +++ b/packages/component-library/.storybook/preview.tsx @@ -76,7 +76,9 @@ export const decorators: Decorator[] = [ "data-background": globals.background, })} > - +
+ +
)} diff --git a/packages/component-library/.storybook/storybook.module.scss b/packages/component-library/.storybook/storybook.module.scss index 4ee4766cc3..ce57052f79 100644 --- a/packages/component-library/.storybook/storybook.module.scss +++ b/packages/component-library/.storybook/storybook.module.scss @@ -7,7 +7,7 @@ body, .contents { height: 100vh; - width: 100vw; + min-width: 100vh; color: theme.color("foreground"); background: theme.color("background", "primary"); display: grid; @@ -19,7 +19,6 @@ body, } &[data-layout="padded"] { - padding: theme.spacing(10); display: block; place-content: unset; } @@ -29,3 +28,19 @@ body, place-content: unset; } } + +.storyWrapper { + padding: theme.spacing(4); + width: 100%; + max-width: min(100%, 1280px); // xl breakpoint + box-sizing: border-box; + + [data-layout="padded"] & { + padding: theme.spacing(10); + } + + [data-layout="fullscreen"] & { + padding: 0; + max-width: none; + } +} From 857cf91500b36a529969f29848e9d57c49bbcaa1 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 05:53:08 +0100 Subject: [PATCH 03/32] docs: add stories for EntityList component --- .../src/EntityList/index.stories.tsx | 233 ++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 packages/component-library/src/EntityList/index.stories.tsx diff --git a/packages/component-library/src/EntityList/index.stories.tsx b/packages/component-library/src/EntityList/index.stories.tsx new file mode 100644 index 0000000000..ab87911c57 --- /dev/null +++ b/packages/component-library/src/EntityList/index.stories.tsx @@ -0,0 +1,233 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { Badge } from "../Badge/index.jsx"; +import { EntityList as EntityListComponent } from "./index.jsx"; + +const meta = { + component: EntityListComponent, + argTypes: { + label: { + control: "text", + description: "Aria label for the list", + table: { + category: "Accessibility", + }, + }, + isLoading: { + control: "boolean", + description: "Show loading state", + table: { + category: "State", + }, + }, + onSelectionChange: { + action: "selectionChanged", + table: { + category: "Events", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +const defaultFields = [ + { id: "name" as const, name: "Name" }, + { id: "status" as const, name: "Status" }, + { id: "price" as const, name: "Price" }, + { id: "change" as const, name: "24h Change" }, +]; + +const sampleRows = [ + { + id: "1", + textValue: "Bitcoin", + data: { + name: "Bitcoin", + status: Active, + price: "$45,234.56", + change: "+2.34%", + }, + }, + { + id: "2", + textValue: "Ethereum", + data: { + name: "Ethereum", + status: Active, + price: "$3,234.56", + change: "-1.23%", + }, + }, + { + id: "3", + textValue: "Solana", + data: { + name: "Solana", + status: Active, + price: "$123.45", + change: "+5.67%", + }, + }, +]; + +export const Default: Story = { + args: { + label: "Cryptocurrency list", + fields: defaultFields, + rows: sampleRows, + isLoading: false, + }, +}; + +export const Loading: Story = { + args: { + label: "Cryptocurrency list", + fields: [ + { id: "name" as const, name: "Name", loadingSkeletonWidth: 80 }, + { id: "status" as const, name: "Status", loadingSkeletonWidth: 60 }, + { id: "price" as const, name: "Price", loadingSkeletonWidth: 100 }, + { id: "change" as const, name: "24h Change", loadingSkeletonWidth: 70 }, + ], + isLoading: true, + }, +}; + +export const WithHeaders: Story = { + args: { + label: "Price feeds", + fields: [ + { id: "symbol" as const, name: "Symbol" }, + { id: "confidence" as const, name: "Confidence" }, + { id: "price" as const, name: "Price" }, + ], + rows: [ + { + id: "btc-usd", + textValue: "BTC/USD", + header:

BTC/USD

, + data: { + symbol: "BTC/USD", + confidence: "±$12.34", + price: "$45,234.56", + }, + }, + { + id: "eth-usd", + textValue: "ETH/USD", + header:

ETH/USD

, + data: { + symbol: "ETH/USD", + confidence: "±$2.34", + price: "$3,234.56", + }, + }, + ], + }, +}; + +export const WithLinks: Story = { + args: { + label: "Blockchain networks", + fields: [ + { id: "network" as const, name: "Network" }, + { id: "chainId" as const, name: "Chain ID" }, + { id: "rpc" as const, name: "RPC" }, + ], + rows: [ + { + id: "ethereum", + textValue: "Ethereum", + href: "#ethereum", + data: { + network: "Ethereum", + chainId: "1", + rpc: "https://eth.example.com", + }, + }, + { + id: "polygon", + textValue: "Polygon", + href: "#polygon", + data: { + network: "Polygon", + chainId: "137", + rpc: "https://polygon.example.com", + }, + }, + ], + }, +}; + +export const SingleRow: Story = { + args: { + label: "Single item list", + fields: [ + { id: "key" as const, name: "Key" }, + { id: "value" as const, name: "Value" }, + ], + rows: [ + { + id: "single", + textValue: "Configuration", + data: { + key: "API_ENDPOINT", + value: "https://api.example.com", + }, + }, + ], + }, +}; + +export const ComplexContent: Story = { + args: { + label: "Complex content list", + fields: [ + { id: "project" as const, name: "Project" }, + { id: "metrics" as const, name: "Metrics" }, + { id: "actions" as const, name: "Actions" }, + ], + rows: [ + { + id: "project-1", + textValue: "Project Alpha", + data: { + project: Project Alpha, + metrics: ( +
+ 10 feeds + 98% uptime +
+ ), + actions: ( +
+ + +
+ ), + }, + }, + { + id: "project-2", + textValue: "Project Beta", + data: { + project: Project Beta, + metrics: ( +
+ 5 feeds + 92% uptime +
+ ), + actions: ( +
+ + +
+ ), + }, + }, + ], + }, +}; \ No newline at end of file From 5fa634f8b14910bd338505e5b42bd31dc7357622 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 05:59:43 +0100 Subject: [PATCH 04/32] docs: add stories for ErrorPage component --- .../src/ErrorPage/index.stories.tsx | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 packages/component-library/src/ErrorPage/index.stories.tsx diff --git a/packages/component-library/src/ErrorPage/index.stories.tsx b/packages/component-library/src/ErrorPage/index.stories.tsx new file mode 100644 index 0000000000..91f00ab6dc --- /dev/null +++ b/packages/component-library/src/ErrorPage/index.stories.tsx @@ -0,0 +1,75 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; + +import { ErrorPage as ErrorPageComponent } from "./index.jsx"; + +const meta = { + component: ErrorPageComponent, + parameters: { + layout: "fullscreen", + }, + argTypes: { + error: { + description: "The error object to display", + table: { + category: "Props", + }, + }, + reset: { + description: "Optional reset function", + table: { + category: "Props", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + error: new Error("Something went wrong while loading the data"), + }, +}; + +export const WithReset: Story = { + args: { + error: new Error("Failed to fetch user profile"), + reset: fn(), + }, +}; + +export const WithDigest: Story = { + args: { + error: Object.assign(new Error("Internal server error"), { + digest: "ERR_500_INTERNAL", + }), + reset: fn(), + }, +}; + +export const NetworkError: Story = { + args: { + error: new Error("NetworkError: Failed to fetch"), + reset: fn(), + }, +}; + +export const ValidationError: Story = { + args: { + error: Object.assign(new Error("Validation failed"), { + digest: "VALIDATION_ERROR_422", + }), + }, +}; + +export const LongErrorMessage: Story = { + args: { + error: new Error( + "Failed to process the request due to an unexpected error in the authentication module. Please check your credentials and try again. If the problem persists, contact support.", + ), + reset: fn(), + }, +}; \ No newline at end of file From 6aa81231721b313b98f30609c52fa56613d9ff70 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 06:03:12 +0100 Subject: [PATCH 05/32] fix: switch from vh to % for preview contents to fix issue with not resizing on control panel height change --- packages/component-library/.storybook/storybook.module.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/component-library/.storybook/storybook.module.scss b/packages/component-library/.storybook/storybook.module.scss index ce57052f79..70d8b2040c 100644 --- a/packages/component-library/.storybook/storybook.module.scss +++ b/packages/component-library/.storybook/storybook.module.scss @@ -6,8 +6,8 @@ body, } .contents { - height: 100vh; - min-width: 100vh; + height: 100%; + min-width: 100%; color: theme.color("foreground"); background: theme.color("background", "primary"); display: grid; From 3d068a38f7220801f31a6ec6202d77cffe230858 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 06:21:05 +0100 Subject: [PATCH 06/32] chore: extract iconControl out into a shared import --- .../component-library/src/Button/index.stories.tsx | 13 +------------ .../component-library/src/Card/index.stories.tsx | 11 ++--------- packages/component-library/src/icon-control.tsx | 12 ++++++++++++ 3 files changed, 15 insertions(+), 21 deletions(-) create mode 100644 packages/component-library/src/icon-control.tsx diff --git a/packages/component-library/src/Button/index.stories.tsx b/packages/component-library/src/Button/index.stories.tsx index 0b33a47187..22dc46b37e 100644 --- a/packages/component-library/src/Button/index.stories.tsx +++ b/packages/component-library/src/Button/index.stories.tsx @@ -1,18 +1,7 @@ -import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { Button as ButtonComponent, VARIANTS, SIZES } from "./index.jsx"; - -const iconControl = { - control: "select", - options: Object.keys(icons), - mapping: Object.fromEntries( - Object.entries(icons).map(([iconName, Icon]) => [ - iconName, - , - ]), - ), -} as const; +import { iconControl } from "../icon-control.jsx"; const meta = { component: ButtonComponent, diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index aac992e9ef..286f421aa1 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -1,7 +1,7 @@ -import * as Icon from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { Card as CardComponent, VARIANTS } from "./index.jsx"; +import { iconControl } from "../icon-control.jsx"; const meta = { component: CardComponent, @@ -44,14 +44,7 @@ const meta = { }, }, icon: { - control: "select", - options: Object.keys(Icon), - mapping: Object.fromEntries( - Object.entries(Icon).map(([key, Icon]) => [ - key, - , - ]), - ), + ...iconControl, table: { category: "Contents", }, diff --git a/packages/component-library/src/icon-control.tsx b/packages/component-library/src/icon-control.tsx new file mode 100644 index 0000000000..ce54eff3a4 --- /dev/null +++ b/packages/component-library/src/icon-control.tsx @@ -0,0 +1,12 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; + +export const iconControl = { + control: "select", + options: Object.keys(icons), + mapping: Object.fromEntries( + Object.entries(icons).map(([iconName, Icon]) => [ + iconName, + , + ]), + ), +} as const; \ No newline at end of file From 35db31d433737932dc7b6983a7030fd7e3776fea Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 06:21:38 +0100 Subject: [PATCH 07/32] docs: add stories for InfoBox component --- .../src/InfoBox/index.stories.module.scss | 7 + .../src/InfoBox/index.stories.tsx | 147 ++++++++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 packages/component-library/src/InfoBox/index.stories.module.scss create mode 100644 packages/component-library/src/InfoBox/index.stories.tsx diff --git a/packages/component-library/src/InfoBox/index.stories.module.scss b/packages/component-library/src/InfoBox/index.stories.module.scss new file mode 100644 index 0000000000..23f471ae6c --- /dev/null +++ b/packages/component-library/src/InfoBox/index.stories.module.scss @@ -0,0 +1,7 @@ +@use "../theme"; + +.variantsList { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} \ No newline at end of file diff --git a/packages/component-library/src/InfoBox/index.stories.tsx b/packages/component-library/src/InfoBox/index.stories.tsx new file mode 100644 index 0000000000..28ff60f9c1 --- /dev/null +++ b/packages/component-library/src/InfoBox/index.stories.tsx @@ -0,0 +1,147 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { InfoBox as InfoBoxComponent, VARIANTS } from "./index.jsx"; +import { iconControl } from "../icon-control.jsx"; +import styles from "./index.stories.module.scss"; + +const meta = { + component: InfoBoxComponent, + argTypes: { + variant: { + control: "select", + options: VARIANTS, + description: "The visual style variant", + table: { + category: "Appearance", + }, + }, + header: { + control: "text", + description: "Custom header text (overrides default)", + table: { + category: "Content", + }, + }, + icon: { + ...iconControl, + description: "Custom icon (overrides default)", + table: { + category: "Content", + }, + }, + children: { + control: "text", + description: "Content to display in the info box", + table: { + category: "Content", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "This is an informational message to help users understand something important.", + }, +}; + +export const AllVariants: Story = { + render: () => ( +
+ + This is a neutral message without any particular emphasis. + + + This is an informational message providing helpful context. + + + This is a warning message alerting users to potential issues. + + + This is an error message indicating something went wrong. + + + This message relates to data or technical information. + + + This is a success message celebrating an achievement! + +
+ ), +}; + +export const CustomHeader: Story = { + args: { + variant: "info", + header: "Did you know?", + children: "You can customize the header text to better suit your content.", + }, +}; + +export const CustomIcon: Story = { + args: { + variant: "info", + icon: , + header: "Pro Tip", + children: "You can also use custom icons to enhance the message.", + }, +}; + +export const LongContent: Story = { + args: { + variant: "warning", + children: ( + <> +

This info box contains multiple paragraphs of content.

+

+ It can handle longer messages that need more detailed explanations, + including lists, links, and other formatted content. +

+
    +
  • First important point
  • +
  • Second important point
  • +
  • Third important point
  • +
+ + ), + }, +}; + +export const ErrorWithInstructions: Story = { + args: { + variant: "error", + header: "Connection Failed", + children: ( + <> + Unable to connect to the server. Please check your internet connection + and try again. If the problem persists, contact{" "} + support. + + ), + }, +}; + +export const SuccessNotification: Story = { + args: { + variant: "success", + header: "Payment Successful!", + children: "Your transaction has been processed successfully. You should receive a confirmation email shortly.", + }, +}; + +export const DataExample: Story = { + args: { + variant: "data", + header: "API Response", + children: ( +
+        {JSON.stringify({ status: "ok", timestamp: 1234567890 }, null, 2)}
+      
+ ), + }, +}; \ No newline at end of file From 30c245bd65faee12329ac4050abe2c861892aef0 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 06:31:48 +0100 Subject: [PATCH 08/32] docs: add stories for Meter component --- .../src/Meter/index.stories.tsx | 199 ++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 packages/component-library/src/Meter/index.stories.tsx diff --git a/packages/component-library/src/Meter/index.stories.tsx b/packages/component-library/src/Meter/index.stories.tsx new file mode 100644 index 0000000000..8abb9516b6 --- /dev/null +++ b/packages/component-library/src/Meter/index.stories.tsx @@ -0,0 +1,199 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { Meter as MeterComponent } from "./index.jsx"; + +const meta = { + component: MeterComponent, + argTypes: { + value: { + control: { type: "range", min: 0, max: 100, step: 1 }, + description: "The current value", + table: { + category: "Value", + }, + }, + minValue: { + control: "number", + description: "The minimum value", + table: { + category: "Value", + }, + }, + maxValue: { + control: "number", + description: "The maximum value", + table: { + category: "Value", + }, + }, + label: { + control: "text", + description: "Aria label for accessibility", + table: { + category: "Accessibility", + }, + }, + startLabel: { + control: "text", + description: "Label shown at the start of the meter", + table: { + category: "Labels", + }, + }, + endLabel: { + control: "text", + description: "Label shown at the end of the meter", + table: { + category: "Labels", + }, + }, + variant: { + control: "radio", + options: ["default", "error"], + description: "Visual variant of the meter", + table: { + category: "Appearance", + }, + }, + labelClassName: { + control: "text", + description: "Class name for the label", + table: { + category: "Labels", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + label: "Progress", + value: 50, + minValue: 0, + maxValue: 100, + }, +}; + +export const WithLabels: Story = { + args: { + label: "Storage usage", + value: 75, + minValue: 0, + maxValue: 100, + startLabel: "0 GB", + endLabel: "100 GB", + }, +}; + +export const ErrorVariant: Story = { + args: { + label: "Critical usage", + value: 95, + minValue: 0, + maxValue: 100, + startLabel: "0%", + endLabel: "100%", + variant: "error", + }, +}; + +export const Empty: Story = { + args: { + label: "No progress", + value: 0, + minValue: 0, + maxValue: 100, + startLabel: "Start", + endLabel: "End", + }, +}; + +export const Full: Story = { + args: { + label: "Complete", + value: 100, + minValue: 0, + maxValue: 100, + startLabel: "0%", + endLabel: "100%", + }, +}; + +export const CustomRange: Story = { + args: { + label: "Temperature", + value: 72, + minValue: 32, + maxValue: 100, + startLabel: "32°F", + endLabel: "100°F", + }, +}; + +export const LoadingProgress: Story = { + args: { + label: "Loading", + value: 33, + minValue: 0, + maxValue: 100, + startLabel: "0 MB", + endLabel: "150 MB", + }, +}; + +export const BatteryLevel: Story = { + args: { + label: "Battery", + value: 20, + minValue: 0, + maxValue: 100, + startLabel: "Empty", + endLabel: "Full", + variant: "error", + }, +}; + +export const PerformanceScore: Story = { + render: () => ( +
+
+

CPU Usage

+ +
+
+

Memory Usage

+ +
+
+

Disk Usage

+ +
+
+ ), +}; \ No newline at end of file From 6e574c252ab7b177cd8c2e143b9dc27578d8f858 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 09:59:50 +0100 Subject: [PATCH 09/32] docs: add stories for NoResults component --- .../src/NoResults/index.stories.tsx | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 packages/component-library/src/NoResults/index.stories.tsx diff --git a/packages/component-library/src/NoResults/index.stories.tsx b/packages/component-library/src/NoResults/index.stories.tsx new file mode 100644 index 0000000000..723c66970d --- /dev/null +++ b/packages/component-library/src/NoResults/index.stories.tsx @@ -0,0 +1,170 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; +import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; + +import { iconControl } from "../icon-control.jsx"; +import { NoResults as NoResultsComponent } from "./index.jsx"; + +const meta = { + component: NoResultsComponent, + parameters: { + layout: "fullscreen", + docs: { + description: { + component: `The NoResults component has two modes: + +1. **Query Mode**: Pass a \`query\` prop to show search-related no results message +2. **Custom Content Mode**: Pass \`icon\`, \`header\`, and \`body\` props together for custom messaging + +You cannot mix props from both modes.`, + }, + }, + }, + argTypes: { + query: { + control: "text", + description: "Search query to display (use this OR custom content props)", + table: { + category: "Query Mode", + type: { summary: "string" }, + }, + }, + icon: { + ...iconControl, + description: "Custom icon to display (requires header and body)", + table: { + category: "Custom Content Mode", + }, + }, + header: { + control: "text", + description: "Custom header text (requires icon and body)", + table: { + category: "Custom Content Mode", + type: { summary: "ReactNode" }, + }, + }, + body: { + control: "text", + description: "Custom body text (requires icon and header)", + table: { + category: "Custom Content Mode", + type: { summary: "ReactNode" }, + }, + }, + variant: { + control: "select", + options: ["success", "error", "warning", "info", "data"], + description: "Visual variant (only applies in custom content mode)", + table: { + category: "Custom Content Mode", + defaultValue: { summary: "info" }, + }, + }, + onClearSearch: { + description: "Callback when clear search button is clicked", + table: { + category: "Common", + }, + }, + className: { + control: "text", + description: "Additional CSS class name", + table: { + category: "Common", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const WithQuery: Story = { + args: { + query: "bitcoin price feed", + onClearSearch: fn(), + }, +}; + +export const EmptyQuery: Story = { + args: { + query: "", + onClearSearch: fn(), + }, +}; + +export const WithoutClearButton: Story = { + args: { + query: "ethereum", + }, +}; + +export const CustomContent: Story = { + args: { + icon: , + header: "No products found", + body: "Try adjusting your filters or search terms to find what you're looking for.", + onClearSearch: fn(), + }, +}; + +export const ErrorVariant: Story = { + args: { + icon: , + header: "Failed to load results", + body: "Something went wrong while fetching your data. Please try again later.", + variant: "error", + }, +}; + +export const SuccessVariant: Story = { + args: { + icon: , + header: "All tasks completed!", + body: "You've finished all your tasks. Take a break or add new ones.", + variant: "success", + }, +}; + +export const WarningVariant: Story = { + args: { + icon: , + header: "No active feeds", + body: "There are currently no active price feeds matching your criteria.", + variant: "warning", + }, +}; + +export const DataVariant: Story = { + args: { + icon: , + header: "No data available", + body: "Historical data for this time period is not available.", + variant: "data", + }, +}; + +export const EmptyInbox: Story = { + args: { + icon: , + header: "Your inbox is empty", + body: "When you receive messages, they'll appear here.", + }, +}; + +export const NoFavorites: Story = { + args: { + icon: , + header: "No favorites yet", + body: "Star your favorite items to quickly access them here.", + }, +}; + +export const LongQuery: Story = { + args: { + query: "This is a very long search query that someone might type when looking for something very specific in the application", + onClearSearch: fn(), + }, +}; \ No newline at end of file From 624fac67e82558f189769024665caae1a56f51fc Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 10:53:42 +0100 Subject: [PATCH 10/32] chore: add @storybook/test dependency for spying on callbacks/actions --- packages/component-library/package.json | 1 + pnpm-lock.yaml | 292 ++++++------------------ pnpm-workspace.yaml | 1 + 3 files changed, 78 insertions(+), 216 deletions(-) diff --git a/packages/component-library/package.json b/packages/component-library/package.json index 5d13271824..2db7729171 100644 --- a/packages/component-library/package.json +++ b/packages/component-library/package.json @@ -68,6 +68,7 @@ "@storybook/blocks": "catalog:", "@storybook/nextjs": "catalog:", "@storybook/react": "catalog:", + "@storybook/test": "catalog:", "@svgr/webpack": "catalog:", "@types/jest": "catalog:", "@types/react": "catalog:", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ff625065c..eb11166331 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -108,6 +108,9 @@ catalogs: '@storybook/react': specifier: ^8.6.12 version: 8.6.12 + '@storybook/test': + specifier: ^8.6.12 + version: 8.6.14 '@svgr/webpack': specifier: ^8.1.0 version: 8.1.0 @@ -1153,7 +1156,7 @@ importers: version: 0.9.36(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)(react-dom@19.1.0(react@19.1.0))(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0) '@solana/wallet-adapter-wallets': specifier: 'catalog:' - version: 0.19.33(@babel/runtime@7.27.0)(@react-native-async-storage/async-storage@1.24.0(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.1.0(react@19.1.0))(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0)(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.2) + version: 0.19.33(@babel/runtime@7.27.0)(@react-native-async-storage/async-storage@1.24.0(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.1.0(react@19.1.0))(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0)(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.2) '@solana/web3.js': specifier: 'catalog:' version: 1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -2010,7 +2013,10 @@ importers: version: 8.6.12(esbuild@0.25.4)(next@15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(babel-plugin-react-compiler@19.1.0-rc.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.86.1))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.86.1)(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))(type-fest@4.39.0)(typescript@5.8.2)(webpack-hot-middleware@2.26.1)(webpack@5.98.0(esbuild@0.25.4)) '@storybook/react': specifier: 'catalog:' - version: 8.6.12(@storybook/test@8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))(typescript@5.8.2) + version: 8.6.12(@storybook/test@8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))(typescript@5.8.2) + '@storybook/test': + specifier: 'catalog:' + version: 8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) '@svgr/webpack': specifier: 'catalog:' version: 8.1.0(typescript@5.8.2) @@ -9937,6 +9943,11 @@ packages: peerDependencies: storybook: ^8.6.12 + '@storybook/instrumenter@8.6.14': + resolution: {integrity: sha512-iG4MlWCcz1L7Yu8AwgsnfVAmMbvyRSk700Mfy2g4c8y5O+Cv1ejshE1LBBsCwHgkuqU0H4R0qu4g23+6UnUemQ==} + peerDependencies: + storybook: ^8.6.14 + '@storybook/manager-api@8.6.12': resolution: {integrity: sha512-O0SpISeJLNTQvhSBOsWzzkCgs8vCjOq1578rwqHlC6jWWm4QmtfdyXqnv7rR1Hk08kQ+Dzqh0uhwHx0nfwy4nQ==} peerDependencies: @@ -10013,6 +10024,11 @@ packages: peerDependencies: storybook: ^8.6.12 + '@storybook/test@8.6.14': + resolution: {integrity: sha512-GkPNBbbZmz+XRdrhMtkxPotCLOQ1BaGNp/gFZYdGDk2KmUWBKmvc5JxxOhtoXM2703IzNFlQHSSNnhrDZYuLlw==} + peerDependencies: + storybook: ^8.6.14 + '@storybook/theming@8.6.12': resolution: {integrity: sha512-6VjZg8HJ2Op7+KV7ihJpYrDnFtd9D1jrQnUS8LckcpuBXrIEbaut5+34ObY8ssQnSqkk2GwIZBBBQYQBCVvkOw==} peerDependencies: @@ -18650,6 +18666,7 @@ packages: path-match@1.2.4: resolution: {integrity: sha512-UWlehEdqu36jmh4h5CWJ7tARp1OEVKGHKm6+dg9qMq5RKUTV5WJrGgaZ3dN2m7WFAXDbjlHzvJvL/IUpy84Ktw==} + deprecated: This package is archived and no longer maintained. For support, visit https://github.com/expressjs/express/discussions path-normalize@6.0.13: resolution: {integrity: sha512-PfC1Pc+IEhI77UEN731pj2nMs9gHAV36IA6IW6VdXWjoQesf+jtO9hdMUqTRS6mwR0T5rmyUrQzd5vw0VwL1Lw==} @@ -25047,7 +25064,7 @@ snapshots: '@babel/template@7.27.0': dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@babel/parser': 7.27.0 '@babel/types': 7.27.1 @@ -25059,7 +25076,7 @@ snapshots: '@babel/traverse@7.27.0': dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@babel/generator': 7.27.0 '@babel/parser': 7.27.0 '@babel/template': 7.27.0 @@ -25071,7 +25088,7 @@ snapshots: '@babel/traverse@7.27.0(supports-color@5.5.0)': dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@babel/generator': 7.27.0 '@babel/parser': 7.27.0 '@babel/template': 7.27.0 @@ -27106,17 +27123,6 @@ snapshots: '@ethersproject/properties': 5.8.0 '@ethersproject/strings': 5.8.0 - '@everstake/wallet-sdk-solana@2.0.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana-program/compute-budget': 0.6.1(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/stake': 0.1.0(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/system': 0.6.2(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - typescript - - ws - '@everstake/wallet-sdk-solana@2.0.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana-program/compute-budget': 0.6.1(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))) @@ -33334,60 +33340,31 @@ snapshots: - react - react-native - '@solana-program/compute-budget@0.6.1(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/compute-budget@0.6.1(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/compute-budget@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/compute-budget@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/stake@0.1.0(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/stake@0.1.0(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.6.2(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.6.2(@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/web3.js': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/system@0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/token-2022@0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))': - dependencies: - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/sysvars': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana-program/token-2022@0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))': dependencies: '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/sysvars': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana-program/token@0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': - dependencies: - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/token@0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -33727,31 +33704,6 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/accounts': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/addresses': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/codecs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/errors': 2.1.0(typescript@5.8.2) - '@solana/functional': 2.1.0(typescript@5.8.2) - '@solana/instructions': 2.1.0(typescript@5.8.2) - '@solana/keys': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/programs': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-parsed-types': 2.1.0(typescript@5.8.2) - '@solana/rpc-spec-types': 2.1.0(typescript@5.8.2) - '@solana/rpc-subscriptions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/signers': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/sysvars': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transaction-confirmation': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/transaction-messages': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transactions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) @@ -33938,15 +33890,6 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@2.0.0(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/errors': 2.0.0(typescript@5.8.2) - '@solana/functional': 2.0.0(typescript@5.8.2) - '@solana/rpc-subscriptions-spec': 2.0.0(typescript@5.8.2) - '@solana/subscribable': 2.0.0(typescript@5.8.2) - typescript: 5.8.2 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@2.0.0(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.0.0(typescript@5.8.2) @@ -33956,15 +33899,6 @@ snapshots: typescript: 5.8.2 ws: 8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@2.1.0(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/errors': 2.1.0(typescript@5.8.2) - '@solana/functional': 2.1.0(typescript@5.8.2) - '@solana/rpc-subscriptions-spec': 2.1.0(typescript@5.8.2) - '@solana/subscribable': 2.1.0(typescript@5.8.2) - typescript: 5.8.2 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) - '@solana/rpc-subscriptions-channel-websocket@2.1.0(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.1.0(typescript@5.8.2) @@ -33990,24 +33924,6 @@ snapshots: '@solana/subscribable': 2.1.0(typescript@5.8.2) typescript: 5.8.2 - '@solana/rpc-subscriptions@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/errors': 2.0.0(typescript@5.8.2) - '@solana/fast-stable-stringify': 2.0.0(typescript@5.8.2) - '@solana/functional': 2.0.0(typescript@5.8.2) - '@solana/promises': 2.0.0(typescript@5.8.2) - '@solana/rpc-spec-types': 2.0.0(typescript@5.8.2) - '@solana/rpc-subscriptions-api': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-subscriptions-channel-websocket': 2.0.0(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-subscriptions-spec': 2.0.0(typescript@5.8.2) - '@solana/rpc-transformers': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-types': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/subscribable': 2.0.0(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/rpc-subscriptions@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.0.0(typescript@5.8.2) @@ -34026,24 +33942,6 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/rpc-subscriptions@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/errors': 2.1.0(typescript@5.8.2) - '@solana/fast-stable-stringify': 2.1.0(typescript@5.8.2) - '@solana/functional': 2.1.0(typescript@5.8.2) - '@solana/promises': 2.1.0(typescript@5.8.2) - '@solana/rpc-spec-types': 2.1.0(typescript@5.8.2) - '@solana/rpc-subscriptions-api': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-subscriptions-channel-websocket': 2.1.0(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-subscriptions-spec': 2.1.0(typescript@5.8.2) - '@solana/rpc-transformers': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-types': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/subscribable': 2.1.0(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/rpc-subscriptions@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.1.0(typescript@5.8.2) @@ -34314,23 +34212,6 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/addresses': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/codecs-strings': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/errors': 2.0.0(typescript@5.8.2) - '@solana/keys': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/promises': 2.0.0(typescript@5.8.2) - '@solana/rpc': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-subscriptions': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transaction-messages': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transactions': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/transaction-confirmation@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) @@ -34348,23 +34229,6 @@ snapshots: - fastestsmallesttextencoderdecoder - ws - '@solana/transaction-confirmation@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/addresses': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/codecs-strings': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/errors': 2.1.0(typescript@5.8.2) - '@solana/keys': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/promises': 2.1.0(typescript@5.8.2) - '@solana/rpc': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-subscriptions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transaction-messages': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transactions': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/transaction-confirmation@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) @@ -34738,11 +34602,11 @@ snapshots: - utf-8-validate - ws - '@solana/wallet-adapter-trezor@0.1.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/wallet-adapter-trezor@0.1.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/wallet-adapter-base': 0.9.24(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/web3.js': 1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@trezor/connect-web': 9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@trezor/connect-web': 9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) buffer: 6.0.3 transitivePeerDependencies: - '@solana/sysvars' @@ -34906,7 +34770,7 @@ snapshots: - ws - zod - '@solana/wallet-adapter-wallets@0.19.33(@babel/runtime@7.27.0)(@react-native-async-storage/async-storage@1.24.0(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.1.0(react@19.1.0))(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0)(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.2)': + '@solana/wallet-adapter-wallets@0.19.33(@babel/runtime@7.27.0)(@react-native-async-storage/async-storage@1.24.0(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bs58@5.0.0)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-dom@19.1.0(react@19.1.0))(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(react@19.1.0)(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod@3.24.2)': dependencies: '@solana/wallet-adapter-alpha': 0.1.11(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-avana': 0.1.14(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) @@ -34939,7 +34803,7 @@ snapshots: '@solana/wallet-adapter-tokenary': 0.1.13(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-tokenpocket': 0.4.20(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-torus': 0.11.29(@babel/runtime@7.27.0)(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@solana/wallet-adapter-trezor': 0.1.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/wallet-adapter-trezor': 0.1.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-trust': 0.1.14(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-unsafe-burner': 0.1.8(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10)) '@solana/wallet-adapter-walletconnect': 0.1.17(@react-native-async-storage/async-storage@1.24.0(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/web3.js@1.98.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2) @@ -35165,31 +35029,6 @@ snapshots: - encoding - utf-8-validate - '@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/accounts': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/addresses': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/codecs': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/errors': 2.0.0(typescript@5.8.2) - '@solana/functional': 2.0.0(typescript@5.8.2) - '@solana/instructions': 2.0.0(typescript@5.8.2) - '@solana/keys': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/programs': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/rpc-parsed-types': 2.0.0(typescript@5.8.2) - '@solana/rpc-spec-types': 2.0.0(typescript@5.8.2) - '@solana/rpc-subscriptions': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/rpc-types': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/signers': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/sysvars': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transaction-confirmation': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/transaction-messages': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - '@solana/transactions': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - ws - '@solana/web3.js@2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2) @@ -35434,6 +35273,12 @@ snapshots: '@vitest/utils': 2.1.9 storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) + '@storybook/instrumenter@8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))': + dependencies: + '@storybook/global': 5.0.0 + '@vitest/utils': 2.1.9 + storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) + '@storybook/manager-api@8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))': dependencies: storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) @@ -35572,6 +35417,21 @@ snapshots: '@storybook/test': 8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) typescript: 5.8.2 + '@storybook/react@8.6.12(@storybook/test@8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))(typescript@5.8.2)': + dependencies: + '@storybook/components': 8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + '@storybook/global': 5.0.0 + '@storybook/manager-api': 8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + '@storybook/preview-api': 8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + '@storybook/react-dom-shim': 8.6.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + '@storybook/theming': 8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) + optionalDependencies: + '@storybook/test': 8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + typescript: 5.8.2 + '@storybook/test@8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))': dependencies: '@storybook/global': 5.0.0 @@ -35583,6 +35443,17 @@ snapshots: '@vitest/spy': 2.0.5 storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) + '@storybook/test@8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/instrumenter': 8.6.14(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3)) + '@testing-library/dom': 10.4.0 + '@testing-library/jest-dom': 6.5.0 + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) + '@vitest/expect': 2.0.5 + '@vitest/spy': 2.0.5 + storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) + '@storybook/theming@8.6.12(storybook@8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3))': dependencies: storybook: 8.6.12(bufferutil@4.0.9)(prettier@3.5.3)(utf-8-validate@6.0.3) @@ -35953,7 +35824,7 @@ snapshots: '@testing-library/dom@10.4.0': dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@babel/runtime': 7.27.0 '@types/aria-query': 5.0.4 aria-query: 5.3.0 @@ -36250,17 +36121,6 @@ snapshots: - expo-localization - react-native - '@trezor/blockchain-link-types@1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': - dependencies: - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@trezor/type-utils': 1.1.5 - '@trezor/utxo-lib': 2.3.3(tslib@2.8.1) - tslib: 2.8.1 - transitivePeerDependencies: - - fastestsmallesttextencoderdecoder - - typescript - - ws - '@trezor/blockchain-link-types@1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) @@ -36323,13 +36183,13 @@ snapshots: - utf-8-validate - ws - '@trezor/blockchain-link@2.4.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@trezor/blockchain-link@2.4.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@everstake/wallet-sdk-solana': 2.0.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/token': 0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token-2022': 0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)) - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@trezor/blockchain-link-types': 1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@everstake/wallet-sdk-solana': 2.0.9(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/token': 0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': 0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)) + '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@trezor/blockchain-link-types': 1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@trezor/blockchain-link-utils': 1.3.3(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) '@trezor/env-utils': 1.3.2(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) '@trezor/utils': 9.3.3(tslib@2.8.1) @@ -36409,9 +36269,9 @@ snapshots: - utf-8-validate - ws - '@trezor/connect-web@9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@trezor/connect-web@9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: - '@trezor/connect': 9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@trezor/connect': 9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@trezor/connect-common': 0.3.3(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) '@trezor/utils': 9.3.3(tslib@2.8.1) tslib: 2.8.1 @@ -36472,7 +36332,7 @@ snapshots: - utf-8-validate - ws - '@trezor/connect@9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@trezor/connect@9.5.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@ethereumjs/common': 4.4.0 '@ethereumjs/tx': 5.4.0 @@ -36480,13 +36340,13 @@ snapshots: '@mobily/ts-belt': 3.13.1 '@noble/hashes': 1.7.1 '@scure/bip39': 1.5.4 - '@solana-program/compute-budget': 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/system': 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token': 0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token-2022': 0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)) - '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@trezor/blockchain-link': 2.4.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@trezor/blockchain-link-types': 1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/compute-budget': 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/system': 0.7.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.5.1(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': 0.4.0(@solana/kit@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)) + '@solana/kit': 2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@trezor/blockchain-link': 2.4.3(@solana/sysvars@2.1.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.2))(bufferutil@4.0.9)(fastestsmallesttextencoderdecoder@1.0.22)(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1)(typescript@5.8.2)(utf-8-validate@5.0.10)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@trezor/blockchain-link-types': 1.3.3(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.8.2)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@trezor/blockchain-link-utils': 1.3.3(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) '@trezor/connect-analytics': 1.3.2(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) '@trezor/connect-common': 0.3.3(react-native@0.78.2(@babel/core@7.27.1)(@babel/preset-env@7.26.9(@babel/core@7.27.1))(@types/react@19.1.0)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10))(tslib@2.8.1) @@ -43681,7 +43541,7 @@ snapshots: fork-ts-checker-webpack-plugin@6.5.3(eslint@9.23.0(jiti@2.4.2))(typescript@4.9.5)(webpack@5.98.0): dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@types/json-schema': 7.0.15 chalk: 4.1.2 chokidar: 3.6.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0705708581..fc1c72ad5c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -81,6 +81,7 @@ catalog: "@storybook/blocks": ^8.6.12 "@storybook/nextjs": ^8.6.12 "@storybook/react": ^8.6.12 + "@storybook/test": "^8.6.12" "@svgr/webpack": ^8.1.0 "@tailwindcss/forms": ^0.5.10 "@tailwindcss/postcss": "^4.1.6" From c10b3caa4f9f464d49feb1d587f1e690e1d60ce3 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 10:54:35 +0100 Subject: [PATCH 11/32] docs: add stories for NotFoundPage component --- .../src/NotFoundPage/index.stories.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 packages/component-library/src/NotFoundPage/index.stories.tsx diff --git a/packages/component-library/src/NotFoundPage/index.stories.tsx b/packages/component-library/src/NotFoundPage/index.stories.tsx new file mode 100644 index 0000000000..713bdafa17 --- /dev/null +++ b/packages/component-library/src/NotFoundPage/index.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { NotFoundPage as NotFoundPageComponent } from "./index.jsx"; + +const meta = { + component: NotFoundPageComponent, + parameters: { + layout: "fullscreen", + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; \ No newline at end of file From 5d242f1bf3115d5ee27a3a69ccb783903a644274 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 10:55:21 +0100 Subject: [PATCH 12/32] docs: add ErrorPage, NoResults, and NotFoundPage as subcomponents of AppShell stories --- .../src/AppShell/index.stories.tsx | 67 +++++++++++++++++-- .../component-library/src/NoResults/index.tsx | 4 +- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/packages/component-library/src/AppShell/index.stories.tsx b/packages/component-library/src/AppShell/index.stories.tsx index bdf1e7f731..862cfa0bae 100644 --- a/packages/component-library/src/AppShell/index.stories.tsx +++ b/packages/component-library/src/AppShell/index.stories.tsx @@ -1,10 +1,26 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { ErrorPage, type Props as ErrorPageProps } from "../ErrorPage/index.jsx"; +import { NetworkError as NetworkErrorStory } from "../ErrorPage/index.stories.jsx"; +import { InfoBox } from "../InfoBox/index.jsx"; +import { NoResults, type Props as NoResultsProps } from "../NoResults/index.jsx"; +import { WarningVariant as WarningVariantStory } from "../NoResults/index.stories.jsx"; +import { NotFoundPage } from "../NotFoundPage/index.jsx"; import { AppBody as AppShellComponent } from "./index.jsx"; const meta = { component: AppShellComponent, + subcomponents: { ErrorPage, NoResults, NotFoundPage }, globals: { + args: { + appName: "Component Library", + children: "Hello world!", + tabs: [ + { children: "Home", segment: "" }, + { children: "Products", segment: "products" }, + { children: "Developers", segment: "developers" }, + ], + }, bare: true, theme: { disable: true, @@ -35,17 +51,54 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; export const AppShell = { args: { - appName: "Component Library", - children: "Hello world!", - tabs: [ - { children: "Home", segment: "" }, - { children: "Foo", segment: "foo" }, - { children: "Bar", segment: "bar" }, - ], + ...meta.globals?.args, }, + render: (args) => ( + + + {args.children} + + + ) } satisfies StoryObj; + +type Story = StoryObj; + +export const ErrorStory: Story = { + args: { + ...meta.globals?.args, + }, + render: (args) => ( + + + + ) +}; + +export const NoResultsStory: Story = { + args: { + ...meta.globals?.args, + }, + render: (args) => ( + + + + ) +}; + +export const NotFoundStory: Story = { + args: { + ...meta.globals?.args, + }, + render: (args) => ( + + + + ) +}; \ No newline at end of file diff --git a/packages/component-library/src/NoResults/index.tsx b/packages/component-library/src/NoResults/index.tsx index 4394a550ea..153692571d 100644 --- a/packages/component-library/src/NoResults/index.tsx +++ b/packages/component-library/src/NoResults/index.tsx @@ -4,10 +4,10 @@ import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass" import clsx from "clsx"; import type { ReactNode } from "react"; -import styles from "./index.module.scss"; import { Button } from "../Button/index.jsx"; +import styles from "./index.module.scss"; -type Props = { +export type Props = { className?: string | undefined; onClearSearch?: (() => void) | undefined; } & ( From 2ebe59ede9a9b13acff88375d12ab82c393eecc1 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:12:20 +0100 Subject: [PATCH 13/32] docs: Add stories for CrossfadeTabPanels component --- .../index.stories.module.scss | 115 ++++++++ .../src/CrossfadeTabPanels/index.stories.tsx | 260 ++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100644 packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss create mode 100644 packages/component-library/src/CrossfadeTabPanels/index.stories.tsx diff --git a/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss b/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss new file mode 100644 index 0000000000..ade719d9a6 --- /dev/null +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss @@ -0,0 +1,115 @@ +@use "../theme"; + +.tabContent { + padding: theme.spacing(8); +} + +.heading { + margin-bottom: theme.spacing(4); +} + +.list { + margin-top: theme.spacing(4); + padding-left: theme.spacing(6); +} + +// Custom styling story +.homePanel { + padding: theme.spacing(8); + background-color: #f0f9ff; + border-radius: theme.border-radius("lg"); + + .heading { + color: #0369a1; + } +} + +.aboutPanel { + padding: theme.spacing(8); + background-color: #f0fdf4; + border-radius: theme.border-radius("lg"); + + .heading { + color: #166534; + } +} + +.contactPanel { + padding: theme.spacing(8); + background-color: #fef3c7; + border-radius: theme.border-radius("lg"); + + .heading { + color: #92400e; + } +} + +// Complex content story +.section { + margin-top: theme.spacing(4); +} + +.grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: theme.spacing(4); + margin-top: theme.spacing(4); +} + +.widget { + padding: theme.spacing(4); + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("base"); +} + +.chartPlaceholder { + padding: theme.spacing(4); + background-color: theme.color("background", "secondary"); + border-radius: theme.border-radius("base"); + margin-bottom: theme.spacing(4); +} + +.chart { + height: 200px; + display: flex; + align-items: center; + justify-content: center; + background-color: theme.color("border"); +} + +// Settings form +.form { + margin-top: theme.spacing(4); +} + +.formField { + margin-bottom: theme.spacing(4); +} + +.label { + display: block; + margin-bottom: theme.spacing(2); +} + +.input, +.select { + padding: theme.spacing(2); + width: 100%; + max-width: 300px; + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("base"); +} + +.button { + padding: theme.spacing(2) theme.spacing(4); + margin-top: theme.spacing(4); + background-color: theme.color("button", "primary", "background", "normal"); + color: theme.color("button", "primary", "foreground"); + border: none; + border-radius: theme.border-radius("base"); + cursor: pointer; + + &:hover { + background-color: theme.color("button", "primary", "background", "hover"); + } +} \ No newline at end of file diff --git a/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx new file mode 100644 index 0000000000..826ed49c04 --- /dev/null +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx @@ -0,0 +1,260 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { CrossfadeTabPanels as CrossfadeTabPanelsComponent } from "./index.jsx"; +import { TabList } from "../TabList/index.jsx"; +import { Tabs } from "../unstyled/Tabs/index.jsx"; +import styles from "./index.stories.module.scss"; + +const meta = { + component: CrossfadeTabPanelsComponent, + parameters: { + docs: { + description: { + component: + "CrossfadeTabPanels provides animated transitions between tab panels using a crossfade effect. It must be used within a Tabs context.", + }, + }, + }, + argTypes: { + items: { + description: "Array of tab panel items with id, optional className, and children", + table: { + category: "Props", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + render: () => ( + + + +

Tab 1 Content

+

This is the content for the first tab.

+ + ), + }, + { + id: "tab2", + children: ( +
+

Tab 2 Content

+

This is the content for the second tab.

+

Notice how it crossfades when switching tabs.

+
+ ), + }, + { + id: "tab3", + children: ( +
+

Tab 3 Content

+

This is the content for the third tab.

+
    +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
+
+ ), + }, + ]} + /> +
+ ), +}; + +export const WithCustomStyling: Story = { + render: () => ( + + + +

Welcome Home

+

This panel has custom styling with a blue theme.

+ + ), + }, + { + id: "about", + children: ( +
+

About Us

+

This panel has custom styling with a green theme.

+
+ ), + }, + { + id: "contact", + children: ( +
+

Contact Us

+

This panel has custom styling with a yellow theme.

+
+ ), + }, + ]} + /> +
+ ), +}; + +export const DifferentHeights: Story = { + render: () => ( + + + +

Short Content

+

Just a single paragraph here.

+ + ), + }, + { + id: "medium", + children: ( +
+

Medium Content

+

This tab has more content than the first one.

+

It includes multiple paragraphs to show how the crossfade handles different heights.

+

The animation should smoothly transition between different content sizes.

+
+ ), + }, + { + id: "long", + children: ( +
+

Long Content

+

This tab contains the most content to demonstrate height transitions.

+

Section 1

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

+

Section 2

+

Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+

Section 3

+

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.

+
+ ), + }, + ]} + /> +
+ ), +}; + +export const ComplexContent: Story = { + render: () => ( + + + +

Dashboard

+
+
+

Widget 1

+

Some dashboard content

+
+
+

Widget 2

+

More dashboard content

+
+
+ + ), + }, + { + id: "analytics", + children: ( +
+

Analytics

+
+
+

Chart Placeholder

+
+ Chart would go here +
+
+

Analytics data and insights would be displayed in this panel.

+
+
+ ), + }, + { + id: "settings", + children: ( +
+

Settings

+
+
+ + +
+
+ + +
+ +
+
+ ), + }, + ]} + /> +
+ ), +}; \ No newline at end of file From fa74d536646d097784b5f59c05a4601ce4509cee Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:18:56 +0100 Subject: [PATCH 14/32] docs: add basic story for dropdown caret --- .../src/DropdownCaretDown/index.stories.tsx | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 packages/component-library/src/DropdownCaretDown/index.stories.tsx diff --git a/packages/component-library/src/DropdownCaretDown/index.stories.tsx b/packages/component-library/src/DropdownCaretDown/index.stories.tsx new file mode 100644 index 0000000000..721161bbb5 --- /dev/null +++ b/packages/component-library/src/DropdownCaretDown/index.stories.tsx @@ -0,0 +1,53 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { DropdownCaretDown as DropdownCaretDownComponent } from "./index.jsx"; + +const meta = { + component: DropdownCaretDownComponent, + argTypes: { + width: { + control: "text", + description: "Width of the icon", + table: { + category: "Dimensions", + defaultValue: { summary: "1em" }, + }, + }, + height: { + control: "text", + description: "Height of the icon", + table: { + category: "Dimensions", + defaultValue: { summary: "1em" }, + }, + }, + className: { + control: "text", + description: "CSS class name", + table: { + category: "Styling", + }, + }, + style: { + control: "object", + description: "Inline styles", + table: { + category: "Styling", + }, + }, + }, + parameters: { + docs: { + description: { + component: + "A dropdown caret icon that points downward. It inherits the current text color and scales with font size using em units.", + }, + }, + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; \ No newline at end of file From 49f83664ae9ff6fba0f3f57cd1e3f1812928447f Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:23:14 +0100 Subject: [PATCH 15/32] docs: add stories for Badge types --- .../src/Badge/index.stories.tsx | 130 +++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-) diff --git a/packages/component-library/src/Badge/index.stories.tsx b/packages/component-library/src/Badge/index.stories.tsx index 65d54edf73..7385cfa1a0 100644 --- a/packages/component-library/src/Badge/index.stories.tsx +++ b/packages/component-library/src/Badge/index.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Badge as BadgeComponent, VARIANTS, SIZES, STYLES } from "./index.jsx"; +import { Badge as BadgeComponent, SIZES, STYLES, VARIANTS } from "./index.jsx"; const meta = { component: BadgeComponent, @@ -33,6 +33,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -44,3 +45,130 @@ export const Badge = { size: "md", }, } satisfies StoryObj; + +type Story = StoryObj; + +const renderAllVariants = (style: typeof STYLES[number], size: typeof SIZES[number], children: React.ReactNode) => ( +
+ {VARIANTS.map((variant) => ( + + {children} + + ))} +
+); + +export const FilledXS: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("filled", "xs", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Extra small filled badges in all variants", + }, + }, + }, +}; + +export const FilledMD: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("filled", "md", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Medium filled badges in all variants", + }, + }, + }, +}; + +export const FilledLG: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("filled", "lg", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Large filled badges in all variants", + }, + }, + }, +}; + +export const OutlineXS: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("outline", "xs", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Extra small outline badges in all variants", + }, + }, + }, +}; + + +export const OutlineMD: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("outline", "md", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Medium outline badges in all variants", + }, + }, + }, +}; + +export const OutlineLG: Story = { + args: { + children: "Badge", + }, + render: ({ children }) => renderAllVariants("outline", "lg", children), + argTypes: { + variant: { table: { disable: true } }, + style: { table: { disable: true } }, + size: { table: { disable: true } }, + }, + parameters: { + docs: { + description: { + story: "Large outline badges in all variants", + }, + }, + }, +}; From 87ea5618424ca75485a0e87743b74a1577914a1c Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:26:44 +0100 Subject: [PATCH 16/32] chore: remove metasyntactic variable names --- packages/component-library/src/Breadcrumbs/index.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/component-library/src/Breadcrumbs/index.stories.tsx b/packages/component-library/src/Breadcrumbs/index.stories.tsx index b0f689eb48..3eba9ce956 100644 --- a/packages/component-library/src/Breadcrumbs/index.stories.tsx +++ b/packages/component-library/src/Breadcrumbs/index.stories.tsx @@ -25,8 +25,8 @@ export const Breadcrumbs = { label: "Breadcrumbs", items: [ { href: "/", label: "Home" }, - { href: "/foo", label: "Foo" }, - { label: "Bar" }, + { href: "#", label: "Products" }, + { label: "Pyth Core" }, ], }, } satisfies StoryObj; From f981f6fe3633311a1686f5637723daba86a1db3a Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:38:57 +0100 Subject: [PATCH 17/32] fix: move inline styles into SCSS modules --- .../src/Badge/index.stories.module.scss | 8 + .../src/Badge/index.stories.tsx | 3 +- .../src/Card/index.stories.module.scss | 58 ++++++ .../src/Card/index.stories.tsx | 169 +++++++++++++++++- 4 files changed, 236 insertions(+), 2 deletions(-) create mode 100644 packages/component-library/src/Badge/index.stories.module.scss create mode 100644 packages/component-library/src/Card/index.stories.module.scss diff --git a/packages/component-library/src/Badge/index.stories.module.scss b/packages/component-library/src/Badge/index.stories.module.scss new file mode 100644 index 0000000000..68dbaa6d30 --- /dev/null +++ b/packages/component-library/src/Badge/index.stories.module.scss @@ -0,0 +1,8 @@ +@use "../theme"; + +.variantsContainer { + display: flex; + gap: theme.spacing(2); + flex-wrap: wrap; + align-items: center; +} \ No newline at end of file diff --git a/packages/component-library/src/Badge/index.stories.tsx b/packages/component-library/src/Badge/index.stories.tsx index 7385cfa1a0..bdaaede160 100644 --- a/packages/component-library/src/Badge/index.stories.tsx +++ b/packages/component-library/src/Badge/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Badge as BadgeComponent, SIZES, STYLES, VARIANTS } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: BadgeComponent, @@ -49,7 +50,7 @@ export const Badge = { type Story = StoryObj; const renderAllVariants = (style: typeof STYLES[number], size: typeof SIZES[number], children: React.ReactNode) => ( -
+
{VARIANTS.map((variant) => ( {children} diff --git a/packages/component-library/src/Card/index.stories.module.scss b/packages/component-library/src/Card/index.stories.module.scss new file mode 100644 index 0000000000..b034506557 --- /dev/null +++ b/packages/component-library/src/Card/index.stories.module.scss @@ -0,0 +1,58 @@ +@use "../theme"; + +// WithFooter story styles +.footerContent { + display: flex; + justify-content: space-between; + align-items: center; +} + +.footerText { + font-size: theme.font-size("sm"); + opacity: 0.7; +} + +.activityList { + margin: 0; + padding-left: theme.spacing(6); +} + +// CompleteExample story styles +.revenueContent { + margin-bottom: theme.spacing(4); +} + +.revenueHeading { + margin: 0 0 theme.spacing(2) 0; + font-size: theme.font-size("4xl"); +} + +.revenueSubtext { + margin: 0; + opacity: 0.7; +} + +.statsGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: theme.spacing(4); +} + +.statLabel { + margin: 0; + font-size: theme.font-size("sm"); + opacity: 0.7; +} + +.statValue { + margin: 0; + font-size: theme.font-size("xl"); + font-weight: theme.font-weight("semibold"); +} + +// AllVariants story styles +.variantsContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} \ No newline at end of file diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index 286f421aa1..2c18789c0e 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -1,7 +1,11 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; -import { Card as CardComponent, VARIANTS } from "./index.jsx"; +import { Badge } from "../Badge/index.jsx"; +import { Button } from "../Button/index.jsx"; import { iconControl } from "../icon-control.jsx"; +import { Card as CardComponent, VARIANTS } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: CardComponent, @@ -62,6 +66,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -74,3 +79,165 @@ export const Card = { footer: "", }, } satisfies StoryObj; + +type Story = StoryObj; + +export const BasicCard: Story = { + args: { + children: ( +

+ This is a basic card with just content. It can contain any React elements + and will display them with appropriate styling. +

+ ), + variant: "secondary", + }, +}; + +export const WithTitleAndIcon: Story = { + args: { + icon: , + title: "Product Details", + children: ( +
+

This card has a title and an icon in the header.

+

Icons help users quickly identify the card's purpose.

+
+ ), + variant: "secondary", + }, +}; + +export const WithToolbar: Story = { + args: { + title: "User Statistics", + toolbar: ( + <> + + + + ), + children: ( +
+

Total Users: 1,234

+

Active Today: 567

+

New This Week: 89

+
+ ), + variant: "secondary", + }, +}; + +export const WithFooter: Story = { + args: { + title: "Latest Activity", + children: ( +
    +
  • User login at 10:30 AM
  • +
  • Data sync completed at 10:15 AM
  • +
  • Backup finished at 9:45 AM
  • +
+ ), + footer: ( +
+ + Last updated 5 minutes ago + + +
+ ), + variant: "secondary", + }, +}; + +export const AsLink: Story = { + args: { + href: "#", + icon: , + title: "Clickable Card", + children: ( +

+ This entire card is clickable and will navigate to the specified URL. + Hover over it to see the interactive state. +

+ ), + variant: "secondary", + }, +}; + +export const AsButton: Story = { + args: { + onPress: () => alert("Card clicked!"), + icon: , + title: "Interactive Card", + children: ( +

+ This card acts as a button. Click anywhere on it to trigger an action. +

+ ), + variant: "secondary", + }, +}; + +export const CompleteExample: Story = { + args: { + icon: , + title: "Revenue Dashboard", + toolbar: ( + <> + Live + + + ), + children: ( +
+
+

$45,234

+

Total Revenue This Month

+
+
+
+

Orders

+

152

+
+
+

Avg. Value

+

$297.59

+
+
+
+ ), + footer: ( + + ), + variant: "primary", + }, +}; + +export const AllVariants: Story = { + render: () => ( +
+ {VARIANTS.map((variant) => ( + } + > +

This is a {variant} variant card.

+
+ ))} +
+ ), +}; From 9ef2c447fbed9387b84d57f2c619c0ce53d9c2f0 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 11:42:41 +0100 Subject: [PATCH 18/32] fix: change invalid Button props --- packages/component-library/src/Card/index.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index 2c18789c0e..4689c7efe2 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -148,7 +148,7 @@ export const WithFooter: Story = { Last updated 5 minutes ago -
@@ -217,7 +217,7 @@ export const CompleteExample: Story = {
), footer: ( - ), From 933088192b209a70577c51b5d5aeea85c3baa602 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 12:02:20 +0100 Subject: [PATCH 19/32] docs: add additional stories for Header component --- .../src/Header/index.stories.tsx | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/packages/component-library/src/Header/index.stories.tsx b/packages/component-library/src/Header/index.stories.tsx index d44702fea0..b5b059dd8d 100644 --- a/packages/component-library/src/Header/index.stories.tsx +++ b/packages/component-library/src/Header/index.stories.tsx @@ -1,6 +1,10 @@ import type { Meta, StoryObj } from "@storybook/react"; import { ThemeProvider } from "next-themes"; +import { TabRoot } from "../AppShell/tabs.jsx"; +import { Badge } from "../Badge/index.jsx"; +import { Button } from "../Button/index.jsx"; +import { MainNavTabs } from "../MainNavTabs/index.jsx"; import { Header as HeaderComponent } from "./index.jsx"; const meta = { @@ -26,6 +30,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -34,3 +39,111 @@ export const Header = { appName: "Component Library", }, } satisfies StoryObj; + +type Story = StoryObj; + +export const Default: Story = { + args: { + appName: "Price Feeds", + }, +}; + +export const WithCustomCTA: Story = { + args: { + appName: "Benchmarks", + mainCta: { + label: "Get Started", + href: "https://pyth.network", + }, + }, +}; + +export const WithMainMenu: Story = { + args: { + appName: "Developer Hub", + }, + decorators: [ + (Story) => ( + + + + ), + ], + render: (args) => ( + + } + /> + ), +}; + +export const WithExtraCTA: Story = { + args: { + appName: "Pyth Network", + extraCta: ( + <> + Beta + + + ), + }, +}; + +export const CompleteExample: Story = { + args: { + appName: "Oracle Dashboard", + mainCta: { + label: "Documentation", + href: "https://docs.pyth.network", + }, + }, + decorators: [ + (Story) => ( + + + + ), + ], + render: (args) => ( + + } + extraCta={ + <> + Live + + + } + /> + ), +}; + +export const MinimalHeader: Story = { + args: { + appName: "Pyth App", + mainCta: undefined, + mainMenu: undefined, + extraCta: undefined, + }, +}; From feca397a0d70271ffd6809ce8f7ce74d5e3727de Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 12:02:46 +0100 Subject: [PATCH 20/32] docs: add autodocs for Link component --- packages/component-library/src/Link/index.stories.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/component-library/src/Link/index.stories.tsx b/packages/component-library/src/Link/index.stories.tsx index 75da4732ee..1e186b0b6b 100644 --- a/packages/component-library/src/Link/index.stories.tsx +++ b/packages/component-library/src/Link/index.stories.tsx @@ -24,6 +24,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; From 20ff158cfafede792d6e926cb6d82ef76a2bdc63 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 12:04:37 +0100 Subject: [PATCH 21/32] chore: remove metasyntactic variable names --- .../component-library/src/MainNavTabs/index.stories.tsx | 6 +++--- .../component-library/src/MobileNavTabs/index.stories.tsx | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/component-library/src/MainNavTabs/index.stories.tsx b/packages/component-library/src/MainNavTabs/index.stories.tsx index 749b5b2ff1..64bc704836 100644 --- a/packages/component-library/src/MainNavTabs/index.stories.tsx +++ b/packages/component-library/src/MainNavTabs/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { MainNavTabs as MainNavTabsComponent } from "./index.jsx"; import { Tabs } from "../unstyled/Tabs/index.jsx"; +import { MainNavTabs as MainNavTabsComponent } from "./index.jsx"; const meta = { component: MainNavTabsComponent, @@ -26,8 +26,8 @@ export const MainNavTabs = { args: { tabs: [ { children: "Home", segment: "" }, - { children: "Foo", segment: "foo" }, - { children: "Bar", segment: "bar" }, + { children: "Products", segment: "products" }, + { children: "Developers", segment: "developers" }, ], }, } satisfies StoryObj; diff --git a/packages/component-library/src/MobileNavTabs/index.stories.tsx b/packages/component-library/src/MobileNavTabs/index.stories.tsx index 34ee9234c2..60d1d96203 100644 --- a/packages/component-library/src/MobileNavTabs/index.stories.tsx +++ b/packages/component-library/src/MobileNavTabs/index.stories.tsx @@ -21,8 +21,8 @@ export const MobileNavTabs = { args: { tabs: [ { children: "Home", segment: "" }, - { children: "Foo", segment: "foo" }, - { children: "Bar", segment: "bar" }, + { children: "Products", segment: "products" }, + { children: "Developers", segment: "developers" }, ], }, } satisfies StoryObj; From d52f029c7c9720b58bef6127550a6595f517065d Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 12:10:39 +0100 Subject: [PATCH 22/32] docs: add stories to SearchInput component --- .../src/SearchInput/index.stories.module.scss | 14 ++ .../src/SearchInput/index.stories.tsx | 151 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 packages/component-library/src/SearchInput/index.stories.module.scss diff --git a/packages/component-library/src/SearchInput/index.stories.module.scss b/packages/component-library/src/SearchInput/index.stories.module.scss new file mode 100644 index 0000000000..793b5ef1ae --- /dev/null +++ b/packages/component-library/src/SearchInput/index.stories.module.scss @@ -0,0 +1,14 @@ +@use "../theme"; + +.controlledContainer { + > p { + margin-top: theme.spacing(4); + } +} + +.sizesContainer, +.statesContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} \ No newline at end of file diff --git a/packages/component-library/src/SearchInput/index.stories.tsx b/packages/component-library/src/SearchInput/index.stories.tsx index 3e9e9ff615..342eaf9bed 100644 --- a/packages/component-library/src/SearchInput/index.stories.tsx +++ b/packages/component-library/src/SearchInput/index.stories.tsx @@ -1,6 +1,9 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; +import { useState } from "react"; import { SearchInput as SearchInputComponent, SIZES } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: SearchInputComponent, @@ -35,7 +38,32 @@ const meta = { category: "State", }, }, + placeholder: { + control: "text", + table: { + category: "Content", + }, + }, + defaultValue: { + control: "text", + table: { + category: "Content", + }, + }, + onSubmit: { + action: "submitted", + table: { + category: "Events", + }, + }, + onChange: { + action: "changed", + table: { + category: "Events", + }, + }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -47,3 +75,126 @@ export const SearchInput = { isDisabled: false, }, } satisfies StoryObj; + +type Story = StoryObj; + +// Size variations +export const ExtraSmall: Story = { + args: { + size: "xs", + placeholder: "Search...", + }, +}; + +export const Small: Story = { + args: { + size: "sm", + placeholder: "Search...", + }, +}; + +export const Medium: Story = { + args: { + size: "md", + placeholder: "Search...", + }, +}; + +export const Large: Story = { + args: { + size: "lg", + placeholder: "Search...", + }, +}; + +// State variations +export const WithValue: Story = { + args: { + size: "md", + defaultValue: "pyth network", + }, +}; + +export const Pending: Story = { + args: { + size: "md", + isPending: true, + defaultValue: "searching...", + }, +}; + +export const Disabled: Story = { + args: { + size: "md", + isDisabled: true, + placeholder: "Search disabled", + }, +}; + +// Width variations +export const FixedWidth: Story = { + args: { + size: "md", + width: 100, + placeholder: "Fixed width", + }, +}; + +export const FluidWidth: Story = { + args: { + size: "md", + placeholder: "Fluid width (default)", + }, +}; + +// Functional examples +export const WithSubmitHandler: Story = { + args: { + size: "md", + placeholder: "Press Enter to search", + onSubmit: fn(), + }, +}; + +export const ControlledInput: Story = { + render: () => { + const [value, setValue] = useState(""); + + return ( +
+ alert(`Searching for: ${value}`)} + placeholder="Controlled search input" + /> +

Current value: {value}

+
+ ); + }, +}; + +export const AllSizes: Story = { + render: () => ( +
+ {SIZES.map((size) => ( + + ))} +
+ ), +}; + +export const AllStates: Story = { + render: () => ( +
+ + + + +
+ ), +}; From b19e10d81a55bd856a6d7ebb485035ca08638832 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 13:26:27 +0100 Subject: [PATCH 23/32] docs: add stories to Select component --- .../src/Select/index.stories.module.scss | 78 ++++ .../src/Select/index.stories.tsx | 431 ++++++++++++++++-- 2 files changed, 476 insertions(+), 33 deletions(-) create mode 100644 packages/component-library/src/Select/index.stories.module.scss diff --git a/packages/component-library/src/Select/index.stories.module.scss b/packages/component-library/src/Select/index.stories.module.scss new file mode 100644 index 0000000000..4c580964d4 --- /dev/null +++ b/packages/component-library/src/Select/index.stories.module.scss @@ -0,0 +1,78 @@ +@use "../theme"; + +.storiesContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(8); +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: theme.spacing(4); + align-items: start; +} + +.row { + display: flex; + align-items: center; + gap: theme.spacing(4); + + > label { + min-width: 80px; + font-size: theme.font-size("xs"); + } +} + +.placementGrid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: theme.spacing(8); + align-items: center; + justify-items: center; + min-height: 300px; +} + +.controlledContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + + > p { + font-size: theme.font-size("xs"); + } +} + +.iconsGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: theme.spacing(4); +} + +.iconLabel { + display: flex; + align-items: center; + gap: theme.spacing(2); +} + +.statusIndicator { + width: 8px; + height: 8px; + border-radius: 50%; + + &[data-status="active"] { + background-color: #10b981; + } + + &[data-status="inactive"] { + background-color: #ef4444; + } + + &[data-status="pending"] { + background-color: #f59e0b; + } + + &[data-status="archived"] { + background-color: #6b7280; + } +} \ No newline at end of file diff --git a/packages/component-library/src/Select/index.stories.tsx b/packages/component-library/src/Select/index.stories.tsx index f151f2cdae..1ac09fe327 100644 --- a/packages/component-library/src/Select/index.stories.tsx +++ b/packages/component-library/src/Select/index.stories.tsx @@ -1,7 +1,11 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; -import { Select as SelectComponent } from "./index.jsx"; +import { SIZES, VARIANTS } from "../Button/index.jsx"; import buttonMeta from "../Button/index.stories.jsx"; +import { Select as SelectComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const { children, beforeIcon, ...argTypes } = buttonMeta.argTypes; @@ -84,55 +88,416 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const Flat = { +type Story = StoryObj; + +export const Default: Story = { args: { - defaultSelectedKey: "foo", - options: ["foo", "bar", "baz"].map((id) => ({ id })), + defaultSelectedKey: "option1", + options: [ + { id: "option1" }, + { id: "option2" }, + { id: "option3" }, + ], variant: "primary", size: "md", - isDisabled: false, - isPending: false, - rounded: false, - hideText: false, - show: (value) => `The option ${value.id.toString()}`, - label: "A SELECT!", hideLabel: true, - buttonLabel: "", }, -} satisfies StoryObj; +}; -export const Grouped = { - argTypes: { - hideGroupLabel: { - control: "boolean", - table: { - category: "Contents", - }, +export const BasicSelect: Story = { + args: { + defaultSelectedKey: "apple", + options: [ + { id: "apple" }, + { id: "banana" }, + { id: "orange" }, + { id: "grape" }, + { id: "strawberry" }, + ], + hideLabel: true, + variant: "primary", + size: "md", + }, +}; + +export const WithCustomDisplay: Story = { + args: { + defaultSelectedKey: "us", + options: [ + { id: "us" }, + { id: "uk" }, + { id: "de" }, + { id: "fr" }, + { id: "jp" }, + ], + show: (value) => { + const countryNames = { + us: "🇺🇸 United States", + uk: "🇬🇧 United Kingdom", + de: "🇩🇪 Germany", + fr: "🇫🇷 France", + jp: "🇯🇵 Japan", + }; + return countryNames[value.id as keyof typeof countryNames] || value.id; }, + hideLabel: true, + variant: "secondary", + size: "md", + }, +}; + +export const WithIcon: Story = { + args: { + defaultSelectedKey: "payment", + options: [ + { id: "payment" }, + { id: "shipping" }, + { id: "tracking" }, + { id: "returns" }, + ], + show: (value) => { + const optionLabels = { + payment: "Payment Methods", + shipping: "Shipping Options", + tracking: "Order Tracking", + returns: "Returns & Refunds", + }; + return optionLabels[value.id as keyof typeof optionLabels] || value.id; + }, + icon: , + hideLabel: true, + variant: "outline", + size: "md", }, +}; + +export const Grouped: Story = { args: { - defaultSelectedKey: "foo1", + defaultSelectedKey: "react", optionGroups: [ - { name: "All", options: ["foo1", "foo2", "Some"].map((id) => ({ id })) }, - { name: "bars", options: ["bar1", "bar2", "bar3"].map((id) => ({ id })) }, { - name: "bazzes", - options: ["baz1", "baz2", "baz3"].map((id) => ({ id })), + name: "Frontend Frameworks", + options: [ + { id: "react" }, + { id: "vue" }, + { id: "angular" }, + { id: "svelte" }, + ], + }, + { + name: "Backend Frameworks", + options: [ + { id: "express" }, + { id: "django" }, + { id: "rails" }, + { id: "laravel" }, + ], + }, + { + name: "Mobile Frameworks", + options: [ + { id: "react-native" }, + { id: "flutter" }, + { id: "ionic" }, + ], }, ], + hideLabel: true, variant: "primary", size: "md", - isDisabled: false, - isPending: false, - rounded: false, - hideText: false, - show: (value) => `The option ${value.id.toString()}`, - label: "FOOS AND BARS", - hideLabel: true, + }, +}; + +export const GroupedWithHiddenLabels: Story = { + args: { + defaultSelectedKey: "admin", + optionGroups: [ + { + name: "User Roles", + options: [ + { id: "admin" }, + { id: "editor" }, + { id: "viewer" }, + ], + }, + { + name: "System Roles", + options: [ + { id: "super-admin" }, + { id: "moderator" }, + ], + }, + ], + show: (value) => { + const roleNames = { + admin: "Administrator", + editor: "Editor", + viewer: "Viewer", + "super-admin": "Super Administrator", + moderator: "Moderator", + }; + return roleNames[value.id as keyof typeof roleNames] || value.id; + }, hideGroupLabel: true, - buttonLabel: "", + hideLabel: true, + variant: "secondary", + size: "md", + }, +}; + +export const AllSizes: Story = { + render: () => ( +
+ {SIZES.map((size) => ( +
+ + +
+ ))} +
+ ), +}; + +export const AllVariants: Story = { + render: () => ( +
+ {VARIANTS.map((variant) => ( +
+ + +
+ ))} +
+ ), +}; + +export const States: Story = { + render: () => { + const states = [ + { key: "normal", label: "NORMAL", props: {} }, + { key: "disabled", label: "DISABLED", props: { isDisabled: true } }, + { key: "pending", label: "PENDING", props: { isPending: true } }, + { key: "rounded", label: "ROUNDED", props: { rounded: true } }, + ]; + + return ( +
+ {states.map((state) => ( +
+ + +
+ ))} +
+ ); }, -} satisfies StoryObj; +}; + +export const ControlledExample: Story = { + render: () => { + const [selected, setSelected] = useState("apple"); + const fruits = [ + { id: "apple", name: "Apple", emoji: "🍎" }, + { id: "banana", name: "Banana", emoji: "🍌" }, + { id: "orange", name: "Orange", emoji: "🍊" }, + { id: "grape", name: "Grape", emoji: "🍇" }, + ]; + + return ( +
+ `${value.emoji} ${value.name}`} + label="Favorite fruit" + hideLabel={true} + variant="primary" + size="md" + /> +

You selected: {fruits.find(f => f.id === selected)?.name}

+
+ ); + }, +}; + +export const WithButtonLabel: Story = { + args: { + defaultSelectedKey: "en", + options: [ + { id: "en" }, + { id: "es" }, + { id: "fr" }, + { id: "de" }, + ], + show: (value) => { + const languages = { + en: "English", + es: "Español", + fr: "Français", + de: "Deutsch", + }; + return languages[value.id as keyof typeof languages] || value.id; + }, + buttonLabel: "Language", + label: "Select language", + hideLabel: true, + variant: "ghost", + size: "sm", + }, +}; + +export const WithDefaultButtonLabel: Story = { + args: { + options: [ + { id: "small" }, + { id: "medium" }, + { id: "large" }, + ], + defaultButtonLabel: "Select size...", + label: "Product size", + hideLabel: false, + variant: "outline", + size: "md", + }, +}; + +export const PopoverPlacements: Story = { + render: () => ( +
+ + + +
+ ), +}; + +export const WithIconsAndCustomContent: Story = { + render: () => ( +
+ { + const items = { + dashboard: { icon: , label: "Dashboard" }, + analytics: { icon: , label: "Analytics" }, + reports: { icon: , label: "Reports" }, + settings: { icon: , label: "Settings" }, + }; + const item = items[value.id as keyof typeof items]; + return ( + + {item.icon} + {item.label} + + ); + }} + icon={} + label="Navigation" + hideLabel={true} + variant="primary" + size="md" + /> + { + const statuses = { + active: "Active", + inactive: "Inactive", + pending: "Pending", + archived: "Archived", + }; + const label = statuses[value.id as keyof typeof statuses]; + return ( + + + {label} + + ); + }} + label="Status filter" + hideLabel={true} + variant="outline" + size="md" + /> +
+ ), +}; From 206a4e9a20da848e89d19df7133284f47782a909 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 15:38:22 +0100 Subject: [PATCH 24/32] docs: add stories for SingleToggleGroup --- .../index.stories.module.scss | 76 ++++ .../src/SingleToggleGroup/index.stories.tsx | 339 +++++++++++++++++- 2 files changed, 411 insertions(+), 4 deletions(-) create mode 100644 packages/component-library/src/SingleToggleGroup/index.stories.module.scss diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.module.scss b/packages/component-library/src/SingleToggleGroup/index.stories.module.scss new file mode 100644 index 0000000000..6e6407bb39 --- /dev/null +++ b/packages/component-library/src/SingleToggleGroup/index.stories.module.scss @@ -0,0 +1,76 @@ +@use "../theme"; + +.iconButton { + display: flex; + align-items: center; + gap: theme.spacing(2); +} + +.controlledContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + + > p { + font-size: theme.font-size("sm"); + color: theme.color("paragraph"); + } +} + +.pricingContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + + > h3 { + margin: 0; + font-size: theme.font-size("lg"); + font-weight: 600; + color: theme.color("heading"); + } +} + +.pricingDetails { + padding: theme.spacing(4); + background-color: theme.color("background", "secondary"); + border-radius: theme.border-radius("md"); + border: 1px solid theme.color("border"); + + > p { + margin: 0; + font-size: theme.font-size("sm"); + color: theme.color("paragraph"); + } +} + +.filterContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + + > p { + font-size: theme.font-size("sm"); + color: theme.color("paragraph"); + } +} + +.statusOption { + display: flex; + align-items: center; + gap: theme.spacing(2); +} + +.count { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 20px; + height: 20px; + padding: 0 theme.spacing(2); + background-color: theme.color("background", "secondary"); + color: theme.color("muted"); + border-radius: theme.border-radius("full"); + font-size: theme.font-size("xs"); + font-weight: 500; + line-height: 1; +} \ No newline at end of file diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.tsx b/packages/component-library/src/SingleToggleGroup/index.stories.tsx index e08b7fef9a..8a38c4db0f 100644 --- a/packages/component-library/src/SingleToggleGroup/index.stories.tsx +++ b/packages/component-library/src/SingleToggleGroup/index.stories.tsx @@ -1,6 +1,9 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; import { SingleToggleGroup as SingleToggleGroupComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: SingleToggleGroupComponent, @@ -15,15 +18,343 @@ const meta = { category: "Behavior", }, }, + selectedKey: { + table: { + category: "Selection", + }, + }, + defaultSelectedKeys: { + table: { + category: "Selection", + }, + }, + isDisabled: { + control: "boolean", + table: { + category: "State", + }, + }, + orientation: { + control: "inline-radio", + options: ["horizontal", "vertical"], + table: { + category: "Layout", + }, + }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const SingleToggleGroup = { +type Story = StoryObj; + +export const Default: Story = { + args: { + items: [ + { id: "btc", children: "BTC" }, + { id: "sol", children: "SOL" }, + { id: "eth", children: "ETH" }, + ], + defaultSelectedKeys: ["btc"], + }, +}; + +export const BasicCryptocurrencies: Story = { + args: { + items: [ + { id: "bitcoin", children: "Bitcoin" }, + { id: "solana", children: "Solana" }, + { id: "ethereum", children: "Ethereum" }, + { id: "avalanche", children: "Avalanche" }, + ], + defaultSelectedKeys: ["bitcoin"], + }, +}; + +export const ViewToggle: Story = { + args: { + items: [ + { id: "grid", children: "Grid", "aria-label": "Grid view" }, + { id: "list", children: "List", "aria-label": "List view" }, + { id: "card", children: "Card", "aria-label": "Card view" }, + ], + defaultSelectedKeys: ["grid"], + }, +}; + +export const WithIcons: Story = { + args: { + items: [ + { + id: "grid", + children: ( + + + Grid + + ), + "aria-label": "Grid view" + }, + { + id: "list", + children: ( + + + List + + ), + "aria-label": "List view" + }, + { + id: "table", + children: ( + + + Table + + ), + "aria-label": "Table view" + }, + ], + defaultSelectedKeys: ["grid"], + }, +}; + +export const IconOnly: Story = { + args: { + items: [ + { + id: "bold", + children: , + "aria-label": "Bold" + }, + { + id: "italic", + children: , + "aria-label": "Italic" + }, + { + id: "underline", + children: , + "aria-label": "Underline" + }, + { + id: "strikethrough", + children: , + "aria-label": "Strikethrough" + }, + ], + defaultSelectedKeys: ["bold"], + }, +}; + +export const TimeRanges: Story = { args: { items: [ - { id: "foo", children: "Foo" }, - { id: "bar", children: "Bar" }, + { id: "1h", children: "1H" }, + { id: "1d", children: "1D" }, + { id: "1w", children: "1W" }, + { id: "1m", children: "1M" }, + { id: "1y", children: "1Y" }, + { id: "all", children: "ALL" }, ], + defaultSelectedKeys: ["1d"], }, -} satisfies StoryObj; +}; + +export const ControlledExample: Story = { + render: () => { + const [selectedTab, setSelectedTab] = useState("overview"); + + const tabs = [ + { id: "overview", children: "Overview" }, + { id: "analytics", children: "Analytics" }, + { id: "reports", children: "Reports" }, + { id: "settings", children: "Settings" }, + ]; + + return ( +
+ +

Current tab: {selectedTab}

+
+ ); + }, +}; + +export const DisabledGroup: Story = { + args: { + items: [ + { id: "option1", children: "Option 1" }, + { id: "option2", children: "Option 2" }, + { id: "option3", children: "Option 3" }, + ], + defaultSelectedKeys: ["option1"], + isDisabled: true, + }, +}; + +export const DisabledIndividualItems: Story = { + args: { + items: [ + { id: "enabled1", children: "Enabled" }, + { id: "disabled", children: "Disabled", isDisabled: true }, + { id: "enabled2", children: "Enabled" }, + ], + defaultSelectedKeys: ["enabled1"], + }, +}; + +export const SortingOptions: Story = { + args: { + items: [ + { id: "name", children: "Name" }, + { id: "date", children: "Date" }, + { id: "size", children: "Size" }, + { id: "type", children: "Type" }, + ], + defaultSelectedKeys: ["name"], + }, +}; + +export const ChartTypes: Story = { + args: { + items: [ + { + id: "line", + children: ( + + + Line + + ) + }, + { + id: "bar", + children: ( + + + Bar + + ) + }, + { + id: "pie", + children: ( + + + Pie + + ) + }, + { + id: "area", + children: ( + + + Area + + ) + }, + ], + defaultSelectedKeys: ["line"], + }, +}; + +export const PricingPlans: Story = { + render: () => { + const [selectedPlan, setSelectedPlan] = useState("monthly"); + + const plans = [ + { id: "monthly", children: "Monthly" }, + { id: "yearly", children: "Yearly (Save 20%)" }, + ]; + + return ( +
+

Billing Period

+ +
+ {selectedPlan === "monthly" ? ( +

$29/month - Billed monthly

+ ) : ( +

$278/year - Billed annually (Save $70)

+ )} +
+
+ ); + }, +}; + +export const NetworkSelection: Story = { + args: { + items: [ + { id: "mainnet", children: "Mainnet" }, + { id: "testnet", children: "Testnet" }, + { id: "devnet", children: "Devnet" }, + ], + defaultSelectedKeys: ["mainnet"], + }, +}; + +export const LanguageSelector: Story = { + args: { + items: [ + { id: "en", children: "EN" }, + { id: "es", children: "ES" }, + { id: "fr", children: "FR" }, + { id: "de", children: "DE" }, + { id: "zh", children: "中" }, + { id: "ja", children: "日" }, + ], + defaultSelectedKeys: ["en"], + }, +}; + +export const StatusFilter: Story = { + render: () => { + const [status, setStatus] = useState("all"); + + const statusOptions = [ + { id: "all", children: "All" }, + { id: "active", children: "Active" }, + { id: "inactive", children: "Inactive" }, + { id: "pending", children: "Pending" }, + ]; + + const getStatusCount = (statusId: string | number) => { + const counts = { all: 156, active: 89, inactive: 45, pending: 22 }; + return counts[statusId as keyof typeof counts] || 0; + }; + + return ( +
+ ({ + ...option, + children: ( + + {option.children} + {getStatusCount(option.id)} + + ) + }))} + selectedKey={status} + onSelectionChange={setStatus} + /> +

Showing {getStatusCount(status)} items with status: {status}

+
+ ); + }, +}; + +// Legacy export for backwards compatibility +export const SingleToggleGroup = Default; \ No newline at end of file From 4c961eb8c63113eaaba2a0f7900d54de2fa593fd Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 15:42:57 +0100 Subject: [PATCH 25/32] docs: add detailed stories for StatCard component --- .../src/StatCard/index.stories.module.scss | 136 ++++++ .../src/StatCard/index.stories.tsx | 395 +++++++++++++++++- 2 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 packages/component-library/src/StatCard/index.stories.module.scss diff --git a/packages/component-library/src/StatCard/index.stories.module.scss b/packages/component-library/src/StatCard/index.stories.module.scss new file mode 100644 index 0000000000..3e98a308ed --- /dev/null +++ b/packages/component-library/src/StatCard/index.stories.module.scss @@ -0,0 +1,136 @@ +@use "../theme"; + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: theme.spacing(4); + align-items: start; +} + +.dashboard { + display: flex; + flex-direction: column; + gap: theme.spacing(6); +} + +.mainStats { + display: grid; + grid-template-columns: 2fr 1fr; + gap: theme.spacing(4); +} + +.secondaryStats { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: theme.spacing(4); +} + +.greenIcon { + color: theme.color("states", "success", "normal"); +} + +.blueIcon { + color: theme.color("states", "info", "normal"); +} + +.redIcon { + color: theme.color("states", "error", "normal"); +} + +.yellowIcon { + color: theme.color("states", "warning", "normal"); +} + +.miniChart { + padding-top: theme.spacing(2); + font-size: theme.font-size("sm"); + color: theme.color("muted"); +} + +.trendIndicator { + display: flex; + align-items: center; + gap: theme.spacing(2); + padding-top: theme.spacing(2); + font-size: theme.font-size("sm"); + color: theme.color("paragraph"); +} + +.networkBreakdown { + display: flex; + gap: theme.spacing(4); + padding-top: theme.spacing(2); + font-size: theme.font-size("sm"); + color: theme.color("muted"); +} + +.progressContainer { + padding-top: theme.spacing(3); +} + +.progressBar { + width: 100%; + height: 8px; + background-color: theme.color("background", "secondary"); + border-radius: theme.border-radius("full"); + overflow: hidden; +} + +.progressFill { + height: 100%; + background-color: theme.color("states", "success", "normal"); + border-radius: theme.border-radius("full"); + transition: width 0.3s ease; + + &[data-progress="98.5"] { + width: 98.5%; + } +} + +.progressLabels { + display: flex; + justify-content: space-between; + margin-top: theme.spacing(1); + font-size: theme.font-size("xs"); + color: theme.color("muted"); +} + +.skeleton { + background: linear-gradient( + 90deg, + theme.color("background", "secondary") 25%, + theme.color("border") 50%, + theme.color("background", "secondary") 75% + ); + background-size: 200% 100%; + animation: loading 1.5s infinite; + border-radius: theme.border-radius("sm"); + padding: theme.spacing(1) theme.spacing(2); +} + +@keyframes loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +.spinner { + width: 16px; + height: 16px; + border: 2px solid theme.color("border"); + border-top: 2px solid theme.color("highlight"); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} \ No newline at end of file diff --git a/packages/component-library/src/StatCard/index.stories.tsx b/packages/component-library/src/StatCard/index.stories.tsx index d911e11848..0e128bd7fc 100644 --- a/packages/component-library/src/StatCard/index.stories.tsx +++ b/packages/component-library/src/StatCard/index.stories.tsx @@ -1,7 +1,10 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { StatCard as StatCardComponent } from "./index.jsx"; +import { Badge } from "../Badge/index.jsx"; import cardMeta, { Card as CardStory } from "../Card/index.stories.jsx"; +import styles from "./index.stories.module.scss"; const cardMetaArgTypes = () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -40,7 +43,44 @@ const meta = { category: "Contents", }, }, + small: { + control: "boolean", + table: { + category: "Layout", + }, + }, + header1: { + table: { + category: "Dual Layout", + }, + }, + header2: { + table: { + category: "Dual Layout", + }, + }, + stat1: { + table: { + category: "Dual Layout", + }, + }, + stat2: { + table: { + category: "Dual Layout", + }, + }, + miniStat1: { + table: { + category: "Dual Layout", + }, + }, + miniStat2: { + table: { + category: "Dual Layout", + }, + }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -50,12 +90,361 @@ const cardStoryArgs = () => { return args; }; -export const StatCard = { +type Story = StoryObj; + +export const Default: Story = { args: { ...cardStoryArgs(), header: "Active Feeds", stat: "552", miniStat: "+5", - corner: ":)", + variant: "secondary", + }, +}; + +export const BasicStats: Story = { + args: { + header: "Total Users", + stat: "12,345", + variant: "secondary", + }, +}; + +export const WithMiniStat: Story = { + args: { + header: "Revenue", + stat: "$45,234", + miniStat: "+12.5%", + variant: "secondary", + }, +}; + +export const WithCorner: Story = { + args: { + header: "System Status", + stat: "Online", + corner: Live, + variant: "secondary", }, -} satisfies StoryObj; +}; + +export const SmallVariant: Story = { + args: { + header: "CPU Usage", + stat: "67%", + miniStat: "+2.1%", + small: true, + variant: "secondary", + }, +}; + +export const CryptocurrencyPrices: Story = { + render: () => ( +
+ +5.2%} + variant="secondary" + /> + -2.1%} + variant="secondary" + /> + +12.8%} + variant="secondary" + /> +
+ ), +}; + +export const BusinessMetrics: Story = { + render: () => ( +
+ } + variant="secondary" + > +
+ Target: $120,000 +
+
+ } + variant="secondary" + /> + } + variant="secondary" + /> +
+ ), +}; + +export const SystemMonitoring: Story = { + render: () => ( +
+ High} + variant="secondary" + small + /> + Critical} + variant="secondary" + small + /> + OK} + variant="secondary" + small + /> + Stable} + variant="secondary" + small + /> +
+ ), +}; + +export const DualLayout: Story = { + args: { + header1: "Inbound", + header2: "Outbound", + stat1: "1,234", + stat2: "856", + miniStat1: "+12%", + miniStat2: "-5%", + variant: "secondary", + }, +}; + +export const DualLayoutComparison: Story = { + args: { + header1: "This Month", + header2: "Last Month", + stat1: "$45,234", + stat2: "$39,876", + miniStat1: "Revenue", + miniStat2: "Revenue", + variant: "secondary", + }, +}; + +export const DualLayoutMetrics: Story = { + render: () => ( +
+ + +
+ ), +}; + +export const WithCustomContent: Story = { + args: { + header: "Sales Performance", + stat: "98.5%", + miniStat: "of monthly target", + corner: On Track, + variant: "secondary", + children: ( +
+
+
+
+
+ $98,500 + $100,000 +
+
+ ), + }, +}; + +export const AnalyticsDashboard: Story = { + render: () => ( +
+
+ Target: 110%} + variant="primary" + > +
+ + Trending upward for 3 months +
+
+ +
+
+ + + +
+
+ ), +}; + +export const PythNetworkStats: Story = { + render: () => ( +
+ Live} + variant="secondary" + > +
+
Mainnet: 380
+
Testnet: 25
+
+
+ } + variant="secondary" + /> + +
+ ), +}; + +export const ErrorStates: Story = { + render: () => ( +
+ Error} + variant="secondary" + /> + N/A} + variant="secondary" + /> + Alert} + variant="secondary" + /> +
+ ), +}; + +export const LoadingStates: Story = { + render: () => ( +
+ Loading...
} + miniStat="Please wait" + variant="secondary" + /> + } + variant="secondary" + /> +
+ ), +}; + +// Legacy export for backwards compatibility +export const StatCard = Default; \ No newline at end of file From 547cb37ddb37001c1788b5e034e0b9583b00be4c Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 15:49:01 +0100 Subject: [PATCH 26/32] chore: move inline styles into SCSS modules --- .../src/EntityList/index.stories.module.scss | 11 +++++++++++ .../src/EntityList/index.stories.tsx | 9 +++++---- .../src/Meter/index.stories.module.scss | 17 +++++++++++++++++ .../src/Meter/index.stories.tsx | 15 ++++++++------- 4 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 packages/component-library/src/EntityList/index.stories.module.scss create mode 100644 packages/component-library/src/Meter/index.stories.module.scss diff --git a/packages/component-library/src/EntityList/index.stories.module.scss b/packages/component-library/src/EntityList/index.stories.module.scss new file mode 100644 index 0000000000..a5df494fac --- /dev/null +++ b/packages/component-library/src/EntityList/index.stories.module.scss @@ -0,0 +1,11 @@ +@use "../theme"; + +.metricsContainer { + display: flex; + gap: theme.spacing(2); +} + +.actionsContainer { + display: flex; + gap: theme.spacing(2); +} \ No newline at end of file diff --git a/packages/component-library/src/EntityList/index.stories.tsx b/packages/component-library/src/EntityList/index.stories.tsx index ab87911c57..0a28a091b7 100644 --- a/packages/component-library/src/EntityList/index.stories.tsx +++ b/packages/component-library/src/EntityList/index.stories.tsx @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Badge } from "../Badge/index.jsx"; import { EntityList as EntityListComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: EntityListComponent, @@ -196,13 +197,13 @@ export const ComplexContent: Story = { data: { project: Project Alpha, metrics: ( -
+
10 feeds 98% uptime
), actions: ( -
+
@@ -215,13 +216,13 @@ export const ComplexContent: Story = { data: { project: Project Beta, metrics: ( -
+
5 feeds 92% uptime
), actions: ( -
+
diff --git a/packages/component-library/src/Meter/index.stories.module.scss b/packages/component-library/src/Meter/index.stories.module.scss new file mode 100644 index 0000000000..39b52f2ee0 --- /dev/null +++ b/packages/component-library/src/Meter/index.stories.module.scss @@ -0,0 +1,17 @@ +@use "../theme"; + +.performanceContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(6); +} + +.performanceSection { + > h3 { + margin: 0; + margin-bottom: theme.spacing(2); + font-size: theme.font-size("lg"); + font-weight: 600; + color: theme.color("heading"); + } +} \ No newline at end of file diff --git a/packages/component-library/src/Meter/index.stories.tsx b/packages/component-library/src/Meter/index.stories.tsx index 8abb9516b6..e1c1241a29 100644 --- a/packages/component-library/src/Meter/index.stories.tsx +++ b/packages/component-library/src/Meter/index.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Meter as MeterComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: MeterComponent, @@ -159,9 +160,9 @@ export const BatteryLevel: Story = { export const PerformanceScore: Story = { render: () => ( -
-
-

CPU Usage

+
+
+

CPU Usage

-
-

Memory Usage

+
+

Memory Usage

-
-

Disk Usage

+
+

Disk Usage

Date: Tue, 3 Jun 2025 15:58:36 +0100 Subject: [PATCH 27/32] docs: add detailed stories for Status component variants --- .../src/Status/index.stories.module.scss | 73 +++++ .../src/Status/index.stories.tsx | 290 +++++++++++++++++- 2 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 packages/component-library/src/Status/index.stories.module.scss diff --git a/packages/component-library/src/Status/index.stories.module.scss b/packages/component-library/src/Status/index.stories.module.scss new file mode 100644 index 0000000000..80d65c2208 --- /dev/null +++ b/packages/component-library/src/Status/index.stories.module.scss @@ -0,0 +1,73 @@ +@use "../theme"; + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: theme.spacing(4); + align-items: center; +} + +.combinationsGrid { + display: flex; + flex-direction: column; + gap: theme.spacing(8); +} + +.styleSection { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} + +.sectionTitle { + margin: 0; + font-size: theme.font-size("lg"); + font-weight: 600; + color: theme.color("heading"); +} + +.sizeSection { + display: flex; + flex-direction: column; + gap: theme.spacing(2); +} + +.sizeTitle { + margin: 0; + font-size: theme.font-size("sm"); + font-weight: 500; + color: theme.color("paragraph"); +} + +.variantsRow { + display: flex; + flex-wrap: wrap; + gap: theme.spacing(3); + align-items: center; +} + +.variantGrid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: theme.spacing(6); +} + +.sizeColumn { + display: flex; + flex-direction: column; + gap: theme.spacing(3); + + > h4 { + margin: 0; + font-size: theme.font-size("sm"); + font-weight: 600; + color: theme.color("heading"); + } +} + +.examplesGrid { + display: flex; + flex-wrap: wrap; + gap: theme.spacing(3); + align-items: center; +} \ No newline at end of file diff --git a/packages/component-library/src/Status/index.stories.tsx b/packages/component-library/src/Status/index.stories.tsx index 69d580f013..d0380065b7 100644 --- a/packages/component-library/src/Status/index.stories.tsx +++ b/packages/component-library/src/Status/index.stories.tsx @@ -6,6 +6,7 @@ import { SIZES, STYLES, } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: StatusComponent, @@ -38,14 +39,297 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const Status = { +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "Status", + variant: "neutral", + style: "filled", + size: "md", + }, +}; + +// Individual variant examples +export const Neutral: Story = { args: { - children: "A STATUS", + children: "Neutral", variant: "neutral", style: "filled", size: "md", }, -} satisfies StoryObj; +}; + +export const Info: Story = { + args: { + children: "Info", + variant: "info", + style: "filled", + size: "md", + }, +}; + +export const Warning: Story = { + args: { + children: "Warning", + variant: "warning", + style: "filled", + size: "md", + }, +}; + +export const Error: Story = { + args: { + children: "Error", + variant: "error", + style: "filled", + size: "md", + }, +}; + +export const Data: Story = { + args: { + children: "Data", + variant: "data", + style: "filled", + size: "md", + }, +}; + +export const Success: Story = { + args: { + children: "Success", + variant: "success", + style: "filled", + size: "md", + }, +}; + +export const Disabled: Story = { + args: { + children: "Disabled", + variant: "disabled", + style: "filled", + size: "md", + }, +}; + +// All combinations grid +export const AllCombinations: Story = { + render: () => ( +
+ {STYLES.map((style) => ( +
+

{style.charAt(0).toUpperCase() + style.slice(1)} Style

+ {SIZES.map((size) => ( +
+

Size: {size.toUpperCase()}

+
+ {VARIANTS.map((variant) => ( + + {variant.charAt(0).toUpperCase() + variant.slice(1)} + + ))} +
+
+ ))} +
+ ))} +
+ ), +}; + +// Grouped by variant +export const NeutralAllStyles: Story = { + render: () => ( +
+ Neutral Filled XS + Neutral Filled MD + Neutral Outline XS + Neutral Outline MD +
+ ), +}; + +export const InfoAllStyles: Story = { + render: () => ( +
+ Info Filled XS + Info Filled MD + Info Outline XS + Info Outline MD +
+ ), +}; + +export const WarningAllStyles: Story = { + render: () => ( +
+ Warning Filled XS + Warning Filled MD + Warning Outline XS + Warning Outline MD +
+ ), +}; + +export const ErrorAllStyles: Story = { + render: () => ( +
+ Error Filled XS + Error Filled MD + Error Outline XS + Error Outline MD +
+ ), +}; + +export const DataAllStyles: Story = { + render: () => ( +
+ Data Filled XS + Data Filled MD + Data Outline XS + Data Outline MD +
+ ), +}; + +export const SuccessAllStyles: Story = { + render: () => ( +
+ Success Filled XS + Success Filled MD + Success Outline XS + Success Outline MD +
+ ), +}; + +export const DisabledAllStyles: Story = { + render: () => ( +
+ Disabled Filled XS + Disabled Filled MD + Disabled Outline XS + Disabled Outline MD +
+ ), +}; + +// Grouped by style +export const AllFilledVariants: Story = { + render: () => ( +
+
+

XS Size

+ {VARIANTS.map((variant) => ( + + {variant} + + ))} +
+
+

MD Size

+ {VARIANTS.map((variant) => ( + + {variant} + + ))} +
+
+ ), +}; + +export const AllOutlineVariants: Story = { + render: () => ( +
+
+

XS Size

+ {VARIANTS.map((variant) => ( + + {variant} + + ))} +
+
+

MD Size

+ {VARIANTS.map((variant) => ( + + {variant} + + ))} +
+
+ ), +}; + +// Real-world examples +export const SystemStatuses: Story = { + render: () => ( +
+ Online + Offline + Maintenance + Updating + Inactive +
+ ), +}; + +export const ConnectionStates: Story = { + render: () => ( +
+ Connected + Disconnected + Reconnecting + Authenticating +
+ ), +}; + +export const DataQuality: Story = { + render: () => ( +
+ Live Data + Cached + Stale + Invalid +
+ ), +}; + +export const UserStatuses: Story = { + render: () => ( +
+ Active + Away + Busy + Offline +
+ ), +}; + +export const DeploymentStatuses: Story = { + render: () => ( +
+ Deployed + Building + Queued + Failed + Cancelled +
+ ), +}; + +// Legacy export for backwards compatibility +export const Status = Default; \ No newline at end of file From b06d1b3e8a7f9d6c46d1850a9e886c30e347a71b Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 16:05:29 +0100 Subject: [PATCH 28/32] docs: add stories for Switch component --- .../src/Switch/index.stories.module.scss | 139 +++++++ .../src/Switch/index.stories.tsx | 386 +++++++++++++++++- 2 files changed, 520 insertions(+), 5 deletions(-) create mode 100644 packages/component-library/src/Switch/index.stories.module.scss diff --git a/packages/component-library/src/Switch/index.stories.module.scss b/packages/component-library/src/Switch/index.stories.module.scss new file mode 100644 index 0000000000..c73cea1245 --- /dev/null +++ b/packages/component-library/src/Switch/index.stories.module.scss @@ -0,0 +1,139 @@ +@use "../theme"; + +.statesGrid { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 600px; +} + +.stateRow { + display: grid; + grid-template-columns: 250px 1fr; + align-items: center; + gap: theme.spacing(4); +} + +.description { + font-size: theme.font-size("sm"); + color: theme.color("muted"); +} + +.controlledContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 400px; + + > p { + margin: 0; + font-size: theme.font-size("sm"); + color: theme.color("paragraph"); + } +} + +.settingsList { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 600px; +} + +.settingItem { + display: flex; + flex-direction: column; + gap: theme.spacing(1); + padding-bottom: theme.spacing(4); + border-bottom: 1px solid theme.color("border"); + + &:last-child { + border-bottom: none; + } +} + +.settingDescription { + font-size: theme.font-size("sm"); + color: theme.color("muted"); + margin-left: theme.spacing(11); // Align with switch content +} + +.featureFlags { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 500px; + + > h3 { + margin: 0; + font-size: theme.font-size("lg"); + font-weight: 600; + color: theme.color("heading"); + } +} + +.flagItem { + padding: theme.spacing(3); + background-color: theme.color("background", "secondary"); + border-radius: theme.border-radius("md"); +} + +.permissionsList { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 500px; + + > h3 { + margin: 0; + font-size: theme.font-size("lg"); + font-weight: 600; + color: theme.color("heading"); + } +} + +.permissionItem { + display: flex; + align-items: center; + gap: theme.spacing(3); + padding: theme.spacing(2) 0; +} + +.lockedBadge { + font-size: theme.font-size("xs"); + padding: theme.spacing(1) theme.spacing(2); + background-color: theme.color("states", "warning", "background"); + color: theme.color("states", "warning", "normal"); + border-radius: theme.border-radius("sm"); + font-weight: 500; +} + +.customLabels { + display: flex; + flex-direction: column; + gap: theme.spacing(4); + max-width: 400px; +} + +.dynamicLabel { + display: inline-flex; + align-items: center; + gap: theme.spacing(2); +} + +.errorExample { + display: flex; + flex-direction: column; + gap: theme.spacing(3); + max-width: 500px; +} + +.errorMessage { + padding: theme.spacing(3); + background-color: theme.color("states", "error", "background"); + color: theme.color("states", "error", "base"); + border-radius: theme.border-radius("md"); + font-size: theme.font-size("sm"); + display: flex; + align-items: center; + gap: theme.spacing(2); +} \ No newline at end of file diff --git a/packages/component-library/src/Switch/index.stories.tsx b/packages/component-library/src/Switch/index.stories.tsx index e36aa4ebc5..b12e55df95 100644 --- a/packages/component-library/src/Switch/index.stories.tsx +++ b/packages/component-library/src/Switch/index.stories.tsx @@ -1,6 +1,9 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; +import { useState } from "react"; import { Switch as SwitchComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: SwitchComponent, @@ -17,7 +20,20 @@ const meta = { category: "State", }, }, + isSelected: { + control: "boolean", + table: { + category: "State", + }, + }, + defaultSelected: { + control: "boolean", + table: { + category: "State", + }, + }, onChange: { + action: "changed", table: { category: "Behavior", }, @@ -29,13 +45,373 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const Switch = { +type Story = StoryObj; + +export const Default: Story = { + args: { + children: "Enable feature", + onChange: fn(), + }, +}; + +export const WithLabel: Story = { + args: { + children: "Enable notifications", + onChange: fn(), + }, +}; + +export const DefaultSelected: Story = { + args: { + children: "Already enabled", + defaultSelected: true, + onChange: fn(), + }, +}; + +export const Disabled: Story = { + args: { + children: "Disabled switch", + isDisabled: true, + onChange: fn(), + }, +}; + +export const DisabledSelected: Story = { + args: { + children: "Disabled but selected", + isDisabled: true, + defaultSelected: true, + onChange: fn(), + }, +}; + +export const Pending: Story = { args: { - children: "Click me!", - isDisabled: false, - isPending: false, + children: "Loading...", + isPending: true, + onChange: fn(), }, -} satisfies StoryObj; +}; + +export const PendingSelected: Story = { + args: { + children: "Saving changes...", + isPending: true, + defaultSelected: true, + onChange: fn(), + }, +}; + +export const AllStates: Story = { + render: () => ( +
+
+ Normal + Default state +
+
+ Selected + Selected state +
+
+ Disabled + Disabled state +
+
+ Disabled Selected + Disabled & selected +
+
+ Pending + Loading state +
+
+ Pending Selected + Loading & selected +
+
+ ), +}; + +export const ControlledExample: Story = { + render: () => { + const [isSelected, setIsSelected] = useState(false); + const handleChange = fn((value: boolean) => { + setIsSelected(value); + }); + + return ( +
+ + Controlled switch + +

Switch is {isSelected ? "ON" : "OFF"}

+
+ ); + }, +}; + +export const WithAsyncAction: Story = { + render: () => { + const [isSelected, setIsSelected] = useState(false); + const [isPending, setIsPending] = useState(false); + + const handleChange = fn(async (value: boolean) => { + setIsPending(true); + // Simulate async operation + await new Promise(resolve => setTimeout(resolve, 2000)); + setIsSelected(value); + setIsPending(false); + }); + + return ( +
+ + Save to server + +

{isPending ? "Saving..." : `Saved state: ${isSelected ? "ON" : "OFF"}`}

+
+ ); + }, +}; + +export const SettingsExample: Story = { + render: () => { + const [settings, setSettings] = useState({ + notifications: true, + darkMode: false, + autoSave: true, + analytics: false, + }); + + const handleSettingChange = (setting: keyof typeof settings) => + fn((value: boolean) => { + setSettings(prev => ({ ...prev, [setting]: value })); + }); + + return ( +
+
+ + Push notifications + + + Receive alerts for important updates + +
+
+ + Dark mode + + + Use dark theme for better night viewing + +
+
+ + Auto-save + + + Automatically save your work + +
+
+ + Analytics (Pro only) + + + Advanced usage analytics + +
+
+ ); + }, +}; + +export const FeatureFlags: Story = { + render: () => { + const [flags, setFlags] = useState({ + betaFeatures: false, + experimentalApi: false, + debugMode: false, + }); + const [pendingFlags, setPendingFlags] = useState([]); + + const handleFlagChange = (flag: keyof typeof flags) => + fn(async (value: boolean) => { + setPendingFlags(prev => [...prev, flag]); + // Simulate API call + await new Promise(resolve => setTimeout(resolve, 1500)); + setFlags(prev => ({ ...prev, [flag]: value })); + setPendingFlags(prev => prev.filter(f => f !== flag)); + }); + + return ( +
+

Feature Flags

+
+ + Enable beta features + +
+
+ + Use experimental API + +
+
+ + Debug mode + +
+
+ ); + }, +}; + +export const PermissionsExample: Story = { + render: () => { + const permissions = [ + { id: 'read', label: 'Read access', enabled: true, locked: false }, + { id: 'write', label: 'Write access', enabled: false, locked: false }, + { id: 'delete', label: 'Delete access', enabled: false, locked: true }, + { id: 'admin', label: 'Admin access', enabled: false, locked: true }, + ]; + + return ( +
+

User Permissions

+ {permissions.map(permission => ( +
+ + {permission.label} + + {permission.locked && ( + Requires upgrade + )} +
+ ))} +
+ ); + }, +}; + +export const WithCustomLabels: Story = { + render: () => ( +
+ + {({ isSelected }) => ( + + {isSelected ? "🌙 Night mode" : "☀️ Day mode"} + + )} + + + {({ isSelected }) => ( + + Status: {isSelected ? "Active" : "Inactive"} + + )} + + + {({ isSelected }) => ( + + {isSelected ? "✅ Subscribed" : "❌ Unsubscribed"} + + )} + +
+ ), +}; + +export const ErrorHandling: Story = { + render: () => { + const [isSelected, setIsSelected] = useState(false); + const [error, setError] = useState(null); + const [isPending, setIsPending] = useState(false); + + const handleChange = fn(async (value: boolean) => { + setError(null); + setIsPending(true); + + try { + // Simulate API call that might fail + await new Promise((resolve, reject) => { + setTimeout(() => { + if (Math.random() > 0.5) { + resolve(true); + } else { + reject(new Error("Failed to update setting")); + } + }, 1000); + }); + setIsSelected(value); + } catch (err) { + setError((err as Error).message); + } finally { + setIsPending(false); + } + }); + + return ( +
+ + Risky operation (50% failure rate) + + {error && ( +
+ ⚠️ {error} +
+ )} +
+ ); + }, +}; + +// Legacy export for backwards compatibility +export const Switch = Default; \ No newline at end of file From ab2bfbe3e0ac93d2e90b16775ac42d0d4c628d8b Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 16:09:10 +0100 Subject: [PATCH 29/32] chore: remove metasyntactic variables --- packages/component-library/src/TabList/index.stories.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/component-library/src/TabList/index.stories.tsx b/packages/component-library/src/TabList/index.stories.tsx index 27dbece720..ef406a5a6d 100644 --- a/packages/component-library/src/TabList/index.stories.tsx +++ b/packages/component-library/src/TabList/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { TabList as TabListComponent } from "./index.jsx"; import { Tabs as UnstyledTabs } from "../unstyled/Tabs/index.jsx"; +import { TabList as TabListComponent } from "./index.jsx"; const meta = { component: TabListComponent, @@ -31,8 +31,9 @@ export const TabList = { args: { label: "Tab List", items: [ - { id: "foo", children: "Foo" }, - { id: "bar", children: "Bar" }, + { id: "btc", children: "BTC" }, + { id: "eth", children: "ETH" }, + { id: "sol", children: "SOL" }, ], }, } satisfies StoryObj; From 32b52fed3e9dd85a8b8b363db5c4a87072b76a3a Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 17:01:18 +0100 Subject: [PATCH 30/32] docs: add stories for Table component --- .../src/Table/index.stories.module.scss | 186 ++++ .../src/Table/index.stories.tsx | 803 +++++++++++++++++- 2 files changed, 969 insertions(+), 20 deletions(-) create mode 100644 packages/component-library/src/Table/index.stories.module.scss diff --git a/packages/component-library/src/Table/index.stories.module.scss b/packages/component-library/src/Table/index.stories.module.scss new file mode 100644 index 0000000000..28ef0a057f --- /dev/null +++ b/packages/component-library/src/Table/index.stories.module.scss @@ -0,0 +1,186 @@ +@use "../theme"; + +.wideTable { + width: 100%; + overflow-x: auto; +} + +.positive { + color: theme.color("states", "success", "normal"); + font-weight: 500; +} + +.negative { + color: theme.color("states", "error", "normal"); + font-weight: 500; +} + +.emptyState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: theme.spacing(4); + padding: theme.spacing(12) theme.spacing(4); + text-align: center; + color: theme.color("muted"); + + > p { + margin: 0; + font-size: theme.font-size("sm"); + } +} + +.largeEmptyState { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: theme.spacing(4); + padding: theme.spacing(16) theme.spacing(4); + text-align: center; + + > h3 { + margin: 0; + font-size: theme.font-size("xl"); + font-weight: 600; + color: theme.color("heading"); + } + + > p { + margin: 0; + font-size: theme.font-size("base"); + color: theme.color("muted"); + } +} + +.userCell { + display: flex; + align-items: center; + gap: theme.spacing(3); +} + +.avatar { + width: 32px; + height: 32px; + border-radius: theme.border-radius("full"); + background-color: theme.color("states", "info", "background"); + color: theme.color("states", "info", "normal"); + display: flex; + align-items: center; + justify-content: center; + font-size: theme.font-size("sm"); + font-weight: 600; + flex-shrink: 0; +} + +.userName { + font-weight: 500; + color: theme.color("foreground"); +} + +.userEmail { + font-size: theme.font-size("sm"); + color: theme.color("muted"); +} + +.actions { + display: flex; + gap: theme.spacing(2); +} + +.assetCell { + display: flex; + flex-direction: column; + gap: theme.spacing(1); + + > strong { + font-weight: 600; + color: theme.color("foreground"); + } +} + +.assetName { + font-size: theme.font-size("sm"); + color: theme.color("muted"); +} + +.userSkeleton { + display: flex; + align-items: center; + gap: theme.spacing(3); +} + +.filterableTable { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} + +.filterInput { + padding: theme.spacing(2) theme.spacing(3); + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("md"); + background-color: theme.color("background", "primary"); + color: theme.color("foreground"); + font-size: theme.font-size("sm"); + width: 100%; + max-width: 300px; + + &:focus { + outline: none; + border-color: theme.color("focus"); + box-shadow: 0 0 0 3px theme.color("focus-dim"); + } + + &::placeholder { + color: theme.color("muted"); + } +} + +.stickyHeaderContainer { + height: 400px; + overflow-y: auto; + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("md"); + position: relative; +} + +.stickyHeaderInfo { + padding: theme.spacing(3); + background-color: theme.color("states", "info", "background"); + color: theme.color("states", "info", "normal"); + text-align: center; + font-size: theme.font-size("sm"); + + > p { + margin: 0; + } +} + +.stickyColumnsWrapper { + width: 100%; +} + +.stickyColumnsContainer { + width: 100%; + max-width: 800px; + overflow-x: auto; + border: 1px solid theme.color("border"); + border-radius: theme.border-radius("md"); +} + +.stickyColumnsInfo { + padding: theme.spacing(3); + background-color: theme.color("states", "info", "background"); + color: theme.color("states", "info", "normal"); + text-align: center; + font-size: theme.font-size("sm"); + position: sticky; + left: 0; + z-index: 10; + + > p { + margin: 0; + } +} \ No newline at end of file diff --git a/packages/component-library/src/Table/index.stories.tsx b/packages/component-library/src/Table/index.stories.tsx index f56424a500..6dc63e5ea8 100644 --- a/packages/component-library/src/Table/index.stories.tsx +++ b/packages/component-library/src/Table/index.stories.tsx @@ -1,6 +1,14 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; +import { useState } from "react"; -import { Table as TableComponent } from "./index.jsx"; +import { Badge } from "../Badge/index.jsx"; +import { Button } from "../Button/index.jsx"; +import { CopyButton } from "../CopyButton/index.jsx"; +import { Status } from "../Status/index.jsx"; +import { Table as TableComponent, type ColumnConfig, type RowConfig, type SortDescriptor } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { component: TableComponent, @@ -29,6 +37,7 @@ const meta = { }, }, label: { + control: "text", table: { category: "Accessibility", }, @@ -57,70 +66,824 @@ const meta = { category: "Variant", }, }, + stickyHeader: { + control: "select", + options: [undefined, "top", "appHeader"], + table: { + category: "Layout", + }, + }, dependencies: { table: { disable: true, }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const Table = { +type Story = StoryObj; + +// Basic example +export const Default: Story = { args: { - label: "A Table", - isUpdating: false, - isLoading: false, - fill: true, - rounded: true, + label: "Price feeds table", columns: [ { name: "PRICE FEED", id: "feed", isRowHeader: true, - loadingSkeletonWidth: 16, }, { name: "PRICE", id: "price", fill: true, - loadingSkeletonWidth: 30, }, { name: "CONFIDENCE", id: "confidence", - loadingSkeletonWidth: 20, alignment: "right", }, ], rows: [ { id: "BTC/USD", - href: "#", data: { feed: "BTC/USD", - price: "$100,000", - confidence: "+/- 5%", + price: "$45,234.56", + confidence: "±$12.34", }, }, { id: "ETH/USD", - href: "#", data: { feed: "ETH/USD", - price: "$1,000", - confidence: "+/- 10%", + price: "$3,234.56", + confidence: "±$2.34", }, }, { id: "SOL/USD", - href: "#", data: { feed: "SOL/USD", - price: "$1,000,000,000", - confidence: "+/- 0.1%", + price: "$123.45", + confidence: "±$0.12", + }, + }, + ], + }, +}; + +// Column configurations +export const ColumnAlignments: Story = { + args: { + label: "Column alignments demo", + fill: true, + rounded: true, + columns: [ + { + name: "LEFT ALIGNED", + id: "left", + alignment: "left", + }, + { + name: "CENTER ALIGNED", + id: "center", + alignment: "center", + }, + { + name: "RIGHT ALIGNED", + id: "right", + alignment: "right", + }, + ], + rows: [ + { + id: "1", + data: { + left: "Left text", + center: "Center text", + right: "Right text", + }, + }, + { + id: "2", + data: { + left: "Another left", + center: "Another center", + right: "Another right", + }, + }, + ], + }, +}; + +export const ColumnWidths: Story = { + args: { + label: "Column widths demo", + columns: [ + { + name: "FIXED WIDTH", + id: "fixed", + width: 150, + }, + { + name: "FILL SPACE", + id: "fill", + fill: true, + }, + { + name: "SMALL", + id: "small", + width: 80, + }, + ], + rows: [ + { + id: "1", + data: { + fixed: "150px width", + fill: "This column fills the remaining space", + small: "80px", + }, + }, + ], + }, +}; + +export const StickyColumns: Story = { + render: () => ( +
+
+

Scroll horizontally to see the first column (NAME) remain sticky

+
+
+ ({ + id: `row-${i}`, + data: { + name: `Product ${i + 1}`, + sku: `SKU-${1000 + i}`, + description: `This is a detailed description for product ${i + 1} that might be quite long`, + category: `Category ${(i % 3) + 1}`, + subcategory: `Subcat ${(i % 2) + 1}`, + brand: `Brand ${String.fromCharCode(65 + (i % 4))}`, + status: + {i % 2 === 0 ? "Active" : "Draft"} + , + stock: i * 10 + 5, + price: `$${(i + 1) * 99}.99`, + discount: i % 3 === 0 ? "10%" : "-", + created: "2024-01-15", + updated: "2024-12-01", + actions: ( +
+ + +
+ ), + }, + }))} + /> +
+
+ ), +}; + +// Loading states +export const Loading: Story = { + args: { + label: "Loading table", + isLoading: true, + columns: [ + { + name: "NAME", + id: "name", + loadingSkeletonWidth: 80, + }, + { + name: "VALUE", + id: "value", + loadingSkeletonWidth: 20, + }, + { + name: "STATUS", + id: "status", + loadingSkeletonWidth: 35, + }, + ], + }, +}; + +export const Updating: Story = { + args: { + label: "Updating table", + isUpdating: true, + columns: [ + { + name: "METRIC", + id: "metric", + }, + { + name: "VALUE", + id: "value", + alignment: "right", + }, + ], + rows: [ + { + id: "cpu", + data: { + metric: "CPU Usage", + value: "67%", + }, + }, + { + id: "memory", + data: { + metric: "Memory", + value: "4.2 GB", }, }, ], }, -} satisfies StoryObj; +}; + +// Sortable columns +export const Sortable: Story = { + render: () => { + const [sortDescriptor, setSortDescriptor] = useState({ + column: "name", + direction: "ascending", + }); + + const data = [ + { id: "1", name: "Bitcoin", symbol: "BTC", price: 45234.56, change: 2.34 }, + { id: "2", name: "Ethereum", symbol: "ETH", price: 3234.56, change: -1.23 }, + { id: "3", name: "Solana", symbol: "SOL", price: 123.45, change: 5.67 }, + { id: "4", name: "Cardano", symbol: "ADA", price: 0.45, change: -0.89 }, + ]; + + const sortedData = [...data].sort((a, b) => { + const column = sortDescriptor.column as keyof typeof a; + const aValue = a[column]; + const bValue = b[column]; + + if (typeof aValue === "string" && typeof bValue === "string") { + return sortDescriptor.direction === "ascending" + ? aValue.localeCompare(bValue) + : bValue.localeCompare(aValue); + } + + if (typeof aValue === "number" && typeof bValue === "number") { + return sortDescriptor.direction === "ascending" + ? aValue - bValue + : bValue - aValue; + } + + return 0; + }); + + const columns: ColumnConfig<"name" | "symbol" | "price" | "change">[] = [ + { + name: "NAME", + id: "name", + isRowHeader: true, + allowsSorting: true, + }, + { + name: "SYMBOL", + id: "symbol", + allowsSorting: true, + }, + { + name: "PRICE", + id: "price", + alignment: "right", + allowsSorting: true, + }, + { + name: "24H CHANGE", + id: "change", + alignment: "right", + allowsSorting: true, + }, + ]; + + const rows: RowConfig<"name" | "symbol" | "price" | "change">[] = sortedData.map(item => ({ + id: item.id, + data: { + name: item.name, + symbol: item.symbol, + price: `$${item.price.toLocaleString()}`, + change: ( + = 0 ? styles.positive : styles.negative}> + {item.change >= 0 ? "+" : ""}{item.change}% + + ), + }, + })); + + return ( + + ); + }, +}; + +// Interactive rows +export const ClickableRows: Story = { + args: { + label: "Clickable rows table", + columns: [ + { + name: "PROJECT", + id: "project", + isRowHeader: true, + }, + { + name: "STATUS", + id: "status", + }, + { + name: "LAST UPDATED", + id: "updated", + alignment: "right", + }, + ], + rows: [ + { + id: "project-1", + href: "#project-1", + data: { + project: "Frontend App", + status: Active, + updated: "2 hours ago", + }, + }, + { + id: "project-2", + href: "#project-2", + data: { + project: "Backend API", + status: Maintenance, + updated: "1 day ago", + }, + }, + { + id: "project-3", + onAction: fn(), + data: { + project: "Mobile App", + status: Building, + updated: "5 minutes ago", + }, + }, + ], + }, +}; + +// Empty states +export const EmptyState: Story = { + args: { + label: "Empty table", + columns: [ + { name: "NAME", id: "name" }, + { name: "VALUE", id: "value" }, + ], + rows: [], + emptyState: ( +
+ +

No data available

+ +
+ ), + }, +}; + +export const EmptyStateHiddenHeaders: Story = { + args: { + label: "Empty table without headers", + columns: [ + { name: "NAME", id: "name" }, + { name: "VALUE", id: "value" }, + ], + rows: [], + hideHeadersInEmptyState: true, + emptyState: ( +
+ +

No results found

+

Try adjusting your search or filters

+ +
+ ), + }, +}; + +// Complex data table +export const ComplexDataTable: Story = { + args: { + label: "User management table", + fill: true, + rounded: true, + columns: [ + { + name: "USER", + id: "user", + isRowHeader: true, + sticky: true, + width: 250, + }, + { + name: "ROLE", + id: "role", + width: 120, + }, + { + name: "STATUS", + id: "status", + width: 100, + }, + { + name: "LAST ACTIVE", + id: "lastActive", + width: 150, + }, + { + name: "ACTIONS", + id: "actions", + alignment: "right", + width: 200, + }, + ], + rows: [ + { + id: "user-1", + data: { + user: ( +
+
JD
+
+
John Doe
+
john@example.com
+
+
+ ), + role: Admin, + status: Active, + lastActive: "2 minutes ago", + actions: ( +
+ + +
+ ), + }, + }, + { + id: "user-2", + data: { + user: ( +
+
JS
+
+
Jane Smith
+
jane@example.com
+
+
+ ), + role: Editor, + status: Active, + lastActive: "1 hour ago", + actions: ( +
+ + +
+ ), + }, + }, + { + id: "user-3", + data: { + user: ( +
+
RJ
+
+
Robert Johnson
+
robert@example.com
+
+
+ ), + role: Viewer, + status: Inactive, + lastActive: "3 days ago", + actions: ( +
+ + +
+ ), + }, + }, + ], + }, +}; + +// Financial data table +export const FinancialDataTable: Story = { + args: { + label: "Portfolio holdings", + columns: [ + { + name: "ASSET", + id: "asset", + isRowHeader: true, + sticky: true, + }, + { + name: "QUANTITY", + id: "quantity", + alignment: "right", + }, + { + name: "AVG COST", + id: "avgCost", + alignment: "right", + }, + { + name: "CURRENT PRICE", + id: "currentPrice", + alignment: "right", + }, + { + name: "VALUE", + id: "value", + alignment: "right", + }, + { + name: "P&L", + id: "pnl", + alignment: "right", + }, + { + name: "P&L %", + id: "pnlPercent", + alignment: "right", + }, + ], + rows: [ + { + id: "btc", + data: { + asset: ( +
+ BTC + Bitcoin +
+ ), + quantity: "0.5234", + avgCost: "$38,450", + currentPrice: "$45,234", + value: "$23,675", + pnl: +$3,548, + pnlPercent: +17.6%, + }, + }, + { + id: "eth", + data: { + asset: ( +
+ ETH + Ethereum +
+ ), + quantity: "5.123", + avgCost: "$3,450", + currentPrice: "$3,234", + value: "$16,568", + pnl: -$1,106, + pnlPercent: -6.3%, + }, + }, + ], + }, +}; + +// API data table with copy functionality +export const ApiEndpointsTable: Story = { + args: { + label: "API endpoints", + columns: [ + { + name: "ENDPOINT", + id: "endpoint", + isRowHeader: true, + fill: true, + }, + { + name: "METHOD", + id: "method", + width: 80, + }, + { + name: "DESCRIPTION", + id: "description", + width: 300, + }, + { + name: "COPY", + id: "copy", + width: 60, + alignment: "center", + }, + ], + rows: [ + { + id: "get-price", + data: { + endpoint: /api/v1/price/{`{symbol}`}, + method: GET, + description: "Get current price for a symbol", + copy: , + }, + }, + { + id: "post-order", + data: { + endpoint: /api/v1/orders, + method: POST, + description: "Create a new order", + copy: , + }, + }, + { + id: "delete-order", + data: { + endpoint: /api/v1/orders/{`{id}`}, + method: DELETE, + description: "Cancel an existing order", + copy: , + }, + }, + ], + }, +}; + +// Sticky header example +export const StickyHeaderTable: Story = { + render: () => ( +
+
+

Scroll down to see the sticky header in action

+
+ ({ + id: `row-${i}`, + data: { + index: i + 1, + data: `Row ${i + 1} data - scroll to see sticky header`, + }, + }))} + /> +
+ ), +}; + +// Table with dependencies (re-render optimization) +export const WithDependencies: Story = { + render: () => { + const [filter, setFilter] = useState(""); + + const allData = [ + { id: "1", name: "Apple", category: "Fruit" }, + { id: "2", name: "Carrot", category: "Vegetable" }, + { id: "3", name: "Banana", category: "Fruit" }, + { id: "4", name: "Broccoli", category: "Vegetable" }, + ]; + + const filteredData = allData.filter(item => + item.name.toLowerCase().includes(filter.toLowerCase()) || + item.category.toLowerCase().includes(filter.toLowerCase()) + ); + + return ( +
+ setFilter(e.target.value)} + className={styles.filterInput} + /> + ({ + id: item.id, + data: { + name: item.name, + category: item.category, + }, + }))} + dependencies={[filter]} + /> +
+ ); + }, +}; + +// Legacy export +export const Table = Default; \ No newline at end of file From d21ed0c7c828a79805609c418e4a694b05acc15d Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 17:40:48 +0100 Subject: [PATCH 31/32] docs: organize components into groups --- packages/component-library/src/AppShell/index.stories.tsx | 1 + packages/component-library/src/Badge/index.stories.tsx | 1 + packages/component-library/src/Breadcrumbs/index.stories.tsx | 1 + packages/component-library/src/Button/index.stories.tsx | 1 + packages/component-library/src/Card/index.stories.tsx | 1 + packages/component-library/src/CopyButton/index.stories.tsx | 1 + .../src/CrossfadeTabPanels/index.stories.tsx | 3 ++- .../src/DropdownCaretDown/index.stories.tsx | 1 + packages/component-library/src/EntityList/index.stories.tsx | 1 + packages/component-library/src/ErrorPage/index.stories.tsx | 1 + packages/component-library/src/Footer/index.stories.tsx | 1 + packages/component-library/src/Header/index.stories.tsx | 1 + packages/component-library/src/InfoBox/index.stories.tsx | 1 + packages/component-library/src/Link/index.stories.tsx | 1 + packages/component-library/src/MainNavTabs/index.stories.tsx | 1 + packages/component-library/src/Meter/index.stories.tsx | 1 + .../component-library/src/MobileNavTabs/index.stories.tsx | 1 + packages/component-library/src/NoResults/index.stories.tsx | 1 + .../component-library/src/NotFoundPage/index.stories.tsx | 1 + packages/component-library/src/Paginator/index.stories.tsx | 1 + packages/component-library/src/SearchInput/index.stories.tsx | 1 + packages/component-library/src/Select/index.stories.tsx | 1 + .../src/SingleToggleGroup/index.stories.tsx | 1 + packages/component-library/src/Skeleton/index.stories.tsx | 1 + packages/component-library/src/Spinner/index.stories.tsx | 1 + packages/component-library/src/StatCard/index.stories.tsx | 1 + packages/component-library/src/Status/index.stories.tsx | 5 +++-- packages/component-library/src/Switch/index.stories.tsx | 1 + packages/component-library/src/TabList/index.stories.tsx | 1 + packages/component-library/src/Table/index.stories.tsx | 1 + packages/component-library/src/Term/index.stories.tsx | 1 + 31 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/component-library/src/AppShell/index.stories.tsx b/packages/component-library/src/AppShell/index.stories.tsx index 862cfa0bae..b394b21a04 100644 --- a/packages/component-library/src/AppShell/index.stories.tsx +++ b/packages/component-library/src/AppShell/index.stories.tsx @@ -9,6 +9,7 @@ import { NotFoundPage } from "../NotFoundPage/index.jsx"; import { AppBody as AppShellComponent } from "./index.jsx"; const meta = { + title: "layouts & pages/AppShell", component: AppShellComponent, subcomponents: { ErrorPage, NoResults, NotFoundPage }, globals: { diff --git a/packages/component-library/src/Badge/index.stories.tsx b/packages/component-library/src/Badge/index.stories.tsx index bdaaede160..cb822db81b 100644 --- a/packages/component-library/src/Badge/index.stories.tsx +++ b/packages/component-library/src/Badge/index.stories.tsx @@ -4,6 +4,7 @@ import { Badge as BadgeComponent, SIZES, STYLES, VARIANTS } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "building blocks/Badge", component: BadgeComponent, argTypes: { children: { diff --git a/packages/component-library/src/Breadcrumbs/index.stories.tsx b/packages/component-library/src/Breadcrumbs/index.stories.tsx index 3eba9ce956..21819bd13f 100644 --- a/packages/component-library/src/Breadcrumbs/index.stories.tsx +++ b/packages/component-library/src/Breadcrumbs/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Breadcrumbs as BreadcrumbsComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/Breadcrumbs", component: BreadcrumbsComponent, argTypes: { label: { diff --git a/packages/component-library/src/Button/index.stories.tsx b/packages/component-library/src/Button/index.stories.tsx index 22dc46b37e..3d8730acee 100644 --- a/packages/component-library/src/Button/index.stories.tsx +++ b/packages/component-library/src/Button/index.stories.tsx @@ -4,6 +4,7 @@ import { Button as ButtonComponent, VARIANTS, SIZES } from "./index.jsx"; import { iconControl } from "../icon-control.jsx"; const meta = { + title: "forms & controls/Button", component: ButtonComponent, argTypes: { children: { diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index 4689c7efe2..402315d3a2 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -8,6 +8,7 @@ import { Card as CardComponent, VARIANTS } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "building blocks/Card", component: CardComponent, globals: { background: "primary", diff --git a/packages/component-library/src/CopyButton/index.stories.tsx b/packages/component-library/src/CopyButton/index.stories.tsx index a175099d1e..ce28c2cd06 100644 --- a/packages/component-library/src/CopyButton/index.stories.tsx +++ b/packages/component-library/src/CopyButton/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { CopyButton as CopyButtonComponent } from "./index.jsx"; const meta = { + title: "forms & controls/CopyButton", component: CopyButtonComponent, argTypes: { text: { diff --git a/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx index 826ed49c04..3df33de39e 100644 --- a/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx @@ -1,11 +1,12 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { CrossfadeTabPanels as CrossfadeTabPanelsComponent } from "./index.jsx"; import { TabList } from "../TabList/index.jsx"; import { Tabs } from "../unstyled/Tabs/index.jsx"; +import { CrossfadeTabPanels as CrossfadeTabPanelsComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "navigation & menus/CrossfadeTabPanels", component: CrossfadeTabPanelsComponent, parameters: { docs: { diff --git a/packages/component-library/src/DropdownCaretDown/index.stories.tsx b/packages/component-library/src/DropdownCaretDown/index.stories.tsx index 721161bbb5..8c2bda1ee8 100644 --- a/packages/component-library/src/DropdownCaretDown/index.stories.tsx +++ b/packages/component-library/src/DropdownCaretDown/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { DropdownCaretDown as DropdownCaretDownComponent } from "./index.jsx"; const meta = { + title: "building blocks/DropdownCaretDown", component: DropdownCaretDownComponent, argTypes: { width: { diff --git a/packages/component-library/src/EntityList/index.stories.tsx b/packages/component-library/src/EntityList/index.stories.tsx index 0a28a091b7..6e660d084c 100644 --- a/packages/component-library/src/EntityList/index.stories.tsx +++ b/packages/component-library/src/EntityList/index.stories.tsx @@ -5,6 +5,7 @@ import { EntityList as EntityListComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "data & tables/EntityList", component: EntityListComponent, argTypes: { label: { diff --git a/packages/component-library/src/ErrorPage/index.stories.tsx b/packages/component-library/src/ErrorPage/index.stories.tsx index 91f00ab6dc..b1435b9a76 100644 --- a/packages/component-library/src/ErrorPage/index.stories.tsx +++ b/packages/component-library/src/ErrorPage/index.stories.tsx @@ -4,6 +4,7 @@ import { fn } from "@storybook/test"; import { ErrorPage as ErrorPageComponent } from "./index.jsx"; const meta = { + title: "layouts & pages/ErrorPage", component: ErrorPageComponent, parameters: { layout: "fullscreen", diff --git a/packages/component-library/src/Footer/index.stories.tsx b/packages/component-library/src/Footer/index.stories.tsx index a6cbb40a6a..c4192c13fe 100644 --- a/packages/component-library/src/Footer/index.stories.tsx +++ b/packages/component-library/src/Footer/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Footer as FooterComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/Footer", component: FooterComponent, parameters: { layout: "fullscreen", diff --git a/packages/component-library/src/Header/index.stories.tsx b/packages/component-library/src/Header/index.stories.tsx index b5b059dd8d..8f37f87f63 100644 --- a/packages/component-library/src/Header/index.stories.tsx +++ b/packages/component-library/src/Header/index.stories.tsx @@ -8,6 +8,7 @@ import { MainNavTabs } from "../MainNavTabs/index.jsx"; import { Header as HeaderComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/Header", component: HeaderComponent, decorators: [ (Story) => ( diff --git a/packages/component-library/src/InfoBox/index.stories.tsx b/packages/component-library/src/InfoBox/index.stories.tsx index 28ff60f9c1..ad644af74a 100644 --- a/packages/component-library/src/InfoBox/index.stories.tsx +++ b/packages/component-library/src/InfoBox/index.stories.tsx @@ -6,6 +6,7 @@ import { iconControl } from "../icon-control.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "overlays & dialogs/InfoBox", component: InfoBoxComponent, argTypes: { variant: { diff --git a/packages/component-library/src/Link/index.stories.tsx b/packages/component-library/src/Link/index.stories.tsx index 1e186b0b6b..11c5dfbe58 100644 --- a/packages/component-library/src/Link/index.stories.tsx +++ b/packages/component-library/src/Link/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Link as LinkComponent } from "./index.jsx"; const meta = { + title: "building blocks/Link", component: LinkComponent, argTypes: { children: { diff --git a/packages/component-library/src/MainNavTabs/index.stories.tsx b/packages/component-library/src/MainNavTabs/index.stories.tsx index 64bc704836..882a27086c 100644 --- a/packages/component-library/src/MainNavTabs/index.stories.tsx +++ b/packages/component-library/src/MainNavTabs/index.stories.tsx @@ -4,6 +4,7 @@ import { Tabs } from "../unstyled/Tabs/index.jsx"; import { MainNavTabs as MainNavTabsComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/MainNavTabs", component: MainNavTabsComponent, argTypes: { tabs: { diff --git a/packages/component-library/src/Meter/index.stories.tsx b/packages/component-library/src/Meter/index.stories.tsx index e1c1241a29..a8d8a61a2a 100644 --- a/packages/component-library/src/Meter/index.stories.tsx +++ b/packages/component-library/src/Meter/index.stories.tsx @@ -4,6 +4,7 @@ import { Meter as MeterComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "data & tables/Meter", component: MeterComponent, argTypes: { value: { diff --git a/packages/component-library/src/MobileNavTabs/index.stories.tsx b/packages/component-library/src/MobileNavTabs/index.stories.tsx index 60d1d96203..e2cdfc29a9 100644 --- a/packages/component-library/src/MobileNavTabs/index.stories.tsx +++ b/packages/component-library/src/MobileNavTabs/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { MobileNavTabs as MobileNavTabsComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/MobileNavTabs", component: MobileNavTabsComponent, parameters: { layout: "padded", diff --git a/packages/component-library/src/NoResults/index.stories.tsx b/packages/component-library/src/NoResults/index.stories.tsx index 723c66970d..2653f5d97e 100644 --- a/packages/component-library/src/NoResults/index.stories.tsx +++ b/packages/component-library/src/NoResults/index.stories.tsx @@ -6,6 +6,7 @@ import { iconControl } from "../icon-control.jsx"; import { NoResults as NoResultsComponent } from "./index.jsx"; const meta = { + title: "layouts & pages/NoResults", component: NoResultsComponent, parameters: { layout: "fullscreen", diff --git a/packages/component-library/src/NotFoundPage/index.stories.tsx b/packages/component-library/src/NotFoundPage/index.stories.tsx index 713bdafa17..de41a60d1b 100644 --- a/packages/component-library/src/NotFoundPage/index.stories.tsx +++ b/packages/component-library/src/NotFoundPage/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { NotFoundPage as NotFoundPageComponent } from "./index.jsx"; const meta = { + title: "layouts & pages/NotFoundPage", component: NotFoundPageComponent, parameters: { layout: "fullscreen", diff --git a/packages/component-library/src/Paginator/index.stories.tsx b/packages/component-library/src/Paginator/index.stories.tsx index 4c1d1b4aa4..52258f480e 100644 --- a/packages/component-library/src/Paginator/index.stories.tsx +++ b/packages/component-library/src/Paginator/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Paginator as PaginatorComponent } from "./index.jsx"; const meta = { + title: "data & tables/Paginator", component: PaginatorComponent, parameters: { layout: "padded", diff --git a/packages/component-library/src/SearchInput/index.stories.tsx b/packages/component-library/src/SearchInput/index.stories.tsx index 342eaf9bed..ef3ebcafec 100644 --- a/packages/component-library/src/SearchInput/index.stories.tsx +++ b/packages/component-library/src/SearchInput/index.stories.tsx @@ -6,6 +6,7 @@ import { SearchInput as SearchInputComponent, SIZES } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "forms & controls/SearchInput", component: SearchInputComponent, argTypes: { label: { diff --git a/packages/component-library/src/Select/index.stories.tsx b/packages/component-library/src/Select/index.stories.tsx index 1ac09fe327..9e46848f2d 100644 --- a/packages/component-library/src/Select/index.stories.tsx +++ b/packages/component-library/src/Select/index.stories.tsx @@ -10,6 +10,7 @@ import styles from "./index.stories.module.scss"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const { children, beforeIcon, ...argTypes } = buttonMeta.argTypes; const meta = { + title: "forms & controls/Select", component: SelectComponent, argTypes: { ...argTypes, diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.tsx b/packages/component-library/src/SingleToggleGroup/index.stories.tsx index 8a38c4db0f..f6deaf269a 100644 --- a/packages/component-library/src/SingleToggleGroup/index.stories.tsx +++ b/packages/component-library/src/SingleToggleGroup/index.stories.tsx @@ -6,6 +6,7 @@ import { SingleToggleGroup as SingleToggleGroupComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "forms & controls/SingleToggleGroup", component: SingleToggleGroupComponent, argTypes: { items: { diff --git a/packages/component-library/src/Skeleton/index.stories.tsx b/packages/component-library/src/Skeleton/index.stories.tsx index 3db5fddce7..c77589845f 100644 --- a/packages/component-library/src/Skeleton/index.stories.tsx +++ b/packages/component-library/src/Skeleton/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Skeleton as SkeletonComponent } from "./index.jsx"; const meta = { + title: "loading/Skeleton", component: SkeletonComponent, argTypes: { label: { diff --git a/packages/component-library/src/Spinner/index.stories.tsx b/packages/component-library/src/Spinner/index.stories.tsx index 8eac92a0db..8c3a2ef007 100644 --- a/packages/component-library/src/Spinner/index.stories.tsx +++ b/packages/component-library/src/Spinner/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Spinner as SpinnerComponent } from "./index.jsx"; const meta = { + title: "loading/Spinner", component: SpinnerComponent, argTypes: { label: { diff --git a/packages/component-library/src/StatCard/index.stories.tsx b/packages/component-library/src/StatCard/index.stories.tsx index 0e128bd7fc..d1ce452ade 100644 --- a/packages/component-library/src/StatCard/index.stories.tsx +++ b/packages/component-library/src/StatCard/index.stories.tsx @@ -13,6 +13,7 @@ const cardMetaArgTypes = () => { }; const meta = { + title: "data & tables/StatCard", component: StatCardComponent, parameters: { layout: "padded", diff --git a/packages/component-library/src/Status/index.stories.tsx b/packages/component-library/src/Status/index.stories.tsx index d0380065b7..268feba1f4 100644 --- a/packages/component-library/src/Status/index.stories.tsx +++ b/packages/component-library/src/Status/index.stories.tsx @@ -1,14 +1,15 @@ import type { Meta, StoryObj } from "@storybook/react"; import { - Status as StatusComponent, - VARIANTS, SIZES, + Status as StatusComponent, STYLES, + VARIANTS, } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "building blocks/Status", component: StatusComponent, argTypes: { children: { diff --git a/packages/component-library/src/Switch/index.stories.tsx b/packages/component-library/src/Switch/index.stories.tsx index b12e55df95..4a3def73f3 100644 --- a/packages/component-library/src/Switch/index.stories.tsx +++ b/packages/component-library/src/Switch/index.stories.tsx @@ -6,6 +6,7 @@ import { Switch as SwitchComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { + title: "forms & controls/Switch", component: SwitchComponent, argTypes: { isDisabled: { diff --git a/packages/component-library/src/TabList/index.stories.tsx b/packages/component-library/src/TabList/index.stories.tsx index ef406a5a6d..889051ff8b 100644 --- a/packages/component-library/src/TabList/index.stories.tsx +++ b/packages/component-library/src/TabList/index.stories.tsx @@ -4,6 +4,7 @@ import { Tabs as UnstyledTabs } from "../unstyled/Tabs/index.jsx"; import { TabList as TabListComponent } from "./index.jsx"; const meta = { + title: "navigation & menus/TabList", component: TabListComponent, argTypes: { items: { diff --git a/packages/component-library/src/Table/index.stories.tsx b/packages/component-library/src/Table/index.stories.tsx index 6dc63e5ea8..9ba7e75560 100644 --- a/packages/component-library/src/Table/index.stories.tsx +++ b/packages/component-library/src/Table/index.stories.tsx @@ -11,6 +11,7 @@ import { Table as TableComponent, type ColumnConfig, type RowConfig, type SortDe import styles from "./index.stories.module.scss"; const meta = { + title: "data & tables/Table", component: TableComponent, parameters: { layout: "padded", diff --git a/packages/component-library/src/Term/index.stories.tsx b/packages/component-library/src/Term/index.stories.tsx index eccde5f6ea..e0555140e8 100644 --- a/packages/component-library/src/Term/index.stories.tsx +++ b/packages/component-library/src/Term/index.stories.tsx @@ -3,6 +3,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Term as TermComponent } from "./index.jsx"; const meta = { + title: "typography/Term", component: TermComponent, argTypes: { children: { From d2923729273021dd5e820b63a684158129886365 Mon Sep 17 00:00:00 2001 From: Aaron Bassett Date: Tue, 3 Jun 2025 18:09:12 +0100 Subject: [PATCH 32/32] fix: apply formatter and linter fixes --- .../src/AppShell/index.stories.tsx | 50 +-- .../src/Badge/index.stories.module.scss | 2 +- .../src/Badge/index.stories.tsx | 7 +- .../src/Card/index.stories.module.scss | 2 +- .../src/Card/index.stories.tsx | 13 +- .../index.stories.module.scss | 2 +- .../src/CrossfadeTabPanels/index.stories.tsx | 55 ++- .../src/DropdownCaretDown/index.stories.tsx | 2 +- .../src/EntityList/index.stories.module.scss | 2 +- .../src/EntityList/index.stories.tsx | 4 +- .../src/ErrorPage/index.stories.tsx | 2 +- .../component-library/src/ErrorPage/index.tsx | 2 +- .../src/Header/index.stories.tsx | 2 +- .../src/InfoBox/index.stories.module.scss | 2 +- .../src/InfoBox/index.stories.tsx | 13 +- .../src/MainNavTabs/index.stories.tsx | 2 +- .../src/Meter/index.stories.module.scss | 2 +- .../src/Meter/index.stories.tsx | 2 +- .../src/NoResults/index.stories.tsx | 5 +- .../component-library/src/NoResults/index.tsx | 2 +- .../src/NotFoundPage/index.stories.tsx | 2 +- .../src/SearchInput/index.stories.module.scss | 8 +- .../src/SearchInput/index.stories.tsx | 19 - .../src/Select/index.stories.module.scss | 25 +- .../src/Select/index.stories.tsx | 102 +---- .../index.stories.module.scss | 69 --- .../src/SingleToggleGroup/index.stories.tsx | 159 ++----- .../src/StatCard/index.stories.module.scss | 6 +- .../src/StatCard/index.stories.tsx | 97 ++++- .../src/Status/index.stories.module.scss | 4 +- .../src/Status/index.stories.tsx | 234 +++++++--- .../src/Switch/index.stories.module.scss | 78 +--- .../src/Switch/index.stories.tsx | 249 +---------- .../src/TabList/index.stories.tsx | 2 +- .../src/Table/index.stories.module.scss | 41 +- .../src/Table/index.stories.tsx | 404 +++++++----------- .../component-library/src/icon-control.tsx | 2 +- 37 files changed, 608 insertions(+), 1066 deletions(-) diff --git a/packages/component-library/src/AppShell/index.stories.tsx b/packages/component-library/src/AppShell/index.stories.tsx index b394b21a04..78df3b18af 100644 --- a/packages/component-library/src/AppShell/index.stories.tsx +++ b/packages/component-library/src/AppShell/index.stories.tsx @@ -1,12 +1,14 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { ErrorPage, type Props as ErrorPageProps } from "../ErrorPage/index.jsx"; +import { AppBody as AppShellComponent } from "./index.jsx"; +import type { Props as ErrorPageProps } from "../ErrorPage/index.jsx"; +import { ErrorPage } from "../ErrorPage/index.jsx"; import { NetworkError as NetworkErrorStory } from "../ErrorPage/index.stories.jsx"; import { InfoBox } from "../InfoBox/index.jsx"; -import { NoResults, type Props as NoResultsProps } from "../NoResults/index.jsx"; +import type { Props as NoResultsProps } from "../NoResults/index.jsx"; +import { NoResults } from "../NoResults/index.jsx"; import { WarningVariant as WarningVariantStory } from "../NoResults/index.stories.jsx"; import { NotFoundPage } from "../NotFoundPage/index.jsx"; -import { AppBody as AppShellComponent } from "./index.jsx"; const meta = { title: "layouts & pages/AppShell", @@ -14,14 +16,14 @@ const meta = { subcomponents: { ErrorPage, NoResults, NotFoundPage }, globals: { args: { - appName: "Component Library", - children: "Hello world!", - tabs: [ - { children: "Home", segment: "" }, - { children: "Products", segment: "products" }, - { children: "Developers", segment: "developers" }, - ], - }, + appName: "Component Library", + children: "Hello world!", + tabs: [ + { children: "Home", segment: "" }, + { children: "Products", segment: "products" }, + { children: "Developers", segment: "developers" }, + ], + }, bare: true, theme: { disable: true, @@ -58,48 +60,46 @@ export default meta; export const AppShell = { args: { - ...meta.globals?.args, + ...meta.globals.args, }, render: (args) => ( - - {args.children} - + {args.children} - ) + ), } satisfies StoryObj; type Story = StoryObj; export const ErrorStory: Story = { args: { - ...meta.globals?.args, + ...meta.globals.args, }, render: (args) => ( - + - ) + ), }; export const NoResultsStory: Story = { args: { - ...meta.globals?.args, + ...meta.globals.args, }, render: (args) => ( - + - ) + ), }; export const NotFoundStory: Story = { args: { - ...meta.globals?.args, + ...meta.globals.args, }, render: (args) => ( - ) -}; \ No newline at end of file + ), +}; diff --git a/packages/component-library/src/Badge/index.stories.module.scss b/packages/component-library/src/Badge/index.stories.module.scss index 68dbaa6d30..e4579798d6 100644 --- a/packages/component-library/src/Badge/index.stories.module.scss +++ b/packages/component-library/src/Badge/index.stories.module.scss @@ -5,4 +5,4 @@ gap: theme.spacing(2); flex-wrap: wrap; align-items: center; -} \ No newline at end of file +} diff --git a/packages/component-library/src/Badge/index.stories.tsx b/packages/component-library/src/Badge/index.stories.tsx index cb822db81b..cdd1eb6db4 100644 --- a/packages/component-library/src/Badge/index.stories.tsx +++ b/packages/component-library/src/Badge/index.stories.tsx @@ -50,7 +50,11 @@ export const Badge = { type Story = StoryObj; -const renderAllVariants = (style: typeof STYLES[number], size: typeof SIZES[number], children: React.ReactNode) => ( +const renderAllVariants = ( + style: (typeof STYLES)[number], + size: (typeof SIZES)[number], + children: React.ReactNode, +) => (
{VARIANTS.map((variant) => ( @@ -136,7 +140,6 @@ export const OutlineXS: Story = { }, }; - export const OutlineMD: Story = { args: { children: "Badge", diff --git a/packages/component-library/src/Card/index.stories.module.scss b/packages/component-library/src/Card/index.stories.module.scss index b034506557..c3a8343cf1 100644 --- a/packages/component-library/src/Card/index.stories.module.scss +++ b/packages/component-library/src/Card/index.stories.module.scss @@ -55,4 +55,4 @@ display: flex; flex-direction: column; gap: theme.spacing(4); -} \ No newline at end of file +} diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index 402315d3a2..7618ba3dfb 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -1,5 +1,6 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; import { Badge } from "../Badge/index.jsx"; import { Button } from "../Button/index.jsx"; @@ -87,8 +88,8 @@ export const BasicCard: Story = { args: { children: (

- This is a basic card with just content. It can contain any React elements - and will display them with appropriate styling. + This is a basic card with just content. It can contain any React + elements and will display them with appropriate styling.

), variant: "secondary", @@ -102,7 +103,7 @@ export const WithTitleAndIcon: Story = { children: (

This card has a title and an icon in the header.

-

Icons help users quickly identify the card's purpose.

+

Icons help users quickly identify the card's purpose.

), variant: "secondary", @@ -146,9 +147,7 @@ export const WithFooter: Story = { ), footer: (
- - Last updated 5 minutes ago - + Last updated 5 minutes ago @@ -175,7 +174,7 @@ export const AsLink: Story = { export const AsButton: Story = { args: { - onPress: () => alert("Card clicked!"), + onPress: fn(), icon: , title: "Interactive Card", children: ( diff --git a/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss b/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss index ade719d9a6..4fd05c9f05 100644 --- a/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.module.scss @@ -112,4 +112,4 @@ &:hover { background-color: theme.color("button", "primary", "background", "hover"); } -} \ No newline at end of file +} diff --git a/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx index 3df33de39e..18a48fc519 100644 --- a/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx @@ -1,9 +1,9 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { TabList } from "../TabList/index.jsx"; -import { Tabs } from "../unstyled/Tabs/index.jsx"; import { CrossfadeTabPanels as CrossfadeTabPanelsComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; +import { TabList } from "../TabList/index.jsx"; +import { Tabs } from "../unstyled/Tabs/index.jsx"; const meta = { title: "navigation & menus/CrossfadeTabPanels", @@ -18,7 +18,8 @@ const meta = { }, argTypes: { items: { - description: "Array of tab panel items with id, optional className, and children", + description: + "Array of tab panel items with id, optional className, and children", table: { category: "Props", }, @@ -156,8 +157,14 @@ export const DifferentHeights: Story = {

Medium Content

This tab has more content than the first one.

-

It includes multiple paragraphs to show how the crossfade handles different heights.

-

The animation should smoothly transition between different content sizes.

+

+ It includes multiple paragraphs to show how the crossfade + handles different heights. +

+

+ The animation should smoothly transition between different + content sizes. +

), }, @@ -166,13 +173,22 @@ export const DifferentHeights: Story = { children: (

Long Content

-

This tab contains the most content to demonstrate height transitions.

+

+ This tab contains the most content to demonstrate height + transitions. +

Section 1

Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Section 2

-

Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

+

+ Sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. +

Section 3

-

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.

+

+ Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris. +

), }, @@ -221,11 +237,12 @@ export const ComplexContent: Story = {

Chart Placeholder

-
- Chart would go here -
+
Chart would go here
-

Analytics data and insights would be displayed in this panel.

+

+ Analytics data and insights would be displayed in this + panel. +

), @@ -237,12 +254,16 @@ export const ComplexContent: Story = {

Settings

- - + +
- - @@ -258,4 +279,4 @@ export const ComplexContent: Story = { /> ), -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/DropdownCaretDown/index.stories.tsx b/packages/component-library/src/DropdownCaretDown/index.stories.tsx index 8c2bda1ee8..b0dbe9f8a5 100644 --- a/packages/component-library/src/DropdownCaretDown/index.stories.tsx +++ b/packages/component-library/src/DropdownCaretDown/index.stories.tsx @@ -51,4 +51,4 @@ export default meta; type Story = StoryObj; -export const Default: Story = {}; \ No newline at end of file +export const Default: Story = {}; diff --git a/packages/component-library/src/EntityList/index.stories.module.scss b/packages/component-library/src/EntityList/index.stories.module.scss index a5df494fac..6e01c79763 100644 --- a/packages/component-library/src/EntityList/index.stories.module.scss +++ b/packages/component-library/src/EntityList/index.stories.module.scss @@ -8,4 +8,4 @@ .actionsContainer { display: flex; gap: theme.spacing(2); -} \ No newline at end of file +} diff --git a/packages/component-library/src/EntityList/index.stories.tsx b/packages/component-library/src/EntityList/index.stories.tsx index 6e660d084c..87e21b645b 100644 --- a/packages/component-library/src/EntityList/index.stories.tsx +++ b/packages/component-library/src/EntityList/index.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Badge } from "../Badge/index.jsx"; import { EntityList as EntityListComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; +import { Badge } from "../Badge/index.jsx"; const meta = { title: "data & tables/EntityList", @@ -232,4 +232,4 @@ export const ComplexContent: Story = { }, ], }, -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/ErrorPage/index.stories.tsx b/packages/component-library/src/ErrorPage/index.stories.tsx index b1435b9a76..d24b436a41 100644 --- a/packages/component-library/src/ErrorPage/index.stories.tsx +++ b/packages/component-library/src/ErrorPage/index.stories.tsx @@ -73,4 +73,4 @@ export const LongErrorMessage: Story = { ), reset: fn(), }, -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/ErrorPage/index.tsx b/packages/component-library/src/ErrorPage/index.tsx index bad5547241..1e84001586 100644 --- a/packages/component-library/src/ErrorPage/index.tsx +++ b/packages/component-library/src/ErrorPage/index.tsx @@ -5,7 +5,7 @@ import { Button } from "../Button"; import { useLogger } from "../useLogger"; import styles from "./index.module.scss"; -type Props = { +export type Props = { error: Error & { digest?: string }; reset?: () => void; }; diff --git a/packages/component-library/src/Header/index.stories.tsx b/packages/component-library/src/Header/index.stories.tsx index 8f37f87f63..0e8f525fc5 100644 --- a/packages/component-library/src/Header/index.stories.tsx +++ b/packages/component-library/src/Header/index.stories.tsx @@ -1,11 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; import { ThemeProvider } from "next-themes"; +import { Header as HeaderComponent } from "./index.jsx"; import { TabRoot } from "../AppShell/tabs.jsx"; import { Badge } from "../Badge/index.jsx"; import { Button } from "../Button/index.jsx"; import { MainNavTabs } from "../MainNavTabs/index.jsx"; -import { Header as HeaderComponent } from "./index.jsx"; const meta = { title: "navigation & menus/Header", diff --git a/packages/component-library/src/InfoBox/index.stories.module.scss b/packages/component-library/src/InfoBox/index.stories.module.scss index 23f471ae6c..a7fb5f34c5 100644 --- a/packages/component-library/src/InfoBox/index.stories.module.scss +++ b/packages/component-library/src/InfoBox/index.stories.module.scss @@ -4,4 +4,4 @@ display: flex; flex-direction: column; gap: theme.spacing(4); -} \ No newline at end of file +} diff --git a/packages/component-library/src/InfoBox/index.stories.tsx b/packages/component-library/src/InfoBox/index.stories.tsx index ad644af74a..e4d7c1b4a1 100644 --- a/packages/component-library/src/InfoBox/index.stories.tsx +++ b/packages/component-library/src/InfoBox/index.stories.tsx @@ -1,8 +1,8 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; -import { InfoBox as InfoBoxComponent, VARIANTS } from "./index.jsx"; import { iconControl } from "../icon-control.jsx"; +import { InfoBox as InfoBoxComponent, VARIANTS } from "./index.jsx"; import styles from "./index.stories.module.scss"; const meta = { @@ -47,7 +47,8 @@ type Story = StoryObj; export const Default: Story = { args: { - children: "This is an informational message to help users understand something important.", + children: + "This is an informational message to help users understand something important.", }, }; @@ -131,7 +132,8 @@ export const SuccessNotification: Story = { args: { variant: "success", header: "Payment Successful!", - children: "Your transaction has been processed successfully. You should receive a confirmation email shortly.", + children: + "Your transaction has been processed successfully. You should receive a confirmation email shortly.", }, }; @@ -141,8 +143,9 @@ export const DataExample: Story = { header: "API Response", children: (
-        {JSON.stringify({ status: "ok", timestamp: 1234567890 }, null, 2)}
+        {/* eslint-disable-next-line unicorn/no-null */}
+        {JSON.stringify({ status: "ok", timestamp: 1_234_567_890 }, null, 2)}
       
), }, -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/MainNavTabs/index.stories.tsx b/packages/component-library/src/MainNavTabs/index.stories.tsx index 882a27086c..fab1e26b97 100644 --- a/packages/component-library/src/MainNavTabs/index.stories.tsx +++ b/packages/component-library/src/MainNavTabs/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Tabs } from "../unstyled/Tabs/index.jsx"; import { MainNavTabs as MainNavTabsComponent } from "./index.jsx"; +import { Tabs } from "../unstyled/Tabs/index.jsx"; const meta = { title: "navigation & menus/MainNavTabs", diff --git a/packages/component-library/src/Meter/index.stories.module.scss b/packages/component-library/src/Meter/index.stories.module.scss index 39b52f2ee0..af35a10a26 100644 --- a/packages/component-library/src/Meter/index.stories.module.scss +++ b/packages/component-library/src/Meter/index.stories.module.scss @@ -14,4 +14,4 @@ font-weight: 600; color: theme.color("heading"); } -} \ No newline at end of file +} diff --git a/packages/component-library/src/Meter/index.stories.tsx b/packages/component-library/src/Meter/index.stories.tsx index a8d8a61a2a..d28636ed77 100644 --- a/packages/component-library/src/Meter/index.stories.tsx +++ b/packages/component-library/src/Meter/index.stories.tsx @@ -198,4 +198,4 @@ export const PerformanceScore: Story = {
), -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/NoResults/index.stories.tsx b/packages/component-library/src/NoResults/index.stories.tsx index 2653f5d97e..5927d58bbb 100644 --- a/packages/component-library/src/NoResults/index.stories.tsx +++ b/packages/component-library/src/NoResults/index.stories.tsx @@ -165,7 +165,8 @@ export const NoFavorites: Story = { export const LongQuery: Story = { args: { - query: "This is a very long search query that someone might type when looking for something very specific in the application", + query: + "This is a very long search query that someone might type when looking for something very specific in the application", onClearSearch: fn(), }, -}; \ No newline at end of file +}; diff --git a/packages/component-library/src/NoResults/index.tsx b/packages/component-library/src/NoResults/index.tsx index 153692571d..2aa9f83aaa 100644 --- a/packages/component-library/src/NoResults/index.tsx +++ b/packages/component-library/src/NoResults/index.tsx @@ -4,8 +4,8 @@ import { MagnifyingGlass } from "@phosphor-icons/react/dist/ssr/MagnifyingGlass" import clsx from "clsx"; import type { ReactNode } from "react"; -import { Button } from "../Button/index.jsx"; import styles from "./index.module.scss"; +import { Button } from "../Button/index.jsx"; export type Props = { className?: string | undefined; diff --git a/packages/component-library/src/NotFoundPage/index.stories.tsx b/packages/component-library/src/NotFoundPage/index.stories.tsx index de41a60d1b..197bd0cd11 100644 --- a/packages/component-library/src/NotFoundPage/index.stories.tsx +++ b/packages/component-library/src/NotFoundPage/index.stories.tsx @@ -14,4 +14,4 @@ export default meta; type Story = StoryObj; -export const Default: Story = {}; \ No newline at end of file +export const Default: Story = {}; diff --git a/packages/component-library/src/SearchInput/index.stories.module.scss b/packages/component-library/src/SearchInput/index.stories.module.scss index 793b5ef1ae..04b138dfd4 100644 --- a/packages/component-library/src/SearchInput/index.stories.module.scss +++ b/packages/component-library/src/SearchInput/index.stories.module.scss @@ -1,14 +1,8 @@ @use "../theme"; -.controlledContainer { - > p { - margin-top: theme.spacing(4); - } -} - .sizesContainer, .statesContainer { display: flex; flex-direction: column; gap: theme.spacing(4); -} \ No newline at end of file +} diff --git a/packages/component-library/src/SearchInput/index.stories.tsx b/packages/component-library/src/SearchInput/index.stories.tsx index ef3ebcafec..e391106fb0 100644 --- a/packages/component-library/src/SearchInput/index.stories.tsx +++ b/packages/component-library/src/SearchInput/index.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; -import { useState } from "react"; import { SearchInput as SearchInputComponent, SIZES } from "./index.jsx"; import styles from "./index.stories.module.scss"; @@ -157,24 +156,6 @@ export const WithSubmitHandler: Story = { }, }; -export const ControlledInput: Story = { - render: () => { - const [value, setValue] = useState(""); - - return ( -
- alert(`Searching for: ${value}`)} - placeholder="Controlled search input" - /> -

Current value: {value}

-
- ); - }, -}; - export const AllSizes: Story = { render: () => (
diff --git a/packages/component-library/src/Select/index.stories.module.scss b/packages/component-library/src/Select/index.stories.module.scss index 4c580964d4..0a1e52099e 100644 --- a/packages/component-library/src/Select/index.stories.module.scss +++ b/packages/component-library/src/Select/index.stories.module.scss @@ -17,7 +17,7 @@ display: flex; align-items: center; gap: theme.spacing(4); - + > label { min-width: 80px; font-size: theme.font-size("xs"); @@ -28,21 +28,10 @@ display: grid; grid-template-columns: repeat(3, 1fr); gap: theme.spacing(8); - align-items: center; - justify-items: center; + place-items: center center; min-height: 300px; } -.controlledContainer { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - - > p { - font-size: theme.font-size("xs"); - } -} - .iconsGrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); @@ -59,20 +48,20 @@ width: 8px; height: 8px; border-radius: 50%; - + &[data-status="active"] { background-color: #10b981; } - + &[data-status="inactive"] { background-color: #ef4444; } - + &[data-status="pending"] { background-color: #f59e0b; } - + &[data-status="archived"] { background-color: #6b7280; } -} \ No newline at end of file +} diff --git a/packages/component-library/src/Select/index.stories.tsx b/packages/component-library/src/Select/index.stories.tsx index 9e46848f2d..27d71b7096 100644 --- a/packages/component-library/src/Select/index.stories.tsx +++ b/packages/component-library/src/Select/index.stories.tsx @@ -1,11 +1,10 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; -import { useState } from "react"; -import { SIZES, VARIANTS } from "../Button/index.jsx"; -import buttonMeta from "../Button/index.stories.jsx"; import { Select as SelectComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; +import { SIZES, VARIANTS } from "../Button/index.jsx"; +import buttonMeta from "../Button/index.stories.jsx"; // eslint-disable-next-line @typescript-eslint/no-unused-vars const { children, beforeIcon, ...argTypes } = buttonMeta.argTypes; @@ -98,11 +97,7 @@ type Story = StoryObj; export const Default: Story = { args: { defaultSelectedKey: "option1", - options: [ - { id: "option1" }, - { id: "option2" }, - { id: "option3" }, - ], + options: [{ id: "option1" }, { id: "option2" }, { id: "option3" }], variant: "primary", size: "md", hideLabel: true, @@ -200,11 +195,7 @@ export const Grouped: Story = { }, { name: "Mobile Frameworks", - options: [ - { id: "react-native" }, - { id: "flutter" }, - { id: "ionic" }, - ], + options: [{ id: "react-native" }, { id: "flutter" }, { id: "ionic" }], }, ], hideLabel: true, @@ -219,18 +210,11 @@ export const GroupedWithHiddenLabels: Story = { optionGroups: [ { name: "User Roles", - options: [ - { id: "admin" }, - { id: "editor" }, - { id: "viewer" }, - ], + options: [{ id: "admin" }, { id: "editor" }, { id: "viewer" }], }, { name: "System Roles", - options: [ - { id: "super-admin" }, - { id: "moderator" }, - ], + options: [{ id: "super-admin" }, { id: "moderator" }], }, ], show: (value) => { @@ -258,11 +242,7 @@ export const AllSizes: Story = { (
- +
))}
@@ -333,43 +309,10 @@ export const States: Story = { }, }; -export const ControlledExample: Story = { - render: () => { - const [selected, setSelected] = useState("apple"); - const fruits = [ - { id: "apple", name: "Apple", emoji: "🍎" }, - { id: "banana", name: "Banana", emoji: "🍌" }, - { id: "orange", name: "Orange", emoji: "🍊" }, - { id: "grape", name: "Grape", emoji: "🍇" }, - ]; - - return ( -
- `${value.emoji} ${value.name}`} - label="Favorite fruit" - hideLabel={true} - variant="primary" - size="md" - /> -

You selected: {fruits.find(f => f.id === selected)?.name}

-
- ); - }, -}; - export const WithButtonLabel: Story = { args: { defaultSelectedKey: "en", - options: [ - { id: "en" }, - { id: "es" }, - { id: "fr" }, - { id: "de" }, - ], + options: [{ id: "en" }, { id: "es" }, { id: "fr" }, { id: "de" }], show: (value) => { const languages = { en: "English", @@ -389,11 +332,7 @@ export const WithButtonLabel: Story = { export const WithDefaultButtonLabel: Story = { args: { - options: [ - { id: "small" }, - { id: "medium" }, - { id: "large" }, - ], + options: [{ id: "small" }, { id: "medium" }, { id: "large" }], defaultButtonLabel: "Select size...", label: "Product size", hideLabel: false, @@ -486,10 +425,7 @@ export const WithIconsAndCustomContent: Story = { const label = statuses[value.id as keyof typeof statuses]; return ( - + {label} ); diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.module.scss b/packages/component-library/src/SingleToggleGroup/index.stories.module.scss index 6e6407bb39..2439152bd1 100644 --- a/packages/component-library/src/SingleToggleGroup/index.stories.module.scss +++ b/packages/component-library/src/SingleToggleGroup/index.stories.module.scss @@ -5,72 +5,3 @@ align-items: center; gap: theme.spacing(2); } - -.controlledContainer { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - - > p { - font-size: theme.font-size("sm"); - color: theme.color("paragraph"); - } -} - -.pricingContainer { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - - > h3 { - margin: 0; - font-size: theme.font-size("lg"); - font-weight: 600; - color: theme.color("heading"); - } -} - -.pricingDetails { - padding: theme.spacing(4); - background-color: theme.color("background", "secondary"); - border-radius: theme.border-radius("md"); - border: 1px solid theme.color("border"); - - > p { - margin: 0; - font-size: theme.font-size("sm"); - color: theme.color("paragraph"); - } -} - -.filterContainer { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - - > p { - font-size: theme.font-size("sm"); - color: theme.color("paragraph"); - } -} - -.statusOption { - display: flex; - align-items: center; - gap: theme.spacing(2); -} - -.count { - display: inline-flex; - align-items: center; - justify-content: center; - min-width: 20px; - height: 20px; - padding: 0 theme.spacing(2); - background-color: theme.color("background", "secondary"); - color: theme.color("muted"); - border-radius: theme.border-radius("full"); - font-size: theme.font-size("xs"); - font-weight: 500; - line-height: 1; -} \ No newline at end of file diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.tsx b/packages/component-library/src/SingleToggleGroup/index.stories.tsx index f6deaf269a..a2ef8b6106 100644 --- a/packages/component-library/src/SingleToggleGroup/index.stories.tsx +++ b/packages/component-library/src/SingleToggleGroup/index.stories.tsx @@ -1,6 +1,5 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; -import { useState } from "react"; import { SingleToggleGroup as SingleToggleGroupComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; @@ -86,35 +85,35 @@ export const ViewToggle: Story = { export const WithIcons: Story = { args: { items: [ - { - id: "grid", + { + id: "grid", children: ( Grid ), - "aria-label": "Grid view" + "aria-label": "Grid view", }, - { - id: "list", + { + id: "list", children: ( List ), - "aria-label": "List view" + "aria-label": "List view", }, - { - id: "table", + { + id: "table", children: ( Table ), - "aria-label": "Table view" + "aria-label": "Table view", }, ], defaultSelectedKeys: ["grid"], @@ -124,25 +123,25 @@ export const WithIcons: Story = { export const IconOnly: Story = { args: { items: [ - { - id: "bold", + { + id: "bold", children: , - "aria-label": "Bold" + "aria-label": "Bold", }, - { - id: "italic", + { + id: "italic", children: , - "aria-label": "Italic" + "aria-label": "Italic", }, - { - id: "underline", + { + id: "underline", children: , - "aria-label": "Underline" + "aria-label": "Underline", }, - { - id: "strikethrough", + { + id: "strikethrough", children: , - "aria-label": "Strikethrough" + "aria-label": "Strikethrough", }, ], defaultSelectedKeys: ["bold"], @@ -163,30 +162,6 @@ export const TimeRanges: Story = { }, }; -export const ControlledExample: Story = { - render: () => { - const [selectedTab, setSelectedTab] = useState("overview"); - - const tabs = [ - { id: "overview", children: "Overview" }, - { id: "analytics", children: "Analytics" }, - { id: "reports", children: "Reports" }, - { id: "settings", children: "Settings" }, - ]; - - return ( -
- -

Current tab: {selectedTab}

-
- ); - }, -}; - export const DisabledGroup: Story = { args: { items: [ @@ -225,76 +200,47 @@ export const SortingOptions: Story = { export const ChartTypes: Story = { args: { items: [ - { - id: "line", + { + id: "line", children: ( Line - ) + ), }, - { - id: "bar", + { + id: "bar", children: ( Bar - ) + ), }, - { - id: "pie", + { + id: "pie", children: ( Pie - ) + ), }, - { - id: "area", + { + id: "area", children: ( Area - ) + ), }, ], defaultSelectedKeys: ["line"], }, }; -export const PricingPlans: Story = { - render: () => { - const [selectedPlan, setSelectedPlan] = useState("monthly"); - - const plans = [ - { id: "monthly", children: "Monthly" }, - { id: "yearly", children: "Yearly (Save 20%)" }, - ]; - - return ( -
-

Billing Period

- -
- {selectedPlan === "monthly" ? ( -

$29/month - Billed monthly

- ) : ( -

$278/year - Billed annually (Save $70)

- )} -
-
- ); - }, -}; - export const NetworkSelection: Story = { args: { items: [ @@ -320,42 +266,5 @@ export const LanguageSelector: Story = { }, }; -export const StatusFilter: Story = { - render: () => { - const [status, setStatus] = useState("all"); - - const statusOptions = [ - { id: "all", children: "All" }, - { id: "active", children: "Active" }, - { id: "inactive", children: "Inactive" }, - { id: "pending", children: "Pending" }, - ]; - - const getStatusCount = (statusId: string | number) => { - const counts = { all: 156, active: 89, inactive: 45, pending: 22 }; - return counts[statusId as keyof typeof counts] || 0; - }; - - return ( -
- ({ - ...option, - children: ( - - {option.children} - {getStatusCount(option.id)} - - ) - }))} - selectedKey={status} - onSelectionChange={setStatus} - /> -

Showing {getStatusCount(status)} items with status: {status}

-
- ); - }, -}; - // Legacy export for backwards compatibility -export const SingleToggleGroup = Default; \ No newline at end of file +export const SingleToggleGroup = Default; diff --git a/packages/component-library/src/StatCard/index.stories.module.scss b/packages/component-library/src/StatCard/index.stories.module.scss index 3e98a308ed..62d07100ce 100644 --- a/packages/component-library/src/StatCard/index.stories.module.scss +++ b/packages/component-library/src/StatCard/index.stories.module.scss @@ -81,7 +81,7 @@ background-color: theme.color("states", "success", "normal"); border-radius: theme.border-radius("full"); transition: width 0.3s ease; - + &[data-progress="98.5"] { width: 98.5%; } @@ -112,6 +112,7 @@ 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } @@ -130,7 +131,8 @@ 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } -} \ No newline at end of file +} diff --git a/packages/component-library/src/StatCard/index.stories.tsx b/packages/component-library/src/StatCard/index.stories.tsx index d1ce452ade..f333efb9ad 100644 --- a/packages/component-library/src/StatCard/index.stories.tsx +++ b/packages/component-library/src/StatCard/index.stories.tsx @@ -2,9 +2,9 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { StatCard as StatCardComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; import { Badge } from "../Badge/index.jsx"; import cardMeta, { Card as CardStory } from "../Card/index.stories.jsx"; -import styles from "./index.stories.module.scss"; const cardMetaArgTypes = () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -124,7 +124,11 @@ export const WithCorner: Story = { args: { header: "System Status", stat: "Online", - corner: Live, + corner: ( + + Live + + ), variant: "secondary", }, }; @@ -146,21 +150,33 @@ export const CryptocurrencyPrices: Story = { header="Bitcoin" stat="$43,892" miniStat="+2.34%" - corner={+5.2%} + corner={ + + +5.2% + + } variant="secondary" /> -2.1%} + corner={ + + -2.1% + + } variant="secondary" /> +12.8%} + corner={ + + +12.8% + + } variant="secondary" />
@@ -206,7 +222,11 @@ export const SystemMonitoring: Story = { header="CPU Usage" stat="67%" miniStat="Normal" - corner={High} + corner={ + + High + + } variant="secondary" small /> @@ -214,7 +234,11 @@ export const SystemMonitoring: Story = { header="Memory" stat="84%" miniStat="8.4 GB / 10 GB" - corner={Critical} + corner={ + + Critical + + } variant="secondary" small /> @@ -222,7 +246,11 @@ export const SystemMonitoring: Story = { header="Disk Space" stat="45%" miniStat="450 GB / 1 TB" - corner={OK} + corner={ + + OK + + } variant="secondary" small /> @@ -230,7 +258,11 @@ export const SystemMonitoring: Story = { header="Network" stat="12.4 MB/s" miniStat="Upload: 2.1 MB/s" - corner={Stable} + corner={ + + Stable + + } variant="secondary" small /> @@ -241,7 +273,7 @@ export const SystemMonitoring: Story = { export const DualLayout: Story = { args: { header1: "Inbound", - header2: "Outbound", + header2: "Outbound", stat1: "1,234", stat2: "856", miniStat1: "+12%", @@ -292,15 +324,16 @@ export const WithCustomContent: Story = { header: "Sales Performance", stat: "98.5%", miniStat: "of monthly target", - corner: On Track, + corner: ( + + On Track + + ), variant: "secondary", children: (
-
+
$98,500 @@ -319,7 +352,11 @@ export const AnalyticsDashboard: Story = { header="Total Revenue" stat="$234,567" miniStat="+18.2% vs last month" - corner={Target: 110%} + corner={ + + Target: 110% + + } variant="primary" >
@@ -371,7 +408,11 @@ export const PythNetworkStats: Story = { header="Price Feeds" stat="400+" miniStat="across all networks" - corner={Live} + corner={ + + Live + + } variant="secondary" >
@@ -406,21 +447,33 @@ export const ErrorStates: Story = { header="Connection Status" stat="Offline" miniStat="Last seen: 2 hours ago" - corner={Error} + corner={ + + Error + + } variant="secondary" /> N/A} + corner={ + + N/A + + } variant="secondary" /> Alert} + corner={ + + Alert + + } variant="secondary" />
@@ -448,4 +501,4 @@ export const LoadingStates: Story = { }; // Legacy export for backwards compatibility -export const StatCard = Default; \ No newline at end of file +export const StatCard = Default; diff --git a/packages/component-library/src/Status/index.stories.module.scss b/packages/component-library/src/Status/index.stories.module.scss index 80d65c2208..08ea5584e5 100644 --- a/packages/component-library/src/Status/index.stories.module.scss +++ b/packages/component-library/src/Status/index.stories.module.scss @@ -56,7 +56,7 @@ display: flex; flex-direction: column; gap: theme.spacing(3); - + > h4 { margin: 0; font-size: theme.font-size("sm"); @@ -70,4 +70,4 @@ flex-wrap: wrap; gap: theme.spacing(3); align-items: center; -} \ No newline at end of file +} diff --git a/packages/component-library/src/Status/index.stories.tsx b/packages/component-library/src/Status/index.stories.tsx index 268feba1f4..3e849ce46e 100644 --- a/packages/component-library/src/Status/index.stories.tsx +++ b/packages/component-library/src/Status/index.stories.tsx @@ -125,7 +125,9 @@ export const AllCombinations: Story = {
{STYLES.map((style) => (
-

{style.charAt(0).toUpperCase() + style.slice(1)} Style

+

+ {style.charAt(0).toUpperCase() + style.slice(1)} Style +

{SIZES.map((size) => (

Size: {size.toUpperCase()}

@@ -153,10 +155,18 @@ export const AllCombinations: Story = { export const NeutralAllStyles: Story = { render: () => (
- Neutral Filled XS - Neutral Filled MD - Neutral Outline XS - Neutral Outline MD + + Neutral Filled XS + + + Neutral Filled MD + + + Neutral Outline XS + + + Neutral Outline MD +
), }; @@ -164,10 +174,18 @@ export const NeutralAllStyles: Story = { export const InfoAllStyles: Story = { render: () => (
- Info Filled XS - Info Filled MD - Info Outline XS - Info Outline MD + + Info Filled XS + + + Info Filled MD + + + Info Outline XS + + + Info Outline MD +
), }; @@ -175,10 +193,18 @@ export const InfoAllStyles: Story = { export const WarningAllStyles: Story = { render: () => (
- Warning Filled XS - Warning Filled MD - Warning Outline XS - Warning Outline MD + + Warning Filled XS + + + Warning Filled MD + + + Warning Outline XS + + + Warning Outline MD +
), }; @@ -186,10 +212,18 @@ export const WarningAllStyles: Story = { export const ErrorAllStyles: Story = { render: () => (
- Error Filled XS - Error Filled MD - Error Outline XS - Error Outline MD + + Error Filled XS + + + Error Filled MD + + + Error Outline XS + + + Error Outline MD +
), }; @@ -197,10 +231,18 @@ export const ErrorAllStyles: Story = { export const DataAllStyles: Story = { render: () => (
- Data Filled XS - Data Filled MD - Data Outline XS - Data Outline MD + + Data Filled XS + + + Data Filled MD + + + Data Outline XS + + + Data Outline MD +
), }; @@ -208,10 +250,18 @@ export const DataAllStyles: Story = { export const SuccessAllStyles: Story = { render: () => (
- Success Filled XS - Success Filled MD - Success Outline XS - Success Outline MD + + Success Filled XS + + + Success Filled MD + + + Success Outline XS + + + Success Outline MD +
), }; @@ -219,10 +269,18 @@ export const SuccessAllStyles: Story = { export const DisabledAllStyles: Story = { render: () => (
- Disabled Filled XS - Disabled Filled MD - Disabled Outline XS - Disabled Outline MD + + Disabled Filled XS + + + Disabled Filled MD + + + Disabled Outline XS + + + Disabled Outline MD +
), }; @@ -234,7 +292,12 @@ export const AllFilledVariants: Story = {

XS Size

{VARIANTS.map((variant) => ( - + {variant} ))} @@ -242,7 +305,12 @@ export const AllFilledVariants: Story = {

MD Size

{VARIANTS.map((variant) => ( - + {variant} ))} @@ -257,7 +325,12 @@ export const AllOutlineVariants: Story = {

XS Size

{VARIANTS.map((variant) => ( - + {variant} ))} @@ -265,7 +338,12 @@ export const AllOutlineVariants: Story = {

MD Size

{VARIANTS.map((variant) => ( - + {variant} ))} @@ -278,11 +356,21 @@ export const AllOutlineVariants: Story = { export const SystemStatuses: Story = { render: () => (
- Online - Offline - Maintenance - Updating - Inactive + + Online + + + Offline + + + Maintenance + + + Updating + + + Inactive +
), }; @@ -290,10 +378,18 @@ export const SystemStatuses: Story = { export const ConnectionStates: Story = { render: () => (
- Connected - Disconnected - Reconnecting - Authenticating + + Connected + + + Disconnected + + + Reconnecting + + + Authenticating +
), }; @@ -301,10 +397,18 @@ export const ConnectionStates: Story = { export const DataQuality: Story = { render: () => (
- Live Data - Cached - Stale - Invalid + + Live Data + + + Cached + + + Stale + + + Invalid +
), }; @@ -312,10 +416,18 @@ export const DataQuality: Story = { export const UserStatuses: Story = { render: () => (
- Active - Away - Busy - Offline + + Active + + + Away + + + Busy + + + Offline +
), }; @@ -323,14 +435,24 @@ export const UserStatuses: Story = { export const DeploymentStatuses: Story = { render: () => (
- Deployed - Building - Queued - Failed - Cancelled + + Deployed + + + Building + + + Queued + + + Failed + + + Cancelled +
), }; // Legacy export for backwards compatibility -export const Status = Default; \ No newline at end of file +export const Status = Default; diff --git a/packages/component-library/src/Switch/index.stories.module.scss b/packages/component-library/src/Switch/index.stories.module.scss index c73cea1245..a1c3ffb60d 100644 --- a/packages/component-library/src/Switch/index.stories.module.scss +++ b/packages/component-library/src/Switch/index.stories.module.scss @@ -19,70 +19,12 @@ color: theme.color("muted"); } -.controlledContainer { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - max-width: 400px; - - > p { - margin: 0; - font-size: theme.font-size("sm"); - color: theme.color("paragraph"); - } -} - -.settingsList { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - max-width: 600px; -} - -.settingItem { - display: flex; - flex-direction: column; - gap: theme.spacing(1); - padding-bottom: theme.spacing(4); - border-bottom: 1px solid theme.color("border"); - - &:last-child { - border-bottom: none; - } -} - -.settingDescription { - font-size: theme.font-size("sm"); - color: theme.color("muted"); - margin-left: theme.spacing(11); // Align with switch content -} - -.featureFlags { - display: flex; - flex-direction: column; - gap: theme.spacing(4); - max-width: 500px; - - > h3 { - margin: 0; - font-size: theme.font-size("lg"); - font-weight: 600; - color: theme.color("heading"); - } -} - -.flagItem { - padding: theme.spacing(3); - background-color: theme.color("background", "secondary"); - border-radius: theme.border-radius("md"); -} - .permissionsList { display: flex; flex-direction: column; gap: theme.spacing(4); max-width: 500px; - + > h3 { margin: 0; font-size: theme.font-size("lg"); @@ -119,21 +61,3 @@ align-items: center; gap: theme.spacing(2); } - -.errorExample { - display: flex; - flex-direction: column; - gap: theme.spacing(3); - max-width: 500px; -} - -.errorMessage { - padding: theme.spacing(3); - background-color: theme.color("states", "error", "background"); - color: theme.color("states", "error", "base"); - border-radius: theme.border-radius("md"); - font-size: theme.font-size("sm"); - display: flex; - align-items: center; - gap: theme.spacing(2); -} \ No newline at end of file diff --git a/packages/component-library/src/Switch/index.stories.tsx b/packages/component-library/src/Switch/index.stories.tsx index 4a3def73f3..f8600866b7 100644 --- a/packages/component-library/src/Switch/index.stories.tsx +++ b/packages/component-library/src/Switch/index.stories.tsx @@ -1,6 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; -import { useState } from "react"; import { Switch as SwitchComponent } from "./index.jsx"; import styles from "./index.stories.module.scss"; @@ -116,210 +115,52 @@ export const AllStates: Story = { Default state
- Selected + + Selected + Selected state
- Disabled + + Disabled + Disabled state
- Disabled Selected + + Disabled Selected + Disabled & selected
- Pending + + Pending + Loading state
- Pending Selected + + Pending Selected + Loading & selected
), }; -export const ControlledExample: Story = { - render: () => { - const [isSelected, setIsSelected] = useState(false); - const handleChange = fn((value: boolean) => { - setIsSelected(value); - }); - - return ( -
- - Controlled switch - -

Switch is {isSelected ? "ON" : "OFF"}

-
- ); - }, -}; - -export const WithAsyncAction: Story = { - render: () => { - const [isSelected, setIsSelected] = useState(false); - const [isPending, setIsPending] = useState(false); - - const handleChange = fn(async (value: boolean) => { - setIsPending(true); - // Simulate async operation - await new Promise(resolve => setTimeout(resolve, 2000)); - setIsSelected(value); - setIsPending(false); - }); - - return ( -
- - Save to server - -

{isPending ? "Saving..." : `Saved state: ${isSelected ? "ON" : "OFF"}`}

-
- ); - }, -}; - -export const SettingsExample: Story = { - render: () => { - const [settings, setSettings] = useState({ - notifications: true, - darkMode: false, - autoSave: true, - analytics: false, - }); - - const handleSettingChange = (setting: keyof typeof settings) => - fn((value: boolean) => { - setSettings(prev => ({ ...prev, [setting]: value })); - }); - - return ( -
-
- - Push notifications - - - Receive alerts for important updates - -
-
- - Dark mode - - - Use dark theme for better night viewing - -
-
- - Auto-save - - - Automatically save your work - -
-
- - Analytics (Pro only) - - - Advanced usage analytics - -
-
- ); - }, -}; - -export const FeatureFlags: Story = { - render: () => { - const [flags, setFlags] = useState({ - betaFeatures: false, - experimentalApi: false, - debugMode: false, - }); - const [pendingFlags, setPendingFlags] = useState([]); - - const handleFlagChange = (flag: keyof typeof flags) => - fn(async (value: boolean) => { - setPendingFlags(prev => [...prev, flag]); - // Simulate API call - await new Promise(resolve => setTimeout(resolve, 1500)); - setFlags(prev => ({ ...prev, [flag]: value })); - setPendingFlags(prev => prev.filter(f => f !== flag)); - }); - - return ( -
-

Feature Flags

-
- - Enable beta features - -
-
- - Use experimental API - -
-
- - Debug mode - -
-
- ); - }, -}; - export const PermissionsExample: Story = { render: () => { const permissions = [ - { id: 'read', label: 'Read access', enabled: true, locked: false }, - { id: 'write', label: 'Write access', enabled: false, locked: false }, - { id: 'delete', label: 'Delete access', enabled: false, locked: true }, - { id: 'admin', label: 'Admin access', enabled: false, locked: true }, + { id: "read", label: "Read access", enabled: true, locked: false }, + { id: "write", label: "Write access", enabled: false, locked: false }, + { id: "delete", label: "Delete access", enabled: false, locked: true }, + { id: "admin", label: "Admin access", enabled: false, locked: true }, ]; return (

User Permissions

- {permissions.map(permission => ( + {permissions.map((permission) => (
{ - const [isSelected, setIsSelected] = useState(false); - const [error, setError] = useState(null); - const [isPending, setIsPending] = useState(false); - - const handleChange = fn(async (value: boolean) => { - setError(null); - setIsPending(true); - - try { - // Simulate API call that might fail - await new Promise((resolve, reject) => { - setTimeout(() => { - if (Math.random() > 0.5) { - resolve(true); - } else { - reject(new Error("Failed to update setting")); - } - }, 1000); - }); - setIsSelected(value); - } catch (err) { - setError((err as Error).message); - } finally { - setIsPending(false); - } - }); - - return ( -
- - Risky operation (50% failure rate) - - {error && ( -
- ⚠️ {error} -
- )} -
- ); - }, -}; - // Legacy export for backwards compatibility -export const Switch = Default; \ No newline at end of file +export const Switch = Default; diff --git a/packages/component-library/src/TabList/index.stories.tsx b/packages/component-library/src/TabList/index.stories.tsx index 889051ff8b..2eaff9a105 100644 --- a/packages/component-library/src/TabList/index.stories.tsx +++ b/packages/component-library/src/TabList/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Tabs as UnstyledTabs } from "../unstyled/Tabs/index.jsx"; import { TabList as TabListComponent } from "./index.jsx"; +import { Tabs as UnstyledTabs } from "../unstyled/Tabs/index.jsx"; const meta = { title: "navigation & menus/TabList", diff --git a/packages/component-library/src/Table/index.stories.module.scss b/packages/component-library/src/Table/index.stories.module.scss index 28ef0a057f..65a7e44d43 100644 --- a/packages/component-library/src/Table/index.stories.module.scss +++ b/packages/component-library/src/Table/index.stories.module.scss @@ -24,7 +24,7 @@ padding: theme.spacing(12) theme.spacing(4); text-align: center; color: theme.color("muted"); - + > p { margin: 0; font-size: theme.font-size("sm"); @@ -39,14 +39,14 @@ gap: theme.spacing(4); padding: theme.spacing(16) theme.spacing(4); text-align: center; - + > h3 { margin: 0; font-size: theme.font-size("xl"); font-weight: 600; color: theme.color("heading"); } - + > p { margin: 0; font-size: theme.font-size("base"); @@ -93,7 +93,7 @@ display: flex; flex-direction: column; gap: theme.spacing(1); - + > strong { font-weight: 600; color: theme.color("foreground"); @@ -111,33 +111,6 @@ gap: theme.spacing(3); } -.filterableTable { - display: flex; - flex-direction: column; - gap: theme.spacing(4); -} - -.filterInput { - padding: theme.spacing(2) theme.spacing(3); - border: 1px solid theme.color("border"); - border-radius: theme.border-radius("md"); - background-color: theme.color("background", "primary"); - color: theme.color("foreground"); - font-size: theme.font-size("sm"); - width: 100%; - max-width: 300px; - - &:focus { - outline: none; - border-color: theme.color("focus"); - box-shadow: 0 0 0 3px theme.color("focus-dim"); - } - - &::placeholder { - color: theme.color("muted"); - } -} - .stickyHeaderContainer { height: 400px; overflow-y: auto; @@ -152,7 +125,7 @@ color: theme.color("states", "info", "normal"); text-align: center; font-size: theme.font-size("sm"); - + > p { margin: 0; } @@ -179,8 +152,8 @@ position: sticky; left: 0; z-index: 10; - + > p { margin: 0; } -} \ No newline at end of file +} diff --git a/packages/component-library/src/Table/index.stories.tsx b/packages/component-library/src/Table/index.stories.tsx index 9ba7e75560..62520dd37e 100644 --- a/packages/component-library/src/Table/index.stories.tsx +++ b/packages/component-library/src/Table/index.stories.tsx @@ -1,14 +1,13 @@ import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { fn } from "@storybook/test"; -import { useState } from "react"; +import { Table as TableComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; import { Badge } from "../Badge/index.jsx"; import { Button } from "../Button/index.jsx"; import { CopyButton } from "../CopyButton/index.jsx"; import { Status } from "../Status/index.jsx"; -import { Table as TableComponent, type ColumnConfig, type RowConfig, type SortDescriptor } from "./index.jsx"; -import styles from "./index.stories.module.scss"; const meta = { title: "data & tables/Table", @@ -223,103 +222,109 @@ export const StickyColumns: Story = { ({ - id: `row-${i}`, - data: { - name: `Product ${i + 1}`, - sku: `SKU-${1000 + i}`, - description: `This is a detailed description for product ${i + 1} that might be quite long`, - category: `Category ${(i % 3) + 1}`, - subcategory: `Subcat ${(i % 2) + 1}`, - brand: `Brand ${String.fromCharCode(65 + (i % 4))}`, - status: - {i % 2 === 0 ? "Active" : "Draft"} - , - stock: i * 10 + 5, - price: `$${(i + 1) * 99}.99`, - discount: i % 3 === 0 ? "10%" : "-", - created: "2024-01-15", - updated: "2024-12-01", - actions: ( -
- - -
- ), - }, - }))} + { + name: "NAME", + id: "name", + sticky: true, + isRowHeader: true, + width: 150, + }, + { + name: "SKU", + id: "sku", + width: 120, + }, + { + name: "DESCRIPTION", + id: "description", + width: 300, + }, + { + name: "CATEGORY", + id: "category", + width: 150, + }, + { + name: "SUBCATEGORY", + id: "subcategory", + width: 150, + }, + { + name: "BRAND", + id: "brand", + width: 120, + }, + { + name: "STATUS", + id: "status", + width: 120, + }, + { + name: "STOCK", + id: "stock", + width: 100, + alignment: "right", + }, + { + name: "PRICE", + id: "price", + width: 100, + alignment: "right", + }, + { + name: "DISCOUNT", + id: "discount", + width: 100, + alignment: "right", + }, + { + name: "CREATED", + id: "created", + width: 120, + }, + { + name: "UPDATED", + id: "updated", + width: 120, + }, + { + name: "ACTIONS", + id: "actions", + width: 150, + alignment: "center", + }, + ]} + rows={Array.from({ length: 8 }, (_, i) => ({ + id: `row-${i.toString()}`, + data: { + name: `Product ${String(i + 1)}`, + sku: `SKU-${String(1000 + i)}`, + description: `This is a detailed description for product ${String(i + 1)} that might be quite long`, + category: `Category ${String((i % 3) + 1)}`, + subcategory: `Subcat ${String((i % 2) + 1)}`, + brand: `Brand ${String.fromCodePoint(65 + (i % 4))}`, + status: ( + + {i % 2 === 0 ? "Active" : "Draft"} + + ), + stock: i * 10 + 5, + price: `$${String((i + 1) * 99)}.99`, + discount: i % 3 === 0 ? "10%" : "-", + created: "2024-01-15", + updated: "2024-12-01", + actions: ( +
+ + +
+ ), + }, + }))} />
@@ -385,93 +390,6 @@ export const Updating: Story = { }, }; -// Sortable columns -export const Sortable: Story = { - render: () => { - const [sortDescriptor, setSortDescriptor] = useState({ - column: "name", - direction: "ascending", - }); - - const data = [ - { id: "1", name: "Bitcoin", symbol: "BTC", price: 45234.56, change: 2.34 }, - { id: "2", name: "Ethereum", symbol: "ETH", price: 3234.56, change: -1.23 }, - { id: "3", name: "Solana", symbol: "SOL", price: 123.45, change: 5.67 }, - { id: "4", name: "Cardano", symbol: "ADA", price: 0.45, change: -0.89 }, - ]; - - const sortedData = [...data].sort((a, b) => { - const column = sortDescriptor.column as keyof typeof a; - const aValue = a[column]; - const bValue = b[column]; - - if (typeof aValue === "string" && typeof bValue === "string") { - return sortDescriptor.direction === "ascending" - ? aValue.localeCompare(bValue) - : bValue.localeCompare(aValue); - } - - if (typeof aValue === "number" && typeof bValue === "number") { - return sortDescriptor.direction === "ascending" - ? aValue - bValue - : bValue - aValue; - } - - return 0; - }); - - const columns: ColumnConfig<"name" | "symbol" | "price" | "change">[] = [ - { - name: "NAME", - id: "name", - isRowHeader: true, - allowsSorting: true, - }, - { - name: "SYMBOL", - id: "symbol", - allowsSorting: true, - }, - { - name: "PRICE", - id: "price", - alignment: "right", - allowsSorting: true, - }, - { - name: "24H CHANGE", - id: "change", - alignment: "right", - allowsSorting: true, - }, - ]; - - const rows: RowConfig<"name" | "symbol" | "price" | "change">[] = sortedData.map(item => ({ - id: item.id, - data: { - name: item.name, - symbol: item.symbol, - price: `$${item.price.toLocaleString()}`, - change: ( - = 0 ? styles.positive : styles.negative}> - {item.change >= 0 ? "+" : ""}{item.change}% - - ), - }, - })); - - return ( - - ); - }, -}; - // Interactive rows export const ClickableRows: Story = { args: { @@ -613,12 +531,20 @@ export const ComplexDataTable: Story = {
), role: Admin, - status: Active, + status: ( + + Active + + ), lastActive: "2 minutes ago", actions: (
- - + +
), }, @@ -636,12 +562,20 @@ export const ComplexDataTable: Story = {
), role: Editor, - status: Active, + status: ( + + Active + + ), lastActive: "1 hour ago", actions: (
- - + +
), }, @@ -659,12 +593,20 @@ export const ComplexDataTable: Story = {
), role: Viewer, - status: Inactive, + status: ( + + Inactive + + ), lastActive: "3 days ago", actions: (
- - + +
), }, @@ -787,7 +729,11 @@ export const ApiEndpointsTable: Story = { id: "get-price", data: { endpoint: /api/v1/price/{`{symbol}`}, - method: GET, + method: ( + + GET + + ), description: "Get current price for a symbol", copy: , }, @@ -796,7 +742,11 @@ export const ApiEndpointsTable: Story = { id: "post-order", data: { endpoint: /api/v1/orders, - method: POST, + method: ( + + POST + + ), description: "Create a new order", copy: , }, @@ -805,7 +755,11 @@ export const ApiEndpointsTable: Story = { id: "delete-order", data: { endpoint: /api/v1/orders/{`{id}`}, - method: DELETE, + method: ( + + DELETE + + ), description: "Cancel an existing order", copy: , }, @@ -829,10 +783,10 @@ export const StickyHeaderTable: Story = { { name: "DATA", id: "data", fill: true }, ]} rows={Array.from({ length: 50 }, (_, i) => ({ - id: `row-${i}`, + id: `row-${i.toString()}`, data: { index: i + 1, - data: `Row ${i + 1} data - scroll to see sticky header`, + data: `Row ${String(i + 1)} data - scroll to see sticky header`, }, }))} /> @@ -840,51 +794,5 @@ export const StickyHeaderTable: Story = { ), }; -// Table with dependencies (re-render optimization) -export const WithDependencies: Story = { - render: () => { - const [filter, setFilter] = useState(""); - - const allData = [ - { id: "1", name: "Apple", category: "Fruit" }, - { id: "2", name: "Carrot", category: "Vegetable" }, - { id: "3", name: "Banana", category: "Fruit" }, - { id: "4", name: "Broccoli", category: "Vegetable" }, - ]; - - const filteredData = allData.filter(item => - item.name.toLowerCase().includes(filter.toLowerCase()) || - item.category.toLowerCase().includes(filter.toLowerCase()) - ); - - return ( -
- setFilter(e.target.value)} - className={styles.filterInput} - /> - ({ - id: item.id, - data: { - name: item.name, - category: item.category, - }, - }))} - dependencies={[filter]} - /> -
- ); - }, -}; - // Legacy export -export const Table = Default; \ No newline at end of file +export const Table = Default; diff --git a/packages/component-library/src/icon-control.tsx b/packages/component-library/src/icon-control.tsx index ce54eff3a4..d804d660ee 100644 --- a/packages/component-library/src/icon-control.tsx +++ b/packages/component-library/src/icon-control.tsx @@ -9,4 +9,4 @@ export const iconControl = { , ]), ), -} as const; \ No newline at end of file +} as const;