From 4ce0e2b0086e5217ad08680abac18d81968e12b1 Mon Sep 17 00:00:00 2001 From: Douglas Henri Date: Wed, 4 Dec 2024 16:03:39 -0300 Subject: [PATCH] AI Assistant: Add disclaimer to image generation input (#40397) * refactor from first proposal * change guideline links to jetpack redirect * add disclaimer to image modals * add AiModalFooter component * use AiModalFooter component on images modal * use AiModalFooter component on logo generator modal * changelog * remove arrow icon and use character instead --- ...etpack-ai-image-generator-input-disclaimer | 4 ++ .../src/components/ai-modal-footer/index.tsx | 71 +++++++++++++++++++ .../ai-modal-footer/stories/index.stories.tsx | 32 +++++++++ .../src/components/ai-modal-footer/style.scss | 15 ++++ .../ai-client/src/components/index.ts | 1 + .../src/components/message/index.tsx | 27 ++++--- .../components/generator-modal.scss | 25 +------ .../components/generator-modal.tsx | 14 +--- .../components/logo-presenter.scss | 14 ++++ .../src/logo-generator/components/prompt.scss | 16 ++++- .../src/logo-generator/components/prompt.tsx | 4 +- ...etpack-ai-image-generator-input-disclaimer | 4 ++ .../components/message/block-message.tsx | 2 +- .../ai-assistant-plugin-sidebar/index.tsx | 2 +- .../ai-image/components/ai-image-modal.scss | 18 +---- .../ai-image/components/ai-image-modal.tsx | 16 ++--- 16 files changed, 188 insertions(+), 77 deletions(-) create mode 100644 projects/js-packages/ai-client/changelog/update-jetpack-ai-image-generator-input-disclaimer create mode 100644 projects/js-packages/ai-client/src/components/ai-modal-footer/index.tsx create mode 100644 projects/js-packages/ai-client/src/components/ai-modal-footer/stories/index.stories.tsx create mode 100644 projects/js-packages/ai-client/src/components/ai-modal-footer/style.scss create mode 100644 projects/plugins/jetpack/changelog/update-jetpack-ai-image-generator-input-disclaimer diff --git a/projects/js-packages/ai-client/changelog/update-jetpack-ai-image-generator-input-disclaimer b/projects/js-packages/ai-client/changelog/update-jetpack-ai-image-generator-input-disclaimer new file mode 100644 index 0000000000000..f3af5b7ea6252 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/update-jetpack-ai-image-generator-input-disclaimer @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +AI Assistant: Add disclaimer to image generation modals diff --git a/projects/js-packages/ai-client/src/components/ai-modal-footer/index.tsx b/projects/js-packages/ai-client/src/components/ai-modal-footer/index.tsx new file mode 100644 index 0000000000000..01a039627c3de --- /dev/null +++ b/projects/js-packages/ai-client/src/components/ai-modal-footer/index.tsx @@ -0,0 +1,71 @@ +/** + * External dependencies + */ +import { Button } from '@wordpress/components'; +import { useCallback } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { Icon, info } from '@wordpress/icons'; +/** + * Internal dependencies + */ +import './style.scss'; +/** + * Types + */ +import type React from 'react'; + +type AiModalFooterProps = { + onGuidelinesClick?: () => void; + onFeedbackClick?: () => void; +}; + +/** + * AiModalFooter component. + * + * @param {AiModalFooterProps} props - component props. + * @return {React.ReactElement} - rendered component. + */ +export default function AiModalFooter( { + onGuidelinesClick, + onFeedbackClick, +}: AiModalFooterProps ): React.ReactElement { + const handleGuidelinesClick = useCallback( () => { + onGuidelinesClick?.(); + }, [ onGuidelinesClick ] ); + + const handleFeedbackClick = useCallback( () => { + onFeedbackClick?.(); + }, [ onFeedbackClick ] ); + + return ( + <> +
+ + + { __( + 'Generated images could be inaccurate, biased or include text.', + 'jetpack-ai-client' + ) } + + +
+ + + ); +} diff --git a/projects/js-packages/ai-client/src/components/ai-modal-footer/stories/index.stories.tsx b/projects/js-packages/ai-client/src/components/ai-modal-footer/stories/index.stories.tsx new file mode 100644 index 0000000000000..59b817a10310f --- /dev/null +++ b/projects/js-packages/ai-client/src/components/ai-modal-footer/stories/index.stories.tsx @@ -0,0 +1,32 @@ +/* + * External Dependencies + */ +import { action } from '@storybook/addon-actions'; +import React from 'react'; +/* + * Internal Dependencies + */ +import AiModalFooter from '../index.js'; + +export default { + title: 'JS Packages/AI Client/AiModalFooter', + component: AiModalFooter, + decorators: [ + Story => ( +
+ +
+ ), + ], +}; + +const DefaultTemplate = () => { + return ( + + ); +}; + +export const Default = DefaultTemplate.bind( {} ); diff --git a/projects/js-packages/ai-client/src/components/ai-modal-footer/style.scss b/projects/js-packages/ai-client/src/components/ai-modal-footer/style.scss new file mode 100644 index 0000000000000..f6f29042ad42f --- /dev/null +++ b/projects/js-packages/ai-client/src/components/ai-modal-footer/style.scss @@ -0,0 +1,15 @@ +.ai-image-modal__footer-disclaimer { + display: flex; + align-items: center; + gap: 4px; + color: var( --jp-gray-50 ); + fill: var( --jp-gray-50 ); + + .components-button.is-link { + color: var( --jp-gray-50 ); + } +} + +.ai-image-modal__feedback-button.components-button.is-link { + text-decoration: none; +} diff --git a/projects/js-packages/ai-client/src/components/index.ts b/projects/js-packages/ai-client/src/components/index.ts index 48b54b61413c0..20d5714db6baf 100644 --- a/projects/js-packages/ai-client/src/components/index.ts +++ b/projects/js-packages/ai-client/src/components/index.ts @@ -1,6 +1,7 @@ export { AIControl, BlockAIControl, ExtensionAIControl } from './ai-control/index.js'; export { default as AiStatusIndicator } from './ai-status-indicator/index.js'; export { default as AudioDurationDisplay } from './audio-duration-display/index.js'; +export { default as AiModalFooter } from './ai-modal-footer/index.js'; export { GuidelineMessage, UpgradeMessage, diff --git a/projects/js-packages/ai-client/src/components/message/index.tsx b/projects/js-packages/ai-client/src/components/message/index.tsx index 64fd0e0ad034c..0c5e8482851e5 100644 --- a/projects/js-packages/ai-client/src/components/message/index.tsx +++ b/projects/js-packages/ai-client/src/components/message/index.tsx @@ -66,7 +66,7 @@ const messageIconsMap = { * React component to render a block message. * * @param {MessageProps} props - Component props. - * @return {React.ReactElement } Banner component. + * @return {React.ReactElement} Banner component. */ export default function Message( { severity = MESSAGE_SEVERITY_INFO, @@ -95,10 +95,23 @@ export default function Message( { ); } +/** + * React component to render a learn more link. + * + * @return {React.ReactElement} - Learn more link component. + */ +function LearnMoreLink(): React.ReactElement { + return ( + + { __( 'Learn more', 'jetpack-ai-client' ) } + + ); +} + /** * React component to render a guideline message. * - * @return {React.ReactElement } - Message component. + * @return {React.ReactElement} - Message component. */ export function GuidelineMessage(): React.ReactElement { return ( @@ -106,9 +119,7 @@ export function GuidelineMessage(): React.ReactElement { { __( 'AI-generated content could be inaccurate or biased.', 'jetpack-ai-client' ) } - - { __( 'Learn more', 'jetpack-ai-client' ) } - + ); } @@ -116,7 +127,7 @@ export function GuidelineMessage(): React.ReactElement { /** * React component to render a fair usage limit message. * - * @return {React.ReactElement } - Message component. + * @return {React.ReactElement} - Message component. */ export function FairUsageLimitMessage(): React.ReactElement { const message = __( @@ -136,7 +147,7 @@ export function FairUsageLimitMessage(): React.ReactElement { * React component to render an upgrade message for free tier users * * @param {number} requestsRemaining - Number of requests remaining. - * @return {React.ReactElement } - Message component. + * @return {React.ReactElement} - Message component. */ export function UpgradeMessage( { requestsRemaining, @@ -175,7 +186,7 @@ export function UpgradeMessage( { * React component to render an error message * * @param {number} requestsRemaining - Number of requests remaining. - * @return {React.ReactElement } - Message component. + * @return {React.ReactElement} - Message component. */ export function ErrorMessage( { error, diff --git a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.scss b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.scss index 19569f461a3f5..a09b76dcc673c 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.scss +++ b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.scss @@ -18,19 +18,6 @@ height: 100%; } } - - .components-button { - &:focus:not(:disabled):not(.is-primary) { - box-shadow: 0 0 0 2px var(--color-link, #3858e9); - } - - &.is-link { - text-decoration: none; - &:not(:disabled) { - color: var(--color-link, #3858e9); - } - } - } } .jetpack-ai-logo-generator-modal__body { @@ -52,17 +39,7 @@ .jetpack-ai-logo-generator__footer { display: flex; - - .jetpack-ai-logo-generator__feedback-button { - display: flex; - gap: 4px; - align-items: center; - margin-top: 8px; - - .icon { - color: var(--studio-gray-20); - } - } + justify-content: space-between; } .jetpack-ai-logo-generator-modal__notice-message-wrapper { diff --git a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx index dfba25feb65fa..d9c140e60d5c2 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx @@ -5,13 +5,13 @@ import { useAnalytics } from '@automattic/jetpack-shared-extension-utils'; import { Modal, Button } from '@wordpress/components'; import { useDispatch, select } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { external, Icon } from '@wordpress/icons'; import clsx from 'clsx'; import debugFactory from 'debug'; import { useState, useEffect, useCallback, useRef } from 'react'; /** * Internal dependencies */ +import AiModalFooter from '../../components/ai-modal-footer/index.js'; import { DEFAULT_LOGO_COST, EVENT_MODAL_OPEN, @@ -24,7 +24,6 @@ import useLogoGenerator from '../hooks/use-logo-generator.js'; import useRequestErrors from '../hooks/use-request-errors.js'; import { isLogoHistoryEmpty, clearDeletedMedia } from '../lib/logo-storage.js'; import { STORE_NAME } from '../store/index.js'; -// import { FairUsageNotice } from './fair-usage-notice.js'; import { FeatureFetchFailureScreen } from './feature-fetch-failure-screen.js'; import { FirstLoadScreen } from './first-load-screen.js'; import { HistoryCarousel } from './history-carousel.js'; @@ -303,16 +302,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { <>
- +
) } diff --git a/projects/js-packages/ai-client/src/logo-generator/components/logo-presenter.scss b/projects/js-packages/ai-client/src/logo-generator/components/logo-presenter.scss index 7086f47cf6638..88f339267eb10 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/logo-presenter.scss +++ b/projects/js-packages/ai-client/src/logo-generator/components/logo-presenter.scss @@ -4,6 +4,20 @@ display: flex; flex-direction: column; gap: 8px; + + .components-button { + &:focus:not(:disabled):not(.is-primary) { + box-shadow: 0 0 0 2px var(--color-link, #3858e9); + } + + &.is-link { + text-decoration: none; + + &:not(:disabled) { + color: var(--color-link, #3858e9); + } + } + } } .jetpack-ai-logo-generator-modal-presenter { diff --git a/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss b/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss index f91e2d63f98fa..2932f64dbc6d8 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss +++ b/projects/js-packages/ai-client/src/logo-generator/components/prompt.scss @@ -5,6 +5,20 @@ flex-direction: column; gap: 8px; font-size: var(--font-body-small); + + .components-button { + &:focus:not(:disabled):not(.is-primary) { + box-shadow: 0 0 0 2px var(--color-link, #3858e9); + } + + &.is-link { + text-decoration: none; + + &:not(:disabled) { + color: var(--color-link, #3858e9); + } + } + } } .jetpack-ai-logo-generator__prompt-header { @@ -30,7 +44,7 @@ } } -.jetpack-ai-logo-generator__prompt-query { +.jetpack-ai-image-generator__prompt-query { display: flex; padding: 8px 8px 8px var(--grid-unit-15, 16px); justify-content: space-between; diff --git a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx index 709013733e8e5..6a447b6abfd1c 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx @@ -104,7 +104,7 @@ export const AiModalPromptInput = ( { }; return ( -
+
- +
) }