Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .storybook/next-intl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const ns = [
"page-upgrades",
"page-developers-index",
"page-roadmap-vision",
"page-staking",
"page-what-is-ethereum",
"page-upgrades-index",
"page-wallets-find-wallet",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Meta, StoryObj } from "@storybook/nextjs"

import InlineLink from "@/components/ui/Link"

import BannerNotification from "."

const meta = {
title: "Components / Callouts / BannerNotification",
component: BannerNotification,
parameters: {
chromatic: { disableSnapshot: true },
layout: "fullscreen",
docs: {
description: {
component:
'Pre-unification visual reference for the existing `BannerNotification`. Renders a full-width primary-action bar at the top of the layout when `shouldShow` is true; returns an empty fragment otherwise. Consumed via `BaseLayout`. Slated to become `variant="notification"` on the unified `Callout` per #18133.',
},
},
},
} satisfies Meta<typeof BannerNotification>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
shouldShow: true,
children: (
<span>
Ethereum 10-year anniversary --{" "}
<InlineLink href="/10-year-anniversary/">read the timeline</InlineLink>
</span>
),
},
}

export const WithIcon: Story = {
args: {
shouldShow: true,
children: (
<span>
New: explore the layer-2 ecosystem on{" "}
<InlineLink href="/layer-2/">our updated hub</InlineLink>.
</span>
),
},
}

export const Hidden: Story = {
args: {
shouldShow: false,
children: <span>This banner is hidden because shouldShow is false.</span>,
},
parameters: {
docs: {
description: {
story:
"Renders an empty fragment when `shouldShow` is false -- the banner is fully suppressed without taking layout space.",
},
},
},
}
64 changes: 64 additions & 0 deletions src/components/Callout/Callout.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Meta, StoryObj } from "@storybook/nextjs"

import { ButtonLink } from "@/components/ui/buttons/Button"

import Callout from "."

import devBlocksImg from "@/public/images/developers-eth-blocks.png"

const meta = {
title: "Components / Callouts / Callout",
component: Callout,
parameters: {
chromatic: { disableSnapshot: true },
docs: {
description: {
component:
"Pre-unification visual reference for the existing `Callout` (client thunk over `CalloutSSR`). Resolves `titleKey` / `descriptionKey` translation keys against the `common` namespace before forwarding to `CalloutSSR`. Cross-namespace lookups use the `ns:key` syntax (consumers in the codebase do this regularly). This component is one of the inputs to the unified `Callout` work in #18133.",
},
},
},
decorators: [
(Story) => (
<div className="mt-32 max-w-md">
<Story />
</div>
),
],
} satisfies Meta<typeof Callout>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
titleKey: "smart-contracts",
image: devBlocksImg,
alt: "Developer blocks illustration",
children: (
<>
<p className="mb-6 text-xl leading-[140%] text-body-medium">
Smart contracts let you write programs that run on Ethereum and settle
without a trusted intermediary.
</p>
<ButtonLink href="/smart-contracts/">Learn more</ButtonLink>
</>
),
},
}

export const NoTitleKey: Story = {
args: {
emoji: ":wallet:",
children: (
<>
<h3 className="mb-8 text-2xl leading-[1.4]">Choose a wallet</h3>
<p className="mb-6 text-xl leading-[140%] text-body-medium">
Self-custody wallets let you hold your own keys and connect to dapps.
</p>
<ButtonLink href="/wallets/find-wallet/">Find a wallet</ButtonLink>
</>
),
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import type { TranslationKey } from "@/lib/types"

import CalloutSSR, { CalloutBaseProps } from "./CalloutSSR"
import CalloutSSR, { CalloutBaseProps } from "@/components/CalloutSSR"

import { useTranslation } from "@/hooks/useTranslation"

Expand Down
53 changes: 53 additions & 0 deletions src/components/CalloutBanner/CalloutBanner.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Meta, StoryObj } from "@storybook/nextjs"

import { ButtonLink } from "@/components/ui/buttons/Button"

import CalloutBanner from "."

import devBlocksImg from "@/public/images/developers-eth-blocks.png"

const meta = {
title: "Components / Callouts / CalloutBanner",
component: CalloutBanner,
parameters: {
chromatic: { disableSnapshot: true },
docs: {
description: {
component:
"Pre-unification visual reference for the existing `CalloutBanner` (server). Horizontal banner with an image on the right and a title + description + children CTA on the left. Resolves `titleKey` / `descriptionKey` against the `page-staking` namespace by default; cross-namespace via `ns:key`. This component is one of the inputs to the unified `Callout` work in #18133.",
},
},
},
decorators: [
(Story) => (
<div className="mt-20">
<Story />
</div>
),
],
} satisfies Meta<typeof CalloutBanner>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
titleKey: "page-staking-join-community",
descriptionKey: "page-staking-join-community-desc",
image: devBlocksImg,
imageWidth: 320,
alt: "Stylised illustration",
children: <ButtonLink href="/staking/">Get involved</ButtonLink>,
},
}

export const WithoutChildren: Story = {
args: {
titleKey: "page-staking-join-community",
descriptionKey: "page-staking-join-community-desc",
image: devBlocksImg,
imageWidth: 320,
alt: "Stylised illustration",
},
}
77 changes: 77 additions & 0 deletions src/components/CalloutSSR/CalloutSSR.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Meta, StoryObj } from "@storybook/nextjs"

import { ButtonLink } from "@/components/ui/buttons/Button"

import CalloutSSR from "."

import devBlocksImg from "@/public/images/developers-eth-blocks.png"

const meta = {
title: "Components / Callouts / CalloutSSR",
component: CalloutSSR,
parameters: {
chromatic: { disableSnapshot: true },
docs: {
description: {
component:
"Pre-unification visual reference for the existing `CalloutSSR` (server). Takes `title` and `description` as plain strings (no translation resolution -- the caller resolves keys). The optical anchor is the optional `image` that floats above the box, or an `emoji` heading if no image is supplied. This component is one of the inputs to the unified `Callout` work in #18133.",
},
},
},
decorators: [
(Story) => (
<div className="mt-32 max-w-md">
<Story />
</div>
),
],
} satisfies Meta<typeof CalloutSSR>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {
args: {
title: "Start building on Ethereum",
description:
"Get the tools, frameworks and tutorials to ship your first dapp.",
image: devBlocksImg,
alt: "Stylised developer blocks illustration",
children: (
<ButtonLink href="/developers/">Open the developers hub</ButtonLink>
),
},
}

export const WithEmoji: Story = {
args: {
emoji: ":sparkles:",
title: "Try smart contracts",
description:
"Smart contracts let you write programs that run on Ethereum and settle without a trusted intermediary.",
children: <ButtonLink href="/smart-contracts/">Learn more</ButtonLink>,
},
}

export const TitleOnly: Story = {
args: {
title: "Start building on Ethereum",
image: devBlocksImg,
alt: "Developer blocks illustration",
},
}

export const ChildrenOnly: Story = {
args: {
children: (
<div className="space-y-4">
<p>
Any custom content can sit inside the box -- this story passes only
children with no title, description, image, or emoji.
</p>
<ButtonLink href="#">Continue</ButtonLink>
</div>
),
},
}
File renamed without changes.
36 changes: 36 additions & 0 deletions src/components/TranslationBanner/TranslationBanner.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Meta, StoryObj } from "@storybook/nextjs"

import TranslationBanner from "."

const meta = {
title: "Components / Callouts / TranslationBanner",
component: TranslationBanner,
parameters: {
chromatic: { disableSnapshot: true },
layout: "fullscreen",
docs: {
description: {
component:
'Pre-unification visual reference for the existing `TranslationBanner`. Client component with three gates: it renders only when the active locale is **not** the default (English), the current pathname matches one of `DO_NOT_TRANSLATE_PATHS` (legal pages, etc.), and the user has not previously dismissed it (`localStorage[dont-show-translation-banner-<path>]` !== `"true"`). Slated to be absorbed into the unified `Callout` per #18133 as a dismissible composition.\n\n**To see the banner in Storybook**, switch the locale toolbar to a non-English locale (e.g. German) and clear `localStorage` for the dismissal key if it has been set previously. The `usePathname` gate may still suppress the banner depending on the Storybook iframe path -- this is documented here as a known limitation of storying the component in isolation.',
},
},
},
} satisfies Meta<typeof TranslationBanner>

export default meta

type Story = StoryObj<typeof meta>

export const Default: Story = {}

export const NonEnglishLocale: Story = {
parameters: {
locale: "de",
docs: {
description: {
story:
"Forces a non-English locale parameter for storybook-next-intl. The banner remains gated on pathname and dismissal state, so it may still render nothing.",
},
},
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import { useEffect, useMemo, useState } from "react"
import { X } from "lucide-react"
import { useLocale } from "next-intl"

import Emoji from "@/components/Emoji"
import { Button } from "@/components/ui/buttons/Button"

import { cn } from "@/lib/utils/cn"

import { DEFAULT_LOCALE } from "@/lib/constants"

import Emoji from "./Emoji"

import useTranslation from "@/hooks/useTranslation"
import { usePathname } from "@/i18n/navigation"
import { DO_NOT_TRANSLATE_PATHS } from "@/scripts/intl-pipeline/constants"
Expand Down
Loading