-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: create card list item component * feat: create disabled variant * feat: create small variantion * test: generate card list unit tests * docs: update css stories * docs: update css stories * style: lint sass file * fix: adjust full width style * fix: adjust backgrounds * fix: remove icon background on small size * fix: remove padding on small size * ci: trigger codecov
- Loading branch information
Luan Peil
authored
Sep 27, 2023
1 parent
4b0a6bf
commit 21f665b
Showing
7 changed files
with
327 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,3 +22,4 @@ | |
@import 'drawer'; | ||
@import 'snackbar'; | ||
@import 'shortcut'; | ||
@import 'card-list-item'; |
118 changes: 118 additions & 0 deletions
118
packages/ocean-core/src/components/_card-list-item.scss
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,118 @@ | ||
.ods-card-list-item { | ||
align-items: center; | ||
border: $border-width-hairline solid $color-interface-light-down; | ||
border-radius: $border-radius-md; | ||
box-sizing: border-box; | ||
cursor: pointer; | ||
display: flex; | ||
flex-direction: row; | ||
gap: $spacing-inline-xs; | ||
padding: $spacing-stack-xs; | ||
transition: 200ms; | ||
width: 320px; | ||
|
||
&__leading-icon { | ||
background-color: $color-interface-light-up; | ||
border-radius: 50%; | ||
box-sizing: content-box; | ||
color: $color-brand-primary-down; | ||
height: $font-size-md; | ||
padding: $spacing-stack-xxs; | ||
transition: 200ms; | ||
width: $font-size-md; | ||
|
||
svg { | ||
height: $font-size-md; | ||
width: $font-size-md; | ||
} | ||
} | ||
|
||
&__content { | ||
display: flex; | ||
flex-direction: column; | ||
width: 100%; | ||
|
||
&__title { | ||
color: $color-interface-dark-pure; | ||
font-family: $font-family-base; | ||
font-size: $font-size-xs; | ||
font-weight: $font-weight-regular; | ||
line-height: $line-height-comfy; | ||
} | ||
|
||
&__description { | ||
color: $color-interface-dark-down; | ||
font-family: $font-family-base; | ||
font-size: $font-size-xxs; | ||
font-weight: $font-weight-regular; | ||
line-height: $line-height-comfy; | ||
} | ||
|
||
&__caption { | ||
color: $color-interface-dark-down; | ||
font-family: $font-family-base; | ||
font-size: $font-size-xxxs; | ||
font-weight: $font-weight-regular; | ||
line-height: $line-height-comfy; | ||
margin-top: $spacing-inset-xxs; | ||
} | ||
} | ||
|
||
&__action { | ||
background-color: transparent; | ||
color: $color-interface-dark-up; | ||
height: $font-size-sm; | ||
width: $font-size-sm; | ||
|
||
&:hover { | ||
background-color: transparent; | ||
} | ||
|
||
svg { | ||
height: $font-size-sm; | ||
width: $font-size-sm; | ||
} | ||
} | ||
|
||
&:hover:not(.ods-card-list-item--disabled) { | ||
background-color: $color-interface-light-up; | ||
|
||
&:not(.ods-card-list-item--size-small) .ods-card-list-item__leading-icon { | ||
background-color: rgba(184, 195, 255, 0.16); | ||
} | ||
} | ||
|
||
&--disabled { | ||
cursor: not-allowed; | ||
|
||
.ods-card-list-item__content__title, | ||
.ods-card-list-item__content__description, | ||
.ods-card-list-item__content__caption { | ||
color: $color-interface-dark-up; | ||
} | ||
|
||
.ods-card-list-item__leading-icon, | ||
.ods-card-list-item__action { | ||
color: $color-interface-light-deep; | ||
} | ||
} | ||
|
||
&--size-small { | ||
.ods-card-list-item__content__title { | ||
font-size: $font-size-xxs; | ||
} | ||
|
||
.ods-card-list-item__content__description { | ||
font-size: $font-size-xxxs; | ||
} | ||
|
||
.ods-card-list-item__leading-icon { | ||
background-color: transparent; | ||
padding: 0; | ||
} | ||
} | ||
|
||
&--full-width { | ||
width: 100%; | ||
} | ||
} |
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 React from 'react'; | ||
import classNames from 'classnames'; | ||
|
||
interface CardListItemProps { | ||
title: string; | ||
description?: string; | ||
caption?: string; | ||
actionIcon?: React.ReactNode; | ||
leadingIcon?: React.ReactNode; | ||
size?: 'small' | 'medium'; | ||
disabled?: boolean; | ||
fullWidth?: boolean; | ||
onClick?: () => void; | ||
} | ||
|
||
const CardListItem = ({ | ||
title, | ||
description, | ||
caption, | ||
leadingIcon, | ||
actionIcon, | ||
size = 'medium', | ||
disabled = false, | ||
fullWidth = false, | ||
onClick, | ||
}: CardListItemProps): JSX.Element => ( | ||
<div | ||
data-testid="card-list-item" | ||
className={classNames( | ||
'ods-card-list-item', | ||
`ods-card-list-item--size-${size}`, | ||
{ 'ods-card-list-item--disabled': disabled }, | ||
{ 'ods-card-list-item--full-width': fullWidth } | ||
)} | ||
onClick={() => { | ||
if (!disabled && onClick) onClick(); | ||
}} | ||
> | ||
{leadingIcon && ( | ||
<div className="ods-card-list-item__leading-icon">{leadingIcon}</div> | ||
)} | ||
<div className="ods-card-list-item__content"> | ||
<div className="ods-card-list-item__content__title">{title}</div> | ||
{description && ( | ||
<div className="ods-card-list-item__content__description"> | ||
{description} | ||
</div> | ||
)} | ||
{caption && size === 'medium' && ( | ||
<div className="ods-card-list-item__content__caption">{caption}</div> | ||
)} | ||
</div> | ||
{actionIcon && ( | ||
<div className="ods-card-list-item__action">{actionIcon}</div> | ||
)} | ||
</div> | ||
); | ||
|
||
export default CardListItem; |
77 changes: 77 additions & 0 deletions
77
packages/ocean-react/src/CardListItem/__tests__/CardListItem.test.tsx
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,77 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, screen } from '@testing-library/react'; | ||
import CardListItem from '../CardListItem'; | ||
|
||
describe('CardListItem', () => { | ||
test('renders the title', () => { | ||
render(<CardListItem title="Test Title" />); | ||
expect(screen.getByText('Test Title')).toBeInTheDocument(); | ||
}); | ||
|
||
test('renders the description', () => { | ||
render(<CardListItem title="Test Title" description="Test Description" />); | ||
expect(screen.getByText('Test Description')).toBeInTheDocument(); | ||
}); | ||
|
||
test('renders the caption when size is medium', () => { | ||
render(<CardListItem title="Test Title" caption="Test Caption" />); | ||
expect(screen.getByText('Test Caption')).toBeInTheDocument(); | ||
}); | ||
|
||
test('does not render the caption when size is small', () => { | ||
render( | ||
<CardListItem title="Test Title" caption="Test Caption" size="small" /> | ||
); | ||
expect(screen.queryByText('Test Caption')).not.toBeInTheDocument(); | ||
}); | ||
|
||
test('calls onClick when clicked and not disabled', () => { | ||
const onClick = jest.fn(); | ||
render(<CardListItem title="Test Title" onClick={onClick} />); | ||
fireEvent.click(screen.getByTestId('card-list-item')); | ||
|
||
expect(onClick).toHaveBeenCalled(); | ||
}); | ||
|
||
test('does not call onClick when clicked and disabled', () => { | ||
const onClick = jest.fn(); | ||
render(<CardListItem title="Test Title" onClick={onClick} disabled />); | ||
fireEvent.click(screen.getByTestId('card-list-item')); | ||
expect(onClick).not.toHaveBeenCalled(); | ||
}); | ||
|
||
test('renders the leading icon', () => { | ||
render( | ||
<CardListItem title="Test Title" leadingIcon={<div>Leading Icon</div>} /> | ||
); | ||
expect(screen.getByText('Leading Icon')).toBeInTheDocument(); | ||
}); | ||
|
||
test('renders the action icon', () => { | ||
render( | ||
<CardListItem title="Test Title" actionIcon={<div>Action Icon</div>} /> | ||
); | ||
expect(screen.getByText('Action Icon')).toBeInTheDocument(); | ||
}); | ||
|
||
test('renders the small size', () => { | ||
render(<CardListItem title="Test Title" size="small" />); | ||
expect(screen.getByTestId('card-list-item')).toHaveClass( | ||
'ods-card-list-item--size-small' | ||
); | ||
}); | ||
|
||
test('renders the disabled state', () => { | ||
render(<CardListItem title="Test Title" disabled />); | ||
expect(screen.getByTestId('card-list-item')).toHaveClass( | ||
'ods-card-list-item--disabled' | ||
); | ||
}); | ||
|
||
test('renders the full width variation', () => { | ||
render(<CardListItem title="Test Title" fullWidth />); | ||
expect(screen.getByTestId('card-list-item')).toHaveClass( | ||
'ods-card-list-item--full-width' | ||
); | ||
}); | ||
}); |
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 { default } from './CardListItem'; |
68 changes: 68 additions & 0 deletions
68
packages/ocean-react/src/CardListItem/stories/CardListItem.stories.mdx
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,68 @@ | ||
import { Meta, Story, Canvas, ArgsTable } from '@storybook/addon-docs'; | ||
import { PlaceholderOutline } from '@useblu/ocean-icons-react'; | ||
import CardListItem from '../CardListItem'; | ||
|
||
<Meta title="Components/CardListItem" component={CardListItem} /> | ||
|
||
# CrossSellCard APIs | ||
|
||
The API documentation of the CardListItem React component. Learn more about the props and the CSS customization points. | ||
|
||
## Import | ||
|
||
```javascript | ||
import { CardListItem } from '@useblu/ocean-react'; | ||
``` | ||
|
||
## Usage | ||
|
||
<Canvas withSource="open" withToolbar> | ||
<Story name="usage"> | ||
<CardListItem | ||
title="Title" | ||
description="Description" | ||
caption="Caption" | ||
leadingIcon={<PlaceholderOutline />} | ||
actionIcon={<PlaceholderOutline />} | ||
/> | ||
</Story> | ||
</Canvas> | ||
|
||
## CSS | ||
|
||
| Global class | Description | | ||
| --------------------------------------------- | ------------------------------------------------------------------ | | ||
| .ods-card-list-item | Styles applied to the root element. | | ||
| .ods-card-list-item--size-small | Styles applied to the root element when size is set to small. | | ||
| .ods-card-list-item--size-medium | Styles applied to the root element when size is set to medium. | | ||
| .ods-card-list-item--disabled | Styles applied to the root element when the component is disabled. | | ||
| .ods-card-list-item--full-width | Styles applied to the root element when is set to full width. | | ||
| .ods-card-list-item\_\_leading-icon | Styles applied to the leading icon. | | ||
| .ods-card-list-item\_\_content | Styles applied to the content element. | | ||
| .ods-card-list-item\_\_content\_\_title | Styles applied to the content title. | | ||
| .ods-card-list-item\_\_content\_\_description | Styles applied to the content description. | | ||
| .ods-card-list-item\_\_content\_\_caption | Styles applied to the content caption. | | ||
| .ods-card-list-item\_\_action-icon | Styles applied to the action icon. | | ||
|
||
If that's not sufficient, you can check the [implementation of the component](https://github.com/ocean-ds/ocean-web/blob/master/packages/ocean-react/src/CardListItem/CardListItem.tsx) for more detail. | ||
|
||
## Playground | ||
|
||
<Canvas> | ||
<Story | ||
name="playground" | ||
args={{ | ||
title: 'Title', | ||
description: 'Description', | ||
caption: 'Caption', | ||
leadingIcon: <PlaceholderOutline />, | ||
actionIcon: <PlaceholderOutline />, | ||
disabled: false, | ||
size: 'medium', | ||
onClick: () => null, | ||
fullWidth: false, | ||
}} | ||
> | ||
{(props) => <CardListItem {...props} />} | ||
</Story> | ||
</Canvas> |
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