diff --git a/CHANGELOG.md b/CHANGELOG.md index 839c179df1..f2de07b60a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -99,6 +99,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Specifically [`OffscreenCanvas.getContext('2d')`](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/getContext) - Added `timestampFormat` option to the default style options and created `AbsoluteTime` component, by [@tdurnford](https://github.com/tdurnford), in PR [#2295](https://github.com/microsoft/BotFramework-WebChat/pull/2295) - `embed`: Added ES5 polyfills and dev server, by [@compulim](https://github.com/compulim), in PR [#2315](https://github.com/microsoft/BotFramework-WebChat/pull/2315) +- Fix [#2380](https://github.com/microsoft/BotFramework-WebChat/issues/2380). Added `botAvatarBackgroundColor` and `userAvatarBackgroundColor` to the default style options, by [@tdurnford](https://github.com/tdurnford) in PR [#2384](https://github.com/microsoft/BotFramework-WebChat/pull/2384) ### Samples diff --git a/__tests__/__image_snapshots__/chrome-docker/basic-js-avatar-background-color-1-snap.png b/__tests__/__image_snapshots__/chrome-docker/basic-js-avatar-background-color-1-snap.png new file mode 100644 index 0000000000..573c231640 Binary files /dev/null and b/__tests__/__image_snapshots__/chrome-docker/basic-js-avatar-background-color-1-snap.png differ diff --git a/__tests__/basic.js b/__tests__/basic.js index 0e1aae0b6d..8ba9e35b3a 100644 --- a/__tests__/basic.js +++ b/__tests__/basic.js @@ -192,3 +192,23 @@ test('absolute timestamp', async () => { expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); }); + +test('avatar background color', async () => { + const styleOptions = { + botAvatarBackgroundColor: 'red', + botAvatarInitials: 'B', + userAvatarBackgroundColor: 'blue', + userAvatarInitials: 'TJ' + }; + + const { driver, pageObjects } = await setupWebDriver({ props: { styleOptions } }); + + await driver.wait(uiConnected(), timeouts.directLine); + await pageObjects.sendMessageViaSendBox('echo "Hello, World!"', { waitForSend: true }); + + await driver.wait(minNumActivitiesShown(3), timeouts.directLine); + + const base64PNG = await driver.takeScreenshot(); + + expect(base64PNG).toMatchImageSnapshot(imageSnapshotOptions); +}); diff --git a/packages/component/src/Styles/StyleSet/Avatar.js b/packages/component/src/Styles/StyleSet/Avatar.js index ad522cdbfc..c52d8a0e9f 100644 --- a/packages/component/src/Styles/StyleSet/Avatar.js +++ b/packages/component/src/Styles/StyleSet/Avatar.js @@ -1,7 +1,12 @@ -export default function createAvatarStyle({ accent, avatarSize, primaryFont }) { +export default function createAvatarStyle({ + accent, + avatarSize, + botAvatarBackgroundColor, + primaryFont, + userAvatarBackgroundColor +}) { return { alignItems: 'center', - backgroundColor: accent, borderRadius: '50%', color: 'White', // TODO: [P2] We should not set "display" in styleSet, this will allow the user to break the layout for no good reasons. @@ -13,6 +18,14 @@ export default function createAvatarStyle({ accent, avatarSize, primaryFont }) { position: 'relative', width: avatarSize, + '&.from-user': { + backgroundColor: userAvatarBackgroundColor || accent + }, + + '&:not(.from-user)': { + backgroundColor: botAvatarBackgroundColor || accent + }, + '& > .image': { left: 0, position: 'absolute', diff --git a/packages/component/src/Styles/StyleSet/CarouselFlipper.js b/packages/component/src/Styles/StyleSet/CarouselFlipper.js index 3ddae5b5f9..0168f8d795 100644 --- a/packages/component/src/Styles/StyleSet/CarouselFlipper.js +++ b/packages/component/src/Styles/StyleSet/CarouselFlipper.js @@ -22,12 +22,12 @@ export default function CarouselFlipper({ '&:focus > div.slider > div.button': { backgroundColor: transcriptOverlayButtonBackgroundOnFocus, - color: transcriptOverlayButtonColorOnFocus + color: transcriptOverlayButtonColorOnFocus || transcriptOverlayButtonColor }, '&:hover > div.slider > div.button': { backgroundColor: transcriptOverlayButtonBackgroundOnHover, - color: transcriptOverlayButtonColorOnHover + color: transcriptOverlayButtonColorOnHover || transcriptOverlayButtonColor } }; } diff --git a/packages/component/src/Styles/StyleSet/ScrollToEndButton.js b/packages/component/src/Styles/StyleSet/ScrollToEndButton.js index 6e541e2a2e..466d1ed453 100644 --- a/packages/component/src/Styles/StyleSet/ScrollToEndButton.js +++ b/packages/component/src/Styles/StyleSet/ScrollToEndButton.js @@ -26,12 +26,12 @@ export default function createScrollToEndButtonStyle({ '&:hover': { backgroundColor: transcriptOverlayButtonBackgroundOnHover, - color: transcriptOverlayButtonColorOnHover + color: transcriptOverlayButtonColorOnHover || transcriptOverlayButtonColor }, '&:focus': { backgroundColor: transcriptOverlayButtonBackgroundOnFocus, - color: transcriptOverlayButtonColorOnFocus + color: transcriptOverlayButtonColorOnFocus || transcriptOverlayButtonColor } }; } diff --git a/packages/component/src/Styles/StyleSet/SendBoxButton.js b/packages/component/src/Styles/StyleSet/SendBoxButton.js index 240dfe7a6a..57c72b3b7a 100644 --- a/packages/component/src/Styles/StyleSet/SendBoxButton.js +++ b/packages/component/src/Styles/StyleSet/SendBoxButton.js @@ -3,7 +3,8 @@ export default function createSendBoxButtonStyle({ sendBoxButtonColorOnDisabled, sendBoxButtonColorOnFocus, sendBoxButtonColorOnHover, - sendBoxHeight + sendBoxHeight, + subtle }) { return { backgroundColor: 'Transparent', @@ -26,7 +27,7 @@ export default function createSendBoxButtonStyle({ }, '& svg': { - fill: sendBoxButtonColor + fill: sendBoxButtonColor || subtle }, '&:disabled svg': { diff --git a/packages/component/src/Styles/StyleSet/SendBoxTextArea.js b/packages/component/src/Styles/StyleSet/SendBoxTextArea.js index 33bd0959c6..251694680f 100644 --- a/packages/component/src/Styles/StyleSet/SendBoxTextArea.js +++ b/packages/component/src/Styles/StyleSet/SendBoxTextArea.js @@ -4,7 +4,8 @@ export default function createSendBoxTextAreaStyle({ sendBoxBackground, sendBoxMaxHeight, sendBoxPlaceholderColor, - sendBoxTextColor + sendBoxTextColor, + subtle }) { return { alignItems: 'center', @@ -51,7 +52,7 @@ export default function createSendBoxTextAreaStyle({ wordBreak: 'break-word', '&::placeholder': { - color: sendBoxPlaceholderColor + color: sendBoxPlaceholderColor || subtle } } } diff --git a/packages/component/src/Styles/StyleSet/SendBoxTextBox.js b/packages/component/src/Styles/StyleSet/SendBoxTextBox.js index e7253ff1eb..20321825ee 100644 --- a/packages/component/src/Styles/StyleSet/SendBoxTextBox.js +++ b/packages/component/src/Styles/StyleSet/SendBoxTextBox.js @@ -1,8 +1,10 @@ export default function createSendBoxTextBoxStyle({ primaryFont, sendBoxBackground, + sendBoxDisabledTextColor, sendBoxPlaceholderColor, - sendBoxTextColor + sendBoxTextColor, + subtle }) { return { alignItems: 'center', @@ -11,15 +13,22 @@ export default function createSendBoxTextBoxStyle({ '& > input': { backgroundColor: sendBoxBackground, border: 0, - color: sendBoxTextColor, fontFamily: 'inherit', fontSize: 'inherit', height: '100%', outline: 0, padding: 0, + '&:not(:disabled)': { + color: sendBoxTextColor + }, + + '&:disabled': { + color: sendBoxDisabledTextColor || subtle + }, + '&::placeholder': { - color: sendBoxPlaceholderColor + color: sendBoxPlaceholderColor || subtle } } }; diff --git a/packages/component/src/Styles/StyleSet/SendStatus.js b/packages/component/src/Styles/StyleSet/SendStatus.js index 17451b61a8..07a006b8fe 100644 --- a/packages/component/src/Styles/StyleSet/SendStatus.js +++ b/packages/component/src/Styles/StyleSet/SendStatus.js @@ -1,6 +1,6 @@ -export default function createSendStatusStyle({ accent, fontSizeSmall, primaryFont, timestampColor }) { +export default function createSendStatusStyle({ accent, fontSizeSmall, primaryFont, subtle, timestampColor }) { return { - color: timestampColor, + color: timestampColor || subtle, fontFamily: primaryFont, fontSize: fontSizeSmall, paddingTop: 5, diff --git a/packages/component/src/Styles/StyleSet/SuggestedAction.js b/packages/component/src/Styles/StyleSet/SuggestedAction.js index e1598a12e1..6dc4706381 100644 --- a/packages/component/src/Styles/StyleSet/SuggestedAction.js +++ b/packages/component/src/Styles/StyleSet/SuggestedAction.js @@ -1,18 +1,24 @@ /* eslint no-magic-numbers: "off" */ export default function createSuggestedActionStyle({ + accent, paddingRegular, paddingWide, primaryFont, suggestedActionBackground, - suggestedActionBorder, + suggestedActionBorderColor, + suggestedActionBorderStyle, + suggestedActionBorderWidth, suggestedActionBorderRadius, suggestedActionImageHeight, suggestedActionTextColor, suggestedActionDisabledBackground, - suggestedActionDisabledBorder, + suggestedActionDisabledBorderColor, + suggestedActionDisabledBorderStyle, + suggestedActionDisabledBorderWidth, suggestedActionDisabledTextColor, - suggestedActionHeight + suggestedActionHeight, + subtle }) { return { paddingBottom: paddingRegular, @@ -30,15 +36,19 @@ export default function createSuggestedActionStyle({ paddingRight: paddingWide, '&:disabled': { - background: suggestedActionDisabledBackground, - border: suggestedActionDisabledBorder, - color: suggestedActionDisabledTextColor + background: suggestedActionDisabledBackground || suggestedActionBackground, + borderColor: suggestedActionDisabledBorderColor, + borderStyle: suggestedActionDisabledBorderStyle, + borderWidth: suggestedActionDisabledBorderWidth, + color: suggestedActionDisabledTextColor || subtle }, '&:not(:disabled)': { background: suggestedActionBackground, - border: suggestedActionBorder, - color: suggestedActionTextColor + borderColor: suggestedActionBorderColor || accent, + borderStyle: suggestedActionBorderStyle, + borderWidth: suggestedActionBorderWidth, + color: suggestedActionTextColor || accent }, '& > img': { diff --git a/packages/component/src/Styles/StyleSet/SuggestedActionsStyleSet.js b/packages/component/src/Styles/StyleSet/SuggestedActionsStyleSet.js index 4ab349b5f3..390fcf5872 100644 --- a/packages/component/src/Styles/StyleSet/SuggestedActionsStyleSet.js +++ b/packages/component/src/Styles/StyleSet/SuggestedActionsStyleSet.js @@ -36,12 +36,12 @@ export default function createSuggestedActionsStyleSet({ '&:focus > div.slider > div': { backgroundColor: transcriptOverlayButtonBackgroundOnFocus, - color: transcriptOverlayButtonColorOnFocus + color: transcriptOverlayButtonColorOnFocus || transcriptOverlayButtonColor }, '&:hover > div.slider > div': { backgroundColor: transcriptOverlayButtonBackgroundOnHover, - color: transcriptOverlayButtonColorOnHover + color: transcriptOverlayButtonColorOnHover || transcriptOverlayButtonColor } }); diff --git a/packages/component/src/Styles/StyleSet/Timestamp.js b/packages/component/src/Styles/StyleSet/Timestamp.js index 426b4b205f..df16aad64b 100644 --- a/packages/component/src/Styles/StyleSet/Timestamp.js +++ b/packages/component/src/Styles/StyleSet/Timestamp.js @@ -1,6 +1,6 @@ -export default function createTimestampStyle({ timestampColor, primaryFont, fontSizeSmall }) { +export default function createTimestampStyle({ fontSizeSmall, primaryFont, subtle, timestampColor }) { return { - color: timestampColor, + color: timestampColor || subtle, fontFamily: primaryFont, fontSize: fontSizeSmall, paddingTop: 5 diff --git a/packages/component/src/Styles/StyleSet/UploadButton.js b/packages/component/src/Styles/StyleSet/UploadButton.js index 40f185b5bf..923a09b0ba 100644 --- a/packages/component/src/Styles/StyleSet/UploadButton.js +++ b/packages/component/src/Styles/StyleSet/UploadButton.js @@ -2,14 +2,15 @@ export default function createUploadButtonStyle({ sendBoxButtonColor, sendBoxButtonColorOnFocus, sendBoxButtonColorOnHover, - sendBoxHeight + sendBoxHeight, + subtle }) { return { // We use the sendBoxHeight, so the button looks square width: sendBoxHeight, '& > .icon > svg': { - fill: sendBoxButtonColor + fill: sendBoxButtonColor || subtle }, '& > input:hover + .icon > svg': { diff --git a/packages/component/src/Styles/createStyleSet.js b/packages/component/src/Styles/createStyleSet.js index 5361d61439..235f23e68a 100644 --- a/packages/component/src/Styles/createStyleSet.js +++ b/packages/component/src/Styles/createStyleSet.js @@ -1,3 +1,4 @@ +/* eslint-disable complexity */ import createActivitiesStyle from './StyleSet/Activities'; import createActivityStyle from './StyleSet/Activity'; import createAudioAttachmentStyle from './StyleSet/AudioAttachment'; @@ -67,7 +68,7 @@ export default function createStyleSet(options) { // Keep this list flat (no nested style) and serializable (no functions) // TODO: [P4] Deprecate this code after bump to v5 - const { bubbleBorder, bubbleFromUserBorder } = options; + const { bubbleBorder, bubbleFromUserBorder, suggestedActionBorder, suggestedActionDisabledBorder } = options; if (bubbleBorder) { console.warn( @@ -109,6 +110,46 @@ export default function createStyleSet(options) { } } + if (suggestedActionBorder) { + console.warn( + 'Web Chat: styleSet.suggestedActionBorder is being deprecated. Please use suggestedActionBorderColor, suggestedActionBorderStyle, and, suggestedActionBorderWidth.' + ); + + const { color, style, width } = parseBorder(suggestedActionBorder); + + if (color && color !== 'initial') { + options.suggestedActionBorderColor = color; + } + + if (style && style !== 'initial') { + options.suggestedActionBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.suggestedActionBorderWidth = parseInt(width, 10); + } + } + + if (suggestedActionDisabledBorder) { + console.warn( + 'Web Chat: styleSet.suggestedActionDisabledBorder is being deprecated. Please use suggestedActionDisabledBorderColor, suggestedActionDisabledBorderStyle, and, suggestedActionDisabledBorderWidth.' + ); + + const { color, style, width } = parseBorder(suggestedActionDisabledBorder); + + if (color && color !== 'initial') { + options.suggestedActionDisabledBorderColor = color; + } + + if (style && style !== 'initial') { + options.suggestedActionDisabledBorderStyle = style; + } + + if (PIXEL_UNIT_PATTERN.test(width)) { + options.suggestedActionDisabledBorderWidth = parseInt(width, 10); + } + } + return { activities: createActivitiesStyle(options), activity: createActivityStyle(options), diff --git a/packages/component/src/Styles/defaultStyleOptions.js b/packages/component/src/Styles/defaultStyleOptions.js index 0624c58b41..574f97dad3 100644 --- a/packages/component/src/Styles/defaultStyleOptions.js +++ b/packages/component/src/Styles/defaultStyleOptions.js @@ -27,12 +27,15 @@ const DEFAULT_OPTIONS = { // Avatar avatarSize: 40, + botAvatarBackgroundColor: undefined, // defaults to accent color botAvatarImage: '', botAvatarInitials: '', + userAvatarBackgroundColor: undefined, // defaults to accent color userAvatarImage: '', userAvatarInitials: '', // Bubble + // TODO: Should we make a bubbleFromBot* bubbleBackground: 'White', bubbleBorderColor: '#E6E6E6', bubbleBorderRadius: 2, @@ -72,18 +75,20 @@ const DEFAULT_OPTIONS = { hideUploadButton: false, microphoneButtonColorOnDictate: '#F33', sendBoxBackground: 'White', - sendBoxButtonColor: '#767676', + sendBoxButtonColor: undefined, // defaults to subtle sendBoxButtonColorOnDisabled: '#CCC', sendBoxButtonColorOnFocus: '#333', sendBoxButtonColorOnHover: '#333', + sendBoxDisabledTextColor: undefined, // defaults to subtle sendBoxHeight: 40, sendBoxMaxHeight: 200, sendBoxTextColor: 'Black', + // TODO: We should deprecate this because there isn't an easy way to make the width of the send box, narrower than the transcript sendBoxBorderBottom: '', sendBoxBorderLeft: '', sendBoxBorderRight: '', sendBoxBorderTop: 'solid 1px #E6E6E6', - sendBoxPlaceholderColor: '#767676', + sendBoxPlaceholderColor: undefined, // defaults to subtle sendBoxTextWrap: false, // Visually show spoken text @@ -91,17 +96,23 @@ const DEFAULT_OPTIONS = { // Suggested actions suggestedActionBackground: 'White', - suggestedActionBorder: `solid 2px ${DEFAULT_ACCENT}`, + suggestedActionBorder: undefined, // split into 3, null + suggestedActionBorderColor: undefined, // defaults to accent + suggestedActionBorderStyle: 'solid', + suggestedActionBoarderWidth: 2, suggestedActionBorderRadius: 0, suggestedActionImageHeight: 20, - suggestedActionTextColor: DEFAULT_ACCENT, - suggestedActionDisabledBackground: 'White', - suggestedActionDisabledBorder: `solid 2px #E6E6E6`, - suggestedActionDisabledTextColor: DEFAULT_SUBTLE, + suggestedActionTextColor: null, + suggestedActionDisabledBackground: undefined, // defaults to suggestedActionBackground + suggestedActionDisabledBorder: null, + suggestedActionDisabledBorderColor: '#E6E6E6', + suggestedActionDisabledBorderStyle: 'solid', + suggestedActionDisabledBorderWidth: 2, + suggestedActionDisabledTextColor: undefined, // defaults to subtle suggestedActionHeight: 40, // Timestamp - timestampColor: DEFAULT_SUBTLE, + timestampColor: undefined, // defaults to subtle timestampFormat: 'relative', // 'absolute' // Transcript overlay buttons (e.g. carousel and suggested action flippers, scroll to bottom, etc.) @@ -109,8 +120,8 @@ const DEFAULT_OPTIONS = { transcriptOverlayButtonBackgroundOnFocus: 'rgba(0, 0, 0, .8)', transcriptOverlayButtonBackgroundOnHover: 'rgba(0, 0, 0, .8)', transcriptOverlayButtonColor: 'White', - transcriptOverlayButtonColorOnFocus: 'White', - transcriptOverlayButtonColorOnHover: 'White', + transcriptOverlayButtonColorOnFocus: undefined, // defaults to transcriptOverlayButtonColor + transcriptOverlayButtonColorOnHover: undefined, // defaults to transcriptOverlayButtonColor // Video videoHeight: 270, // based on bubbleMaxWidth, 480 / 16 * 9 = 270 @@ -119,7 +130,7 @@ const DEFAULT_OPTIONS = { connectivityIconPadding: PADDING_REGULAR * 1.2, connectivityMarginLeftRight: PADDING_REGULAR * 1.4, connectivityMarginTopBottom: PADDING_REGULAR * 0.8, - connectivityTextSize: 12, + connectivityTextSize: '75%', failedConnectivity: '#C50F1F', slowConnectivity: '#EAA300', notificationText: '#5E5E5E',