Skip to content

Commit

Permalink
fix: display skeleton pool badge if undefined (#71)
Browse files Browse the repository at this point in the history
* chore: move skeleton from shadcn to primitives

* chore: add skeleton variant to Badge

* chore: refactored PoolBadge to PoolStatusBadge and PoolTypeBadge

* fix: wrong skeleton imports

* fix: allow undefined strategyName for skeleton badge

* revert PoolBadge.mdx deletion

* fix: storybook and invalid badges
  • Loading branch information
hussedev authored Dec 2, 2024
1 parent ac5beb7 commit 0a501d4
Show file tree
Hide file tree
Showing 20 changed files with 370 additions and 126 deletions.
8 changes: 4 additions & 4 deletions src/components/Badges/PoolBadge/PoolBadge.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ The `PoolBadge` component is a versatile UI element that indicates either the st

# Example

<Story of={PoolBadgeStories.PoolStatusBadge} />
<Story of={PoolBadgeStories.PoolStatusStory} />

# Controls

<Controls of={PoolBadgeStories.PoolStatusBadge} />
<Controls of={PoolBadgeStories.PoolStatusStory} />

<Story of={PoolBadgeStories.PoolTypeBadge} />
<Story of={PoolBadgeStories.PoolTypeStory} />

# Controls

<Controls of={PoolBadgeStories.PoolTypeBadge} />
<Controls of={PoolBadgeStories.PoolTypeStory} />

# Other variations

Expand Down
131 changes: 77 additions & 54 deletions src/components/Badges/PoolBadge/PoolBadge.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,38 @@ import { PoolStatus, PoolType } from "@/types";
import { PoolBadge } from "./PoolBadge";

const meta: Meta<typeof PoolBadge> = {
title: "Components/PoolBadge",
title: "Components/Badges/PoolBadge",
component: PoolBadge,
argTypes: {
badge: {
control: "select",
options: [...Object.values(PoolStatus), ...Object.values(PoolType), undefined],
description: "The specific badge value be it a PoolStatus or PoolType.",
},
// Exclude the type from the controls
type: {
control: "radio",
options: ["poolStatus", "poolType"],
description: "The type of badge to display.",
},
},
args: {
type: "poolStatus",
badge: PoolStatus.ApplicationsInProgress,
},
};

export default meta;
type Story = StoryObj<typeof PoolBadge>;

export const PoolStatusBadge: Story = {
export const Default: Story = {};

export const PoolStatusStory: Story = {
name: "Pool Status Badge",
argTypes: {
badge: {
control: "select",
options: Object.values(PoolStatus),
options: [...Object.values(PoolStatus), undefined],
description: "The specific badge value.",
},
// Exclude the type from the controls
Expand All @@ -33,11 +53,12 @@ export const PoolStatusBadge: Story = {
};

// Story for poolType
export const PoolTypeBadge: Story = {
export const PoolTypeStory: Story = {
name: "Pool Type Badge",
argTypes: {
badge: {
control: "select",
options: Object.values(PoolType),
options: [...Object.values(PoolType), undefined],
description: "The specific badge value.",
},
type: {
Expand All @@ -52,74 +73,76 @@ export const PoolTypeBadge: Story = {
},
};

export const PreRound: Story = {
args: {
type: "poolStatus",
badge: PoolStatus.PreRound,
},
parameters: {
docs: {
storyDescription: "Displays the `Pre Round` status badge.",
export const UndefinedPoolStatus: Story = {
argTypes: {
badge: {
control: "select",
options: [undefined],
description: "The specific badge value.",
},
type: {
table: {
disable: true,
},
},
},
};

export const RoundInProgress: Story = {
args: {
type: "poolStatus",
badge: PoolStatus.RoundInProgress,
},
parameters: {
docs: {
storyDescription: "Displays the `Round In Progress` status badge.",
},
badge: undefined,
},
};

export const ApplicationsInProgress: Story = {
args: {
type: "poolStatus",
badge: PoolStatus.ApplicationsInProgress,
},
parameters: {
docs: {
storyDescription: "Displays the `Applications In Progress` status badge.",
export const UndefinedPoolType: Story = {
argTypes: {
badge: {
control: "select",
options: [undefined],
description: "The specific badge value.",
},
type: {
table: {
disable: true,
},
},
},
};

export const FundingPending: Story = {
args: {
type: "poolStatus",
badge: PoolStatus.FundingPending,
},
parameters: {
docs: {
storyDescription: "Displays the `Funding Pending` status badge.",
},
type: "poolType",
badge: undefined,
},
};

export const QuadraticFunding: Story = {
export const InvalidPoolStatus: Story = {
argTypes: {
badge: {
control: "select",
options: Object.values(PoolType),
},
type: {
table: {
disable: true,
},
},
},
args: {
type: "poolType",
type: "poolStatus",
badge: PoolType.QuadraticFunding,
},
parameters: {
docs: {
storyDescription: "Displays the `Quadratic Funding` type badge.",
},
},
};

export const DirectGrants: Story = {
export const InvalidPoolType: Story = {
argTypes: {
badge: {
control: "select",
options: Object.values(PoolStatus),
},
type: {
table: {
disable: true,
},
},
},
args: {
type: "poolType",
badge: PoolType.DirectGrants,
},
parameters: {
docs: {
storyDescription: "Displays the `Direct Grants` type badge.",
},
badge: PoolStatus.ApplicationsInProgress,
},
};
75 changes: 16 additions & 59 deletions src/components/Badges/PoolBadge/PoolBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,26 @@
import * as React from "react";

import { tv } from "tailwind-variants";
import { match } from "ts-pattern";
import { match, P } from "ts-pattern";

import { cn } from "@/lib/utils";
import { Badge } from "@/primitives";
import { PoolStatus, PoolType } from "@/types";
import { isPoolStatus, isPoolType, PoolStatus, PoolType } from "@/types";

const PoolBadgeVariants = tv({
variants: {
variant: {
"pre-round": "border border-green-400 bg-white text-green-400",
"round-in-progress": "border-transparent bg-green-200 text-black",
"applications-in-progress": "border-transparent bg-blue-100",
"funding-pending": "border border-red-400 bg-white text-red-400",
"quadratic-funding": "border-transparent bg-green-100",
"direct-grants": "border-transparent bg-yellow-100",
},
},
});
import { PoolStatusBadge } from "../PoolStatusBadge";
import { PoolTypeBadge } from "../PoolTypeBadge";

export interface PoolStatusBadgeProps {
type: "poolStatus";
badge: PoolStatus;
export interface PoolBadgeProps {
type: "poolStatus" | "poolType";
badge?: PoolStatus | PoolType;
className?: string;
}

export interface PoolTypeBadgeProps {
type: "poolType";
badge: PoolType;
className?: string;
}

export type PoolBadgeProps = PoolStatusBadgeProps | PoolTypeBadgeProps;

export const PoolBadge: React.FC<PoolBadgeProps> = (props) => {
const { variant, text } = match(props)
.with({ type: "poolStatus", badge: PoolStatus.PreRound }, () => ({
variant: PoolBadgeVariants({ variant: "pre-round" }),
text: "Pre round",
}))
.with({ type: "poolStatus", badge: PoolStatus.RoundInProgress }, () => ({
variant: PoolBadgeVariants({ variant: "round-in-progress" }),
text: "Round in progress",
}))
.with({ type: "poolStatus", badge: PoolStatus.ApplicationsInProgress }, () => ({
variant: PoolBadgeVariants({ variant: "applications-in-progress" }),
text: "Applications in progress",
}))
.with({ type: "poolStatus", badge: PoolStatus.FundingPending }, () => ({
variant: PoolBadgeVariants({ variant: "funding-pending" }),
text: "Funding pending",
}))
.with({ type: "poolType", badge: PoolType.QuadraticFunding }, () => ({
variant: PoolBadgeVariants({ variant: "quadratic-funding" }),
text: "Quadratic funding",
}))
.with({ type: "poolType", badge: PoolType.DirectGrants }, () => ({
variant: PoolBadgeVariants({ variant: "direct-grants" }),
text: "Direct grants",
}))
.otherwise(() => ({
variant: "border border-red-400 bg-white text-red-400",
text: "Error: Invalid badge type",
}));

return <Badge className={cn(props.className, variant)}>{text}</Badge>;
export const PoolBadge: React.FC<PoolBadgeProps> = ({ type, badge, className }) => {
return match({ type, badge })
.with({ type: "poolStatus", badge: P.optional(P.when(isPoolStatus)) }, () => (
<PoolStatusBadge className={className} value={badge as PoolStatus} />
))
.with({ type: "poolType", badge: P.optional(P.when(isPoolType)) }, () => (
<PoolTypeBadge className={className} value={badge as PoolType} />
))
.otherwise(() => <Badge variant="outlined-error">Error: Invalid badge type</Badge>);
};
84 changes: 84 additions & 0 deletions src/components/Badges/PoolStatusBadge/PoolStatusBadge.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Meta, StoryObj } from "@storybook/react";

import { PoolStatus } from "@/types";

import { PoolStatusBadge } from "./PoolStatusBadge";

const meta: Meta<typeof PoolStatusBadge> = {
title: "Components/Badges/PoolBadge/PoolStatusBadge",
component: PoolStatusBadge,
parameters: {
toc: { disable: true },
},
};

export default meta;
type Story = StoryObj<typeof PoolStatusBadge>;

export const Default: Story = {
argTypes: {
value: {
control: "select",
options: Object.values(PoolStatus),
description: "The specific badge value.",
},
},
args: {
value: PoolStatus.ApplicationsInProgress,
},
};

export const PreRound: Story = {
args: {
value: PoolStatus.PreRound,
},
parameters: {
docs: {
storyDescription: "Displays the `Pre Round` status badge.",
},
},
};

export const RoundInProgress: Story = {
args: {
value: PoolStatus.RoundInProgress,
},
parameters: {
docs: {
storyDescription: "Displays the `Round In Progress` status badge.",
},
},
};

export const ApplicationsInProgress: Story = {
args: {
value: PoolStatus.ApplicationsInProgress,
},
parameters: {
docs: {
storyDescription: "Displays the `Applications In Progress` status badge.",
},
},
};

export const FundingPending: Story = {
args: {
value: PoolStatus.FundingPending,
},
parameters: {
docs: {
storyDescription: "Displays the `Funding Pending` status badge.",
},
},
};

export const Undefined: Story = {
args: {
value: undefined,
},
parameters: {
docs: {
storyDescription: "Displays a skeleton badge when the value is undefined.",
},
},
};
Loading

0 comments on commit 0a501d4

Please sign in to comment.