Skip to content

Commit 85f8288

Browse files
committed
Productionalize
1 parent 2ce7d88 commit 85f8288

File tree

7 files changed

+164
-111
lines changed

7 files changed

+164
-111
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ Breaking changes in this release:
400400
- Fixed virtual keyboard should show up on tap after being suppressed, in iOS 26.2, by [@compulim](https://github.com/compulim) in PR [#5678](https://github.com/microsoft/BotFramework-WebChat/pull/5678)
401401
- Fixed compatibility with `create-react-app` by adding file extension to `core-js` imports, by [@compulim](https://github.com/compulim) in PR [#5680](https://github.com/microsoft/BotFramework-WebChat/pull/5680)
402402
- Fixed virtual keyboard should be collapsed after being suppressed, in iOS 26.3, by [@compulim](https://github.com/compulim) in PR [#5757](https://github.com/microsoft/BotFramework-WebChat/pull/5757)
403+
- Fixed Fluent/Copilot typing indicator animation background color, in PR [#5770](https://github.com/microsoft/BotFramework-WebChat/pull/5770), by [@OEvgeny](https://github.com/OEvgeny)
403404

404405
## [4.18.0] - 2024-07-10
405406

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<script>
5+
location = './typingIndicator.scroll?theme=fluent&fluentTheme=dark';
6+
</script>
7+
</head>
8+
<body></body>
9+
</html>
44.5 KB
Loading
45.1 KB
Loading
Lines changed: 152 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,127 +1,170 @@
11
<!doctype html>
22
<html lang="en-US">
3-
<head>
4-
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5-
<script crossorigin="anonymous" src="https://unpkg.com/react@16.8.6/umd/react.production.min.js"></script>
6-
<script crossorigin="anonymous" src="https://unpkg.com/react-dom@16.8.6/umd/react-dom.production.min.js"></script>
7-
<script crossorigin="anonymous" src="/test-harness.js"></script>
8-
<script crossorigin="anonymous" src="/test-page-object.js"></script>
9-
<script crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
10-
<script crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
11-
<style>
12-
#webchat .webchat__typing-indicator {
13-
background-image: url(data:image/gif;base64,R0lGODlhQAAYAPUAAOzv8evu8Ort7+fq7Ons7ujr7eXo6uTn6ebp6+Xn6ezu8OPm6N/i49/i5OHk5uDj5d/h49PV17/BwsLExdja3MvNz72/wL7Awc/S08TGyMDCw9TW2NbZ2tvd39nc3d3f4ens7bO0tbS2t7GztLW3uK6vsMnLzamqq7m7vK2ur6yurp2en6KjpJeXmI2NjpGSkpOUlJiYmZqbmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQABwD/ACwAAAAAQAAYAAAG8ECAcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvtegOGgTAwLBQPRQNAMAw0HGRAPA4gVAMUjWW/KA89IiqCHkJqbHImMS4uKxFjcnVFdgpOeHuXEghCZgAeKYKgHURsiYumHI9DdlQSmHsYkEIooKAoRQErpqYndKpVrXvAFn60tL0QL7qLMWKxQqtSwhbARSXFgkUPycoyIKmRrJfBG36zxRKjACzKLiG94ELNTwwXroecByPFfQCGABAwdHX79owKmQoTMkRYxWlIhkAZEhQSIoDMhxItZJDgR4YMNADNKHkZSbKkyZMoU6pcybKly5dBAAA7); background-color: black;
14-
}
15-
</style>
16-
</head>
17-
<body>
18-
<main id="webchat"></main>
19-
<script type="importmap">
3+
4+
<head>
5+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
6+
<script type="importmap">
207
{
218
"imports": {
9+
"@fluentui/react-provider": "/__dist__/packages/test/test-assets/out/@fluentui/react-provider.js",
10+
"@fluentui/tokens": "/__dist__/packages/test/test-assets/out/@fluentui/tokens.js",
2211
"@testduet/wait-for": "https://unpkg.com/@testduet/wait-for@main/dist/wait-for.mjs",
23-
"jest-mock": "https://esm.sh/jest-mock",
24-
"react-dictate-button/internal": "https://unpkg.com/react-dictate-button@main/dist/react-dictate-button.internal.mjs"
12+
"react": "https://esm.sh/react@18",
13+
"react-dom": "https://esm.sh/react-dom@18",
14+
"react-dom/": "https://esm.sh/react-dom@18/",
15+
"react-jsx-runtime": "https://esm.sh/react@18/jsx-runtime"
2516
}
2617
}
2718
</script>
28-
<script type="module">
29-
import { waitFor } from '@testduet/wait-for';
19+
<script crossorigin="anonymous" src="/test-harness.js"></script>
20+
<script crossorigin="anonymous" src="/test-page-object.js"></script>
21+
<script type="module">
22+
import React from 'react';
23+
window.React = React;
24+
</script>
25+
<script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
26+
<script defer crossorigin="anonymous" src="/__dist__/botframework-webchat-fluent-theme.production.min.js"></script>
27+
<style>
28+
main {
29+
display: flex;
30+
}
31+
32+
#webchat .webchat__typing-indicator {
33+
background-image: url(data:image/gif;base64,R0lGODlhQAAYAPUAAOzv8evu8Ort7+fq7Ons7ujr7eXo6uTn6ebp6+Xn6ezu8OPm6N/i49/i5OHk5uDj5d/h49PV17/BwsLExdja3MvNz72/wL7Awc/S08TGyMDCw9TW2NbZ2tvd39nc3d3f4ens7bO0tbS2t7GztLW3uK6vsMnLzamqq7m7vK2ur6yurp2en6KjpJeXmI2NjpGSkpOUlJiYmZqbmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQABwD/ACwAAAAAQAAYAAAG8ECAcEgsGo/IpHLJbDqf0Kh0Sq1ar9isdsvtegOGgTAwLBQPRQNAMAw0HGRAPA4gVAMUjWW/KA89IiqCHkJqbHImMS4uKxFjcnVFdgpOeHuXEghCZgAeKYKgHURsiYumHI9DdlQSmHsYkEIooKAoRQErpqYndKpVrXvAFn60tL0QL7qLMWKxQqtSwhbARSXFgkUPycoyIKmRrJfBG36zxRKjACzKLiG94ELNTwwXroecByPFfQCGABAwdHX79owKmQoTMkRYxWlIhkAZEhQSIoDMhxItZJDgR4YMNADNKHkZSbKkyZMoU6pcybKly5dBAAA7);
34+
background-color: black;
35+
}
36+
</style>
37+
</head>
38+
39+
<body>
40+
<main id="webchat"></main>
41+
<script type="module">
42+
import { FluentProvider } from '@fluentui/react-provider';
43+
import { webDarkTheme, webLightTheme } from '@fluentui/tokens';
44+
import { waitFor } from '@testduet/wait-for';
45+
import React from 'react';
46+
import { createRoot } from 'react-dom/client';
47+
48+
const { searchParams } = new URL(location);
49+
const fluentTheme = searchParams.get('fluentTheme');
50+
const isFluentTheme = searchParams.get('theme') === 'fluent';
51+
const isLivestream = searchParams.has('livestream');
52+
const variant = searchParams.get('variant');
53+
54+
run(async function () {
55+
await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
56+
features: [
57+
{ name: 'prefers-reduced-motion', value: 'reduce' },
58+
...(fluentTheme === 'dark' || fluentTheme === 'light'
59+
? [{ name: 'prefers-color-scheme', value: fluentTheme }]
60+
: [])
61+
]
62+
});
3063

31-
const isLivestream = new URL(location).searchParams.has('livestream');
64+
const { directLine, store } = testHelpers.createDirectLineEmulator();
3265

33-
run(async function () {
66+
if (isFluentTheme) {
3467
const {
35-
React: { createElement },
36-
ReactDOM: { render },
3768
WebChat: { FluentThemeProvider, ReactWebChat }
38-
} = window; // Imports in UMD fashion.
69+
} = window;
70+
71+
const theme =
72+
fluentTheme === 'dark' || window.matchMedia('(prefers-color-scheme: dark)').matches
73+
? webDarkTheme
74+
: webLightTheme;
75+
76+
const root = createRoot(document.getElementById('webchat'));
77+
78+
root.render(
79+
React.createElement(
80+
FluentProvider,
81+
{ theme },
82+
React.createElement(
83+
FluentThemeProvider,
84+
variant ? { variant } : {},
85+
React.createElement(ReactWebChat, { directLine, store })
86+
)
87+
)
88+
);
89+
} else {
90+
renderWebChat({ directLine, store }, document.getElementById('webchat'));
91+
}
3992

40-
await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
41-
features: [{ name: 'prefers-reduced-motion', value: 'reduce' }]
42-
});
93+
await pageConditions.uiConnected();
4394

44-
const { directLine, store } = testHelpers.createDirectLineEmulator();
95+
// WHEN: Receive a bot message.
96+
await directLine.emulateIncomingActivity({
97+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
98+
id: 'a-00001',
99+
text: 'In minim amet culpa adipisicing aliqua culpa minim culpa officia culpa laboris non commodo. Velit nisi ut sit amet in sunt eu voluptate Lorem eu do sint proident aute. Nulla nisi commodo consectetur anim id non ut est anim veniam occaecat excepteur dolor nulla. Adipisicing et dolor ex cillum sit ipsum amet labore officia dolor non ad aliquip officia. Irure quis occaecat cupidatat ut commodo culpa eiusmod ipsum pariatur. Excepteur aliqua consectetur anim laborum enim ipsum tempor occaecat voluptate.',
100+
type: 'message'
101+
});
45102

46-
renderWebChat(
47-
{ directLine, store },
48-
document.getElementById('webchat')
49-
);
103+
await directLine.emulateIncomingActivity({
104+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
105+
id: 'a-00002',
106+
text: 'Ad minim fugiat sint et laboris consectetur eu ut in nisi fugiat cillum est labore. Et proident tempor veniam ex est incididunt Lorem. Culpa sit id eu voluptate.',
107+
type: 'message'
108+
});
50109

51-
await pageConditions.uiConnected();
52-
53-
// WHEN: Receive a bot message.
54-
await directLine.emulateIncomingActivity({
55-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
56-
id: 'a-00001',
57-
text: 'In minim amet culpa adipisicing aliqua culpa minim culpa officia culpa laboris non commodo. Velit nisi ut sit amet in sunt eu voluptate Lorem eu do sint proident aute. Nulla nisi commodo consectetur anim id non ut est anim veniam occaecat excepteur dolor nulla. Adipisicing et dolor ex cillum sit ipsum amet labore officia dolor non ad aliquip officia. Irure quis occaecat cupidatat ut commodo culpa eiusmod ipsum pariatur. Excepteur aliqua consectetur anim laborum enim ipsum tempor occaecat voluptate.',
58-
type: 'message'
59-
});
60-
61-
await directLine.emulateIncomingActivity({
62-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
63-
id: 'a-00002',
64-
text: 'Ad minim fugiat sint et laboris consectetur eu ut in nisi fugiat cillum est labore. Et proident tempor veniam ex est incididunt Lorem. Culpa sit id eu voluptate.',
65-
type: 'message'
66-
});
67-
68-
await directLine.emulateIncomingActivity({
69-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
70-
id: 'a-00003',
71-
text: 'Est voluptate eiusmod ad Lorem irure amet sint ea aliqua labore eu do nostrud exercitation. Non adipisicing non amet laborum. Anim fugiat minim cupidatat consequat ipsum minim ex mollit commodo ut aliqua quis consequat dolore. Cupidatat tempor laborum consectetur eiusmod cillum do consequat ad pariatur amet magna aliquip occaecat officia.',
72-
type: 'message'
73-
});
74-
75-
// WHEN: Bot send either a contentless livestream or typing activity.
76-
await directLine.emulateIncomingActivity({
77-
...(isLivestream
78-
? {
79-
channelData: {
80-
streamSequence: 1,
81-
streamType: 'streaming'
82-
}
83-
}
84-
: {}),
85-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
86-
id: 'a-00004',
87-
type: 'typing'
88-
});
89-
90-
// THEN: Should show typing indicator.
91-
await waitFor(() => expect(pageElements.typingIndicator()).toBeTruthy());
92-
93-
// THEN: Should match snapshot.
94-
await host.snapshot('local');
95-
96-
// ---
97-
98-
// WHEN: Bot send either a contentless livestream or typing activity.
99-
await directLine.emulateIncomingActivity({
100-
...(isLivestream
101-
? {
102-
channelData: {
103-
streamId: 'a-00004',
104-
streamType: 'final'
105-
}
110+
await directLine.emulateIncomingActivity({
111+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
112+
id: 'a-00003',
113+
text: 'Est voluptate eiusmod ad Lorem irure amet sint ea aliqua labore eu do nostrud exercitation. Non adipisicing non amet laborum. Anim fugiat minim cupidatat consequat ipsum minim ex mollit commodo ut aliqua quis consequat dolore. Cupidatat tempor laborum consectetur eiusmod cillum do consequat ad pariatur amet magna aliquip occaecat officia.',
114+
type: 'message'
115+
});
116+
117+
// WHEN: Bot send either a contentless livestream or typing activity.
118+
await directLine.emulateIncomingActivity({
119+
...(isLivestream
120+
? {
121+
channelData: {
122+
streamSequence: 1,
123+
streamType: 'streaming'
124+
}
125+
}
126+
: {}),
127+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
128+
id: 'a-00004',
129+
type: 'typing'
130+
});
131+
132+
// THEN: Should show typing indicator.
133+
await waitFor(() => expect(pageElements.typingIndicator()).toBeTruthy());
134+
135+
// THEN: Should match snapshot.
136+
await host.snapshot('local');
137+
138+
// ---
139+
140+
// WHEN: Bot send either a contentless livestream or typing activity.
141+
await directLine.emulateIncomingActivity({
142+
...(isLivestream
143+
? {
144+
channelData: {
145+
streamId: 'a-00004',
146+
streamType: 'final'
147+
}
148+
}
149+
: {
150+
channelData: {
151+
webChat: {
152+
styleOptions: { typingAnimationDuration: 0 }
106153
}
107-
: {
108-
channelData: {
109-
webChat: {
110-
styleOptions: { typingAnimationDuration: 0 }
111-
}
112-
}
113-
}),
114-
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
115-
id: 'a-00005',
116-
type: 'typing'
117-
});
118-
119-
// THEN: Should hide typing indicator.
120-
await waitFor(() => expect(pageElements.typingIndicator()).toBeFalsy());
121-
122-
// THEN: Should match snapshot.
123-
await host.snapshot('local');
154+
}
155+
}),
156+
from: { id: 'u-00001', name: 'Bot', role: 'bot' },
157+
id: 'a-00005',
158+
type: 'typing'
124159
});
125-
</script>
126-
</body>
127-
</html>
160+
161+
// THEN: Should hide typing indicator.
162+
await waitFor(() => expect(pageElements.typingIndicator()).toBeFalsy());
163+
164+
// THEN: Should match snapshot.
165+
await host.snapshot('local');
166+
});
167+
</script>
168+
</body>
169+
170+
</html>

packages/fluent-theme/src/components/assets/SlidingDots.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const SlidingDots = ({ className }: SlidingDotsProps) => {
1414

1515
const altText = localize('TYPING_INDICATOR_ALT');
1616

17-
return <img aria-label={altText} className={className} src={url.href} />;
17+
return <img alt={altText} className={className} src={url.href} />;
1818
};
1919

2020
SlidingDots.displayName = 'SlidingDots';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { createDarkTheme, webLightTheme } from '@fluentui/tokens';
1+
export { createDarkTheme, webDarkTheme, webLightTheme } from '@fluentui/tokens';

0 commit comments

Comments
 (0)