-
Notifications
You must be signed in to change notification settings - Fork 439
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: requirement building blocks (#1571)
* feat: DataBlock component * feat: ChainIndicator component * feat: simplify the DataBlock component * feat: DataBlockWithCopy component * feat: Requirement compound component * feat: RequirementLink component * cleanup(DataBlock): remove unused stuff * cleanup: simplify DataBlock stories * fix(DataBlockWithCopy): adjust height, add `"use client"` * fix(Providers): add TooltipProvider * fix(DataBlockWithCopy): tooltip trigger * fix(DataBlockWithCopy): remove icon color * refactor: make a `SupportedChainID` type * fix(Button): adjust spacing for `sm` size
- Loading branch information
1 parent
7e25c56
commit 5494dee
Showing
20 changed files
with
344 additions
and
20 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Badge } from "@/components/ui/Badge"; | ||
import { CHAINS, type SupportedChainID } from "@/config/chains"; | ||
|
||
export const ChainIndicator = ({ chain }: { chain: SupportedChainID }) => ( | ||
<Badge size="sm"> | ||
<img | ||
src={CHAINS[chain].icon} | ||
alt={CHAINS[chain].name} | ||
className="size-3.5" | ||
/> | ||
<span>{CHAINS[chain].name}</span> | ||
</Badge> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import type { PropsWithChildren } from "react"; | ||
|
||
export const DataBlock = ({ children }: PropsWithChildren): JSX.Element => { | ||
return ( | ||
<span className="h-6 break-words rounded-md bg-blackAlpha px-1.5 py-0.5 font-mono text-sm dark:bg-blackAlpha-hard"> | ||
{children} | ||
</span> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
"use client"; | ||
|
||
import { | ||
Tooltip, | ||
TooltipContent, | ||
TooltipPortal, | ||
TooltipTrigger, | ||
} from "@/components/ui/Tooltip"; | ||
import { Check } from "@phosphor-icons/react/dist/ssr"; | ||
import { useClipboard } from "foxact/use-clipboard"; | ||
import { useDebouncedState } from "foxact/use-debounced-state"; | ||
import { type PropsWithChildren, useEffect } from "react"; | ||
import { DataBlock } from "./DataBlock"; | ||
|
||
type Props = { | ||
text: string; | ||
}; | ||
|
||
export const DataBlockWithCopy = ({ | ||
text, | ||
children, | ||
}: PropsWithChildren<Props>): JSX.Element => { | ||
const { copied, copy } = useClipboard({ | ||
timeout: 1500, | ||
}); | ||
|
||
/** | ||
* Maintaining a debounced copied state too, so we can change the tooltip content only after the tooltip is actually invisible | ||
*/ | ||
|
||
const [debouncedCopied, debouncilySetState] = useDebouncedState(copied, 200); | ||
|
||
useEffect(() => { | ||
debouncilySetState(copied); | ||
}, [debouncilySetState, copied]); | ||
|
||
const tooltipInCopiedState = copied || debouncedCopied; | ||
|
||
return ( | ||
<Tooltip open={copied || undefined}> | ||
<TooltipTrigger | ||
onClick={() => copy(text)} | ||
className="inline-flex rounded-md" | ||
> | ||
<DataBlock> | ||
<span>{children ?? text}</span> | ||
</DataBlock> | ||
</TooltipTrigger> | ||
|
||
<TooltipPortal> | ||
<TooltipContent side="top" className="flex items-center gap-1.5"> | ||
{tooltipInCopiedState && <Check weight="bold" />} | ||
<span>{tooltipInCopiedState ? "Copied" : "Click to copy"}</span> | ||
</TooltipContent> | ||
</TooltipPortal> | ||
</Tooltip> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { cn } from "@/lib/cssUtils"; | ||
import type { PropsWithChildren } from "react"; | ||
|
||
export const Requirement = ({ | ||
className, | ||
children, | ||
}: PropsWithChildren<{ className?: string }>) => ( | ||
<div className={cn("flex w-full items-center gap-4 py-2", className)}> | ||
{children} | ||
</div> | ||
); | ||
|
||
export const RequirementImage = ({ | ||
className, | ||
children, | ||
}: PropsWithChildren<{ className?: string }>) => ( | ||
<div | ||
className={cn( | ||
"flex size-11 shrink-0 items-center justify-center overflow-hidden rounded-full bg-blackAlpha dark:bg-blackAlpha-hard", | ||
className, | ||
)} | ||
> | ||
{children} | ||
</div> | ||
); | ||
|
||
export const RequirementContent = ({ | ||
className, | ||
children, | ||
}: PropsWithChildren<{ className?: string }>) => ( | ||
<div className={cn("flex flex-grow flex-col items-start", className)}> | ||
{children} | ||
</div> | ||
); | ||
|
||
export const RequirementFooter = ({ | ||
className, | ||
children, | ||
}: PropsWithChildren<{ className?: string }>) => ( | ||
<div | ||
className={cn( | ||
"flex flex-wrap items-center gap-1.5 has-[>*]:mt-1", | ||
className, | ||
)} | ||
> | ||
{children} | ||
</div> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import type { PropsWithChildren } from "react"; | ||
import { Anchor } from "../ui/Anchor"; | ||
|
||
export const RequirementLink = ({ | ||
href, | ||
children, | ||
}: PropsWithChildren<{ href: string }>) => ( | ||
<Anchor | ||
href={href} | ||
target="_blank" | ||
rel="noopener" | ||
variant="secondary" | ||
showExternal | ||
className="font-medium text-xs" | ||
> | ||
{children} | ||
</Anchor> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { mainnet, sepolia } from "viem/chains"; | ||
import type { Register } from "wagmi"; | ||
|
||
export const CHAINS = { | ||
[mainnet.id]: { | ||
name: mainnet.name, | ||
icon: "/chainLogos/eth.svg", | ||
}, | ||
[sepolia.id]: { | ||
name: sepolia.name, | ||
icon: "/chainLogos/eth.svg", | ||
}, | ||
} satisfies Record< | ||
SupportedChainID, | ||
{ | ||
name: string; | ||
icon: string; | ||
} | ||
>; | ||
|
||
export type SupportedChainID = Register["config"]["chains"][number]["id"]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { ChainIndicator } from "@/components/requirements/ChainIndicator"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
const meta: Meta<typeof ChainIndicator> = { | ||
title: "Requirement building blocks/ChainIndicator", | ||
component: ChainIndicator, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof ChainIndicator>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
chain: 1, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { DataBlock } from "@/components/requirements/DataBlock"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
const meta: Meta<typeof DataBlock> = { | ||
title: "Requirement building blocks/DataBlock", | ||
component: DataBlock, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof DataBlock>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
children: "DataBlock", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { DataBlockWithCopy } from "@/components/requirements/DataBlockWithCopy"; | ||
import { TooltipProvider } from "@/components/ui/Tooltip"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
const meta: Meta<typeof DataBlockWithCopy> = { | ||
title: "Requirement building blocks/DataBlockWithCopy", | ||
component: DataBlockWithCopy, | ||
decorators: (Story) => ( | ||
<TooltipProvider> | ||
<Story /> | ||
</TooltipProvider> | ||
), | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof DataBlockWithCopy>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
children: "DataBlockWithCopy", | ||
text: "DataBlockWithCopy", | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { ChainIndicator } from "@/components/requirements/ChainIndicator"; | ||
import { DataBlockWithCopy } from "@/components/requirements/DataBlockWithCopy"; | ||
import { | ||
Requirement, | ||
RequirementContent, | ||
RequirementFooter, | ||
RequirementImage, | ||
} from "@/components/requirements/Requirement"; | ||
import { RequirementLink } from "@/components/requirements/RequirementLink"; | ||
import { Card } from "@/components/ui/Card"; | ||
import { TooltipProvider } from "@/components/ui/Tooltip"; | ||
import { QuestionMark } from "@phosphor-icons/react/dist/ssr"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
const RequirementExample = () => ( | ||
<Card className="max-w-sm px-6 py-4"> | ||
<Requirement> | ||
<RequirementImage> | ||
<QuestionMark weight="bold" className="size-6" /> | ||
</RequirementImage> | ||
<RequirementContent> | ||
<p> | ||
<span>{"Copy "}</span> | ||
<DataBlockWithCopy text="this text" /> | ||
<span>{" to your clipboard"}</span> | ||
</p> | ||
|
||
<RequirementFooter className="text-secondary text-sm"> | ||
<ChainIndicator chain={1} /> | ||
<RequirementLink href="https://polygonscan.com/token/0xff04820c36759c9f5203021fe051239ad2dcca8a"> | ||
View on explorer | ||
</RequirementLink> | ||
</RequirementFooter> | ||
</RequirementContent> | ||
</Requirement> | ||
</Card> | ||
); | ||
|
||
const meta: Meta<typeof RequirementExample> = { | ||
title: "Requirement building blocks/Requirement", | ||
component: RequirementExample, | ||
decorators: (Story) => ( | ||
<TooltipProvider> | ||
<Story /> | ||
</TooltipProvider> | ||
), | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof RequirementExample>; | ||
|
||
export const Default: Story = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { RequirementLink } from "@/components/requirements/RequirementLink"; | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
const meta: Meta<typeof RequirementLink> = { | ||
title: "Requirement building blocks/RequirementLink", | ||
component: RequirementLink, | ||
}; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof RequirementLink>; | ||
|
||
export const Default: Story = { | ||
args: { | ||
href: "https://polygonscan.com/token/0xff04820c36759c9f5203021fe051239ad2dcca8a", | ||
children: "Guild Pin contract", | ||
}, | ||
}; |
Oops, something went wrong.