Skip to content

Commit

Permalink
Fix citation modal width on mobile device (#4867)
Browse files Browse the repository at this point in the history
* Modal width for mobile device

* Fix citation button font

* Add tests

* Style citation button

* Use calculated width

* Update tests

* Fit and finish

* Update snapshots

* Update entry

* Fix ESLint
  • Loading branch information
compulim authored Sep 25, 2023
1 parent 8d04e66 commit afe913c
Show file tree
Hide file tree
Showing 27 changed files with 199 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

- Fixes [#4865](https://github.com/microsoft/BotFramework-WebChat/issues/4865). Fixed <kbd>CTRL</kbd> + <kbd>Z</kbd> should undo correctly, by [@compulim](https://github.com/compulim), in PR [#4861](https://github.com/microsoft/BotFramework-WebChat/issues/pull/4861)
- Fixes [#4863](https://github.com/microsoft/BotFramework-WebChat/issues/4863). Disable dark theme for link references until chat history has dark theme support, by [@compulim](https://github.com/compulim), in PR [#4864](https://github.com/microsoft/BotFramework-WebChat/pull/4864)
- Fixes [#4866](https://github.com/microsoft/BotFramework-WebChat/issues/4866). Citation modal show fill screen width on mobile device and various fit-and-finish, by [@compulim](https://github.com/compulim), in PR [#4867](https://github.com/microsoft/BotFramework-WebChat/pull/4867)

### Added

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.
56 changes: 56 additions & 0 deletions __tests__/html/citation.showModal.width.desktop.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<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>
</head>
<body>
<main id="webchat"></main>
<script>
run(async function () {
const { directLine, store } = testHelpers.createDirectLineEmulator();

WebChat.renderWebChat(
{
directLine,
store
},
document.getElementById('webchat')
);

await host.windowSize(1024, 768, document.getElementById('webchat'));
await pageConditions.uiConnected();

await directLine.emulateIncomingActivity({
entities: [
{
'@context': 'https://schema.org',
'@id': 'cite:1',
'@type': 'Claim',
type: 'https://schema.org/Claim',
text: 'Reprehenderit exercitation laborum labore ut. Nostrud do et ut nostrud nisi excepteur labore adipisicing nostrud nostrud ipsum id dolore. Anim aliquip incididunt incididunt sunt sit proident consectetur exercitation qui aliqua aliquip adipisicing nisi et. Id commodo labore sunt quis do aute cillum laborum veniam [proident](https://bing.com/).'
}
],
text: `Sure, you should override the default proxy settings[1]\u200C[2], when your proxy server requires authentication[3].
[1]: https://support.microsoft.com/en-us/windows/use-a-proxy-server-in-windows-03096c53-0554-4ffe-b6ab-8b1deee8dae1
[2]: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-proxy-server-settings "Configure proxy server settings - Windows Server"
[3]: cite:1 "Citation-1"
`,
type: 'message'
});

await host.snapshot();

const markdownElement = pageElements.activities()[0].querySelector('.webchat__text-content__markdown');
const markdownButtons = markdownElement.querySelectorAll('button');

await host.click(markdownButtons[0]);

await host.snapshot();
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions __tests__/html/citation.showModal.width.desktop.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('citation modal dialog', () => {
test('should show 60% on desktop', () => runHTML('citation.showModal.width.desktop.html'));
});
55 changes: 55 additions & 0 deletions __tests__/html/citation.showModal.width.mobile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
<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>
</head>
<body>
<main id="webchat"></main>
<script>
run(async function () {
const { directLine, store } = testHelpers.createDirectLineEmulator();

WebChat.renderWebChat(
{
directLine,
store
},
document.getElementById('webchat')
);

await pageConditions.uiConnected();

await directLine.emulateIncomingActivity({
entities: [
{
'@context': 'https://schema.org',
'@id': 'cite:1',
'@type': 'Claim',
type: 'https://schema.org/Claim',
text: 'Reprehenderit exercitation laborum labore ut. Nostrud do et ut nostrud nisi excepteur labore adipisicing nostrud nostrud ipsum id dolore. Anim aliquip incididunt incididunt sunt sit proident consectetur exercitation qui aliqua aliquip adipisicing nisi et. Id commodo labore sunt quis do aute cillum laborum veniam [proident](https://bing.com/).'
}
],
text: `Sure, you should override the default proxy settings[1]\u200C[2], when your proxy server requires authentication[3].
[1]: https://support.microsoft.com/en-us/windows/use-a-proxy-server-in-windows-03096c53-0554-4ffe-b6ab-8b1deee8dae1
[2]: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-proxy-server-settings "Configure proxy server settings - Windows Server"
[3]: cite:1 "Citation-1"
`,
type: 'message'
});

await host.snapshot();

const markdownElement = pageElements.activities()[0].querySelector('.webchat__text-content__markdown');
const markdownButtons = markdownElement.querySelectorAll('button');

await host.click(markdownButtons[0]);

await host.snapshot();
});
</script>
</body>
</html>
5 changes: 5 additions & 0 deletions __tests__/html/citation.showModal.width.mobile.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('citation modal dialog', () => {
test('should show full-width on mobile device', () => runHTML('citation.showModal.width.mobile.html'));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import classNames from 'classnames';
import React, { Fragment, memo } from 'react';

import useRenderMarkdownAsHTML from '../../../hooks/useRenderMarkdownAsHTML';
import useStyleSet from '../../../hooks/useStyleSet';

type Props = Readonly<{
headerText?: string;
markdown: string;
}>;

const CitationModalContent = memo(({ headerText, markdown }: Props) => {
const [{ renderMarkdown: renderMarkdownStyleSet }] = useStyleSet();
const renderMarkdownAsHTML = useRenderMarkdownAsHTML();

return (
<Fragment>
{headerText && <h2 className="webchat__citation-modal-dialog__header">{headerText}</h2>}
{renderMarkdownAsHTML ? (
<div
className={classNames(
'webchat__citation-modal-dialog__body',
'webchat__render-markdown',
renderMarkdownStyleSet + ''
)}
// The content rendered by `renderMarkdownAsHTML` is sanitized.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: renderMarkdownAsHTML(markdown) }}
/>
) : (
<div className={classNames('webchat__render-markdown', renderMarkdownStyleSet + '')}>{markdown}</div>
)}
</Fragment>
);
});

CitationModalContent.displayName = 'CitationModalContent';

export default CitationModalContent;
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { isClaim, type Claim } from '../../../types/external/OrgSchema/Claim';
import { isThing } from '../../../types/external/OrgSchema/Thing';
import { type PropsOf } from '../../../types/PropsOf';
import { type WebChatActivity } from 'botframework-webchat-core';
import CitationModalContext from './CitationModalContent';
import isHTMLButtonElement from './isHTMLButtonElement';
import LinkDefinitions from './LinkDefinitions';
import useRenderMarkdownAsHTML from '../../../hooks/useRenderMarkdownAsHTML';
Expand All @@ -21,7 +22,13 @@ type Props = Readonly<{
}>;

const MarkdownTextContent = memo(({ entities, markdown }: Props) => {
const [{ renderMarkdown: renderMarkdownStyleSet, textContent: textContentStyleSet }] = useStyleSet();
const [
{
citationModalDialog: citationModalDialogStyleSet,
renderMarkdown: renderMarkdownStyleSet,
textContent: textContentStyleSet
}
] = useStyleSet();
const entitiesRef = useRefFrom(entities);
const renderMarkdownAsHTML = useRenderMarkdownAsHTML();
const showModal = useShowModal();
Expand All @@ -41,19 +48,12 @@ const MarkdownTextContent = memo(({ entities, markdown }: Props) => {

const showClaimModal = useCallback(
(claim: Claim) => {
showModal(
() => (
<div
className={classNames('webchat__render-markdown', renderMarkdownStyleSet + '')}
// The content rendered by `renderMarkdownAsHTML` is sanitized.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: renderMarkdownAsHTML(claim.text) }}
/>
),
{ 'aria-label': claim.alternateName || claim.name || citationModalDialogLabel }
);
showModal(() => <CitationModalContext headerText={claim.name} markdown={claim.text} />, {
'aria-label': claim.alternateName || claim.name || citationModalDialogLabel,
className: classNames('webchat__citation-modal-dialog', citationModalDialogStyleSet)
});
},
[citationModalDialogLabel, renderMarkdownAsHTML, renderMarkdownStyleSet, showModal]
[citationModalDialogStyleSet, citationModalDialogLabel, showModal]
);

const handleCitationClick = useCallback<PropsOf<typeof LinkDefinitions>['onCitationClick']>(
Expand Down
9 changes: 9 additions & 0 deletions packages/component/src/Styles/StyleSet/CitationModalDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default function createCitationModalDialogStyle() {
return {
'&.webchat__citation-modal-dialog': {
'& .webchat__citation-modal-dialog__body': {
lineHeight: '20px'
}
}
};
}
15 changes: 12 additions & 3 deletions packages/component/src/Styles/StyleSet/ModalDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export default function createModalDialogStyleSet() {
return {
'&.webchat__modal-dialog': {
fontFamily: CSSTokens.FontPrimary,
maxHeight: 'calc(100% - 32px)',
maxWidth: 'calc(100% - 32px)',
width: '100%',

[NOT_FORCED_COLORS_SELECTOR]: {
Expand All @@ -19,11 +21,18 @@ export default function createModalDialogStyleSet() {

'& .webchat__modal-dialog__box': {
borderRadius: 2,
height: `calc(100% - ${CSSTokens.PaddingRegular} * 2)`,
overflow: 'hidden',
margin: 'auto',
maxWidth: '60%',
width: `calc(100% - ${CSSTokens.PaddingRegular} * 2)`,

'@media screen and (max-width: 639px)': {
maxWidth: 'unset'
},

'@media screen and (min-width: 640px)': {
maxWidth: '60%',
minWidth: 'calc(640px - 32px)',
width: '60%'
},

[LIGHT_THEME_SELECTOR]: {
// From Power BI:
Expand Down
2 changes: 2 additions & 0 deletions packages/component/src/Styles/StyleSet/RenderMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export default function createMarkdownStyle() {
background: 'transparent',
border: 0,
cursor: 'pointer',
fontFamily: 'unset',
fontSize: 'unset',
padding: 0,
textDecoration: 'underline',
whiteSpace: 'nowrap',
Expand Down
2 changes: 2 additions & 0 deletions packages/component/src/Styles/createStyleSet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import createBubbleStyle from './StyleSet/Bubble';
import createCarouselFilmStrip from './StyleSet/CarouselFilmStrip';
import createCarouselFilmStripAttachment from './StyleSet/CarouselFilmStripAttachment';
import createCarouselFlipper from './StyleSet/CarouselFlipper';
import createCitationModalDialogStyle from './StyleSet/CitationModalDialog';
import createConnectivityNotification from './StyleSet/ConnectivityNotification';
import createCSSCustomPropertiesStyle from './StyleSet/CSSCustomProperties';
import createDictationInterimsStyle from './StyleSet/DictationInterims';
Expand Down Expand Up @@ -99,6 +100,7 @@ export default function createStyleSet(styleOptions: StyleOptions) {

// Following styles follows new house rules:
// - Use CSS var instead of strictStyleOptions
citationModalDialog: createCitationModalDialogStyle(),
cssCustomProperties: createCSSCustomPropertiesStyle(strictStyleOptions),
linkDefinitions: createLinkDefinitionsStyle(),
modalDialog: createModalDialogStyle(),
Expand Down

0 comments on commit afe913c

Please sign in to comment.