From 1c8cf3df19e2d0313d11a06975e845fcf23788a4 Mon Sep 17 00:00:00 2001 From: Daniela Muller <62384394+danimuller20@users.noreply.github.com> Date: Wed, 26 Jun 2024 09:44:27 -0300 Subject: [PATCH] feat: update card list item component (#1113) * feat: update card list item component * feat: update card list item component * chore: update card list items documentation * test: update tests * style: add mixincode * style: update card list item style * chore: remove unused background color --- .../src/components/_card-list-item.scss | 103 +++++++++--- .../src/CardListItem/CardListItem.tsx | 154 +++++++++++++----- .../__tests__/CardListItem.test.tsx | 7 + .../stories/CardListItem.stories.mdx | 10 ++ 4 files changed, 210 insertions(+), 64 deletions(-) diff --git a/packages/ocean-core/src/components/_card-list-item.scss b/packages/ocean-core/src/components/_card-list-item.scss index be0c5d164..55ee5c2b3 100644 --- a/packages/ocean-core/src/components/_card-list-item.scss +++ b/packages/ocean-core/src/components/_card-list-item.scss @@ -1,29 +1,28 @@ +@mixin default-line { + animation: pulse 1.5s infinite ease-in-out; + background-color: $color-interface-light-up; + border-radius: $border-radius-tiny; +} + .ods-card-list-item { align-items: center; border: $border-width-hairline solid $color-interface-light-down; - border-radius: $border-radius-md; + border-radius: $border-radius-sm; box-sizing: border-box; cursor: pointer; display: flex; flex-direction: row; - gap: $spacing-inline-xs; - padding: $spacing-stack-xs; + gap: $spacing-inline-xxs-extra; + padding: $spacing-stack-xs $spacing-inline-xxs-extra $spacing-stack-xs + $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; + color: $color-brand-primary-down; + height: $spacing-stack-sm; + width: $spacing-stack-sm; } } @@ -52,9 +51,9 @@ color: $color-interface-dark-down; font-family: $font-family-base; font-size: $font-size-xxxs; - font-weight: $font-weight-regular; + font-weight: $font-weight-medium; line-height: $line-height-comfy; - margin-top: $spacing-inset-xxs; + margin-top: $spacing-inline-xxs; } } @@ -74,12 +73,8 @@ } } - &:hover:not(.ods-card-list-item--disabled) { + &:hover:not(.ods-card-list-item--disabled, .ods-card-list-item--loading) { 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 { @@ -110,9 +105,75 @@ background-color: transparent; padding: 0; } + + .ods-card-list-item__lines { + margin-left: 0; + } + + .ods-card-list-item__circle { + height: 20px; + min-height: 20px; + min-width: 20px; + width: 20px; + } + + .ods-card-list-item__lines__line2 { + width: 87px; + } + + .ods-card-list-item__lines__line2 { + width: 260px; + } } &--full-width { width: 100%; } + + &__circle { + animation: pulse 1.5s infinite ease-in-out; + background-color: $color-interface-light-up; + border-radius: 50%; + height: $spacing-stack-lg; + width: $spacing-stack-lg; + } + + &__lines { + display: flex; + flex-direction: column; + gap: $spacing-inline-xxs; + margin-left: $spacing-inline-xxxs; + + &__line1 { + @include default-line; + height: 16px; + width: 80px; + } + + &__line2 { + @include default-line; + height: 16px; + width: 236px; + } + + &__line3 { + @include default-line; + height: 16px; + width: 118px; + } + } +} + +@keyframes pulse { + 0% { + opacity: 1; + } + + 50% { + opacity: 0.5; + } + + 100% { + opacity: 1; + } } diff --git a/packages/ocean-react/src/CardListItem/CardListItem.tsx b/packages/ocean-react/src/CardListItem/CardListItem.tsx index 31b1714a9..516631152 100644 --- a/packages/ocean-react/src/CardListItem/CardListItem.tsx +++ b/packages/ocean-react/src/CardListItem/CardListItem.tsx @@ -1,59 +1,127 @@ -import React from 'react'; +import React, { ComponentPropsWithoutRef, forwardRef } from 'react'; import classNames from 'classnames'; -interface CardListItemProps { +type CardListItemProps = { + /* + * The title of the card list item. + */ title: string; + /* + * The description of the card list item. + */ description?: string; + /* + * The caption of the card list item. + */ caption?: string; + /* + * The action icon of the card list item. + */ actionIcon?: React.ReactNode; + /* + * The leading icon of the card list item. + */ leadingIcon?: React.ReactNode; + /* + * The size of the card list item. + */ size?: 'small' | 'medium'; + /* + * Whether the card list item is disabled. + */ disabled?: boolean; + /* + * Whether the card list item is full width. + */ fullWidth?: boolean; + /* + * The function to call when the card list item is clicked. + */ onClick?: () => void; -} + /* + * Whether the card list item is loading. + */ + loading?: boolean; +} & ComponentPropsWithoutRef<'div'>; -const CardListItem = ({ - title, - description, - caption, - leadingIcon, - actionIcon, - size = 'medium', - disabled = false, - fullWidth = false, - onClick, -}: CardListItemProps): JSX.Element => ( -
{ - if (!disabled && onClick) onClick(); - }} - > - {leadingIcon && ( -
{leadingIcon}
- )} -
-
{title}
- {description && ( -
- {description} +const CardListItem = forwardRef( + ( + { + title, + description, + caption, + leadingIcon, + actionIcon, + size = 'medium', + disabled = false, + fullWidth = false, + onClick, + loading, + ...rest + }, + ref + ): JSX.Element => + loading ? ( +
+
+
+
+
+ {size === 'medium' && ( +
+ )}
- )} - {caption && size === 'medium' && ( -
{caption}
- )} -
- {actionIcon && ( -
{actionIcon}
- )} -
+
+ ) : ( +
{ + if (!disabled && onClick) onClick(); + }} + > + {leadingIcon && ( +
{leadingIcon}
+ )} +
+
{title}
+ {description && ( +
+ {description} +
+ )} + {caption && size === 'medium' && ( +
+ {caption} +
+ )} +
+ {actionIcon && ( +
{actionIcon}
+ )} +
+ ) ); +CardListItem.displayName = 'CardListItem'; + export default CardListItem; diff --git a/packages/ocean-react/src/CardListItem/__tests__/CardListItem.test.tsx b/packages/ocean-react/src/CardListItem/__tests__/CardListItem.test.tsx index e780894af..b0b8d23e4 100644 --- a/packages/ocean-react/src/CardListItem/__tests__/CardListItem.test.tsx +++ b/packages/ocean-react/src/CardListItem/__tests__/CardListItem.test.tsx @@ -74,4 +74,11 @@ describe('CardListItem', () => { 'ods-card-list-item--full-width' ); }); + + test('renders the loading state', () => { + render(); + expect(screen.getByTestId('card-list-item')).toHaveClass( + 'ods-card-list-item--loading' + ); + }); }); diff --git a/packages/ocean-react/src/CardListItem/stories/CardListItem.stories.mdx b/packages/ocean-react/src/CardListItem/stories/CardListItem.stories.mdx index 6b533133c..fc212309f 100644 --- a/packages/ocean-react/src/CardListItem/stories/CardListItem.stories.mdx +++ b/packages/ocean-react/src/CardListItem/stories/CardListItem.stories.mdx @@ -28,6 +28,10 @@ import { CardListItem } from '@useblu/ocean-react'; +## Props + + + ## CSS | Global class | Description | @@ -43,6 +47,12 @@ import { CardListItem } from '@useblu/ocean-react'; | .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. | +| .ods-card-list-item--loading | Styles applied to the root element when loading | +| .ods-card-list-item\_\_circle | Styles applied to the content of loading representing icon | +| .ods-card-list-item\_\_lines | Styles applied to the content of loading representing a box | +| .ods-card-list-item**lines**line1 | Styles applied to the content of loading representing a line | +| .ods-card-list-item**lines**line2 | Styles applied to the content of loading representing a line | +| .ods-card-list-item**lines**line3 | Styles applied to the content of loading representing a line | 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.