Skip to content

Commit

Permalink
Add scrollbar to math (#5380)
Browse files Browse the repository at this point in the history
* Add scrollbar to math

* Update PR number

* Add scrollbar-width: thin to white-label

* Make scrollable focusable

* Add padding for scrollbar
  • Loading branch information
compulim authored Nov 15, 2024
1 parent 7f9f47e commit e88f4b6
Show file tree
Hide file tree
Showing 31 changed files with 152 additions and 7 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Improved view code dialog UI in Fluent theme with better styling and accessibility, in PR [#5337](https://github.com/microsoft/BotFramework-WebChat/pull/5337), by [@OEvgeny](https://github.com/OEvgeny)
- Switched math block syntax from `$$` to Tex-style `\[ \]` and `\( \)` delimiters with improved rendering and error handling, in PR [#5353](https://github.com/microsoft/BotFramework-WebChat/pull/5353), by [@OEvgeny](https://github.com/OEvgeny)
- Improved avatar display and grouping behavior by fixing rendering issues and activity sender identification, in PR [#5346](https://github.com/microsoft/BotFramework-WebChat/pull/5346), by [@OEvgeny](https://github.com/OEvgeny)
- Activity "copy" button will use `outerHTML` and `textContent` for clipboard content, in PR [#5378](https://github.com/microsoft/BotFramework-WebChat/pull/5378), by [@compulim](https://github.com/compuilm)
- Activity "copy" button will use `outerHTML` and `textContent` for clipboard content, in PR [#5378](https://github.com/microsoft/BotFramework-WebChat/pull/5378), by [@compulim](https://github.com/compulim)

### Fixed

Expand All @@ -108,6 +108,7 @@ Notes: web developers are advised to use [`~` (tilde range)](https://github.com/
- Fixed [#5350](https://github.com/microsoft/BotFramework-WebChat/issues/pull/5350). Bundled `shiki` in component package, in PR [#5349](https://github.com/microsoft/BotFramework-WebChat/pull5349), by [@compulim](https://github.com/compulim)
- Fixed modal dialog rendering to prevent visual flicker and improve UX when opening code views, in PR [#5374](https://github.com/microsoft/BotFramework-WebChat/pull/5374), by [@OEvgeny](https://github.com/OEvgeny)
- Fixed math parsing that could cause Web Chat to hang when processing certain LaTeX expressions, in PR [#5377](https://github.com/microsoft/BotFramework-WebChat/pull/5377), by [@OEvgeny](https://github.com/OEvgeny)
- Fixed long math formula should be scrollable, in PR [#5380](https://github.com/microsoft/BotFramework-WebChat/pull/5380), by [@compulim](https://github.com/compulim)

# Removed

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
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.
File renamed without changes.
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!doctype html>
<html>
<head>
<script>
location = './layout.scroll?theme=light&variant=copilot';
</script>
</head>
<body></body>
</html>
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.
121 changes: 121 additions & 0 deletions __tests__/html2/markdown/math/layout.scroll.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<!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="/test-harness.js"></script>
<script crossorigin="anonymous" src="/test-page-object.js"></script>
<script crossorigin="anonymous" src="/__dist__/fluent-bundle.production.min.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 {
Fluent: { createDarkTheme, createLightTheme, FluentProvider },
ReactDOMClient: { createRoot },
WebChat: { FluentThemeProvider, ReactWebChat, testIds }
} = window; // Imports in UMD fashion.

const { directLine, store } = testHelpers.createDirectLineEmulator();
const searchParams = new URLSearchParams(location.search);

const App = () => <ReactWebChat directLine={directLine} store={store} />;

const customBrandRamp = {
10: '#124C32',
20: '#1A5B3E',
30: '#216A4A',
40: '#297956',
50: '#308861',
60: '#38976D',
70: '#40A779',
80: '#158051',
90: '#4FC590',
100: '#56D49C',
110: '#5EE3A8',
120: '#79E8B7',
130: '#94ECC5',
140: '#AFF1D3',
150: '#C9F6E2',
160: '#E4FAF1'
};

const root = createRoot(document.getElementById('webchat'));

if (searchParams.get('variant') === 'copilot' || searchParams.get('variant') === 'fluent') {
root.render(
<FluentProvider
theme={
searchParams.get('theme') === 'dark'
? createDarkTheme(customBrandRamp)
: createLightTheme(customBrandRamp)
}
>
<FluentThemeProvider variant={searchParams.get('variant') || ''}>
<App />
</FluentThemeProvider>
</FluentProvider>
);
} else {
root.render(<App />);
}

await pageConditions.uiConnected();

await directLine.emulateIncomingActivity({
type: 'message',
from: {
role: 'bot'
},
text: 'To calculate the number of oranges in a crate, you can use a few different methods depending on the information you have. Here are some formulae that might help:\n\n1. **Volume Method**:\n If you know the volume of the crate and the average volume of an orange, you can estimate the number of oranges.\n \\[\n \\text{Number of Oranges} = \\frac{\\text{Volume of Crate}}{\\text{Average Volume of an Orange}}\n \\]\n\n2. **Weight Method**:\n If you know the total weight of the crate and the average weight of an orange, you can use this formula.\n \\[\n \\text{Number of Oranges} = \\frac{\\text{Total Weight of Crate}}{\\text{Average Weight of an Orange}}\n \\]\n\n3. **Layer Method**:\n If you know the dimensions of the crate and the average dimensions of an orange, you can calculate how many layers of oranges fit in the crate.\n \\[\n \\text{Number of Oranges} = \\left(\\frac{\\text{Length of Crate}}{\\text{Average Diameter of an Orange}}\\right) \\times \\left(\\frac{\\text{Width of Crate}}{\\text{Average Diameter of an Orange}}\\right) \\times \\left(\\frac{\\text{Height of Crate}}{\\text{Average Diameter of an Orange}}\\right)\n \\]\n\nThese methods can give you a good estimate. Do you have specific measurements or weights for your crate and oranges? That would help in applying these formulae more accurately.'
});

await pageConditions.numActivitiesShown(1);

await host.snapshot('local');

// WHEN: Press ENTER over the activity.
document.querySelector(`#webchat [data-testid="${testIds.sendBoxTextBox}"]`).focus();

await host.sendShiftTab(
(searchParams.get('variant') === 'copilot' || searchParams.get('variant') === 'fluent') ? 2 : 3
);
await host.sendKeys('ENTER');

// THEN: Should focus on the first <figure>.
expect(document).toHaveProperty(
'activeElement',
pageElements.activityContents()[0].querySelectorAll('figure')[0]
);
// expect(document).toHaveProperty('activeElement.tagName', 'FIGURE');
await host.snapshot('local');

// ----------------------------------------

// WHEN: Press RIGHT key.
await host.sendKeys('RIGHT');

// THEN: Should scroll to the right.
await pageConditions.became('should scroll to the right', () => document.activeElement.scrollLeft > 10, 1000);
await pageConditions.stabilized('should finish scrolling', () => document.activeElement.scrollLeft, 5, 1000);
await host.snapshot('local');

// ----------------------------------------

// WHEN: Press TAB key.
await host.sendKeys('TAB');

// THEN: Should focus on the second <figure>.
expect(document).toHaveProperty(
'activeElement',
pageElements.activityContents()[0].querySelectorAll('figure')[1]
);
await host.snapshot('local');
});
</script>
</body>
</html>
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.
Binary file removed __tests__/html2/markdown/math3.html.snap-1.png
Binary file not shown.
Binary file removed __tests__/html2/markdown/math3.html.snap-2.png
Binary file not shown.
Binary file removed __tests__/html2/markdown/math3.html.snap-3.png
Binary file not shown.
Binary file removed __tests__/html2/markdown/math4.html.snap-3.png
Binary file not shown.
3 changes: 2 additions & 1 deletion packages/bundle/src/markdown/mathExtension/htmlRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export default function createHtmlRenderer(options: CreateHtmlRendererOptions =
type: 'block' | 'inline' | 'error' = defaults.type,
tag: 'figure' | 'span' | 'pre' | 'code' = defaults.tag
) => {
this.tag(`<${tag} data-math-type="${type}">`);
// Math could be scrollable, need to be tabbable.
this.tag(`<${tag} data-math-type="${type}" tabindex="0">`);
this.raw(content);
this.tag(`</${tag}>`);
};
Expand Down
16 changes: 13 additions & 3 deletions packages/component/src/Styles/StyleSet/RenderMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,28 @@ export default function createMarkdownStyle() {
content: "'['"
},

'& [data-math-type=block] math': {
'& [data-math-type=block]': {
alignItems: 'center',
display: 'flex',
flexDirection: 'column'
flexDirection: 'column',
marginBottom: '-4px',
paddingBottom: '4px',
outlineOffset: '2px',
overflowX: 'auto',
overflowY: 'clip',
scrollbarWidth: 'thin'
},

'& [data-math-type=inline] math': {
'& [data-math-type=inline]': {
alignItems: 'center',
display: 'inline-flex',
flexDirection: 'column'
},

'& :is([data-math-type=block], [data-math-type=inline]) > span': {
display: 'contents'
},

'& .webchat__render-markdown__code-block': {
whiteSpace: 'pre-wrap'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const DEFAULT_ALLOWED_TAGS: ReadonlyMap<string, Readonly<{ attributes: ReadonlyS
['del', []],
['div', []],
['em', []],
['figure', ['data-math-type']],
['figure', ['data-math-type', 'tabindex']],
['h1', []],
['h2', []],
['h3', []],
Expand Down
5 changes: 4 additions & 1 deletion packages/fluent-theme/src/components/theme/Theme.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@

/* Scrollbars */
:global(.webchat-fluent).theme :global(.webchat__basic-transcript .webchat__basic-transcript__scrollable),
:global(.webchat-fluent).theme :global(.webchat__view-code-dialog__code-body) {
:global(.webchat-fluent).theme :global(.webchat__view-code-dialog__code-body),
:global(.webchat-fluent).theme :global(.webchat__render-markdown [data-math-type='block']) {
/* Edge uses -webkit-scrollbar if scrollbar-* is not set */
scrollbar-color: unset;
scrollbar-width: unset;
Expand All @@ -233,6 +234,7 @@
-moz-scrollbar-width: thin;

&::-webkit-scrollbar {
height: var(--webchat-spacingVerticalMNudge);
width: var(--webchat-spacingVerticalMNudge);
visibility: hidden;
}
Expand All @@ -242,6 +244,7 @@
}

&:hover::-webkit-scrollbar {
height: var(--webchat-spacingVerticalMNudge);
width: var(--webchat-spacingVerticalMNudge);
}

Expand Down

0 comments on commit e88f4b6

Please sign in to comment.