Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fluent theme] Hide buttons, suggested actions FnF and flow layout, DTMF FnF #5132

Merged
merged 9 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pull-request-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ env:
CI_PULL_REQUEST: 1 # Skip nightly tests
NODE_ENV: test # Add instrumentation code
node-version: 18.18 # Need to bump jest@29 to resolve something in https://github.com/facebook/react-native/issues/35701
skip-secure-feed: false
skip-secure-feed: true # Terrapin service is degrading and their team told us to disable Terrapin to unblock ourselves

jobs:
build:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- `styleOptions.maxMessageLength` to specify maximum length of the outgoing message
- Drag-and-drop file support, in PR [#5122](https://github.com/microsoft/BotFramework-WebChat/pull/5122)
- Added telephone keypad (DTMF keypad), in PR [#5122](https://github.com/microsoft/BotFramework-WebChat/pull/5122)
- Added support of `styleOptions.hideUploadButton`, in PR [#5132](https://github.com/microsoft/BotFramework-WebChat/pull/5132)
- Added `styleOptions.hideTelephoneKeypadButton` and default to `true`, in PR [#5132](https://github.com/microsoft/BotFramework-WebChat/pull/5132)
- Fit-and-finish on suggested actions and telephone keypad, in PR [#5132](https://github.com/microsoft/BotFramework-WebChat/pull/5132)
- Fixed to keep telephone keypad on-screen on click, in PR [#5132](https://github.com/microsoft/BotFramework-WebChat/pull/5132)
- Added `<ThemeProvider>` component to apply theme pack to Web Chat, by [@compulim](https://github.com/compulim), in PR [#5120](https://github.com/microsoft/BotFramework-WebChat/pull/5120)
- Added `useMakeThumbnail` hook option to create a thumbnail from the file given, by [@compulim](https://github.com/compulim), in PR [#5123](https://github.com/microsoft/BotFramework-WebChat/pull/5123) and [#5122](https://github.com/microsoft/BotFramework-WebChat/pull/5122)

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions __tests__/html/fluentTheme/hideAttachFileButton.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.production.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.production.min.js"></script>
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<script crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
</head>
<body>
<main id="webchat"></main>
<script type="text/babel">
run(async function () {
const {
React,
ReactDOM: { render },
WebChat: { FluentThemeProvider, ReactWebChat }
} = window; // Imports in UMD fashion.

const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ hideUploadButton: true }} />
);

render(
<FluentThemeProvider>
<App />
</FluentThemeProvider>,
document.getElementById('webchat')
);

await pageConditions.uiConnected();

// THEN: No attach button should be render.
expect(pageElements.byTestId(WebChat.testIds.sendBoxUploadButton)).toBeFalsy();
await host.snapshot();
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions __tests__/html/fluentTheme/hideAttachFileButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('Fluent theme applied', () => {
test('when styleOptions.hideUploadButton is truthy should not render attach file button', () => runHTML('fluentTheme/hideAttachFileButton'));
});
80 changes: 80 additions & 0 deletions __tests__/html/fluentTheme/suggestedActions.layout.flow.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!doctype html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<script crossorigin="anonymous" src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.production.min.js"></script>
<script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.production.min.js"></script>
<script crossorigin="anonymous" src="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
<script crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
</head>
<body>
<main id="webchat"></main>
<script type="text/babel">
run(async function () {
const {
React,
ReactDOM: { render },
WebChat: { FluentThemeProvider, ReactWebChat }
} = window; // Imports in UMD fashion.

const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ suggestedActionLayout: 'flow' }} />
);

render(
<FluentThemeProvider>
<App />
</FluentThemeProvider>,
document.getElementById('webchat')
);

await pageConditions.uiConnected();

await directLine.emulateIncomingActivity({
type: 'message',
textFormat: 'plain',
text: 'Please select one of the actions below',
suggestedActions: {
actions: [
{ title: 'A', type: 'imBack' },
{ title: 'B', type: 'imBack' },
{ title: 'C', type: 'imBack' },
{ title: 'D', type: 'imBack' },
{ title: 'E', type: 'imBack' },
{ title: 'F', type: 'imBack' },
{ title: 'G', type: 'imBack' },
{ title: 'H', type: 'imBack' },
{ title: 'I', type: 'imBack' },
{ title: 'J', type: 'imBack' },
{ title: 'K', type: 'imBack' },
{ title: 'L', type: 'imBack' },
{ title: 'M', type: 'imBack' },
{ title: 'N', type: 'imBack' },
{ title: 'O', type: 'imBack' },
{ title: 'P', type: 'imBack' },
{ title: 'Q', type: 'imBack' },
{ title: 'R', type: 'imBack' },
{ title: 'S', type: 'imBack' },
{ title: 'T', type: 'imBack' },
{ title: 'U', type: 'imBack' },
{ title: 'V', type: 'imBack' },
{ title: 'W', type: 'imBack' },
{ title: 'X', type: 'imBack' },
{ title: 'Y', type: 'imBack' },
{ title: 'Z', type: 'imBack' }
],
to: []
}
});

// THEN: Should render the activity.
await host.snapshot();
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions __tests__/html/fluentTheme/suggestedActions.layout.flow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @jest-environment ./packages/test/harness/src/host/jest/WebDriverEnvironment.js */

describe('Fluent theme applied', () => {
test('renders suggested actions with a flow layout', () => runHTML('fluentTheme/suggestedActions.layout.flow'));
});
4 changes: 3 additions & 1 deletion __tests__/html/fluentTheme/tabOrder.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => <ReactWebChat directLine={directLine} store={store} />;
const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ hideTelephoneKeypadButton: false }} />
);

render(
<FluentThemeProvider>
Expand Down
4 changes: 3 additions & 1 deletion __tests__/html/fluentTheme/telephoneKeypad.showHide.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => <ReactWebChat directLine={directLine} store={store} />;
const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ hideTelephoneKeypadButton: false }} />
);

render(
<FluentThemeProvider>
Expand Down
19 changes: 9 additions & 10 deletions __tests__/html/fluentTheme/telephoneKeypad.tap.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@

const { directLine, store } = testHelpers.createDirectLineEmulator();

const App = () => <ReactWebChat directLine={directLine} store={store} />;
const App = () => (
<ReactWebChat directLine={directLine} store={store} styleOptions={{ hideTelephoneKeypadButton: false }} />
);

render(
<FluentThemeProvider>
Expand All @@ -40,24 +42,21 @@
await pageConditions.numActivitiesShown(1);

// WHEN: Telephone keypad button is clicked.
await host.click(
document.querySelector(`[data-testid="${WebChat.testIds.sendBoxTelephoneKeypadToolbarButton}"]`)
);
await host.click(pageElements.byTestId(WebChat.testIds.sendBoxTelephoneKeypadToolbarButton));

await (
await directLine.actPostActivity(() =>
host.click(document.querySelector(`[data-testid="${WebChat.testIds.sendBoxTelephoneKeypadButton5}"]`))
host.click(pageElements.byTestId(WebChat.testIds.sendBoxTelephoneKeypadButton5))
)
).resolveAll();

// THEN: Should send "/DTMF 5" and focus on the send box.
// THEN: Should send "/DTMF 5".
await pageConditions.numActivitiesShown(2);
expect(pageElements.activityContents()[1]).toHaveProperty('textContent', '/DTMF 5');

// Commented out because it is not working today.
// expect(document.activeElement).toBe(
// document.querySelector(`[data-testid="${WebChat.testIds.sendBoxTextBox}"]`)
// );
// THEN: Should not close the keypad and keep focusing on the button "5".
expect(pageElements.byTestId(WebChat.testIds.sendBoxTelephoneKeypadButton5)).toBeTruthy();
expect(document.activeElement).toBe(pageElements.byTestId(WebChat.testIds.sendBoxTelephoneKeypadButton5));

await host.snapshot();
});
Expand Down
8 changes: 8 additions & 0 deletions packages/api/src/StyleOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,14 @@ type StyleOptions = {

hideSendBox?: boolean;
hideUploadButton?: boolean;

/**
* (EXPERIMENTAL) `true`, if the telephone keypad button should be shown, otherwise, `false`. Defaults to `true`.
*
* @deprecated This is an experimental style options and should not be used without understanding its risk.
*/
hideTelephoneKeypadButton?: boolean | undefined;

microphoneButtonColorOnDictate?: string;
sendBoxBackground?: string;

Expand Down
1 change: 1 addition & 0 deletions packages/api/src/defaultStyleOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const DEFAULT_OPTIONS: Required<StyleOptions> = {
// Send box
hideSendBox: false,
hideUploadButton: false,
hideTelephoneKeypadButton: true,
microphoneButtonColorOnDictate: '#F33',
sendBoxBackground: 'White',
uploadAccept: undefined,
Expand Down
3 changes: 2 additions & 1 deletion packages/fluent-theme/src/components/Theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ const styles = {

'--webchat-colorStatusDangerForeground1': 'var(--colorStatusDangerForeground1, #b10e1c)',

// https://github.com/microsoft/fluentui/blob/master/packages/tokens/src/global/colors.ts
// https://github.com/microsoft/fluentui/blob/master/packages/theme/src/colors/FluentColors.ts
'--webchat-colorGray30': 'var(--colorGray30, #edebe9)',
'--webchat-colorGray160': 'var(--colorGray160, #323130)',
'--webchat-colorGray190': 'var(--colorGray190, #201f1e)',
'--webchat-colorGray200': 'var(--colorGray200, #1b1a19)',

// https://github.com/microsoft/fluentui/blob/master/packages/tokens/src/global/borderRadius.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const styles = {
},

'&::-webkit-scrollbar-track': {
backgroundColor: ' var(--webchat-colorNeutralBackground5)',
backgroundColor: 'var(--webchat-colorNeutralBackground5)',
borderRadius: '16px'
},

Expand Down
2 changes: 1 addition & 1 deletion packages/fluent-theme/src/components/sendbox/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const styles = {
color: 'var(--webchat-colorCompoundBrandForeground1Pressed)'
},
'&[aria-disabled="true"]': {
color: ' var(--webchat-colorNeutralForegroundDisabled)',
color: 'var(--webchat-colorNeutralForegroundDisabled)',
cursor: 'not-allowed'
}
},
Expand Down
19 changes: 7 additions & 12 deletions packages/fluent-theme/src/components/sendbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ function SendBox(
const inputRef = useRef<HTMLTextAreaElement>(null);
const [message, setMessage] = useState('');
const [attachments, setAttachments] = useSendBoxAttachments();
const [{ maxMessageLength }] = useStyleOptions();
const [{ hideTelephoneKeypadButton, hideUploadButton, maxMessageLength }] = useStyleOptions();
const isMessageLengthExceeded = !!maxMessageLength && message.length > maxMessageLength;
const classNames = useStyles(styles);
const localize = useLocalizer();
const sendMessage = useSendMessage();
const makeThumbnail = useMakeThumbnail();
const errorMessageId = useUniqueId('webchat-fluent__sendbox__error-message-id');
const [errorRef, errorMessage] = useSubmitError({ message, attachments });
const [telephoneKeypadShown, setTelephoneKeypadShown] = useTelephoneKeypadShown();
const [telephoneKeypadShown] = useTelephoneKeypadShown();

const attachmentsRef = useRefFrom(attachments);
const messageRef = useRefFrom(message);
Expand Down Expand Up @@ -162,14 +162,9 @@ function SendBox(
);

const handleTelephoneKeypadButtonClick = useCallback(
(dtmf: DTMF) => {
// TODO: We need more official way of sending DTMF.
sendMessage(`/DTMF ${dtmf}`);

// TODO: In the future when we work on input modality, it should manage the focus in a better way.
setTelephoneKeypadShown(false);
},
[sendMessage, setTelephoneKeypadShown]
// TODO: We need more official way of sending DTMF.
(dtmf: DTMF) => sendMessage(`/DTMF ${dtmf}`),
[sendMessage]
);

const aria = {
Expand Down Expand Up @@ -211,8 +206,8 @@ function SendBox(
</div>
)}
<Toolbar>
<TelephoneKeypadToolbarButton />
<AddAttachmentButton onFilesAdded={handleAddFiles} />
{!hideTelephoneKeypadButton && <TelephoneKeypadToolbarButton />}
{!hideUploadButton && <AddAttachmentButton onFilesAdded={handleAddFiles} />}
<ToolbarSeparator />
<ToolbarButton
aria-label={localize('TEXT_INPUT_SEND_BUTTON_ALT')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { hooks } from 'botframework-webchat-component';
import { type DirectLineCardAction } from 'botframework-webchat-core';
import cx from 'classnames';
import React, { MouseEventHandler, memo, useCallback, useRef } from 'react';
import AccessibleButton from './AccessibleButton';
import { useStyles } from '../../styles';
import AccessibleButton from './AccessibleButton';

const { useScrollToEnd, useStyleSet, usePerformCardAction, useFocus, useSuggestedActions, useDisabled } = hooks;
const { useDisabled, useFocus, usePerformCardAction, useScrollToEnd, useStyleSet, useSuggestedActions } = hooks;

type SuggestedActionProps = Readonly<{
buttonText: string | undefined;
Expand All @@ -31,17 +31,16 @@ type SuggestedActionProps = Readonly<{

const styles = {
'webchat-fluent__suggested-action': {
alignItems: 'center',
background: 'transparent',
border: '1px solid var(--webchat-colorBrandStroke2)',
borderRadius: '8px',
cursor: 'pointer',
fontSize: '12px',
lineHeight: '14px',
padding: '6px 8px 4px',
textAlign: 'start',
display: 'flex',
fontSize: '12px',
gap: '4px',
alignItems: 'center',
padding: '4px 8px 4px',
textAlign: 'start',
transition: 'all .15s ease-out',

'@media (hover: hover)': {
Expand All @@ -50,21 +49,20 @@ const styles = {
color: 'var(--webchat-colorBrandForeground2Hover)'
}
},

'&:not([aria-disabled="true"]):active': {
backgroundColor: 'var(--webchat-colorBrandBackground2Pressed)',
color: 'var(--webchat-colorBrandForeground2Pressed)'
},

'&[aria-disabled="true"]': {
color: ' var(--webchat-colorNeutralForegroundDisabled)',
color: 'var(--webchat-colorNeutralForegroundDisabled)',
cursor: 'not-allowed'
}
},

'webchat-fluent__suggested-action__image': {
width: '1em',
height: '1em',
fontSize: '20px',
translate: '0 -1px'
height: '12px'
compulim marked this conversation as resolved.
Show resolved Hide resolved
}
};

Expand Down
Loading
Loading