From 0a1585ed111ef745d3dabbedfa181617a5a5ec4d Mon Sep 17 00:00:00 2001 From: Lee Chase Date: Mon, 19 Feb 2024 15:41:04 +0000 Subject: [PATCH] feat: Tearsheet ai (#4215) * chore: wip * feat: tearsheet AI enhancements * feat: add gradient glow to container --- .../__snapshots__/styles.test.js.snap | 19 ++++++- .../src/components/Tearsheet/_tearsheet.scss | 36 ++++++++++++- .../components/Tearsheet/Tearsheet.stories.js | 42 ++++++++++++++- .../Tearsheet/TearsheetNarrow.stories.js | 49 +++++++++++++++-- .../components/Tearsheet/TearsheetShell.js | 11 +++- .../Tearsheet/TearsheetShell.stories.js | 53 ++++++++++++++++++- .../templates-react-16/package.json | 2 +- .../templates-react-17/package.json | 2 +- 8 files changed, 200 insertions(+), 14 deletions(-) diff --git a/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap b/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap index e01a9c6e3e..024ce2108b 100644 --- a/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap +++ b/packages/ibm-products-styles/src/__tests__/__snapshots__/styles.test.js.snap @@ -2725,6 +2725,12 @@ p.c4p--about-modal__copyright-text:first-child { max-height: calc(100% - 3rem); transform: translate3d(0, min(95vh, 500px), 0); } +.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__container { + border: 1px solid transparent; + /* override carbon ai removing background gradient */ + background: linear-gradient(to top, var(--cds-layer), var(--cds-layer)) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, #78a9ff), var(--cds-ai-border-end, #d0e2ff)) border-box, linear-gradient(to top, var(--cds-layer), var(--cds-layer)) border-box; + box-shadow: 0 4px 10px 2px var(--cds-ai-drop-shadow, rgba(15, 98, 254, 0.32)); +} .c4p--tearsheet.c4p--tearsheet.c4p--tearsheet .c4p--tearsheet__container { transition: transform 240ms cubic-bezier(0, 0, 0.3, 1), max-height 240ms cubic-bezier(0, 0, 0.3, 1); } @@ -2822,8 +2828,11 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-nav { padding: 1.5rem 2rem 0; } -.c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon { - padding-right: 4rem; +.c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon, .c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header { + padding-right: 5rem; +} +.c4p--tearsheet.c4p--tearsheet--wide.c4p--tearsheet--has-slug .c4p--tearsheet__header.c4p--tearsheet__header--with-close-icon { + margin-right: 3rem; } .c4p--tearsheet.c4p--tearsheet--narrow .c4p--tearsheet__header-description { max-width: 80%; @@ -2876,6 +2885,9 @@ p.c4p--about-modal__copyright-text:first-child { overflow: auto; flex-grow: 1; } +.c4p--tearsheet.c4p--tearsheet--has-slug .c4p--tearsheet__main { + background: linear-gradient(to top, var(--cds-ai-aura-start, rgba(69, 137, 255, 0.1)) 0%, var(--cds-ai-aura-end, rgba(255, 255, 255, 0)) 50%) padding-box, linear-gradient(to top, var(--cds-background, #ffffff), var(--cds-background, #ffffff)) padding-box, linear-gradient(to bottom, var(--cds-ai-border-start, #78a9ff), var(--cds-ai-border-end, #d0e2ff)) border-box, linear-gradient(to top, var(--cds-background, #ffffff), var(--cds-background, #ffffff)) border-box; +} .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__content .cds--pagination, .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__content .cds--pagination__control-buttons, .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__content .cds--text-input, @@ -2914,6 +2926,9 @@ p.c4p--about-modal__copyright-text:first-child { .c4p--tearsheet.c4p--tearsheet--wide .c4p--tearsheet__buttons { background: var(--cds-background, #ffffff); } +.c4p--tearsheet.c4p--tearsheet--has-slug:not(.c4p--tearsheet--has-close) .cds--slug { + inset-inline-end: 0; +} .c4p--create-tearsheet-narrow .cds--modal-header__heading, .c4p--create-tearsheet-narrow .cds--modal-header__label, diff --git a/packages/ibm-products-styles/src/components/Tearsheet/_tearsheet.scss b/packages/ibm-products-styles/src/components/Tearsheet/_tearsheet.scss index eae14d7038..60f19faeaf 100644 --- a/packages/ibm-products-styles/src/components/Tearsheet/_tearsheet.scss +++ b/packages/ibm-products-styles/src/components/Tearsheet/_tearsheet.scss @@ -93,6 +93,22 @@ $motion-duration: $duration-moderate-02; transform: translate3d(0, calc(min(95vh, 500px)), 0); } + &.#{$block-class}.#{$block-class}.#{$block-class}.#{$block-class}--has-slug + .#{$block-class}__container { + border: 1px solid transparent; + /* override carbon ai removing background gradient */ + background: linear-gradient(to top, var(--cds-layer), var(--cds-layer)) + padding-box, + linear-gradient( + to bottom, + var(--cds-ai-border-start, #78a9ff), + var(--cds-ai-border-end, #d0e2ff) + ) + border-box, + linear-gradient(to top, var(--cds-layer), var(--cds-layer)) border-box; + box-shadow: 0 4px 10px 2px $ai-drop-shadow; + } + // extra specificity to ensure this transition overrides the carbon default &.#{$block-class}.#{$block-class} .#{$block-class}__container { transition: transform $motion-duration motion(entrance, expressive), @@ -223,8 +239,14 @@ $motion-duration: $duration-moderate-02; } &.#{$block-class}--wide + .#{$block-class}__header.#{$block-class}__header--with-close-icon, + &.#{$block-class}--has-slug .#{$block-class}__header.#{$block-class}__header { + padding-right: $spacing-11; + } + + &.#{$block-class}--wide.#{$block-class}--has-slug .#{$block-class}__header.#{$block-class}__header--with-close-icon { - padding-right: $spacing-10; + margin-right: $spacing-09; } &.#{$block-class}--narrow .#{$block-class}__header-description { @@ -292,6 +314,10 @@ $motion-duration: $duration-moderate-02; flex-grow: 1; } + &.#{$block-class}--has-slug .#{$block-class}__main { + @include utilities.callout-gradient('default', 0); + } + &.#{$block-class}--wide .#{$block-class}__content { // Revert background color overridden by Carbon's modal - https://github.com/carbon-design-system/carbon/blob/main/packages/styles/scss/components/modal/_modal.scss#L54 .#{$carbon-prefix}--pagination, @@ -320,7 +346,8 @@ $motion-duration: $duration-moderate-02; .#{$carbon-prefix}--dropdown--light .#{$carbon-prefix}--dropdown-list, /* stylelint-disable-next-line prettier/prettier */ .#{$carbon-prefix}--number--light input[type='number'], - .#{$carbon-prefix}--date-picker--light .#{$carbon-prefix}--date-picker__input { + .#{$carbon-prefix}--date-picker--light + .#{$carbon-prefix}--date-picker__input { background-color: $field-02; } } @@ -340,4 +367,9 @@ $motion-duration: $duration-moderate-02; &.#{$block-class}--wide .#{$block-class}__buttons { background: $background; } + + &.#{$block-class}--has-slug:not(.#{$block-class}--has-close) + .#{$carbon-prefix}--slug { + inset-inline-end: 0; + } } diff --git a/packages/ibm-products/src/components/Tearsheet/Tearsheet.stories.js b/packages/ibm-products/src/components/Tearsheet/Tearsheet.stories.js index 4229b8abb0..840abf4ae7 100644 --- a/packages/ibm-products/src/components/Tearsheet/Tearsheet.stories.js +++ b/packages/ibm-products/src/components/Tearsheet/Tearsheet.stories.js @@ -21,6 +21,8 @@ import { Tabs, TabList, TextInput, + unstable__Slug as Slug, + unstable__SlugContent as SlugContent, } from '@carbon/react'; import { Tearsheet, deprecatedProps } from './Tearsheet'; @@ -102,6 +104,17 @@ export default { navigation: { control: { disable: true } }, open: { control: { disable: true } }, portalTarget: { control: { disable: true } }, + slug: { + control: { + type: 'select', + labels: { + 0: 'No AI slug', + 1: 'with AI Slug', + }, + default: 0, + }, + options: [0, 1], + }, }, }; @@ -160,9 +173,29 @@ const tabs = ( const title = 'Title of the tearsheet'; +const sampleSlug = ( + + +
+

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

+
+
+
+); + // Template. // eslint-disable-next-line react/prop-types -const Template = ({ actions, ...args }) => { +const Template = ({ actions, slug, ...args }) => { const [open, setOpen] = useState(false); const wiredActions = @@ -193,6 +226,7 @@ const Template = ({ actions, ...args }) => { actions={wiredActions} open={open} onClose={() => setOpen(false)} + slug={slug && sampleSlug} > {mainContent} @@ -202,7 +236,7 @@ const Template = ({ actions, ...args }) => { }; // eslint-disable-next-line react/prop-types -const StackedTemplate = ({ actions, ...args }) => { +const StackedTemplate = ({ actions, slug, ...args }) => { const [open1, setOpen1] = useState(false); const [open2, setOpen2] = useState(false); const [open3, setOpen3] = useState(false); @@ -294,6 +328,7 @@ const StackedTemplate = ({ actions, ...args }) => { open={open1} onClose={() => setOpen1(false)} selectorPrimaryFocus="#stacked-input-1" + slug={slug && sampleSlug} >
Main content 1 @@ -323,6 +358,7 @@ const StackedTemplate = ({ actions, ...args }) => { open={open2} onClose={() => setOpen2(false)} selectorPrimaryFocus="#stacked-input-2" + slug={slug && sampleSlug} >
Main content 2 @@ -339,6 +375,7 @@ const StackedTemplate = ({ actions, ...args }) => { open={open3} onClose={() => setOpen3(false)} selectorPrimaryFocus="#stacked-input-3" + slug={slug && sampleSlug} >
Main content 3 @@ -408,6 +445,7 @@ export const fullyLoaded = prepareStory(Template, { onClose: action('onClose called'), title, actions: 0, + slug: 1, }, }); diff --git a/packages/ibm-products/src/components/Tearsheet/TearsheetNarrow.stories.js b/packages/ibm-products/src/components/Tearsheet/TearsheetNarrow.stories.js index 576a0c2116..e8a8c4e485 100644 --- a/packages/ibm-products/src/components/Tearsheet/TearsheetNarrow.stories.js +++ b/packages/ibm-products/src/components/Tearsheet/TearsheetNarrow.stories.js @@ -11,7 +11,14 @@ import { action } from '@storybook/addon-actions'; import { pkg } from '../../settings'; -import { Button, Form, FormGroup, TextInput } from '@carbon/react'; +import { + Button, + Form, + FormGroup, + TextInput, + unstable__Slug as Slug, + unstable__SlugContent as SlugContent, +} from '@carbon/react'; import { TearsheetNarrow, deprecatedProps } from './TearsheetNarrow'; @@ -57,6 +64,17 @@ export default { onClose: { control: { disable: true } }, open: { control: { disable: true } }, portalTarget: { control: { disable: true } }, + slug: { + control: { + type: 'select', + labels: { + 0: 'No AI slug', + 1: 'with AI Slug', + }, + default: 0, + }, + options: [0, 1], + }, }, }; @@ -83,9 +101,29 @@ const mainContent = ( const title = 'Title of the tearsheet'; +const sampleSlug = ( + + +
+

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

+
+
+
+); + // Template. // eslint-disable-next-line react/prop-types -const Template = ({ actions, ...args }) => { +const Template = ({ actions, slug, ...args }) => { const [open, setOpen] = useState(false); const ref = useRef(); @@ -113,6 +151,7 @@ const Template = ({ actions, ...args }) => { actions={wiredActions} open={open} onClose={() => setOpen(false)} + slug={slug && sampleSlug} > {mainContent} @@ -122,7 +161,7 @@ const Template = ({ actions, ...args }) => { }; // eslint-disable-next-line react/prop-types -const StackedTemplate = ({ actions, ...args }) => { +const StackedTemplate = ({ actions, slug, ...args }) => { const [open1, setOpen1] = useState(false); const [open2, setOpen2] = useState(false); const [open3, setOpen3] = useState(false); @@ -194,6 +233,7 @@ const StackedTemplate = ({ actions, ...args }) => { title="Tearsheet #1" open={open1} onClose={() => setOpen1(false)} + slug={slug && sampleSlug} >
Main content 1 @@ -205,6 +245,7 @@ const StackedTemplate = ({ actions, ...args }) => { title="Tearsheet #2" open={open2} onClose={() => setOpen2(false)} + slug={slug && sampleSlug} selectorPrimaryFocus="#main-content" >
@@ -217,6 +258,7 @@ const StackedTemplate = ({ actions, ...args }) => { title="Tearsheet #3" open={open3} onClose={() => setOpen3(false)} + slug={slug && sampleSlug} selectorPrimaryFocus="#main-content" >
@@ -250,6 +292,7 @@ export const fullyLoaded = prepareStory(Template, { onClose: action('onClose called'), title, actions: 0, + slug: 1, }, }); diff --git a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.js b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.js index 835bb5ee1d..bfe3c44037 100644 --- a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.js +++ b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.js @@ -86,9 +86,10 @@ export const TearsheetShell = React.forwardRef( navigation, onClose, open, + portalTarget: portalTargetIn, selectorPrimaryFocus, size, - portalTarget: portalTargetIn, + slug, title, verticalPosition, // Collect any other property values passed in. @@ -231,7 +232,10 @@ export const TearsheetShell = React.forwardRef( depth > 1 || (depth === 1 && prevDepth.current > 1), [`${bc}--wide`]: wide, [`${bc}--narrow`]: !wide, + [`${bc}--has-slug`]: slug, + [`${bc}--has-close`]: effectiveHasCloseIcon, })} + slug={slug} style={{ [`--${bc}--stacking-scale-factor-single`]: (width - 32) / width, [`--${bc}--stacking-scale-factor-double`]: (width - 64) / width, @@ -506,6 +510,11 @@ TearsheetShell.propTypes = { */ size: PropTypes.oneOf(['narrow', 'wide']).isRequired, + /** + * **Experimental:** Provide a `Slug` component to be rendered inside the `SidePanel` component + */ + slug: PropTypes.node, + /** * The main title of the tearsheet, displayed in the header area. */ diff --git a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.stories.js b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.stories.js index 9c1b5a70f7..8b4f111c21 100644 --- a/packages/ibm-products/src/components/Tearsheet/TearsheetShell.stories.js +++ b/packages/ibm-products/src/components/Tearsheet/TearsheetShell.stories.js @@ -14,7 +14,11 @@ import { } from '../../global/js/utils/story-helper'; import { TearsheetShell, deprecatedProps } from './TearsheetShell'; import { getDeprecatedArgTypes } from '../../global/js/utils/props-helper'; -import { Button } from '@carbon/react'; +import { + Button, + unstable__Slug as Slug, + unstable__SlugContent as SlugContent, +} from '@carbon/react'; // import mdx from './TearsheetShell.mdx'; @@ -28,7 +32,23 @@ export default { }, argTypes: { ...getDeprecatedArgTypes(deprecatedProps), + influencer: { + control: { + type: 'boolean', + }, + }, portalTarget: { control: { disable: true } }, + slug: { + control: { + type: 'select', + labels: { + 0: 'No AI slug', + 1: 'with AI Slug', + }, + default: 0, + }, + options: [0, 1], + }, }, }; @@ -50,8 +70,28 @@ const dummyContent = (
); +const sampleSlug = ( + + +
+

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

+
+
+
+); + // Template. -const Template = ({ open: _open, ...args }, context) => { +const Template = ({ influencer, open: _open, slug, ...args }, context) => { const ref = useRef(); const [open, setOpen] = useState(context.viewMode !== 'docs' && _open); const [beenOpen, setBeenOpen] = useState(false); @@ -65,8 +105,17 @@ const Template = ({ open: _open, ...args }, context) => { + Influencer +
+ ) + } open={open} onClose={() => setOpen(false)} + slug={slug && sampleSlug} + title={'Tearsheet title'} > {dummyContent} diff --git a/scripts/example-gallery-builder/update-example/templates-react-16/package.json b/scripts/example-gallery-builder/update-example/templates-react-16/package.json index 667668e3e3..639bbfcc56 100644 --- a/scripts/example-gallery-builder/update-example/templates-react-16/package.json +++ b/scripts/example-gallery-builder/update-example/templates-react-16/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@carbon/ibm-products": "^2.21.0", - "@carbon/react": "^1.48.1", + "@carbon/react": "^1.49.0", "lodash": "^4.17.21", "react": "^16.14.0", "react-dom": "^16.14.0", diff --git a/scripts/example-gallery-builder/update-example/templates-react-17/package.json b/scripts/example-gallery-builder/update-example/templates-react-17/package.json index 8acb93467c..060a943fd7 100644 --- a/scripts/example-gallery-builder/update-example/templates-react-17/package.json +++ b/scripts/example-gallery-builder/update-example/templates-react-17/package.json @@ -18,7 +18,7 @@ }, "dependencies": { "@carbon/ibm-products": "^2.21.0", - "@carbon/react": "^1.48.1", + "@carbon/react": "^1.49.0", "lodash": "^4.17.21", "react": "^17.0.2", "react-dom": "^17.0.2",