Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: requirement building blocks #1571

Merged
merged 14 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 8 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 public/chainLogos/eth.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/components/SignInDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,15 @@ const WalletList = () => {
<span>{"By continuing, you agree to our "}</span>
<Anchor
href="/privacy-policy"
variant="muted"
variant="secondary"
onClick={() => setOpen(false)}
>
Privacy Policy
</Anchor>
<span>{" and "}</span>
<Anchor
href="/terms-of-use"
variant="muted"
variant="secondary"
onClick={() => setOpen(false)}
>
Terms of use
Expand Down
16 changes: 16 additions & 0 deletions src/components/requirements/ChainIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Badge } from "@/components/ui/Badge";
import { CHAINS } from "@/config/chains";
import type { Register } from "wagmi";

export const ChainIndicator = ({
chain,
}: { chain: Register["config"]["chains"][number]["id"] }) => (
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think, should we extract the Register["config"]["chains"][number]["id"] to a type somewhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like a common type, we can extract it into a wagmi type file.

<Badge size="sm">
<img
src={CHAINS[chain].icon}
alt={CHAINS[chain].name}
className="size-3.5"
/>
<span>{CHAINS[chain].name}</span>
</Badge>
);
9 changes: 9 additions & 0 deletions src/components/requirements/DataBlock.tsx
BrickheadJohnny marked this conversation as resolved.
Show resolved Hide resolved
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="break-words rounded-md bg-blackAlpha px-1.5 py-0.5 font-mono text-sm dark:bg-blackAlpha-hard">
{children}
</span>
);
};
55 changes: 55 additions & 0 deletions src/components/requirements/DataBlockWithCopy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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="rounded-md">
<DataBlock>
<span>{children ?? text}</span>
</DataBlock>
</TooltipTrigger>

<TooltipPortal>
<TooltipContent side="top" className="flex items-center gap-1.5">
{tooltipInCopiedState && (
<Check weight="bold" className="text-icon-success" />
)}
<span>{tooltipInCopiedState ? "Copied" : "Click to copy"}</span>
</TooltipContent>
</TooltipPortal>
</Tooltip>
);
};
48 changes: 48 additions & 0 deletions src/components/requirements/Requirement.tsx
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>
);
18 changes: 18 additions & 0 deletions src/components/requirements/RequirementLink.tsx
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>
);
2 changes: 1 addition & 1 deletion src/components/ui/Anchor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const anchorVariants = cva(
variant: {
default: "text-foreground hover:underline",
highlighted: "text-blue-500 dark:text-blue-400 hover:underline",
muted: "text-muted-foreground hover:underline",
secondary: "text-foreground-secondary hover:underline",
unstyled: "",
},
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const badgeVariants = cva(
{
variants: {
size: {
sm: "text-xs h-5",
sm: "text-xs h-5 gap-1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could have this on all sizes like on button.

md: "text-sm h-6",
lg: "text-base h-8",
},
Expand Down
19 changes: 19 additions & 0 deletions src/config/chains.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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<
Register["config"]["chains"][number]["id"],
{
name: string;
icon: string;
}
>;
6 changes: 3 additions & 3 deletions src/stories/Anchor.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ export const Default: Story = {
},
};

export const Muted: Story = {
export const Secondary: Story = {
args: {
...Default.args,
variant: "muted",
children: "Muted",
variant: "secondary",
children: "Secondary",
},
argTypes: {
...Default.argTypes,
Expand Down
17 changes: 17 additions & 0 deletions src/stories/requirements/ChainIndicator.stories.tsx
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,
},
};
17 changes: 17 additions & 0 deletions src/stories/requirements/DataBlock.stories.tsx
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",
},
};
24 changes: 24 additions & 0 deletions src/stories/requirements/DataBlockWithCopy.stories.tsx
BrickheadJohnny marked this conversation as resolved.
Show resolved Hide resolved
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",
},
};
53 changes: 53 additions & 0 deletions src/stories/requirements/Requirement.stories.tsx
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 = {};
18 changes: 18 additions & 0 deletions src/stories/requirements/RequirementLink.stories.tsx
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",
},
};
13 changes: 13 additions & 0 deletions src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ html {
--blue-800: #1e40af;
--blue-900: #1e3a8a;

--orange-50: #fff7ed;
BrickheadJohnny marked this conversation as resolved.
Show resolved Hide resolved
--orange-100: #ffedd5;
--orange-200: #fed7aa;
--orange-300: #fdba74;
--orange-400: #fb923c;
--orange-500: #f97316;
--orange-600: #ea580c;
--orange-700: #c2410c;
--orange-800: #9a3412;
--orange-900: #7c2d12;

--red-50: #fef2f2;
--red-100: #fee2e2;
--red-200: #fecaca;
Expand Down Expand Up @@ -156,6 +167,7 @@ html {

--icon-success: var(--green-500);
--icon-error: var(--red-500);
--icon-warning: var(--orange-500);
}

.dark {
Expand Down Expand Up @@ -213,6 +225,7 @@ html {

--icon-success: var(--green-400);
--icon-error: var(--red-400);
--icon-warning: var(--orange-300);
}

body {
Expand Down
Loading
Loading