botframework-webchat-fluent-theme 4.17.1 → 4.18.1-hotfix.20260127.b53acdf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/botframework-webchat-fluent-theme.css.map +1 -1
  2. package/dist/botframework-webchat-fluent-theme.d.mts +23 -5
  3. package/dist/botframework-webchat-fluent-theme.d.ts +23 -5
  4. package/dist/botframework-webchat-fluent-theme.development.css.map +1 -1
  5. package/dist/botframework-webchat-fluent-theme.development.js +11 -1
  6. package/dist/botframework-webchat-fluent-theme.development.js.map +1 -1
  7. package/dist/botframework-webchat-fluent-theme.js +1 -1
  8. package/dist/botframework-webchat-fluent-theme.js.map +1 -1
  9. package/dist/botframework-webchat-fluent-theme.mjs +1 -1
  10. package/dist/botframework-webchat-fluent-theme.mjs.map +1 -1
  11. package/dist/botframework-webchat-fluent-theme.production.min.css.map +1 -1
  12. package/dist/botframework-webchat-fluent-theme.production.min.js +11 -1
  13. package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
  14. package/package.json +27 -26
  15. package/src/bundle.ts +2 -0
  16. package/src/components/activity/ActivityDecorator.module.css +432 -0
  17. package/src/components/activity/ActivityDecorator.tsx +26 -0
  18. package/src/components/activity/ActivityLoader.module.css +10 -0
  19. package/src/components/activity/ActivityLoader.tsx +21 -0
  20. package/src/components/activity/CopilotMessageHeader.module.css +38 -0
  21. package/src/components/activity/CopilotMessageHeader.tsx +49 -0
  22. package/src/components/activity/index.ts +2 -0
  23. package/src/components/activity/private/isAIGeneratedActivity.ts +5 -0
  24. package/src/components/activity/private/useActivityAuthor.ts +16 -0
  25. package/src/components/activity/private/useActivityStyleOptions.ts +19 -0
  26. package/src/components/assets/AssetComposer.tsx +37 -0
  27. package/src/components/assets/AssetName.ts +1 -0
  28. package/src/components/assets/SlidingDots.tsx +61 -0
  29. package/src/components/assets/private/Context.ts +24 -0
  30. package/src/components/assets/private/useAssetURL.ts +12 -0
  31. package/src/components/assets/private/useContext.ts +8 -0
  32. package/src/components/dropZone/DropZone.module.css +3 -4
  33. package/src/components/dropZone/DropZone.tsx +41 -6
  34. package/src/components/linerActivity/index.ts +2 -0
  35. package/src/components/linerActivity/private/LinerActivity.tsx +20 -0
  36. package/src/components/linerActivity/private/LinerMessageActivity.module.css +28 -0
  37. package/src/components/linerActivity/private/isLinerMessageActivity.ts +7 -0
  38. package/src/components/preChatActivity/PreChatMessageActivity.module.css +56 -0
  39. package/src/components/preChatActivity/PreChatMessageActivity.tsx +60 -0
  40. package/src/components/preChatActivity/StarterPromptsCardAction.module.css +126 -0
  41. package/src/components/preChatActivity/StarterPromptsCardAction.tsx +75 -0
  42. package/src/components/preChatActivity/StarterPromptsToolbar.module.css +18 -0
  43. package/src/components/preChatActivity/StarterPromptsToolbar.tsx +47 -0
  44. package/src/components/preChatActivity/index.tsx +2 -0
  45. package/src/components/preChatActivity/isPreChatMessageActivity.ts +7 -0
  46. package/src/components/sendBox/Attachments.module.css +1 -1
  47. package/src/components/sendBox/Attachments.tsx +5 -4
  48. package/src/components/sendBox/ErrorMessage.tsx +15 -4
  49. package/src/components/sendBox/SendBox.module.css +21 -6
  50. package/src/components/sendBox/SendBox.tsx +95 -56
  51. package/src/components/sendBox/TextArea.module.css +27 -8
  52. package/src/components/sendBox/TextArea.tsx +60 -31
  53. package/src/components/sendBox/Toolbar.module.css +15 -7
  54. package/src/components/sendBox/Toolbar.tsx +17 -7
  55. package/src/components/sendBox/index.tsx +1 -1
  56. package/src/components/sendBox/private/useSubmitError.ts +17 -4
  57. package/src/components/sendBox/private/useTranscriptNavigation.ts +53 -0
  58. package/src/components/suggestedActions/AccessibleButton.tsx +15 -13
  59. package/src/components/suggestedActions/SuggestedAction.module.css +14 -13
  60. package/src/components/suggestedActions/SuggestedAction.tsx +7 -4
  61. package/src/components/suggestedActions/SuggestedActions.module.css +2 -3
  62. package/src/components/suggestedActions/SuggestedActions.tsx +49 -46
  63. package/src/components/telephoneKeypad/private/Button.module.css +2 -3
  64. package/src/components/telephoneKeypad/private/Button.tsx +1 -5
  65. package/src/components/telephoneKeypad/private/TelephoneKeypad.module.css +0 -1
  66. package/src/components/telephoneKeypad/private/TelephoneKeypad.tsx +4 -8
  67. package/src/components/telephoneKeypad/types.ts +1 -1
  68. package/src/components/theme/Theme.module.css +665 -15
  69. package/src/components/theme/Theme.tsx +4 -3
  70. package/src/components/typingIndicator/SlidingDotsTypingIndicator.module.css +12 -0
  71. package/src/components/typingIndicator/SlidingDotsTypingIndicator.tsx +19 -0
  72. package/src/env.d.ts +1 -7
  73. package/src/external.umd/botframework-webchat-api/decorator.ts +1 -0
  74. package/src/external.umd/botframework-webchat-component/decorator.ts +1 -0
  75. package/src/external.umd/botframework-webchat-component/index.ts +5 -0
  76. package/src/external.umd/botframework-webchat-component/internal.ts +1 -0
  77. package/src/icons/AddDocumentIcon.tsx +8 -16
  78. package/src/icons/AttachmentIcon.tsx +8 -16
  79. package/src/icons/InfoSmallIcon.tsx +7 -15
  80. package/src/icons/SendIcon.tsx +7 -15
  81. package/src/icons/TelephoneKeypadIcon.tsx +7 -15
  82. package/src/index.ts +2 -4
  83. package/src/private/FluentThemeProvider.tsx +91 -10
  84. package/src/private/VariantComposer.ts +29 -0
  85. package/src/private/createComposer.tsx +16 -0
  86. package/src/private/useVariants.ts +7 -0
  87. package/src/styles/createStyles.ts +5 -0
  88. package/src/styles/index.ts +3 -2
  89. package/src/styles/useStyles.ts +2 -19
  90. package/src/styles/useVariantClassName.ts +16 -0
  91. package/src/testIds.ts +3 -0
  92. package/src/tsconfig.json +12 -10
  93. package/src/types/PropsOf.ts +2 -5
  94. package/src/external.umd/botframework-webchat-component.ts +0 -4
  95. package/src/styles/injectStyle.ts +0 -9
  96. /package/src/external.umd/{botframework-webchat-api.ts → botframework-webchat-api/index.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "botframework-webchat-fluent-theme",
3
- "version": "4.17.1",
3
+ "version": "4.18.1-hotfix.20260127.b53acdf",
4
4
  "description": "Fluent theme for Bot Framework Web Chat",
5
5
  "main": "./dist/botframework-webchat-fluent-theme.js",
6
6
  "types": "./dist/botframework-webchat-fluent-theme.d.ts",
@@ -38,22 +38,25 @@
38
38
  "src/**/*"
39
39
  ],
40
40
  "scripts": {
41
- "auditfix": "npm audit fix --legacy-peer-deps || exit 0",
42
41
  "build": "tsup",
43
- "bump": "npm run bump:prod && npm run bump:dev && npm run bump:auditfix",
44
- "bump:auditfix": "npm audit fix --legacy-peer-deps || exit 0",
45
- "bump:dev": "if [ `cat package.json | jq -r '.devDependencies | length'` -ne 0 ]; then npm install --legacy-peer-deps $(cat package.json | jq -r '(.pinDependencies // {}) as $p | ((.devDependencies // {}) | keys) | map(. + \"@\" + ($p[.] // [\"latest\"])[0]) | .[]'); fi",
46
- "bump:prod": "if [ `cat package.json | jq -r '.dependencies | length'` -ne 0 ]; then npm install --legacy-peer-deps --save-exact $(cat package.json | jq -r '(.pinDependencies // {}) as $p | ((.dependencies // {}) | keys) | map(. + \"@\" + ($p[.] // [\"latest\"])[0]) | .[]'); fi",
42
+ "bump": "npm run bump:prod && npm run bump:dev && (npm audit fix || exit 0)",
43
+ "bump:dev": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.devDependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install $PACKAGES_TO_BUMP || true",
44
+ "bump:prod": "PACKAGES_TO_BUMP=$(cat package.json | jq -r '(.pinDependencies // {}) as $P | (.localDependencies // {} | keys) as $L | (.dependencies // {}) | to_entries | map(select(.key as $K | $L | contains([$K]) | not)) | map(.key + \"@\" + ($P[.key] // [\"latest\"])[0]) | join(\" \")') && [ ! -z \"$PACKAGES_TO_BUMP\" ] && npm install --save-exact $PACKAGES_TO_BUMP || true",
47
45
  "eslint": "npm run precommit",
48
- "postauditfix": "npm run postbump",
49
- "postbump": "cat package.json | jq '. + (.dependencies = ((.dependencies + (.localPeerDependencies // {})) | to_entries | sort_by(.key) | from_entries)) | (.devDependencies = ((.devDependencies + (.localPeerDevDependencies // {})) | to_entries | sort_by(.key) | from_entries))' > package-temp.json && mv package-temp.json package.json",
50
- "preauditfix": "npm run prebump",
51
- "prebump": "cat package.json | jq '(((.localPeerDependencies // {}) | keys | map([\"dependencies\", .])) + ((.localPeerDevDependencies // {}) | keys | map([\"devDependencies\", .]))) as $localPeerPaths | delpaths($localPeerPaths)' > package-temp.json && mv package-temp.json package.json",
46
+ "postversion": "cat package.json | jq '.version as $V | (.localDependencies // {} | with_entries(select(.value == \"production\") | { key: .key, value: $V })) as $L1 | (.localDependencies // {} | with_entries(select(.value == \"development\") | { key: .key, value: $V })) as $L2 | ((.dependencies // {}) + $L1 | to_entries | sort_by(.key) | from_entries) as $D1 | ((.devDependencies // {}) + $L2 | to_entries | sort_by(.key) | from_entries) as $D2 | . + { dependencies: $D1, devDependencies: $D2 }' > package-temp.json && mv package-temp.json package.json",
52
47
  "precommit": "npm run precommit:eslint -- src && npm run precommit:typecheck",
53
48
  "precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
54
49
  "precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
50
+ "preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
55
51
  "start": "npm run build -- --watch"
56
52
  },
53
+ "localDependencies": {
54
+ "botframework-webchat-api": "production",
55
+ "botframework-webchat-base": "development",
56
+ "botframework-webchat-component": "production",
57
+ "botframework-webchat-core": "production",
58
+ "botframework-webchat-styles": "development"
59
+ },
57
60
  "pinDependencies": {
58
61
  "@types/react": [
59
62
  "16",
@@ -63,26 +66,24 @@
63
66
  "devDependencies": {
64
67
  "@tsconfig/strictest": "^2.0.5",
65
68
  "@types/math-random": "^1.0.2",
66
- "@types/node": "^20.10.3",
67
- "@types/react": "^16.14.60",
68
- "tsup": "^8.0.2",
69
- "typescript": "^5.3.2"
69
+ "@types/node": "^22.13.4",
70
+ "@types/react": "^16.14.62",
71
+ "botframework-webchat-base": "4.18.1-hotfix.20260127.b53acdf",
72
+ "botframework-webchat-styles": "4.18.1-hotfix.20260127.b53acdf",
73
+ "tsup": "^8.3.6",
74
+ "typescript": "^5.7.3"
70
75
  },
71
76
  "dependencies": {
72
- "botframework-webchat-api": "4.17.1",
73
- "botframework-webchat-component": "4.17.1",
74
- "botframework-webchat-core": "4.17.1",
75
- "classnames": "^2.5.1",
76
- "inject-meta-tag": "^0.0.1",
77
- "math-random": "^2.0.1",
78
- "use-ref-from": "^0.1.0"
77
+ "botframework-webchat-api": "4.18.1-hotfix.20260127.b53acdf",
78
+ "botframework-webchat-component": "4.18.1-hotfix.20260127.b53acdf",
79
+ "botframework-webchat-core": "4.18.1-hotfix.20260127.b53acdf",
80
+ "classnames": "2.5.1",
81
+ "inject-meta-tag": "0.0.1",
82
+ "math-random": "2.0.1",
83
+ "use-ref-from": "0.1.0",
84
+ "valibot": "1.1.0"
79
85
  },
80
86
  "peerDependencies": {
81
87
  "react": ">= 16.8.6"
82
- },
83
- "localPeerDependencies": {
84
- "botframework-webchat-api": "0.0.0-0",
85
- "botframework-webchat-component": "0.0.0-0",
86
- "botframework-webchat-core": "0.0.0-0"
87
88
  }
88
89
  }
package/src/bundle.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import { SendBox as FluentSendBox } from './components/sendBox/index';
1
2
  import { FluentThemeProvider, testIds } from './index';
2
3
 
3
4
  (globalThis as any).WebChat = {
4
5
  ...(globalThis as any).WebChat,
5
6
  FluentThemeProvider,
7
+ FluentSendBox,
6
8
  testIds: {
7
9
  ...(globalThis as any).WebChat?.testIds,
8
10
  ...testIds
@@ -0,0 +1,432 @@
1
+ :global(.webchat-fluent) .activity-decorator {
2
+ display: contents;
3
+ font-family: var(--webchat__font--primary);
4
+
5
+ --webchat__bubble--inline-padding: var(--webchat-spacingHorizontalL);
6
+ --webchat__bubble--block-padding: var(--webchat-spacingVerticalM);
7
+ --webchat__bubble--min-height: var(--webchat-bubble-minHeight);
8
+ --webchat__bubble--max-width: var(--webchat-bubble-maxWidth);
9
+ --webchat__bubble--min-width: var(--webchat-bubble-minWidth);
10
+
11
+ --webchat-bubble-maxWidth: var(--bubble-maxWidth, max(450px, 75%));
12
+ --webchat-bubble-minWidth: var(--bubble-minWidth, auto);
13
+ --webchat-bubble-minHeight: var(--bubble-minHeight, 36px);
14
+ --webchat-externalLink-mask: var(
15
+ --externalLink-mask,
16
+ var(--webchat__icon-url--external-link) center center /
17
+ 10px 10px
18
+ );
19
+ --webchat-externalLink-maxWidth: var(--externalLink-maxWidth, 204px);
20
+
21
+ /* Override for stacked layout message which has user message bubble props */
22
+ &:has(:global(.webchat__stacked-layout .webchat__bubble--from-user)) {
23
+ --webchat__bubble--background-color: var(--webchat-colorBrandBackground2);
24
+ --webchat__bubble--block-padding: var(--webchat-spacingVerticalS);
25
+ --webchat__bubble--min-width: auto;
26
+ }
27
+ }
28
+
29
+ /* Decorator fluent variant */
30
+ :global(.webchat-fluent) .activity-decorator.variant-fluent {
31
+ --webchat__bubble--background-color: var(--webchat-colorNeutralBackground1);
32
+ --webchat__bubble--border-radius: var(--webchat-borderRadiusXLarge);
33
+ --webchat__bubble--box-shadow: var(--webchat-shadow4);
34
+ }
35
+
36
+ /* Decorator copilot variant */
37
+ :global(.webchat-fluent) .activity-decorator.variant-copilot {
38
+ --webchat__bubble--border-radius: var(--webchat-borderRadiusXLarge);
39
+
40
+ :global(.webchat__activity-status) {
41
+ margin: 0 0 var(--webchat-spacingHorizontalXXS);
42
+ }
43
+
44
+ :global(.webchat__stacked-layout__status) {
45
+ order: -1;
46
+ }
47
+
48
+ &:has(:global(.webchat__bubble--from-user)) :global(.webchat__bubble) {
49
+ margin-block-end: var(--webchat-spacingVerticalM);
50
+ }
51
+
52
+ /* Hide generated badge as it is in the copilot header */
53
+ :global(.webchat__bubble .webchat__text-content .webchat__text-content__generated-badge) {
54
+ display: none;
55
+ }
56
+ }
57
+
58
+ /* Decorator copilot variant which has bot message */
59
+ :global(.webchat-fluent) .activity-decorator.variant-copilot:not(:has(:global(.webchat__bubble--from-user))) {
60
+ --webchat__bubble--block-padding: 0;
61
+ --webchat__bubble--border-radius: var(--webchat-borderRadiusMedium);
62
+ --webchat__bubble--inline-padding: 0;
63
+ --webchat__bubble--max-width: 100%;
64
+ --webchat__bubble--min-height: 20px;
65
+
66
+ display: flex;
67
+ flex-flow: column nowrap;
68
+ gap: var(--webchat-spacingVerticalS);
69
+ margin-inline: var(--webchat-spacingHorizontalM);
70
+ padding: var(--webchat-spacingVerticalMNudge) var(--webchat-spacingHorizontalM) var(--webchat-spacingVerticalM);
71
+ position: relative;
72
+
73
+ :global(.webchat__stacked-layout) {
74
+ margin: 0;
75
+ position: static;
76
+ }
77
+
78
+ :global(.webchat__bubble) {
79
+ position: static;
80
+ width: var(--webchat__bubble--max-width);
81
+ }
82
+
83
+ :global(.webchat__bubble .webchat__bubble__content) {
84
+ overflow: visible;
85
+ }
86
+
87
+ :global(.webchat__text-content) {
88
+ margin-inline-start: 28px;
89
+ }
90
+
91
+ :global(.border-loader) {
92
+ display: flex;
93
+ flex-flow: column nowrap;
94
+ gap: var(--webchat-spacingVerticalS);
95
+ padding-inline-end: var(--webchat-spacingHorizontalM);
96
+ width: 500px;
97
+ }
98
+
99
+ :global(.border-loader__track) {
100
+ border-radius: inherit;
101
+ box-sizing: border-box;
102
+ clip-path: border-box;
103
+ margin-inline-start: 28px;
104
+ order: -1;
105
+ width: auto;
106
+ }
107
+
108
+ :global(.webchat__stacked-layout__status) {
109
+ display: none;
110
+ }
111
+ }
112
+
113
+ /* Transcript activity non-empty */
114
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__basic-transcript__activity-body:not(:empty)) {
115
+ padding-block-end: var(--webchat-spacingVerticalXL);
116
+ }
117
+
118
+ /* Stacked layout */
119
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__stacked-layout) {
120
+ display: flex;
121
+ flex-flow: column nowrap;
122
+ }
123
+
124
+ /* Stacked layout which has message bubble */
125
+ :global(.webchat-fluent)
126
+ .activity-decorator
127
+ :global(.webchat__stacked-layout .webchat__stacked-layout__content:has(.webchat__bubble)) {
128
+ max-width: 100%;
129
+ overflow: visible;
130
+ }
131
+
132
+ /* Message status */
133
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__stacked-layout .webchat__stacked-layout__status) {
134
+ font-size: var(--webchat__font-size--small);
135
+ line-height: var(--webchat__line-height--small);
136
+ }
137
+
138
+ /* Message bubble */
139
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__stacked-layout .webchat__bubble) {
140
+ max-width: min(var(--webchat__bubble--max-width), 100%);
141
+ min-width: var(--webchat__bubble--min-width);
142
+ overflow: visible;
143
+
144
+ /* Take all width available when has message bubble latency loader */
145
+ &:has(:global(.border-loader)) {
146
+ width: 100%;
147
+ }
148
+
149
+ /* Ensure activity loader doesn't have bubble and shadow */
150
+ &:has(:global(.activity-loader)) :global(.webchat__bubble__content) {
151
+ background: transparent;
152
+ box-shadow: none;
153
+ }
154
+ }
155
+
156
+ /* Message bubble content */
157
+ :global(.webchat-fluent)
158
+ .activity-decorator
159
+ :global(.webchat__stacked-layout .webchat__bubble .webchat__bubble__content) {
160
+ background-color: var(--webchat__bubble--background-color);
161
+ border-radius: var(--webchat__bubble--border-radius);
162
+ border-width: 0;
163
+ box-shadow: var(--webchat__bubble--box-shadow);
164
+ box-sizing: border-box;
165
+ color: var(--webchat-colorNeutralForeground1);
166
+ max-width: 100%;
167
+ min-height: var(--webchat__bubble--min-height);
168
+ }
169
+
170
+ /* Message bubble text content */
171
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__stacked-layout .webchat__bubble .webchat__text-content) {
172
+ font-size: var(--webchat__font-size--medium);
173
+ line-height: var(--webchat__line-height--medium);
174
+ min-height: auto;
175
+ padding-block: var(--webchat__bubble--block-padding);
176
+ padding-inline: var(--webchat__bubble--inline-padding);
177
+
178
+ &:empty {
179
+ padding-block-end: 0;
180
+ }
181
+
182
+ + :global(.webchat__text-content) {
183
+ margin-top: calc(var(--webchat__bubble--block-padding) * -1);
184
+ }
185
+ }
186
+
187
+ /* Message bubble text content generated badge */
188
+ :global(.webchat-fluent)
189
+ .activity-decorator
190
+ :global(.webchat__stacked-layout .webchat__bubble .webchat__text-content__generated-badge) {
191
+ align-items: center;
192
+ align-self: flex-start;
193
+ background-color: var(--webchat-colorNeutralBackground5);
194
+ border-radius: var(--webchat-borderRadiusMedium);
195
+ box-sizing: border-box;
196
+ color: var(--webchat-colorNeutralForeground3);
197
+ cursor: default;
198
+ display: inline-flex;
199
+ font-size: var(--webchat-fontSizeBase100);
200
+ height: 16px;
201
+ line-height: var(--webchat-lineHeightBase100);
202
+ padding-inline: var(--webchat-spacingHorizontalXS);
203
+ }
204
+
205
+ /* Message bubble attachment content */
206
+ :global(.webchat-fluent)
207
+ .activity-decorator
208
+ :global(.webchat__stacked-layout .webchat__bubble .webchat__fileContent__badge) {
209
+ cursor: default;
210
+ font-size: var(--webchat-fontSizeBase300);
211
+ line-height: var(--webchat-lineHeightBase300);
212
+
213
+ :global(.webchat__fileContent__fileName) {
214
+ color: var(--webchat-colorBrandForegroundLink);
215
+ font-family: inherit;
216
+ }
217
+ :global(.webchat__fileContent__size) {
218
+ color: var(--webchat-colorNeutralForeground2);
219
+ font-family: inherit;
220
+ }
221
+ }
222
+
223
+ /* Markdown links and citation links */
224
+ :global(.webchat-fluent)
225
+ .activity-decorator
226
+ :global(.webchat__render-markdown)
227
+ a[href]:not(:global(.webchat__render-markdown__pure-identifier)) {
228
+ color: var(--webchat-colorBrandForegroundLink);
229
+ text-decoration-color: transparent;
230
+
231
+ &:target {
232
+ color: var(--webchat-colorBrandForegroundLinkSelected);
233
+ }
234
+
235
+ &:hover {
236
+ color: var(--webchat-colorBrandForegroundLinkHover);
237
+ text-decoration: underline 1px currentColor;
238
+ }
239
+
240
+ &:active {
241
+ color: var(--webchat-colorBrandForegroundLinkPressed);
242
+ }
243
+
244
+ &:focus-visible {
245
+ outline: none;
246
+ text-decoration: underline 1px double var(--webchat-colorStrokeFocus2);
247
+ }
248
+
249
+ :global(.webchat__render-markdown__external-link-icon) {
250
+ background: currentColor;
251
+ -webkit-mask: var(--webchat__icon-url--external-link) no-repeat;
252
+ mask: var(--webchat__icon-url--external-link) no-repeat;
253
+ }
254
+ }
255
+
256
+ /* Citation inline references */
257
+ :global(.webchat-fluent)
258
+ .activity-decorator
259
+ :global(.webchat__render-markdown)
260
+ :global(.webchat__render-markdown__citation),
261
+ :global(.webchat-fluent)
262
+ .activity-decorator
263
+ :global(.webchat__render-markdown)
264
+ :global(.webchat__render-markdown__pure-identifier) {
265
+ align-items: center;
266
+ background-color: var(--webchat-colorNeutralBackground3);
267
+ border-radius: var(--webchat-borderRadiusMedium);
268
+ border: var(--webchat-strokeWidthThin) solid var(--webchat-colorNeutralStroke2);
269
+ box-sizing: border-box;
270
+ color: var(--webchat-colorNeutralForeground2);
271
+ display: inline-flex;
272
+ font-size: var(--webchat-fontSizeBase100);
273
+ font-weight: var(--webchat-fontWeightSemibold);
274
+ height: 14px;
275
+ justify-content: center;
276
+ line-height: var(--webchat-lineHeightBase100);
277
+ margin-left: var(--webchat-spacingHorizontalXXS);
278
+ margin-right: var(--webchat-spacingHorizontalXXS);
279
+ min-width: 14px;
280
+ text-decoration: none;
281
+ transition: all var(--webchat-durationNormal) var(--webchat-curveDecelerateMid);
282
+ vertical-align: calc((var(--webchat-lineHeightBase100) - var(--webchat-fontSizeBase100)) / 2);
283
+
284
+ &:hover {
285
+ background-color: var(--webchat-colorBrandBackground2Hover);
286
+ border-color: var(--webchat-colorBrandStroke2Hover);
287
+ color: var(--webchat-colorBrandForeground2Hover);
288
+ cursor: pointer;
289
+ }
290
+
291
+ &:hover:active {
292
+ background-color: var(--webchat-colorBrandBackground2Pressed);
293
+ border-color: var(--webchat-colorBrandStroke2Pressed);
294
+ color: var(--webchat-colorBrandForeground2Pressed);
295
+ }
296
+
297
+ &::before,
298
+ &::after {
299
+ all: unset;
300
+ }
301
+
302
+ &:has(:global(.webchat__render-markdown__external-link-icon)) {
303
+ padding-inline: 3px;
304
+ }
305
+
306
+ :global(.webchat__render-markdown__external-link-icon) {
307
+ background: currentColor;
308
+ height: 0.7em;
309
+ -webkit-mask: var(--webchat__icon-url--external-link) no-repeat;
310
+ mask: var(--webchat__icon-url--external-link) no-repeat;
311
+ }
312
+ }
313
+
314
+ /* Citation summary chevron */
315
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__link-definitions__header) {
316
+ border-radius: var(--webchat-borderRadiusMedium);
317
+
318
+ :global(.webchat__link-definitions__header-text) {
319
+ color: var(--webchat-colorNeutralForeground3);
320
+ }
321
+
322
+ :global(.webchat__link-definitions__header-chevron) {
323
+ fill: var(--webchat-colorNeutralForeground3);
324
+ font-size: var(--webchat__font-size--small);
325
+ width: 1em;
326
+ }
327
+
328
+ &:focus-visible {
329
+ outline-offset: 1px;
330
+ outline: var(--webchat-strokeWidthThin) solid var(--webchat-colorStrokeFocus2);
331
+ }
332
+ }
333
+
334
+ /* Citation link definitions */
335
+ :global(.webchat-fluent) .activity-decorator :global(.webchat__link-definitions) {
336
+ --webchat__citation__external-link--mask: var(--webchat-externalLink-mask);
337
+ --webchat__citation__link--max-width: var(--webchat-externalLink-maxWidth);
338
+
339
+ :global(.webchat__link-definitions__list) {
340
+ color: var(--webchat__color--subtle);
341
+ display: flex;
342
+ flex-flow: row wrap;
343
+ gap: var(--webchat-spacingHorizontalS);
344
+ }
345
+
346
+ :global(.webchat__link-definitions__list-item) {
347
+ border-radius: var(--webchat-borderRadiusMedium);
348
+ max-width: var(--webchat__citation__link--max-width);
349
+ }
350
+
351
+ :global(.webchat__link-definitions__list-item-box) {
352
+ background-color: var(--webchat-colorNeutralBackground3);
353
+ border-radius: var(--webchat-borderRadiusMedium);
354
+ border: var(--webchat-strokeWidthThin) solid var(--webchat-colorNeutralStroke2);
355
+ box-sizing: border-box;
356
+ color: currentColor;
357
+ display: inline-flex;
358
+ font-size: var(--webchat__font-size--small);
359
+ height: 24px;
360
+ padding-inline-end: var(--webchat-spacingHorizontalS);
361
+ }
362
+
363
+ :global(.webchat__link-definitions__list-item-body) {
364
+ font-family: inherit;
365
+ gap: var(--webchat-spacingHorizontalSNudge);
366
+ min-width: 0;
367
+ padding: 0;
368
+ }
369
+
370
+ :global(.webchat__link-definitions__badge) {
371
+ align-self: center;
372
+ background-color: transparent;
373
+ border-radius: 0;
374
+ border: none;
375
+ color: currentColor;
376
+ font-size: var(--webchat-fontSizeBase100);
377
+ font-weight: var(--webchat-fontWeightSemibold);
378
+ line-height: var(--webchat-lineHeightBase100);
379
+ margin: 0;
380
+ min-width: 20px;
381
+ padding: 0;
382
+ position: relative;
383
+ text-align: center;
384
+ }
385
+
386
+ :global(.webchat__link-definitions__badge)::after {
387
+ border-right: var(--webchat-strokeWidthThin) solid var(--webchat-colorNeutralStroke2);
388
+ bottom: 0;
389
+ content: '';
390
+ display: block;
391
+ height: 16px;
392
+ position: absolute;
393
+ right: 0;
394
+ top: 0;
395
+ width: 0;
396
+ }
397
+
398
+ :global(.webchat__link-definitions__list-item-main-text) {
399
+ gap: var(--webchat-spacingHorizontalXS);
400
+ }
401
+
402
+ :global(.webchat__link-definitions__list-item-text) {
403
+ color: currentColor;
404
+ text-decoration: none;
405
+ text-overflow: ellipsis;
406
+ }
407
+
408
+ :global(.webchat__link-definitions__list-item-main-text):has(
409
+ :global(.webchat__link-definitions__open-in-new-window-icon)
410
+ )::before {
411
+ align-self: center;
412
+ background: currentColor;
413
+ color: currentColor;
414
+ content: '';
415
+ flex: none;
416
+ font-size: var(--webchat-fontSizeBase400);
417
+ height: 1em;
418
+ -webkit-mask: var(--webchat__citation__external-link--mask) no-repeat;
419
+ mask: var(--webchat__citation__external-link--mask) no-repeat;
420
+ padding: 0;
421
+ width: 1em;
422
+ }
423
+
424
+ /* It seems Copilot does not show per-item sensitivity label, i.e. "General", etc. */
425
+ :global(.webchat__link-definitions__list-item-badge) {
426
+ display: none;
427
+ }
428
+
429
+ :global(.webchat__link-definitions__open-in-new-window-icon) {
430
+ display: none;
431
+ }
432
+ }
@@ -0,0 +1,26 @@
1
+ import { WebChatActivity } from 'botframework-webchat-component';
2
+ import cx from 'classnames';
3
+ import React, { ReactNode, memo } from 'react';
4
+ import useVariants from '../../private/useVariants';
5
+ import { useStyles, useVariantClassName } from '../../styles';
6
+ import styles from './ActivityDecorator.module.css';
7
+ import CopilotMessageHeader from './CopilotMessageHeader';
8
+
9
+ function ActivityDecorator({ activity, children }: Readonly<{ activity: WebChatActivity; children: ReactNode }>) {
10
+ const classNames = useStyles(styles);
11
+ const variants = useVariants();
12
+ const variantClassName = useVariantClassName(styles);
13
+
14
+ const shouldRenderHeader = variants.includes('copilot') && activity?.from?.role === 'bot' && !!children;
15
+
16
+ return (
17
+ <div className={cx(classNames['activity-decorator'], variantClassName)}>
18
+ {shouldRenderHeader && <CopilotMessageHeader activity={activity} />}
19
+ {children}
20
+ </div>
21
+ );
22
+ }
23
+
24
+ ActivityDecorator.displayName = 'ActivityDecorator';
25
+
26
+ export default memo(ActivityDecorator);
@@ -0,0 +1,10 @@
1
+ :global(.webchat-fluent) .activity-loader {
2
+ flex: none;
3
+ height: 8px;
4
+ margin: var(--webchat-spacingHorizontalM) 0 0 18px;
5
+ width: auto;
6
+
7
+ &.variant-fluent {
8
+ margin: 0 0 var(--webchat-spacingHorizontalM) var(--webchat-spacingVerticalSNudge);
9
+ }
10
+ }
@@ -0,0 +1,21 @@
1
+ import { useStyles } from 'botframework-webchat-styles/react';
2
+ import cx from 'classnames';
3
+ import React, { Fragment, memo, type ReactNode } from 'react';
4
+
5
+ import { useVariantClassName } from '../../styles';
6
+ import SlidingDots from '../assets/SlidingDots';
7
+ import styles from './ActivityLoader.module.css';
8
+
9
+ function FluentActivityLoader({ children }: Readonly<{ children?: ReactNode | undefined }>) {
10
+ const classNames = useStyles(styles);
11
+ const variantClassName = useVariantClassName(classNames);
12
+
13
+ return (
14
+ <Fragment>
15
+ {children}
16
+ <SlidingDots className={cx(classNames['activity-loader'], variantClassName)} />
17
+ </Fragment>
18
+ );
19
+ }
20
+
21
+ export default memo(FluentActivityLoader);
@@ -0,0 +1,38 @@
1
+ :global(.webchat-fluent) .copilot-message-header {
2
+ align-items: center;
3
+ box-sizing: border-box;
4
+ cursor: default;
5
+ display: flex;
6
+ flex-wrap: nowrap;
7
+ gap: var(--webchat-spacingHorizontalS);
8
+ max-width: var(--webchat__bubble--max-width);
9
+ }
10
+
11
+ :global(.webchat-fluent) .copilot-message-header__avatar {
12
+ aspect-ratio: 1;
13
+ background-color: var(--background-color);
14
+ border-radius: var(--webchat-borderRadiusSmall);
15
+ width: 20px;
16
+ }
17
+
18
+ :global(.webchat-fluent) .copilot-message-header__title {
19
+ font-size: var(--webchat-fontSizeBase300);
20
+ font-weight: var(--webchat-fontWeightSemibold);
21
+ line-height: var(--webchat-lineHeightBase300);
22
+ overflow: hidden;
23
+ text-overflow: ellipsis;
24
+ text-wrap: nowrap;
25
+ }
26
+
27
+ :global(.webchat-fluent) .copilot-message-header__ai-generated-content {
28
+ align-items: center;
29
+ background-color: var(--webchat-colorNeutralBackground5);
30
+ border-radius: var(--webchat-borderRadiusMedium);
31
+ color: var(--webchat-colorNeutralForeground3);
32
+ display: flex;
33
+ flex: none;
34
+ font-size: var(--webchat-fontSizeBase100);
35
+ height: 20px;
36
+ line-height: var(--webchat-lineHeightBase100);
37
+ padding-inline: var(--webchat-spacingHorizontalXS);
38
+ }
@@ -0,0 +1,49 @@
1
+ import React, { memo, useMemo, type CSSProperties } from 'react';
2
+ import { WebChatActivity, hooks } from 'botframework-webchat-component';
3
+
4
+ import useActivityStyleOptions from './private/useActivityStyleOptions';
5
+ import isAIGeneratedActivity from './private/isAIGeneratedActivity';
6
+ import useActivityAuthor from './private/useActivityAuthor';
7
+ import { useStyles } from '../../styles';
8
+ import styles from './CopilotMessageHeader.module.css';
9
+
10
+ const { useLocalizer } = hooks;
11
+
12
+ function CopilotMessageHeader({ activity }: Readonly<{ activity?: WebChatActivity | undefined }>) {
13
+ const [{ botAvatarImage, botAvatarBackgroundColor }] = useActivityStyleOptions(activity);
14
+ const classNames = useStyles(styles);
15
+ const localize = useLocalizer();
16
+ const isAIGenerated = isAIGeneratedActivity(activity);
17
+
18
+ const avatarStyle = useMemo(
19
+ () => ({ '--background-color': botAvatarBackgroundColor }) as CSSProperties,
20
+ [botAvatarBackgroundColor]
21
+ );
22
+
23
+ const author = useActivityAuthor(activity);
24
+ const avatarImage = author?.image || botAvatarImage;
25
+ const botTitle = author?.name || activity?.from?.name;
26
+
27
+ return (
28
+ <div className={classNames['copilot-message-header']}>
29
+ {avatarImage && (
30
+ <img
31
+ alt={localize('AVATAR_ALT', botTitle)}
32
+ className={classNames['copilot-message-header__avatar']}
33
+ src={avatarImage}
34
+ style={avatarStyle}
35
+ />
36
+ )}
37
+ <span className={classNames['copilot-message-header__title']} title={botTitle}>
38
+ {botTitle}
39
+ </span>
40
+ {isAIGenerated && (
41
+ <span className={classNames['copilot-message-header__ai-generated-content']}>
42
+ {localize('ACTIVITY_CONTENT_CAUTION')}
43
+ </span>
44
+ )}
45
+ </div>
46
+ );
47
+ }
48
+
49
+ export default memo(CopilotMessageHeader);
@@ -0,0 +1,2 @@
1
+ export { default as ActivityDecorator } from './ActivityDecorator';
2
+ export { default as useActivityAuthor } from './private/useActivityAuthor';