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..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; - width: 100vw; + height: 100%; + min-width: 100%; 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; + } +} 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/packages/component-library/src/AppShell/index.stories.tsx b/packages/component-library/src/AppShell/index.stories.tsx index bdf1e7f731..78df3b18af 100644 --- a/packages/component-library/src/AppShell/index.stories.tsx +++ b/packages/component-library/src/AppShell/index.stories.tsx @@ -1,10 +1,29 @@ import type { Meta, StoryObj } from "@storybook/react"; 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 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"; const meta = { + title: "layouts & pages/AppShell", 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 +54,52 @@ 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) => ( + + + + ), +}; 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..e4579798d6 --- /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; +} diff --git a/packages/component-library/src/Badge/index.stories.tsx b/packages/component-library/src/Badge/index.stories.tsx index 65d54edf73..cdd1eb6db4 100644 --- a/packages/component-library/src/Badge/index.stories.tsx +++ b/packages/component-library/src/Badge/index.stories.tsx @@ -1,8 +1,10 @@ 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"; +import styles from "./index.stories.module.scss"; const meta = { + title: "building blocks/Badge", component: BadgeComponent, argTypes: { children: { @@ -33,6 +35,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -44,3 +47,133 @@ 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", + }, + }, + }, +}; diff --git a/packages/component-library/src/Breadcrumbs/index.stories.tsx b/packages/component-library/src/Breadcrumbs/index.stories.tsx index b0f689eb48..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: { @@ -25,8 +26,8 @@ export const Breadcrumbs = { label: "Breadcrumbs", items: [ { href: "/", label: "Home" }, - { href: "/foo", label: "Foo" }, - { label: "Bar" }, + { href: "#", label: "Products" }, + { label: "Pyth Core" }, ], }, } satisfies StoryObj; diff --git a/packages/component-library/src/Button/index.stories.tsx b/packages/component-library/src/Button/index.stories.tsx index 0b33a47187..3d8730acee 100644 --- a/packages/component-library/src/Button/index.stories.tsx +++ b/packages/component-library/src/Button/index.stories.tsx @@ -1,20 +1,10 @@ -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 = { + title: "forms & controls/Button", component: ButtonComponent, argTypes: { 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..c3a8343cf1 --- /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); +} diff --git a/packages/component-library/src/Card/index.stories.tsx b/packages/component-library/src/Card/index.stories.tsx index aac992e9ef..7618ba3dfb 100644 --- a/packages/component-library/src/Card/index.stories.tsx +++ b/packages/component-library/src/Card/index.stories.tsx @@ -1,9 +1,15 @@ -import * as Icon from "@phosphor-icons/react/dist/ssr"; +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"; +import { iconControl } from "../icon-control.jsx"; 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", @@ -44,14 +50,7 @@ const meta = { }, }, icon: { - control: "select", - options: Object.keys(Icon), - mapping: Object.fromEntries( - Object.entries(Icon).map(([key, Icon]) => [ - key, - , - ]), - ), + ...iconControl, table: { category: "Contents", }, @@ -69,6 +68,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -81,3 +81,163 @@ 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: fn(), + 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.

+
+ ))} +
+ ), +}; 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..ce28c2cd06 --- /dev/null +++ b/packages/component-library/src/CopyButton/index.stories.tsx @@ -0,0 +1,66 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { CopyButton as CopyButtonComponent } from "./index.jsx"; + +const meta = { + title: "forms & controls/CopyButton", + 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; 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..4fd05c9f05 --- /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"); + } +} 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..18a48fc519 --- /dev/null +++ b/packages/component-library/src/CrossfadeTabPanels/index.stories.tsx @@ -0,0 +1,282 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +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", + 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

+
+
+ + +
+
+ + +
+ +
+
+ ), + }, + ]} + /> +
+ ), +}; 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..b0dbe9f8a5 --- /dev/null +++ b/packages/component-library/src/DropdownCaretDown/index.stories.tsx @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { DropdownCaretDown as DropdownCaretDownComponent } from "./index.jsx"; + +const meta = { + title: "building blocks/DropdownCaretDown", + 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 = {}; 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..6e01c79763 --- /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); +} 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..87e21b645b --- /dev/null +++ b/packages/component-library/src/EntityList/index.stories.tsx @@ -0,0 +1,235 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +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", + 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: ( +
+ + +
+ ), + }, + }, + ], + }, +}; 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..d24b436a41 --- /dev/null +++ b/packages/component-library/src/ErrorPage/index.stories.tsx @@ -0,0 +1,76 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; + +import { ErrorPage as ErrorPageComponent } from "./index.jsx"; + +const meta = { + title: "layouts & pages/ErrorPage", + 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(), + }, +}; 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/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 d44702fea0..0e8f525fc5 100644 --- a/packages/component-library/src/Header/index.stories.tsx +++ b/packages/component-library/src/Header/index.stories.tsx @@ -2,8 +2,13 @@ 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"; const meta = { + title: "navigation & menus/Header", component: HeaderComponent, decorators: [ (Story) => ( @@ -26,6 +31,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; @@ -34,3 +40,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, + }, +}; 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..a7fb5f34c5 --- /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); +} 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..e4d7c1b4a1 --- /dev/null +++ b/packages/component-library/src/InfoBox/index.stories.tsx @@ -0,0 +1,151 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { iconControl } from "../icon-control.jsx"; +import { InfoBox as InfoBoxComponent, VARIANTS } from "./index.jsx"; +import styles from "./index.stories.module.scss"; + +const meta = { + title: "overlays & dialogs/InfoBox", + 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: ( +
+        {/* eslint-disable-next-line unicorn/no-null */}
+        {JSON.stringify({ status: "ok", timestamp: 1_234_567_890 }, null, 2)}
+      
+ ), + }, +}; diff --git a/packages/component-library/src/Link/index.stories.tsx b/packages/component-library/src/Link/index.stories.tsx index 75da4732ee..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: { @@ -24,6 +25,7 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; diff --git a/packages/component-library/src/MainNavTabs/index.stories.tsx b/packages/component-library/src/MainNavTabs/index.stories.tsx index 749b5b2ff1..fab1e26b97 100644 --- a/packages/component-library/src/MainNavTabs/index.stories.tsx +++ b/packages/component-library/src/MainNavTabs/index.stories.tsx @@ -4,6 +4,7 @@ import { MainNavTabs as MainNavTabsComponent } from "./index.jsx"; import { Tabs } from "../unstyled/Tabs/index.jsx"; const meta = { + title: "navigation & menus/MainNavTabs", component: MainNavTabsComponent, argTypes: { tabs: { @@ -26,8 +27,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/Meter/index.stories.module.scss b/packages/component-library/src/Meter/index.stories.module.scss new file mode 100644 index 0000000000..af35a10a26 --- /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"); + } +} 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..d28636ed77 --- /dev/null +++ b/packages/component-library/src/Meter/index.stories.tsx @@ -0,0 +1,201 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { Meter as MeterComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; + +const meta = { + title: "data & tables/Meter", + 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

+ +
+
+ ), +}; diff --git a/packages/component-library/src/MobileNavTabs/index.stories.tsx b/packages/component-library/src/MobileNavTabs/index.stories.tsx index 34ee9234c2..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", @@ -21,8 +22,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; 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..5927d58bbb --- /dev/null +++ b/packages/component-library/src/NoResults/index.stories.tsx @@ -0,0 +1,172 @@ +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 = { + title: "layouts & pages/NoResults", + 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(), + }, +}; diff --git a/packages/component-library/src/NoResults/index.tsx b/packages/component-library/src/NoResults/index.tsx index 4394a550ea..2aa9f83aaa 100644 --- a/packages/component-library/src/NoResults/index.tsx +++ b/packages/component-library/src/NoResults/index.tsx @@ -7,7 +7,7 @@ import type { ReactNode } from "react"; import styles from "./index.module.scss"; import { Button } from "../Button/index.jsx"; -type Props = { +export type Props = { className?: string | undefined; onClearSearch?: (() => void) | undefined; } & ( 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..197bd0cd11 --- /dev/null +++ b/packages/component-library/src/NotFoundPage/index.stories.tsx @@ -0,0 +1,17 @@ +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", + }, + tags: ["autodocs"], +} satisfies Meta; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; 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.module.scss b/packages/component-library/src/SearchInput/index.stories.module.scss new file mode 100644 index 0000000000..04b138dfd4 --- /dev/null +++ b/packages/component-library/src/SearchInput/index.stories.module.scss @@ -0,0 +1,8 @@ +@use "../theme"; + +.sizesContainer, +.statesContainer { + display: flex; + flex-direction: column; + gap: theme.spacing(4); +} diff --git a/packages/component-library/src/SearchInput/index.stories.tsx b/packages/component-library/src/SearchInput/index.stories.tsx index 3e9e9ff615..e391106fb0 100644 --- a/packages/component-library/src/SearchInput/index.stories.tsx +++ b/packages/component-library/src/SearchInput/index.stories.tsx @@ -1,8 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; 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: { @@ -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,108 @@ 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 AllSizes: Story = { + render: () => ( +
+ {SIZES.map((size) => ( + + ))} +
+ ), +}; + +export const AllStates: Story = { + render: () => ( +
+ + + + +
+ ), +}; 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..0a1e52099e --- /dev/null +++ b/packages/component-library/src/Select/index.stories.module.scss @@ -0,0 +1,67 @@ +@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); + place-items: center center; + min-height: 300px; +} + +.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; + } +} diff --git a/packages/component-library/src/Select/index.stories.tsx b/packages/component-library/src/Select/index.stories.tsx index f151f2cdae..27d71b7096 100644 --- a/packages/component-library/src/Select/index.stories.tsx +++ b/packages/component-library/src/Select/index.stories.tsx @@ -1,11 +1,15 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; 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; const meta = { + title: "forms & controls/Select", component: SelectComponent, argTypes: { ...argTypes, @@ -84,55 +88,353 @@ 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", }, -} satisfies StoryObj; +}; + +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) => ( +
+ + +
+ ))} +
+ ); + }, +}; + +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" + /> +
+ ), +}; 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..2439152bd1 --- /dev/null +++ b/packages/component-library/src/SingleToggleGroup/index.stories.module.scss @@ -0,0 +1,7 @@ +@use "../theme"; + +.iconButton { + display: flex; + align-items: center; + gap: theme.spacing(2); +} diff --git a/packages/component-library/src/SingleToggleGroup/index.stories.tsx b/packages/component-library/src/SingleToggleGroup/index.stories.tsx index e08b7fef9a..a2ef8b6106 100644 --- a/packages/component-library/src/SingleToggleGroup/index.stories.tsx +++ b/packages/component-library/src/SingleToggleGroup/index.stories.tsx @@ -1,8 +1,11 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; import { SingleToggleGroup as SingleToggleGroupComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { + title: "forms & controls/SingleToggleGroup", component: SingleToggleGroupComponent, argTypes: { items: { @@ -15,15 +18,253 @@ 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: "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"], + }, +}; + +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: "foo", children: "Foo" }, - { id: "bar", children: "Bar" }, + { id: "name", children: "Name" }, + { id: "date", children: "Date" }, + { id: "size", children: "Size" }, + { id: "type", children: "Type" }, ], + defaultSelectedKeys: ["name"], }, -} satisfies StoryObj; +}; + +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 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"], + }, +}; + +// Legacy export for backwards compatibility +export const SingleToggleGroup = Default; 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.module.scss b/packages/component-library/src/StatCard/index.stories.module.scss new file mode 100644 index 0000000000..62d07100ce --- /dev/null +++ b/packages/component-library/src/StatCard/index.stories.module.scss @@ -0,0 +1,138 @@ +@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); + } +} diff --git a/packages/component-library/src/StatCard/index.stories.tsx b/packages/component-library/src/StatCard/index.stories.tsx index d911e11848..f333efb9ad 100644 --- a/packages/component-library/src/StatCard/index.stories.tsx +++ b/packages/component-library/src/StatCard/index.stories.tsx @@ -1,6 +1,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"; const cardMetaArgTypes = () => { @@ -10,6 +13,7 @@ const cardMetaArgTypes = () => { }; const meta = { + title: "data & tables/StatCard", component: StatCardComponent, parameters: { layout: "padded", @@ -40,7 +44,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 +91,414 @@ 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; 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..08ea5584e5 --- /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; +} diff --git a/packages/component-library/src/Status/index.stories.tsx b/packages/component-library/src/Status/index.stories.tsx index 69d580f013..3e849ce46e 100644 --- a/packages/component-library/src/Status/index.stories.tsx +++ b/packages/component-library/src/Status/index.stories.tsx @@ -1,13 +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: { @@ -38,14 +40,419 @@ const meta = { }, }, }, + tags: ["autodocs"], } satisfies Meta; export default meta; -export const Status = { +type Story = StoryObj; + +export const Default: Story = { args: { - children: "A STATUS", + children: "Status", variant: "neutral", style: "filled", size: "md", }, -} satisfies StoryObj; +}; + +// Individual variant examples +export const Neutral: Story = { + args: { + children: "Neutral", + variant: "neutral", + style: "filled", + size: "md", + }, +}; + +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; 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..a1c3ffb60d --- /dev/null +++ b/packages/component-library/src/Switch/index.stories.module.scss @@ -0,0 +1,63 @@ +@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"); +} + +.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); +} diff --git a/packages/component-library/src/Switch/index.stories.tsx b/packages/component-library/src/Switch/index.stories.tsx index e36aa4ebc5..f8600866b7 100644 --- a/packages/component-library/src/Switch/index.stories.tsx +++ b/packages/component-library/src/Switch/index.stories.tsx @@ -1,8 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; import { Switch as SwitchComponent } from "./index.jsx"; +import styles from "./index.stories.module.scss"; const meta = { + title: "forms & controls/Switch", component: SwitchComponent, argTypes: { isDisabled: { @@ -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,167 @@ 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: "Click me!", - isDisabled: false, - isPending: false, + children: "Enable notifications", + onChange: fn(), }, -} satisfies StoryObj; +}; + +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: "Loading...", + isPending: true, + onChange: fn(), + }, +}; + +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 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"} + + )} + +
+ ), +}; + +// Legacy export for backwards compatibility +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 27dbece720..2eaff9a105 100644 --- a/packages/component-library/src/TabList/index.stories.tsx +++ b/packages/component-library/src/TabList/index.stories.tsx @@ -4,6 +4,7 @@ import { TabList as TabListComponent } from "./index.jsx"; import { Tabs as UnstyledTabs } from "../unstyled/Tabs/index.jsx"; const meta = { + title: "navigation & menus/TabList", component: TabListComponent, argTypes: { items: { @@ -31,8 +32,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; 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..65a7e44d43 --- /dev/null +++ b/packages/component-library/src/Table/index.stories.module.scss @@ -0,0 +1,159 @@ +@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); +} + +.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; + } +} diff --git a/packages/component-library/src/Table/index.stories.tsx b/packages/component-library/src/Table/index.stories.tsx index f56424a500..62520dd37e 100644 --- a/packages/component-library/src/Table/index.stories.tsx +++ b/packages/component-library/src/Table/index.stories.tsx @@ -1,8 +1,16 @@ +import * as icons from "@phosphor-icons/react/dist/ssr"; import type { Meta, StoryObj } from "@storybook/react"; +import { fn } from "@storybook/test"; 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"; const meta = { + title: "data & tables/Table", component: TableComponent, parameters: { layout: "padded", @@ -29,6 +37,7 @@ const meta = { }, }, label: { + control: "text", table: { category: "Accessibility", }, @@ -57,70 +66,733 @@ 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.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: ( +
+ + +
+ ), + }, + }))} + /> +
+
+ ), +}; + +// 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; +}; + +// 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.toString()}`, + data: { + index: i + 1, + data: `Row ${String(i + 1)} data - scroll to see sticky header`, + }, + }))} + /> +
+ ), +}; + +// Legacy export +export const Table = Default; 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: { diff --git a/packages/component-library/src/icon-control.tsx b/packages/component-library/src/icon-control.tsx new file mode 100644 index 0000000000..d804d660ee --- /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; 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"