-
Notifications
You must be signed in to change notification settings - Fork 14
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: create colony cards for landing page #3425
base: feat/landing-page
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import { Plus } from '@phosphor-icons/react'; | ||
import clsx from 'clsx'; | ||
import React from 'react'; | ||
|
||
import LoadingSkeleton from '~common/LoadingSkeleton/LoadingSkeleton.tsx'; | ||
import { formatText } from '~utils/intl.ts'; | ||
import Button from '~v5/shared/Button/Button.tsx'; | ||
|
||
export interface ColonyCardProps { | ||
colonyName?: string; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think all of the conditional rendering we're doing with skeletons and handling the create new colony function is putting way too many things into this component.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bassgeta Ok, I will add |
||
colonyAvatar?: string; | ||
membersCount?: number; | ||
invitationsRemaining?: number; | ||
loading?: boolean; | ||
onCreate?: () => void; | ||
} | ||
|
||
const displayName = 'frame.LandingPage'; | ||
|
||
export const ColonyCard = ({ | ||
colonyName, | ||
colonyAvatar, | ||
invitationsRemaining, | ||
membersCount = 0, | ||
loading, | ||
onCreate, | ||
}: ColonyCardProps) => { | ||
return ( | ||
<div | ||
className={clsx( | ||
'flex h-[4.5rem] items-center gap-[.875rem] rounded border px-5 py-4 transition-colors duration-normal', | ||
{ | ||
'cursor-pointer': colonyName && !loading, | ||
'hover:border-gray-900': !loading, | ||
}, | ||
)} | ||
> | ||
<div className="flex h-8 w-8 items-center justify-center"> | ||
<LoadingSkeleton isLoading={loading} className="h-8 w-8 rounded-full"> | ||
{colonyName && colonyAvatar ? ( | ||
<img | ||
src={colonyAvatar} | ||
alt="Colony avatar" | ||
className="w-8 rounded-full" | ||
/> | ||
) : ( | ||
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-100"> | ||
<Plus size={18} className="text-gray-900 " /> | ||
</div> | ||
)} | ||
</LoadingSkeleton> | ||
</div> | ||
{loading ? ( | ||
<div className="flex flex-col gap-1"> | ||
<LoadingSkeleton isLoading className="h-5 w-[7.5rem] rounded" /> | ||
<LoadingSkeleton | ||
isLoading | ||
className="h-[.6875rem] w-[4.25rem] rounded" | ||
/> | ||
</div> | ||
) : ( | ||
<div className="flex w-full items-center justify-between"> | ||
{colonyName ? ( | ||
<p className="text-md font-medium">{colonyName}</p> | ||
) : ( | ||
<div className="flex flex-col gap-1"> | ||
<div className="flex"> | ||
<span className="rounded bg-blue-100 px-[.1875rem] py-[.1563rem] text-2xs font-extrabold text-blue-400"> | ||
{formatText( | ||
{ | ||
id: 'landingPage.card.remaining', | ||
}, | ||
{ remaining: invitationsRemaining }, | ||
).toUpperCase()} | ||
</span> | ||
</div> | ||
<p className="text-md font-medium"> | ||
{formatText({ | ||
id: 'landingPage.card.createColony', | ||
})} | ||
</p> | ||
</div> | ||
)} | ||
|
||
{colonyName ? ( | ||
<p className="text-xs font-normal"> | ||
{formatText( | ||
{ | ||
id: 'landingPage.card.members', | ||
}, | ||
{ members: membersCount.toLocaleString('en-US') }, | ||
)} | ||
</p> | ||
) : ( | ||
<Button icon={Plus} onClick={onCreate}> | ||
Create | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please extract this into a |
||
</Button> | ||
)} | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}; | ||
|
||
ColonyCard.displayName = displayName; | ||
|
||
export default ColonyCard; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { type Meta, type StoryObj } from '@storybook/react'; | ||
import React from 'react'; | ||
|
||
import ColonyCard from '~frame/LandingPage/ColonyCard.tsx'; | ||
|
||
const meta: Meta<typeof ColonyCard> = { | ||
title: 'Common/Colony Card', | ||
component: ColonyCard, | ||
decorators: [ | ||
(Story) => ( | ||
<div className="mx-auto max-w-[41.75rem]"> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
argTypes: { | ||
colonyName: { | ||
name: 'Colony name', | ||
control: { | ||
type: 'text', | ||
}, | ||
}, | ||
colonyAvatar: { | ||
name: 'Colony avatar', | ||
control: { | ||
type: 'text', | ||
}, | ||
}, | ||
membersCount: { | ||
name: 'Members count', | ||
control: { | ||
type: 'number', | ||
}, | ||
}, | ||
invitationsRemaining: { | ||
name: 'Invitations remaining', | ||
control: { | ||
type: 'number', | ||
}, | ||
}, | ||
loading: { | ||
name: 'Loading', | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof ColonyCard>; | ||
|
||
export const ActiveColony: Story = { | ||
args: { | ||
colonyName: 'Beta colony', | ||
colonyAvatar: 'https://picsum.photos/200', | ||
membersCount: 1520, | ||
invitationsRemaining: 2, | ||
}, | ||
}; | ||
|
||
export const CreateColony: Story = { | ||
args: { | ||
invitationsRemaining: 3, | ||
}, | ||
}; | ||
|
||
export const Loading: Story = { | ||
args: { | ||
loading: true, | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given we have multiple scenarios for the
ColonyCard
, namely the loading state, creating a colony and active colony, we should definitely create multiple instances of theColonyCard
and use them accordingly:LoadingColonyCard
,CreateColonyCard
andActiveColonyCard
- the last two could instantiate aBaseColonyCard
which could have the following implementation