From 1b5513e79d517755808d0a5e577646f946663780 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Tue, 26 Nov 2024 17:35:34 +0530 Subject: [PATCH 1/8] chore(cards): rename aiLabel to decorator --- .../src/components/Card/_card.scss | 18 ++++---- .../ibm-products/src/components/Card/Card.tsx | 25 ++++++----- .../src/components/Card/CardHeader.tsx | 38 ++++++++++------- .../ExpressiveCard.docs-page.js | 6 +-- .../ExpressiveCard/ExpressiveCard.stories.jsx | 41 +++++++++++-------- .../ExpressiveCard/ExpressiveCard.tsx | 20 ++++----- .../ProductiveCard.docs-page.js | 6 +-- .../ProductiveCard/ProductiveCard.stories.jsx | 37 ++++++++++------- .../ProductiveCard/ProductiveCard.tsx | 14 +++---- 9 files changed, 119 insertions(+), 86 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index d7d2c28ead..bf5a447a39 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -5,7 +5,7 @@ // LICENSE file in the root directory of this source tree. // -// NOTE: Please do not remove the duplicate `slug` and `ai-label` classes. We need both until slug is fully deprecated +// NOTE: Please do not remove the duplicate `slug` and `decorator` classes. We need both until slug is fully deprecated // Standard imports. @use '@carbon/styles/scss/theme' as *; @@ -151,18 +151,18 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}__header-container--has-slug, -.#{$block-class}__header-container--has-ai-label { +.#{$block-class}__header-container--has-decorator { width: 100%; padding-right: $spacing-07; } .#{$block-class}__header-container--has-slug.#{$block-class}__header-container--has-actions, -.#{$block-class}__header-container--has-ai-label.#{$block-class}__header-container--has-actions { +.#{$block-class}__header-container--has-decorator.#{$block-class}__header-container--has-actions { padding-right: $spacing-08; } .#{$block-class}__header-container--has-slug.#{$block-class}__header-container--large-tile-or-label, -.#{$block-class}__header-container--has-ai-label.#{$block-class}__header-container--large-tile-or-label { +.#{$block-class}__header-container--has-decorator.#{$block-class}__header-container--large-tile-or-label { padding-right: $spacing-09; } @@ -176,7 +176,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}--has-slug, -.#{$block-class}--has-ai-label { +.#{$block-class}--has-decorator { @include utilities.ai-popover-gradient('default', 0, 'layer'); border: 1px solid transparent; @@ -184,8 +184,12 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; 0 4px 10px 2px $ai-drop-shadow; } +.#{$block-class}--has-decorator-non-ai-label { + background-color: $layer-01; +} + .#{$block-class}__clickable.#{$block-class}--has-slug::before, -.#{$block-class}__clickable.#{$block-class}--has-ai-label::before { +.#{$block-class}__clickable.#{$block-class}--has-decorator::before { @include utilities.ai-popover-gradient('hover', 0, 'layer'); position: absolute; @@ -201,7 +205,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}__clickable.#{$block-class}--has-slug:hover::before, -.#{$block-class}__clickable.#{$block-class}--has-ai-label:hover::before { +.#{$block-class}__clickable.#{$block-class}--has-decorator:hover::before { opacity: 1; } diff --git a/packages/ibm-products/src/components/Card/Card.tsx b/packages/ibm-products/src/components/Card/Card.tsx index 20c3eda738..4df3f5228e 100644 --- a/packages/ibm-products/src/components/Card/Card.tsx +++ b/packages/ibm-products/src/components/Card/Card.tsx @@ -83,14 +83,14 @@ interface CardProp extends PropsWithChildren { /** * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug?: ReactNode | boolean; /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. */ - aiLabel?: ReactNode | boolean; + decorator?: ReactNode | boolean; status?: 'complete' | 'incomplete'; title?: ReactNode; @@ -103,7 +103,7 @@ export const Card = forwardRef( // The component props, in alphabetical order (for consistency). actionIcons = Object.freeze([]), actionsPlacement = 'bottom', - aiLabel, + decorator, metadata = Object.freeze([]), children, className, @@ -262,7 +262,10 @@ export const Card = forwardRef( [`${blockClass}__clickable`]: clickable, [`${blockClass}__media-left`]: mediaPosition === 'left', [`${blockClass}--has-slug`]: !!slug, - [`${blockClass}--has-ai-label`]: !!aiLabel, + [`${blockClass}--has-decorator-non-ai-label`]: + !!decorator && decorator['type']?.displayName !== 'AILabel', + [`${blockClass}--has-decorator`]: + !!decorator && decorator['type']?.displayName === 'AILabel', }, className ), @@ -287,7 +290,7 @@ export const Card = forwardRef( const getHeaderProps = () => ({ actions: actionsPlacement === 'top' ? getActions() : '', - aiLabel, + decorator, noActionIcons: getIcons().length > 0 && actionsPlacement === 'top' ? false : true, actionsPlacement, @@ -395,13 +398,13 @@ Card.propTypes = { }) ), actionsPlacement: PropTypes.oneOf(['top', 'bottom']), - /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. - */ - aiLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), children: PropTypes.node, className: PropTypes.string, clickZone: PropTypes.oneOf(['one', 'two', 'three']), + /** + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + */ + decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /**@ts-ignore */ description: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), disabled: PropTypes.bool, @@ -455,7 +458,7 @@ Card.propTypes = { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), diff --git a/packages/ibm-products/src/components/Card/CardHeader.tsx b/packages/ibm-products/src/components/Card/CardHeader.tsx index c261f5a3a0..d9ae2736ae 100644 --- a/packages/ibm-products/src/components/Card/CardHeader.tsx +++ b/packages/ibm-products/src/components/Card/CardHeader.tsx @@ -20,9 +20,9 @@ const defaults = { interface CardHeaderProps { actions?: ReactNode; /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. */ - aiLabel?: ReactNode | boolean; + decorator?: ReactNode | boolean; description?: ReactNode; hasActions?: boolean; /** @@ -46,7 +46,7 @@ interface CardHeaderProps { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug?: ReactNode; @@ -56,7 +56,7 @@ interface CardHeaderProps { export const CardHeader = ({ actions, - aiLabel, + decorator, noActionIcons, onPrimaryButtonClick, onSecondaryButtonClick, @@ -107,17 +107,17 @@ export const CardHeader = ({ ); - let normalizedAiLabel: React.ReactElement | null = null; - if (aiLabel || slug) { + let normalizedDecorator: React.ReactElement | null = null; + if (decorator || slug) { if ( inClickableCard || - typeof aiLabel === 'boolean' || + typeof decorator === 'boolean' || typeof slug === 'boolean' ) { - normalizedAiLabel = hollowAiIcon; + normalizedDecorator = hollowAiIcon; } else { - const element = aiLabel || slug; - normalizedAiLabel = React.cloneElement( + const element = decorator || slug; + normalizedDecorator = React.cloneElement( element as React.ReactElement, { size: @@ -133,7 +133,7 @@ export const CardHeader = ({ className={cx([ `${headerClass}-container`, { [`${headerClass}-container--has-slug`]: !!slug }, - { [`${headerClass}-container--has-ai-label`]: !!aiLabel }, + { [`${headerClass}-container--has-decorator`]: !!decorator }, { [`${headerClass}-container--has-actions`]: !!hasActions }, { [`${headerClass}-container--large-tile-or-label`]: @@ -180,7 +180,15 @@ export const CardHeader = ({ )} )} - {normalizedAiLabel} + {slug ? ( + normalizedDecorator + ) : decorator ? ( +
+ {normalizedDecorator} +
+ ) : ( + '' + )} ); @@ -189,9 +197,9 @@ export const CardHeader = ({ CardHeader.propTypes = { actions: PropTypes.oneOfType([PropTypes.array, PropTypes.node]), /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. */ - aiLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), + decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), description: PropTypes.oneOfType([ PropTypes.string, PropTypes.object, @@ -219,7 +227,7 @@ CardHeader.propTypes = { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), diff --git a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.docs-page.js b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.docs-page.js index 18937b7bc9..14e041fbba 100644 --- a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.docs-page.js +++ b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.docs-page.js @@ -53,7 +53,7 @@ const DocsPage = () => ( {renderedContent}} + decorator={{renderedContent}} title="Title">

expressive card body content block. description inviting the user to take action on the card. @@ -64,7 +64,7 @@ const DocsPage = () => ( }, { description: - 'Clickable tiles only accept a boolean value of true for the aiLabel property.', + 'Clickable tiles only accept a boolean value of true for the decorator property.', source: { language: 'html', code: ` @@ -73,7 +73,7 @@ const DocsPage = () => ( primaryButtonText="Primary" onClick={() => {}} onKeyDown={() => {}} - aiLabel={true} + decorator={true} title="Title">

expressive card body content block. description inviting the user to take action on the card. diff --git a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx index 5ed6d1fbe8..95861b8347 100644 --- a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx +++ b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx @@ -13,17 +13,17 @@ import { Column, Grid, usePrefix, - unstable__Slug as Slug, - unstable__SlugContent as SlugContent, + AILabel, + AILabelContent, } from '@carbon/react'; import { ExpressiveCard } from '.'; import DocsPage from './ExpressiveCard.docs-page'; import { action } from '@storybook/addon-actions'; -const sampleSlug = ( - - +const sampleDecorator = ( + +

AI Explained

84%

@@ -37,8 +37,8 @@ const sampleSlug = (

Model type

Foundation model

- - + + ); export default { @@ -82,22 +82,22 @@ export default { labels: { 0: 'No AI slug', 1: 'with AI Slug', - 2: 'with hollow slug (boolean)', }, default: 0, }, - options: [0, 1, 2], + options: [false, true], }, - aiLabel: { + decorator: { control: { type: 'select', labels: { 0: 'No AI label', 1: 'with AI label', + 2: 'with hollow AI label (boolean)', }, default: 0, }, - options: [false, true], + options: [0, 1, 2], }, }, decorators: [ @@ -126,13 +126,22 @@ const defaultProps = { }; const Template = (opts) => { - const { children, columnSizeSm, columnSizeMd, columnSizeLg, slug, ...args } = - opts; + const { + children, + columnSizeSm, + columnSizeMd, + columnSizeLg, + decorator, + ...args + } = opts; return ( - + {children} @@ -147,7 +156,7 @@ const MediaTemplate = (opts) => { columnSizeMd, columnSizeLg, mediaRatio = '1x1', - slug, + decorator, ...args } = opts; return ( @@ -155,7 +164,7 @@ const MediaTemplate = (opts) => { {mediaRatio}} - slug={slug && (slug === 2 || sampleSlug)} + decorator={decorator && (decorator === 2 || sampleDecorator)} {...args} > {children} diff --git a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx index 9a4de0db85..5d615d54b3 100644 --- a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx +++ b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx @@ -28,10 +28,6 @@ export interface ExpressiveCardProps extends PropsWithChildren { * Icons that are displayed on card. Refer to design documentation for implementation guidelines. Note- href will supersede onClick */ actionIcons?: ActionIcon[]; - /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. - */ - aiLabel?: ReactNode | boolean; /** * Content that shows in the body of the card */ @@ -40,6 +36,10 @@ export interface ExpressiveCardProps extends PropsWithChildren { * Optional user provided class */ className?: string; + /** + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + */ + decorator?: ReactNode | boolean; /** * Optional header description */ @@ -107,7 +107,7 @@ export interface ExpressiveCardProps extends PropsWithChildren { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug?: ReactNode | boolean; @@ -152,10 +152,6 @@ ExpressiveCard.propTypes = { href: PropTypes.string, }) ), - /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. - */ - aiLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** * Content that shows in the body of the card */ @@ -164,6 +160,10 @@ ExpressiveCard.propTypes = { * Optional user provided class */ className: PropTypes.string, + /** + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + */ + decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** * Optional header description */ @@ -242,7 +242,7 @@ ExpressiveCard.propTypes = { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), diff --git a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.docs-page.js b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.docs-page.js index 0ed7f84866..7b70135e77 100644 --- a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.docs-page.js +++ b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.docs-page.js @@ -54,7 +54,7 @@ const DocsPage = () => ( onClick={() => {}} onKeyDown={() => {}} primaryButtonText="Ghost button" - aiLabel={... || true} + decorator={... || true} title="Title" > @@ -72,7 +72,7 @@ const DocsPage = () => ( }, { description: - 'Clickable tiles only accept a boolean value of true for the aiLabel property.', + 'Clickable tiles only accept a boolean value of true for the decorator property.', source: { language: 'html', code: ` @@ -80,7 +80,7 @@ const DocsPage = () => ( onClick={() => {}} onKeyDown={() => {}} primaryButtonText="Ghost button" - aiLabel={true} + decorator={true} title="Title" > diff --git a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx index bea6afca41..4d196ee49c 100644 --- a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx +++ b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx @@ -12,8 +12,8 @@ import { Grid, Column, usePrefix, - unstable__Slug as Slug, - unstable__SlugContent as SlugContent, + AILabel, + AILabelContent, } from '@carbon/react'; import { ProductiveCard } from '.'; import DocsPage from './ProductiveCard.docs-page'; @@ -21,9 +21,9 @@ import { action } from '@storybook/addon-actions'; const storyClass = 'productive-card-stories'; -const sampleSlug = ( - - +const sampleDecorator = ( + +

AI Explained

84%

@@ -37,8 +37,8 @@ const sampleSlug = (

Model type

Foundation model

-
-
+ + ); export default { @@ -76,22 +76,22 @@ export default { labels: { 0: 'No AI slug', 1: 'with AI Slug', - 2: 'with hollow slug (boolean)', }, default: 0, }, - options: [0, 1], + options: [false, true], }, - aiLabel: { + decorator: { control: { type: 'select', labels: { 0: 'No AI label', 1: 'with AI label', + 2: 'with hollow AI label (boolean)', }, default: 0, }, - options: [false, true], + options: [0, 1], }, }, decorators: [ @@ -137,12 +137,21 @@ const defaultProps = { }; const Template = (opts) => { - const { children, columnSizeSm, columnSizeMd, columnSizeLg, slug, ...args } = - opts; + const { + children, + columnSizeSm, + columnSizeMd, + columnSizeLg, + decorator, + ...args + } = opts; return ( - + {children} diff --git a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx index a2b4bbef91..9acab0896c 100644 --- a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx +++ b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx @@ -43,9 +43,9 @@ export interface ProductiveCardProps extends PropsWithChildren { */ actionIcons?: ActionIcon[]; /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. */ - aiLabel?: ReactNode | boolean; + decorator?: ReactNode | boolean; /** * Determines if the action icons are on the top or bottom of the card @@ -134,7 +134,7 @@ export interface ProductiveCardProps extends PropsWithChildren { /** * **Experimental:** For all cases a `Slug` component can be provided. * Clickable tiles only accept a boolean value of true and display a hollow slug. - * @deprecated please use the `aiLabel` prop + * @deprecated please use the `decorator` prop */ slug?: ReactNode | boolean; @@ -204,10 +204,6 @@ ProductiveCard.propTypes = { * Determines if the action icons are on the top or bottom of the card */ actionsPlacement: PropTypes.oneOf(['top', 'bottom']), - /** - * Optional prop that is intended for any scenario where something is being generated by AI to reinforce AI transparency, accountability, and explainability at the UI level. - */ - aiLabel: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** * Content that shows in the body of the card */ @@ -220,6 +216,10 @@ ProductiveCard.propTypes = { * Designates which zones of the card are clickable. Refer to design documentation for implementation guidelines */ clickZone: PropTypes.oneOf(['one', 'two', 'three']), + /** + * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + */ + decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** * Optional header description */ From cdf2e653e339c5023e05bf475ccde7c53c725362 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:07:55 +0530 Subject: [PATCH 2/8] feat(cards): update style and prop description --- .../src/components/Card/_card.scss | 7 ++ .../ibm-products/src/components/Card/Card.tsx | 4 +- .../src/components/Card/CardHeader.tsx | 4 +- .../ExpressiveCard/ExpressiveCard.stories.jsx | 74 +++++++++++++------ .../ExpressiveCard/ExpressiveCard.tsx | 4 +- .../ProductiveCard/ProductiveCard.stories.jsx | 70 ++++++++++++------ .../ProductiveCard/ProductiveCard.tsx | 4 +- 7 files changed, 112 insertions(+), 55 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index bf5a447a39..3a38973c12 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -144,6 +144,13 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; position: relative; } +.#{$block-class}__header__inner-wrapper--decorator > * { + // stylelint-disable-next-line + position: absolute !important; + top: $spacing-05; + right: $spacing-05; +} + .#{$block-class} .#{c4p-settings.$carbon-prefix}--slug { position: absolute; top: $spacing-05; diff --git a/packages/ibm-products/src/components/Card/Card.tsx b/packages/ibm-products/src/components/Card/Card.tsx index 4df3f5228e..2e62b355b2 100644 --- a/packages/ibm-products/src/components/Card/Card.tsx +++ b/packages/ibm-products/src/components/Card/Card.tsx @@ -88,7 +88,7 @@ interface CardProp extends PropsWithChildren { slug?: ReactNode | boolean; /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator?: ReactNode | boolean; @@ -402,7 +402,7 @@ Card.propTypes = { className: PropTypes.string, clickZone: PropTypes.oneOf(['one', 'two', 'three']), /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /**@ts-ignore */ diff --git a/packages/ibm-products/src/components/Card/CardHeader.tsx b/packages/ibm-products/src/components/Card/CardHeader.tsx index d9ae2736ae..65bb665edc 100644 --- a/packages/ibm-products/src/components/Card/CardHeader.tsx +++ b/packages/ibm-products/src/components/Card/CardHeader.tsx @@ -20,7 +20,7 @@ const defaults = { interface CardHeaderProps { actions?: ReactNode; /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator?: ReactNode | boolean; description?: ReactNode; @@ -197,7 +197,7 @@ export const CardHeader = ({ CardHeader.propTypes = { actions: PropTypes.oneOfType([PropTypes.array, PropTypes.node]), /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), description: PropTypes.oneOfType([ diff --git a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx index 95861b8347..64abe02de8 100644 --- a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx +++ b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.stories.jsx @@ -7,7 +7,7 @@ import React from 'react'; import styles from './_storybook-styles.scss?inline'; // import index in case more files are added later. -import { ArrowRight, Cloud, Add } from '@carbon/react/icons'; +import { ArrowRight, Cloud, Add, Information } from '@carbon/react/icons'; import { AspectRatio, Column, @@ -15,31 +15,52 @@ import { usePrefix, AILabel, AILabelContent, + Toggletip, + ToggletipButton, + ToggletipContent, } from '@carbon/react'; import { ExpressiveCard } from '.'; import DocsPage from './ExpressiveCard.docs-page'; import { action } from '@storybook/addon-actions'; -const sampleDecorator = ( - - -
-

AI Explained

-

84%

-

Confidence score

-

- This is not really Lorem Ipsum but the spell checker did not like the - previous text with it's non-words which is why this unwieldy - sentence, should one choose to call it that, here. -

-
-

Model type

-

Foundation model

-
-
-
-); +const sampleDecorator = (decorator) => { + switch (decorator) { + case 1: + return ( + + +
+

AI Explained

+

84%

+

Confidence score

+

+ This is not really Lorem Ipsum but the spell checker did not + like the previous text with it's non-words which is why + this unwieldy sentence, should one choose to call it that, here. +

+
+

Model type

+

Foundation model

+
+
+
+ ); + case 2: + return ( + + + + + +

Custom content here

+
+
+ ); + default: + return; + } +}; export default { title: 'IBM Products/Components/Cards/ExpressiveCard', @@ -93,11 +114,12 @@ export default { labels: { 0: 'No AI label', 1: 'with AI label', - 2: 'with hollow AI label (boolean)', + 2: 'With non AI Label component', + 3: 'with hollow AI label (boolean)', }, default: 0, }, - options: [0, 1, 2], + options: [0, 1, 2, 3], }, }, decorators: [ @@ -140,7 +162,9 @@ const Template = (opts) => { {children} @@ -164,7 +188,9 @@ const MediaTemplate = (opts) => { {mediaRatio}} - decorator={decorator && (decorator === 2 || sampleDecorator)} + decorator={ + decorator && (decorator === 3 || sampleDecorator(decorator)) + } {...args} > {children} diff --git a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx index 5d615d54b3..2faec964d8 100644 --- a/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx +++ b/packages/ibm-products/src/components/ExpressiveCard/ExpressiveCard.tsx @@ -37,7 +37,7 @@ export interface ExpressiveCardProps extends PropsWithChildren { */ className?: string; /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator?: ReactNode | boolean; /** @@ -161,7 +161,7 @@ ExpressiveCard.propTypes = { */ className: PropTypes.string, /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** diff --git a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx index 4d196ee49c..7a903a788f 100644 --- a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx +++ b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.stories.jsx @@ -7,13 +7,16 @@ import React from 'react'; import styles from './_storybook-styles.scss?inline'; // import index in case more files are added later. -import { TrashCan, Edit } from '@carbon/react/icons'; +import { TrashCan, Edit, Information } from '@carbon/react/icons'; import { Grid, Column, usePrefix, AILabel, AILabelContent, + Toggletip, + ToggletipButton, + ToggletipContent, } from '@carbon/react'; import { ProductiveCard } from '.'; import DocsPage from './ProductiveCard.docs-page'; @@ -21,25 +24,43 @@ import { action } from '@storybook/addon-actions'; const storyClass = 'productive-card-stories'; -const sampleDecorator = ( - - -
-

AI Explained

-

84%

-

Confidence score

-

- This is not really Lorem Ipsum but the spell checker did not like the - previous text with it's non-words which is why this unwieldy - sentence, should one choose to call it that, here. -

-
-

Model type

-

Foundation model

-
-
-
-); +const sampleDecorator = (decorator) => { + switch (decorator) { + case 1: + return ( + + +
+

AI Explained

+

84%

+

Confidence score

+

+ This is not really Lorem Ipsum but the spell checker did not + like the previous text with it's non-words which is why + this unwieldy sentence, should one choose to call it that, here. +

+
+

Model type

+

Foundation model

+
+
+
+ ); + case 2: + return ( + + + + + +

Custom content here

+
+
+ ); + default: + return; + } +}; export default { title: 'IBM Products/Components/Cards/ProductiveCard', @@ -87,11 +108,12 @@ export default { labels: { 0: 'No AI label', 1: 'with AI label', - 2: 'with hollow AI label (boolean)', + 2: 'With non AI Label component', + 3: 'with hollow AI label (boolean)', }, default: 0, }, - options: [0, 1], + options: [0, 1, 2, 3], }, }, decorators: [ @@ -150,7 +172,9 @@ const Template = (opts) => { {children} diff --git a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx index 9acab0896c..c1bd9dccaf 100644 --- a/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx +++ b/packages/ibm-products/src/components/ProductiveCard/ProductiveCard.tsx @@ -43,7 +43,7 @@ export interface ProductiveCardProps extends PropsWithChildren { */ actionIcons?: ActionIcon[]; /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator?: ReactNode | boolean; @@ -217,7 +217,7 @@ ProductiveCard.propTypes = { */ clickZone: PropTypes.oneOf(['one', 'two', 'three']), /** - * Optional prop that can be used to pass any component, such as Tooltip or Toggletip. + * Optional prop that allows you to pass any component. */ decorator: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), /** From 0d38079d8fb8f4ca587aa47c31f65eb683b0c639 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:30:09 +0530 Subject: [PATCH 3/8] feat(cards): style update --- .../ibm-products-styles/src/components/Card/_card.scss | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index 3a38973c12..fa642e093f 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -144,19 +144,13 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; position: relative; } -.#{$block-class}__header__inner-wrapper--decorator > * { +.#{$block-class}__header__inner-wrapper--decorator { // stylelint-disable-next-line position: absolute !important; top: $spacing-05; right: $spacing-05; } -.#{$block-class} .#{c4p-settings.$carbon-prefix}--slug { - position: absolute; - top: $spacing-05; - right: $spacing-05; -} - .#{$block-class}__header-container--has-slug, .#{$block-class}__header-container--has-decorator { width: 100%; From d702a8a5e03b3915266e08f83e72fc65ae87c142 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Wed, 27 Nov 2024 14:42:09 +0530 Subject: [PATCH 4/8] feat(cards): style fix --- .../src/components/Card/_card.scss | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index fa642e093f..4effb557c7 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -144,11 +144,22 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; position: relative; } +.#{$block-class} .#{c4p-settings.$carbon-prefix}--slug { + position: absolute; + top: $spacing-05; + right: $spacing-05; +} + .#{$block-class}__header__inner-wrapper--decorator { - // stylelint-disable-next-line - position: absolute !important; + position: absolute; top: $spacing-05; right: $spacing-05; + + .#{c4p-settings.$carbon-prefix}--slug { + position: relative; + top: unset; + right: unset; + } } .#{$block-class}__header-container--has-slug, From b3d8dc8fd0dc284df5e1d096794c9a9ec362af5c Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:46:17 +0530 Subject: [PATCH 5/8] fix(cards): class names update --- .../src/components/Card/_card.scss | 14 +++++++------- packages/ibm-products/src/components/Card/Card.tsx | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index 4effb557c7..973a51724e 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -144,7 +144,8 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; position: relative; } -.#{$block-class} .#{c4p-settings.$carbon-prefix}--slug { +.#{$block-class} .#{c4p-settings.$carbon-prefix}--slug, +.#{$block-class} .#{c4p-settings.$carbon-prefix}--ai-label { position: absolute; top: $spacing-05; right: $spacing-05; @@ -155,7 +156,8 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; top: $spacing-05; right: $spacing-05; - .#{c4p-settings.$carbon-prefix}--slug { + .#{c4p-settings.$carbon-prefix}--slug, + .#{c4p-settings.$carbon-prefix}--ai-label { position: relative; top: unset; right: unset; @@ -188,7 +190,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}--has-slug, -.#{$block-class}--has-decorator { +.#{$block-class}--has-ai-label { @include utilities.ai-popover-gradient('default', 0, 'layer'); border: 1px solid transparent; @@ -196,11 +198,8 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; 0 4px 10px 2px $ai-drop-shadow; } -.#{$block-class}--has-decorator-non-ai-label { - background-color: $layer-01; -} - .#{$block-class}__clickable.#{$block-class}--has-slug::before, +.#{$block-class}__clickable.#{$block-class}--has-ai-label::before, .#{$block-class}__clickable.#{$block-class}--has-decorator::before { @include utilities.ai-popover-gradient('hover', 0, 'layer'); @@ -217,6 +216,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}__clickable.#{$block-class}--has-slug:hover::before, +.#{$block-class}__clickable.#{$block-class}--has-ai-label:hover::before, .#{$block-class}__clickable.#{$block-class}--has-decorator:hover::before { opacity: 1; } diff --git a/packages/ibm-products/src/components/Card/Card.tsx b/packages/ibm-products/src/components/Card/Card.tsx index 2e62b355b2..f26e51bba2 100644 --- a/packages/ibm-products/src/components/Card/Card.tsx +++ b/packages/ibm-products/src/components/Card/Card.tsx @@ -262,9 +262,9 @@ export const Card = forwardRef( [`${blockClass}__clickable`]: clickable, [`${blockClass}__media-left`]: mediaPosition === 'left', [`${blockClass}--has-slug`]: !!slug, - [`${blockClass}--has-decorator-non-ai-label`]: - !!decorator && decorator['type']?.displayName !== 'AILabel', [`${blockClass}--has-decorator`]: + !!decorator && decorator['type']?.displayName !== 'AILabel', + [`${blockClass}--has-ai-label`]: !!decorator && decorator['type']?.displayName === 'AILabel', }, className From c2f23fb0110f93119b6641406171092000170043 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Tue, 3 Dec 2024 15:52:45 +0530 Subject: [PATCH 6/8] chore(cards): update test cases --- .../src/components/Card/CardHeader.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/ibm-products/src/components/Card/CardHeader.test.js b/packages/ibm-products/src/components/Card/CardHeader.test.js index e0e57ff907..4fd17e9cba 100644 --- a/packages/ibm-products/src/components/Card/CardHeader.test.js +++ b/packages/ibm-products/src/components/Card/CardHeader.test.js @@ -8,6 +8,7 @@ import { render } from '@testing-library/react'; import React from 'react'; import { CardHeader } from '.'; +import { AILabel } from '@carbon/react'; import { pkg } from '../../settings'; const { name } = CardHeader; @@ -50,4 +51,13 @@ describe(name, () => { const { getByText } = render(); expect(getByText('action 1')).toBeVisible(); }); + + it('should respect decorator prop', () => { + const { container } = render(} />); + expect( + container.querySelector( + `.${blockClass}__header__inner-wrapper--decorator` + ) + ).not.toBeNull(); + }); }); From 7a962dae3a8d78a3d537eb7d00503c1f90349782 Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:07:30 +0530 Subject: [PATCH 7/8] fix(cards): remove popover style for decorator class --- packages/ibm-products-styles/src/components/Card/_card.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index 973a51724e..44c9820d1f 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -199,8 +199,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}__clickable.#{$block-class}--has-slug::before, -.#{$block-class}__clickable.#{$block-class}--has-ai-label::before, -.#{$block-class}__clickable.#{$block-class}--has-decorator::before { +.#{$block-class}__clickable.#{$block-class}--has-ai-label::before { @include utilities.ai-popover-gradient('hover', 0, 'layer'); position: absolute; From f86b8c7f69ea54d876d1c08ab308136d540652cf Mon Sep 17 00:00:00 2001 From: Sangeetha Babu <58620134+sangeethababu9223@users.noreply.github.com> Date: Wed, 4 Dec 2024 10:14:10 +0530 Subject: [PATCH 8/8] fix(cards): remove popover style for decorator class --- packages/ibm-products-styles/src/components/Card/_card.scss | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/ibm-products-styles/src/components/Card/_card.scss b/packages/ibm-products-styles/src/components/Card/_card.scss index 44c9820d1f..7be0074587 100644 --- a/packages/ibm-products-styles/src/components/Card/_card.scss +++ b/packages/ibm-products-styles/src/components/Card/_card.scss @@ -215,8 +215,7 @@ $block-class: #{c4p-settings.$pkg-prefix}--card; } .#{$block-class}__clickable.#{$block-class}--has-slug:hover::before, -.#{$block-class}__clickable.#{$block-class}--has-ai-label:hover::before, -.#{$block-class}__clickable.#{$block-class}--has-decorator:hover::before { +.#{$block-class}__clickable.#{$block-class}--has-ai-label:hover::before { opacity: 1; }