-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: APP-2619 - Implement Card and CardSummary components
- Loading branch information
Showing
12 changed files
with
256 additions
and
0 deletions.
There are no files selected for viewing
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,33 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import { Card } from './card'; | ||
|
||
const meta: Meta<typeof Card> = { | ||
title: 'components/Cards/Card', | ||
component: Card, | ||
tags: ['autodocs'], | ||
parameters: { | ||
design: { | ||
type: 'figma', | ||
url: 'https://www.figma.com/file/jfKRr1V9evJUp1uBeyP3Zz/v1.0.0?type=design&node-id=10157-27011&mode=design&t=2bLCEeKZ7ueBboTs-4', | ||
}, | ||
}, | ||
}; | ||
|
||
type Story = StoryObj<typeof Card>; | ||
|
||
/** | ||
* Default usage example of the Card component. | ||
*/ | ||
export const Default: Story = { | ||
args: { | ||
className: 'min-w-[320px]', | ||
children: ( | ||
<div className="flex flex-col items-center p-2"> | ||
<p className="text-xs font-semibold leading-normal">Example</p> | ||
<p className="text-xs font-normal leading-normal">Description</p> | ||
</div> | ||
), | ||
}, | ||
}; | ||
|
||
export default meta; |
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,16 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import { Card, type ICardProps } from './card'; | ||
|
||
describe('<Card /> component', () => { | ||
const createTestComponent = (props?: Partial<ICardProps>) => { | ||
const completeProps = { ...props }; | ||
|
||
return <Card {...completeProps} />; | ||
}; | ||
|
||
it('renders the card content', () => { | ||
const children = 'cardContent'; | ||
render(createTestComponent({ children })); | ||
expect(screen.getByText(children)).toBeInTheDocument(); | ||
}); | ||
}); |
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,12 @@ | ||
import classNames from 'classnames'; | ||
import type { HTMLAttributes } from 'react'; | ||
|
||
export interface ICardProps extends HTMLAttributes<HTMLDivElement> {} | ||
|
||
export const Card: React.FC<ICardProps> = (props) => { | ||
const { className, ...otherProps } = props; | ||
|
||
return ( | ||
<div className={classNames('rounded-xl border border-neutral-100 bg-neutral-0', className)} {...otherProps} /> | ||
); | ||
}; |
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 @@ | ||
export { Card, type ICardProps } from './card'; |
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,37 @@ | ||
import type { IconType } from '../../icon'; | ||
import type { ICardProps } from '../card/card'; | ||
|
||
export interface ICardSummaryAction { | ||
/** | ||
* Label of the summary action. | ||
*/ | ||
label: string; | ||
/** | ||
* Callback called on summary action click. | ||
*/ | ||
onClick?: () => void; | ||
} | ||
|
||
export interface ICardSummaryProps extends ICardProps { | ||
/** | ||
* Icon displayed on the card. | ||
*/ | ||
icon: IconType; | ||
/** | ||
* Value of the summary. | ||
*/ | ||
value: string; | ||
/** | ||
* Description of the summary. | ||
*/ | ||
description: string; | ||
/** | ||
* Action of the summary. | ||
*/ | ||
action: ICardSummaryAction; | ||
/** | ||
* Renders the action as stacked when set to true. | ||
* @default true | ||
*/ | ||
isStacked?: boolean; | ||
} |
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,44 @@ | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
import { IconType } from '../../icon'; | ||
import { CardSummary } from './cardSummary'; | ||
|
||
const meta: Meta<typeof CardSummary> = { | ||
title: 'components/Cards/CardSummary', | ||
component: CardSummary, | ||
tags: ['autodocs'], | ||
parameters: { | ||
design: { | ||
type: 'figma', | ||
url: 'https://www.figma.com/file/jfKRr1V9evJUp1uBeyP3Zz/v1.0.0?type=design&node-id=10157-27206&mode=dev', | ||
}, | ||
}, | ||
}; | ||
|
||
type Story = StoryObj<typeof CardSummary>; | ||
|
||
/** | ||
* Default usage example of the CardSummary component. | ||
*/ | ||
export const Default: Story = { | ||
args: { | ||
value: '5', | ||
description: 'Proposals created', | ||
action: { label: 'Create proposal', onClick: () => alert('Click') }, | ||
icon: IconType.APP_GOVERNANCE, | ||
}, | ||
}; | ||
|
||
/** | ||
* Set the `isStacked` property to false to render a CardSummary component with a horizontal layout (only rendered on screens > MD). | ||
*/ | ||
export const HorizontalLayout: Story = { | ||
args: { | ||
value: '22', | ||
description: 'Members', | ||
action: { label: 'Delegate', onClick: () => alert('Click') }, | ||
icon: IconType.APP_COMMUNITY, | ||
isStacked: false, | ||
}, | ||
}; | ||
|
||
export default meta; |
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,45 @@ | ||
import { fireEvent, render, screen } from '@testing-library/react'; | ||
import { IconType } from '../../icon'; | ||
import { CardSummary } from './cardSummary'; | ||
import type { ICardSummaryProps } from './cardSummary.api'; | ||
|
||
describe('<CardSummary /> component', () => { | ||
const createTestComponent = (props?: Partial<ICardSummaryProps>) => { | ||
const completeProps: ICardSummaryProps = { | ||
value: '1', | ||
description: 'description-test', | ||
action: { label: 'action' }, | ||
icon: IconType.ADD, | ||
...props, | ||
}; | ||
|
||
return <CardSummary {...completeProps} />; | ||
}; | ||
|
||
it('renders the summary value and description', () => { | ||
const value = '22'; | ||
const description = 'Proposals created'; | ||
render(createTestComponent({ value, description })); | ||
expect(screen.getByText(value)).toBeInTheDocument(); | ||
expect(screen.getByText(description)).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders the specified icon', () => { | ||
const icon = IconType.BLOCKCHAIN; | ||
render(createTestComponent({ icon })); | ||
expect(screen.getByTestId(icon)).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders the specified action', () => { | ||
const label = 'action-test'; | ||
const onClick = jest.fn(); | ||
const action = { label, onClick }; | ||
render(createTestComponent({ action })); | ||
|
||
const button = screen.getByRole('button', { name: label }); | ||
expect(button).toBeInTheDocument(); | ||
|
||
fireEvent.click(button); | ||
expect(onClick).toHaveBeenCalled(); | ||
}); | ||
}); |
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,59 @@ | ||
import classNames from 'classnames'; | ||
import { AvatarIcon } from '../../avatars'; | ||
import { Button } from '../../button'; | ||
import { IconType } from '../../icon'; | ||
import { Card } from '../card'; | ||
import type { ICardSummaryProps } from './cardSummary.api'; | ||
|
||
export const CardSummary: React.FC<ICardSummaryProps> = (props) => { | ||
const { icon, value, description, action, isStacked = true, className, ...otherProps } = props; | ||
|
||
const containerClassNames = classNames( | ||
'grid grid-cols-[auto_max-content] items-center gap-4 p-4 md:px-6 md:py-5', | ||
{ 'grid-cols-[auto_max-content] md:gap-5': isStacked }, | ||
{ | ||
'grid-cols-[auto_max-content] md:grid-flow-col md:grid-cols-[auto_1fr_1fr_max-content] md:gap-6': | ||
!isStacked, | ||
}, | ||
); | ||
|
||
return ( | ||
<Card | ||
className={classNames( | ||
{ 'w-[320px] md:w-[480px]': isStacked }, | ||
{ 'w-[320px] md:w-[640px]': !isStacked }, | ||
className, | ||
)} | ||
{...otherProps} | ||
> | ||
<div className={containerClassNames}> | ||
<AvatarIcon | ||
variant="neutral" | ||
icon={icon} | ||
size="md" | ||
responsiveSize={{ md: 'lg' }} | ||
className="self-center" | ||
/> | ||
<Button | ||
variant="tertiary" | ||
size="md" | ||
responsiveSize={{ md: 'lg' }} | ||
iconLeft={IconType.ADD} | ||
onClick={action.onClick} | ||
> | ||
{action.label} | ||
</Button> | ||
<div | ||
className={classNames( | ||
'col-span-2 flex gap-x-2 gap-y-1', | ||
{ 'flex-col': isStacked }, | ||
{ 'flex-col md:col-start-2 md:flex-row md:items-baseline': !isStacked }, | ||
)} | ||
> | ||
<p className="text-2xl font-semibold leading-tight text-neutral-800 md:text-3xl">{value}</p> | ||
<p className="text-base font-normal leading-tight text-neutral-400">{description}</p> | ||
</div> | ||
</div> | ||
</Card> | ||
); | ||
}; |
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,2 @@ | ||
export { CardSummary } from './cardSummary'; | ||
export { type ICardSummaryProps } from './cardSummary.api'; |
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,2 @@ | ||
export * from './card'; | ||
export * from './cardSummary'; |
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