botframework-webchat-fluent-theme 4.17.0-main.20240416.4ff01ae → 4.17.0-main.20240416.e3f5401
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.
- package/dist/botframework-webchat-fluent-theme.development.js +2065 -357
- package/dist/botframework-webchat-fluent-theme.development.js.map +1 -1
- package/dist/botframework-webchat-fluent-theme.production.min.js +3 -1
- package/dist/botframework-webchat-fluent-theme.production.min.js.map +1 -1
- package/dist/index.js +632 -333
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +516 -217
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
- package/src/components/Theme.tsx +65 -4
- package/src/components/dropZone/index.tsx +31 -6
- package/src/components/sendbox/AddAttachmentButton.tsx +17 -5
- package/src/components/sendbox/Attachments.tsx +12 -3
- package/src/components/sendbox/ErrorMessage.tsx +13 -2
- package/src/components/sendbox/TelephoneKeypadToolbarButton.tsx +1 -1
- package/src/components/sendbox/TextArea.tsx +70 -9
- package/src/components/sendbox/Toolbar.tsx +55 -4
- package/src/components/sendbox/index.tsx +69 -9
- package/src/components/suggestedActions/SuggestedAction.tsx +43 -3
- package/src/components/suggestedActions/index.tsx +29 -6
- package/src/components/telephoneKeypad/private/Button.tsx +67 -5
- package/src/components/telephoneKeypad/private/TelephoneKeypad.tsx +35 -4
- package/src/index.ts +0 -3
- package/src/private/useStyleToEmotionObject.ts +32 -0
- package/src/styles/index.ts +15 -0
- package/src/tsconfig.json +1 -2
- package/dist/botframework-webchat-fluent-theme.development.css.map +0 -1
- package/dist/botframework-webchat-fluent-theme.production.min.css.map +0 -1
- package/dist/index.css.map +0 -1
- package/src/components/Theme.module.css +0 -60
- package/src/components/dropZone/index.module.css +0 -23
- package/src/components/sendbox/AddAttachmentButton.module.css +0 -10
- package/src/components/sendbox/Attachments.module.css +0 -7
- package/src/components/sendbox/ErrorMessage.module.css +0 -9
- package/src/components/sendbox/TextArea.module.css +0 -61
- package/src/components/sendbox/Toolbar.module.css +0 -49
- package/src/components/sendbox/index.module.css +0 -58
- package/src/components/suggestedActions/SuggestedAction.module.css +0 -34
- package/src/components/suggestedActions/index.module.css +0 -23
- package/src/components/telephoneKeypad/private/Button.module.css +0 -62
- package/src/components/telephoneKeypad/private/TelephoneKeypad.module.css +0 -30
- package/src/env.d.ts +0 -7
- package/src/styles/injectStyle.ts +0 -9
- package/src/styles/useStyles.ts +0 -19
- package/src/styles.ts +0 -4
|
@@ -1,15 +1,40 @@
|
|
|
1
|
-
import { hooks } from 'botframework-webchat-
|
|
1
|
+
import { hooks } from 'botframework-webchat-api';
|
|
2
2
|
import cx from 'classnames';
|
|
3
3
|
import React, { memo, useCallback, useEffect, useRef, useState, type DragEventHandler } from 'react';
|
|
4
4
|
import { useRefFrom } from 'use-ref-from';
|
|
5
5
|
|
|
6
6
|
import { AddDocumentIcon } from '../../icons/AddDocumentIcon';
|
|
7
|
-
import testIds from '../../testIds';
|
|
8
|
-
import styles from './index.module.css';
|
|
9
7
|
import { useStyles } from '../../styles';
|
|
8
|
+
import testIds from '../../testIds';
|
|
10
9
|
|
|
11
10
|
const { useLocalizer } = hooks;
|
|
12
11
|
|
|
12
|
+
const styles = {
|
|
13
|
+
'webchat-fluent__sendbox__attachment-drop-zone': {
|
|
14
|
+
backgroundColor: 'var(--webchat-colorNeutralBackground4)',
|
|
15
|
+
borderRadius: 'inherit',
|
|
16
|
+
cursor: 'copy',
|
|
17
|
+
display: 'grid',
|
|
18
|
+
gap: '8px',
|
|
19
|
+
inset: '0',
|
|
20
|
+
placeContent: 'center',
|
|
21
|
+
placeItems: 'center',
|
|
22
|
+
position: 'absolute'
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
'webchat-fluent__sendbox__attachment-drop-zone--droppable': {
|
|
26
|
+
backgroundColor: '#e00',
|
|
27
|
+
color: 'White'
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
'webchat-fluent__sendbox__attachment-drop-zone-icon': {
|
|
31
|
+
height: '36px',
|
|
32
|
+
// Set "pointer-events: none" to ignore dragging over the icon. Otherwise, when dragging over the icon, it would disable the "--droppable" modifier.
|
|
33
|
+
pointerEvents: 'none',
|
|
34
|
+
width: '36px'
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
13
38
|
const handleDragOver: DragEventHandler<HTMLDivElement> = event => {
|
|
14
39
|
// This is for preventing the browser from opening the dropped file in a new tab.
|
|
15
40
|
event.preventDefault();
|
|
@@ -88,15 +113,15 @@ const DropZone = (props: { readonly onFilesAdded: (files: File[]) => void }) =>
|
|
|
88
113
|
|
|
89
114
|
return dropZoneState ? (
|
|
90
115
|
<div
|
|
91
|
-
className={cx(classNames['
|
|
92
|
-
[classNames['
|
|
116
|
+
className={cx(classNames['webchat-fluent__sendbox__attachment-drop-zone'], {
|
|
117
|
+
[classNames['webchat-fluent__sendbox__attachment-drop-zone--droppable']]: dropZoneState === 'droppable'
|
|
93
118
|
})}
|
|
94
119
|
data-testid={testIds.sendBoxDropZone}
|
|
95
120
|
onDragOver={handleDragOver}
|
|
96
121
|
onDrop={handleDrop}
|
|
97
122
|
ref={dropZoneRef}
|
|
98
123
|
>
|
|
99
|
-
<AddDocumentIcon className={classNames['
|
|
124
|
+
<AddDocumentIcon className={classNames['webchat-fluent__sendbox__attachment-drop-zone-icon']} />
|
|
100
125
|
{localize('TEXT_INPUT_DROP_ZONE')}
|
|
101
126
|
</div>
|
|
102
127
|
) : null;
|
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { hooks } from 'botframework-webchat-
|
|
1
|
+
import { hooks } from 'botframework-webchat-api';
|
|
2
2
|
import React, { useCallback, useRef, type ChangeEventHandler, memo } from 'react';
|
|
3
3
|
import { useRefFrom } from 'use-ref-from';
|
|
4
4
|
import { AttachmentIcon } from '../../icons/AttachmentIcon';
|
|
5
|
+
import { useStyles } from '../../styles';
|
|
5
6
|
import testIds from '../../testIds';
|
|
6
7
|
import { ToolbarButton } from './Toolbar';
|
|
7
|
-
import styles from './AddAttachmentButton.module.css';
|
|
8
|
-
import { useStyles } from '../../styles';
|
|
9
8
|
|
|
10
9
|
const { useLocalizer, useStyleOptions } = hooks;
|
|
11
10
|
|
|
11
|
+
const styles = {
|
|
12
|
+
'webchat-fluent__sendbox__add-attachment': {
|
|
13
|
+
display: 'grid'
|
|
14
|
+
},
|
|
15
|
+
|
|
16
|
+
'webchat-fluent__sendbox__add-attachment-input': {
|
|
17
|
+
fontSize: 0,
|
|
18
|
+
height: 0,
|
|
19
|
+
opacity: 0,
|
|
20
|
+
width: 0
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
12
24
|
function AddAttachmentButton(
|
|
13
25
|
props: Readonly<{
|
|
14
26
|
disabled?: boolean | undefined;
|
|
@@ -37,12 +49,12 @@ function AddAttachmentButton(
|
|
|
37
49
|
);
|
|
38
50
|
|
|
39
51
|
return (
|
|
40
|
-
<div className={classNames['
|
|
52
|
+
<div className={classNames['webchat-fluent__sendbox__add-attachment']}>
|
|
41
53
|
<input
|
|
42
54
|
accept={uploadAccept}
|
|
43
55
|
aria-disabled={props.disabled}
|
|
44
56
|
aria-hidden="true"
|
|
45
|
-
className={classNames['
|
|
57
|
+
className={classNames['webchat-fluent__sendbox__add-attachment-input']}
|
|
46
58
|
multiple={uploadMultiple}
|
|
47
59
|
onInput={props.disabled ? undefined : handleFileChange}
|
|
48
60
|
readOnly={props.disabled}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { hooks } from 'botframework-webchat-
|
|
1
|
+
import { hooks } from 'botframework-webchat-api';
|
|
2
2
|
import React, { memo } from 'react';
|
|
3
|
-
import styles from './Attachments.module.css';
|
|
4
3
|
import { useStyles } from '../../styles';
|
|
5
4
|
|
|
6
5
|
const { useLocalizer } = hooks;
|
|
7
6
|
|
|
7
|
+
const styles = {
|
|
8
|
+
'webchat-fluent__sendbox__attachment': {
|
|
9
|
+
border: '1px solid var(--webchat-colorNeutralStroke1)',
|
|
10
|
+
borderRadius: 'var(--webchat-borderRadiusLarge)',
|
|
11
|
+
cursor: 'default',
|
|
12
|
+
padding: '6px 8px',
|
|
13
|
+
width: 'fit-content'
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
8
17
|
const attachmentsPluralStringIds = {
|
|
9
18
|
one: 'TEXT_INPUT_ATTACHMENTS_ONE',
|
|
10
19
|
two: 'TEXT_INPUT_ATTACHMENTS_TWO',
|
|
@@ -22,7 +31,7 @@ function Attachments({
|
|
|
22
31
|
const localizeWithPlural = useLocalizer({ plural: true });
|
|
23
32
|
|
|
24
33
|
return attachments.length ? (
|
|
25
|
-
<div className={classNames['
|
|
34
|
+
<div className={classNames['webchat-fluent__sendbox__attachment']}>
|
|
26
35
|
{localizeWithPlural(attachmentsPluralStringIds, attachments.length)}
|
|
27
36
|
</div>
|
|
28
37
|
) : null;
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
|
-
import styles from './ErrorMessage.module.css';
|
|
3
2
|
import { useStyles } from '../../styles';
|
|
4
3
|
|
|
4
|
+
const styles = {
|
|
5
|
+
'webchat-fluent___sendbox__error-message': {
|
|
6
|
+
fontSize: 0,
|
|
7
|
+
height: 0,
|
|
8
|
+
width: 0,
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
top: 0,
|
|
11
|
+
left: 0,
|
|
12
|
+
color: 'transparent'
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
5
16
|
function ErrorMessage(props: Readonly<{ id: string; error?: string | undefined }>) {
|
|
6
17
|
const classNames = useStyles(styles);
|
|
7
18
|
return (
|
|
8
19
|
// eslint-disable-next-line react/forbid-dom-props
|
|
9
|
-
<span className={classNames['
|
|
20
|
+
<span className={classNames['webchat-fluent___sendbox__error-message']} id={props.id} role="alert">
|
|
10
21
|
{props.error}
|
|
11
22
|
</span>
|
|
12
23
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { memo, useCallback } from 'react';
|
|
2
2
|
|
|
3
|
-
import { hooks } from 'botframework-webchat-
|
|
3
|
+
import { hooks } from 'botframework-webchat-api';
|
|
4
4
|
import { TelephoneKeypadIcon } from '../../icons/TelephoneKeypad';
|
|
5
5
|
import testIds from '../../testIds';
|
|
6
6
|
import { useTelephoneKeypadShown } from '../TelephoneKeypad';
|
|
@@ -1,7 +1,68 @@
|
|
|
1
1
|
import cx from 'classnames';
|
|
2
2
|
import React, { forwardRef, useCallback, type FormEventHandler, type KeyboardEventHandler } from 'react';
|
|
3
|
+
|
|
3
4
|
import { useStyles } from '../../styles';
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
const styles = {
|
|
7
|
+
'webchat-fluent__sendbox__text-area': {
|
|
8
|
+
display: 'grid',
|
|
9
|
+
gridTemplateAreas: `'main'`,
|
|
10
|
+
maxHeight: '200px',
|
|
11
|
+
overflow: 'hidden'
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
'webchat-fluent__sendbox__text-area--hidden': {
|
|
15
|
+
// TODO: Not perfect way of hiding the text box.
|
|
16
|
+
height: 0,
|
|
17
|
+
visibility: 'collapse'
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
'webchat-fluent__sendbox__text-area-shared': {
|
|
21
|
+
border: 'none',
|
|
22
|
+
font: 'inherit',
|
|
23
|
+
gridArea: 'main',
|
|
24
|
+
outline: 'inherit',
|
|
25
|
+
overflowWrap: 'anywhere',
|
|
26
|
+
resize: 'inherit',
|
|
27
|
+
scrollbarGutter: 'stable'
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
'webchat-fluent__sendbox__text-area-doppelganger': {
|
|
31
|
+
overflow: 'hidden',
|
|
32
|
+
visibility: 'hidden',
|
|
33
|
+
whiteSpace: 'pre-wrap'
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
'webchat-fluent__sendbox__text-area-input': {
|
|
37
|
+
height: '100%',
|
|
38
|
+
padding: 0
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
'webchat-fluent__sendbox__text-area-input--scroll': {
|
|
42
|
+
/* Firefox */
|
|
43
|
+
MozScrollbarColor: 'var(--webchat-colorNeutralBackground5) var(--webchat-colorNeutralForeground2)',
|
|
44
|
+
MozScrollbarWidth: 'thin',
|
|
45
|
+
|
|
46
|
+
/* Chrome, Edge, and Safari */
|
|
47
|
+
'&::-webkit-scrollbar': {
|
|
48
|
+
width: '8px'
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
'&::-webkit-scrollbar-track': {
|
|
52
|
+
backgroundColor: 'var(--webchat-colorNeutralBackground5)',
|
|
53
|
+
borderRadius: '16px'
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
'&::-webkit-scrollbar-thumb': {
|
|
57
|
+
backgroundColor: 'var(--webchat-colorNeutralForeground2)',
|
|
58
|
+
borderRadius: '16px'
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
'&::-webkit-scrollbar-corner': {
|
|
62
|
+
backgroundColor: 'var(--webchat-colorNeutralBackground5)'
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
5
66
|
|
|
6
67
|
const TextArea = forwardRef<
|
|
7
68
|
HTMLTextAreaElement,
|
|
@@ -42,9 +103,9 @@ const TextArea = forwardRef<
|
|
|
42
103
|
return (
|
|
43
104
|
<div
|
|
44
105
|
className={cx(
|
|
45
|
-
classNames['
|
|
106
|
+
classNames['webchat-fluent__sendbox__text-area'],
|
|
46
107
|
{
|
|
47
|
-
[classNames['
|
|
108
|
+
[classNames['webchat-fluent__sendbox__text-area--hidden']]: props.hidden
|
|
48
109
|
},
|
|
49
110
|
props.className
|
|
50
111
|
)}
|
|
@@ -52,9 +113,9 @@ const TextArea = forwardRef<
|
|
|
52
113
|
>
|
|
53
114
|
<div
|
|
54
115
|
className={cx(
|
|
55
|
-
classNames['
|
|
56
|
-
classNames['
|
|
57
|
-
classNames['
|
|
116
|
+
classNames['webchat-fluent__sendbox__text-area-doppelganger'],
|
|
117
|
+
classNames['webchat-fluent__sendbox__text-area-shared'],
|
|
118
|
+
classNames['webchat-fluent__sendbox__text-area-input--scroll']
|
|
58
119
|
)}
|
|
59
120
|
>
|
|
60
121
|
{props.value || props.placeholder}{' '}
|
|
@@ -62,9 +123,9 @@ const TextArea = forwardRef<
|
|
|
62
123
|
<textarea
|
|
63
124
|
aria-label={props['aria-label']}
|
|
64
125
|
className={cx(
|
|
65
|
-
classNames['
|
|
66
|
-
classNames['
|
|
67
|
-
classNames['
|
|
126
|
+
classNames['webchat-fluent__sendbox__text-area-input'],
|
|
127
|
+
classNames['webchat-fluent__sendbox__text-area-shared'],
|
|
128
|
+
classNames['webchat-fluent__sendbox__text-area-input--scroll']
|
|
68
129
|
)}
|
|
69
130
|
data-testid={props['data-testid']}
|
|
70
131
|
onInput={props.onInput}
|
|
@@ -1,8 +1,59 @@
|
|
|
1
1
|
import cx from 'classnames';
|
|
2
2
|
import React, { memo, type MouseEventHandler, type ReactNode } from 'react';
|
|
3
|
-
import styles from './Toolbar.module.css';
|
|
4
3
|
import { useStyles } from '../../styles';
|
|
5
4
|
|
|
5
|
+
const styles = {
|
|
6
|
+
'webchat-fluent__sendbox__toolbar': {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
gap: '4px',
|
|
9
|
+
marginInlineStart: 'auto'
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
'webchat-fluent__sendbox__toolbar-button': {
|
|
13
|
+
alignItems: 'center',
|
|
14
|
+
appearance: 'none',
|
|
15
|
+
aspectRatio: '1',
|
|
16
|
+
background: 'transparent',
|
|
17
|
+
border: 'none',
|
|
18
|
+
borderRadius: 'var(--webchat-borderRadiusSmall)',
|
|
19
|
+
cursor: 'pointer',
|
|
20
|
+
display: 'flex',
|
|
21
|
+
justifyContent: 'center',
|
|
22
|
+
padding: '3px',
|
|
23
|
+
width: '32px',
|
|
24
|
+
|
|
25
|
+
'> svg': {
|
|
26
|
+
fontSize: '20px',
|
|
27
|
+
pointerEvents: 'none'
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
'@media (hover: hover)': {
|
|
31
|
+
'&:not([aria-disabled="true"]):hover': {
|
|
32
|
+
backgroundColor: 'var(--webchat-colorSubtleBackgroundHover)',
|
|
33
|
+
color: 'var(--webchat-colorCompoundBrandForeground1Hover)'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
'&:not([aria-disabled="true"]):active': {
|
|
37
|
+
backgroundColor: 'var(--webchat-colorSubtleBackgroundPressed)',
|
|
38
|
+
color: 'var(--webchat-colorCompoundBrandForeground1Pressed)'
|
|
39
|
+
},
|
|
40
|
+
'&[aria-disabled="true"]': {
|
|
41
|
+
color: 'var(--webchat-colorNeutralForegroundDisabled)',
|
|
42
|
+
cursor: 'not-allowed'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
'webchat-fluent__sendbox__toolbar-separator': {
|
|
47
|
+
alignSelf: 'center',
|
|
48
|
+
borderInlineEnd: '1px solid var(--webchat-colorNeutralStroke2)',
|
|
49
|
+
height: '28px',
|
|
50
|
+
|
|
51
|
+
'&:first-child, &:last-child, &:only-child': {
|
|
52
|
+
display: 'none'
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
6
57
|
const preventDefaultHandler: MouseEventHandler<HTMLButtonElement> = event => event.preventDefault();
|
|
7
58
|
|
|
8
59
|
export const ToolbarButton = memo(
|
|
@@ -22,7 +73,7 @@ export const ToolbarButton = memo(
|
|
|
22
73
|
return (
|
|
23
74
|
<button
|
|
24
75
|
aria-label={props['aria-label']}
|
|
25
|
-
className={cx(classNames['
|
|
76
|
+
className={cx(classNames['webchat-fluent__sendbox__toolbar-button'], props.className)}
|
|
26
77
|
data-testid={props['data-testid']}
|
|
27
78
|
onClick={props.disabled ? preventDefaultHandler : props.onClick}
|
|
28
79
|
type={props.type === 'submit' ? 'submit' : 'button'}
|
|
@@ -42,7 +93,7 @@ ToolbarButton.displayName = 'ToolbarButton';
|
|
|
42
93
|
export const Toolbar = memo((props: Readonly<{ children?: ReactNode | undefined; className?: string | undefined }>) => {
|
|
43
94
|
const classNames = useStyles(styles);
|
|
44
95
|
|
|
45
|
-
return <div className={cx(classNames['
|
|
96
|
+
return <div className={cx(classNames['webchat-fluent__sendbox__toolbar'], props.className)}>{props.children}</div>;
|
|
46
97
|
});
|
|
47
98
|
|
|
48
99
|
Toolbar.displayName = 'Toolbar';
|
|
@@ -54,7 +105,7 @@ export const ToolbarSeparator = memo(
|
|
|
54
105
|
return (
|
|
55
106
|
<div
|
|
56
107
|
aria-orientation="vertical"
|
|
57
|
-
className={cx(classNames['
|
|
108
|
+
className={cx(classNames['webchat-fluent__sendbox__toolbar-separator'], props.className)}
|
|
58
109
|
role="separator"
|
|
59
110
|
/>
|
|
60
111
|
);
|
|
@@ -3,6 +3,7 @@ import cx from 'classnames';
|
|
|
3
3
|
import React, { memo, useCallback, useRef, useState, type FormEventHandler, type MouseEventHandler } from 'react';
|
|
4
4
|
import { useRefFrom } from 'use-ref-from';
|
|
5
5
|
import { SendIcon } from '../../icons/SendIcon';
|
|
6
|
+
import { useStyles } from '../../styles';
|
|
6
7
|
import testIds from '../../testIds';
|
|
7
8
|
import DropZone from '../DropZone';
|
|
8
9
|
import SuggestedActions from '../SuggestedActions';
|
|
@@ -15,11 +16,70 @@ import TextArea from './TextArea';
|
|
|
15
16
|
import { Toolbar, ToolbarButton, ToolbarSeparator } from './Toolbar';
|
|
16
17
|
import useSubmitError from './private/useSubmitError';
|
|
17
18
|
import useUniqueId from './private/useUniqueId';
|
|
18
|
-
import styles from './index.module.css';
|
|
19
|
-
import { useStyles } from '../../styles';
|
|
20
19
|
|
|
21
20
|
const { useStyleOptions, useMakeThumbnail, useLocalizer, useSendBoxAttachments, useSendMessage } = hooks;
|
|
22
21
|
|
|
22
|
+
const styles = {
|
|
23
|
+
'webchat-fluent__sendbox': {
|
|
24
|
+
color: 'var(--webchat-colorNeutralForeground1)',
|
|
25
|
+
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
26
|
+
padding: '0 10px 10px',
|
|
27
|
+
textRendering: 'optimizeLegibility'
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
'webchat-fluent__sendbox__sendbox': {
|
|
31
|
+
backgroundColor: 'var(--webchat-colorNeutralBackground1)',
|
|
32
|
+
border: '1px solid var(--webchat-colorNeutralStroke1)',
|
|
33
|
+
borderRadius: 'var(--webchat-borderRadiusLarge)',
|
|
34
|
+
display: 'grid',
|
|
35
|
+
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
36
|
+
fontSize: '14px',
|
|
37
|
+
gap: '6px',
|
|
38
|
+
lineHeight: '20px',
|
|
39
|
+
padding: '8px',
|
|
40
|
+
position: 'relative',
|
|
41
|
+
|
|
42
|
+
'&:focus-within': {
|
|
43
|
+
borderColor: 'var(--webchat-colorNeutralStroke1Selected)',
|
|
44
|
+
// TODO clarify with design the color:
|
|
45
|
+
// - Teams is using colorCompoundBrandForeground1
|
|
46
|
+
// - Fluent is using colorCompoundBrandStroke
|
|
47
|
+
// - we are using colorCompoundBrandForeground1Hover
|
|
48
|
+
boxShadow: 'inset 0 -6px 0 -3px var(--webchat-colorCompoundBrandForeground1Hover)'
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
'webchat-fluent__sendbox__sendbox-text': {
|
|
53
|
+
backgroundColor: 'transparent',
|
|
54
|
+
border: 'none',
|
|
55
|
+
flex: 'auto',
|
|
56
|
+
fontFamily: 'var(--webchat-fontFamilyBase)',
|
|
57
|
+
fontSize: '14px',
|
|
58
|
+
lineHeight: '20px',
|
|
59
|
+
outline: 'none',
|
|
60
|
+
padding: '4px 4px 0',
|
|
61
|
+
resize: 'none'
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
'webchat-fluent__sendbox__sendbox-controls': {
|
|
65
|
+
alignItems: 'center',
|
|
66
|
+
display: 'flex',
|
|
67
|
+
paddingInlineStart: '4px'
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
'webchat-fluent__sendbox__text-counter': {
|
|
71
|
+
color: 'var(--webchat-colorNeutralForeground4)',
|
|
72
|
+
cursor: 'default',
|
|
73
|
+
fontFamily: 'var(--webchat-fontFamilyNumeric)',
|
|
74
|
+
fontSize: '10px',
|
|
75
|
+
lineHeight: '14px'
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
'webchat-fluent__sendbox__text-counter--error': {
|
|
79
|
+
color: 'var(--webchat-colorStatusDangerForeground1)'
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
23
83
|
function SendBox(
|
|
24
84
|
props: Readonly<{
|
|
25
85
|
className?: string | undefined;
|
|
@@ -35,7 +95,7 @@ function SendBox(
|
|
|
35
95
|
const localize = useLocalizer();
|
|
36
96
|
const sendMessage = useSendMessage();
|
|
37
97
|
const makeThumbnail = useMakeThumbnail();
|
|
38
|
-
const errorMessageId = useUniqueId('
|
|
98
|
+
const errorMessageId = useUniqueId('webchat-fluent__sendbox__error-message-id');
|
|
39
99
|
const [errorRef, errorMessage] = useSubmitError({ message, attachments });
|
|
40
100
|
const [telephoneKeypadShown] = useTelephoneKeypadShown();
|
|
41
101
|
|
|
@@ -116,9 +176,9 @@ function SendBox(
|
|
|
116
176
|
};
|
|
117
177
|
|
|
118
178
|
return (
|
|
119
|
-
<form {...aria} className={cx(classNames['
|
|
179
|
+
<form {...aria} className={cx(classNames['webchat-fluent__sendbox'], props.className)} onSubmit={handleFormSubmit}>
|
|
120
180
|
<SuggestedActions />
|
|
121
|
-
<div className={cx(classNames['
|
|
181
|
+
<div className={cx(classNames['webchat-fluent__sendbox__sendbox'])} onClickCapture={handleSendBoxClick}>
|
|
122
182
|
<TelephoneKeypadSurrogate
|
|
123
183
|
autoFocus={true}
|
|
124
184
|
isHorizontal={false}
|
|
@@ -126,7 +186,7 @@ function SendBox(
|
|
|
126
186
|
/>
|
|
127
187
|
<TextArea
|
|
128
188
|
aria-label={isMessageLengthExceeded ? localize('TEXT_INPUT_LENGTH_EXCEEDED_ALT') : localize('TEXT_INPUT_ALT')}
|
|
129
|
-
className={classNames['
|
|
189
|
+
className={classNames['webchat-fluent__sendbox__sendbox-text']}
|
|
130
190
|
data-testid={testIds.sendBoxTextBox}
|
|
131
191
|
hidden={telephoneKeypadShown}
|
|
132
192
|
onInput={handleMessageChange}
|
|
@@ -135,11 +195,11 @@ function SendBox(
|
|
|
135
195
|
value={message}
|
|
136
196
|
/>
|
|
137
197
|
<Attachments attachments={attachments} />
|
|
138
|
-
<div className={cx(classNames['
|
|
198
|
+
<div className={cx(classNames['webchat-fluent__sendbox__sendbox-controls'])}>
|
|
139
199
|
{maxMessageLength && (
|
|
140
200
|
<div
|
|
141
|
-
className={cx(classNames['
|
|
142
|
-
[classNames['
|
|
201
|
+
className={cx(classNames['webchat-fluent__sendbox__text-counter'], {
|
|
202
|
+
[classNames['webchat-fluent__sendbox__text-counter--error']]: isMessageLengthExceeded
|
|
143
203
|
})}
|
|
144
204
|
>
|
|
145
205
|
{`${message.length}/${maxMessageLength}`}
|
|
@@ -2,7 +2,6 @@ import { hooks } from 'botframework-webchat-component';
|
|
|
2
2
|
import { type DirectLineCardAction } from 'botframework-webchat-core';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import React, { MouseEventHandler, memo, useCallback, useRef } from 'react';
|
|
5
|
-
import styles from './SuggestedAction.module.css';
|
|
6
5
|
import { useStyles } from '../../styles';
|
|
7
6
|
import AccessibleButton from './AccessibleButton';
|
|
8
7
|
|
|
@@ -30,6 +29,43 @@ type SuggestedActionProps = Readonly<{
|
|
|
30
29
|
value?: any;
|
|
31
30
|
}>;
|
|
32
31
|
|
|
32
|
+
const styles = {
|
|
33
|
+
'webchat-fluent__suggested-action': {
|
|
34
|
+
alignItems: 'center',
|
|
35
|
+
background: 'transparent',
|
|
36
|
+
border: '1px solid var(--webchat-colorBrandStroke2)',
|
|
37
|
+
borderRadius: '8px',
|
|
38
|
+
cursor: 'pointer',
|
|
39
|
+
display: 'flex',
|
|
40
|
+
fontSize: '12px',
|
|
41
|
+
gap: '4px',
|
|
42
|
+
padding: '4px 8px 4px',
|
|
43
|
+
textAlign: 'start',
|
|
44
|
+
transition: 'all .15s ease-out',
|
|
45
|
+
|
|
46
|
+
'@media (hover: hover)': {
|
|
47
|
+
'&:not([aria-disabled="true"]):hover': {
|
|
48
|
+
backgroundColor: 'var(--webchat-colorBrandBackground2Hover)',
|
|
49
|
+
color: 'var(--webchat-colorBrandForeground2Hover)'
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
'&:not([aria-disabled="true"]):active': {
|
|
54
|
+
backgroundColor: 'var(--webchat-colorBrandBackground2Pressed)',
|
|
55
|
+
color: 'var(--webchat-colorBrandForeground2Pressed)'
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
'&[aria-disabled="true"]': {
|
|
59
|
+
color: 'var(--webchat-colorNeutralForegroundDisabled)',
|
|
60
|
+
cursor: 'not-allowed'
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
'webchat-fluent__suggested-action__image': {
|
|
65
|
+
height: '12px'
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
33
69
|
function SuggestedAction({
|
|
34
70
|
buttonText,
|
|
35
71
|
className,
|
|
@@ -72,13 +108,17 @@ function SuggestedAction({
|
|
|
72
108
|
|
|
73
109
|
return (
|
|
74
110
|
<AccessibleButton
|
|
75
|
-
className={cx(
|
|
111
|
+
className={cx(
|
|
112
|
+
classNames['webchat-fluent__suggested-action'],
|
|
113
|
+
suggestedActionStyleSet + '',
|
|
114
|
+
(className || '') + ''
|
|
115
|
+
)}
|
|
76
116
|
disabled={disabled}
|
|
77
117
|
onClick={handleClick}
|
|
78
118
|
ref={focusRef}
|
|
79
119
|
type="button"
|
|
80
120
|
>
|
|
81
|
-
{image && <img alt={imageAlt} className={classNames['
|
|
121
|
+
{image && <img alt={imageAlt} className={classNames['webchat-fluent__suggested-action__image']} src={image} />}
|
|
82
122
|
<span>{buttonText}</span>
|
|
83
123
|
</AccessibleButton>
|
|
84
124
|
);
|
|
@@ -1,13 +1,36 @@
|
|
|
1
1
|
import { hooks } from 'botframework-webchat-component';
|
|
2
2
|
import cx from 'classnames';
|
|
3
3
|
import React, { memo, type ReactNode } from 'react';
|
|
4
|
+
import { useStyles } from '../../styles';
|
|
4
5
|
import SuggestedAction from './SuggestedAction';
|
|
5
6
|
import computeSuggestedActionText from './private/computeSuggestedActionText';
|
|
6
|
-
import styles from './index.module.css';
|
|
7
|
-
import { useStyles } from '../../styles';
|
|
8
7
|
|
|
9
8
|
const { useLocalizer, useStyleOptions, useStyleSet, useSuggestedActions } = hooks;
|
|
10
9
|
|
|
10
|
+
const styles = {
|
|
11
|
+
'webchat-fluent__suggested-actions': {
|
|
12
|
+
alignItems: 'flex-end',
|
|
13
|
+
alignSelf: 'flex-end',
|
|
14
|
+
display: 'flex',
|
|
15
|
+
gap: '8px',
|
|
16
|
+
|
|
17
|
+
'&:not(:empty)': {
|
|
18
|
+
paddingBlockEnd: '8px',
|
|
19
|
+
paddingInlineStart: '4px'
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
'&.webchat-fluent__suggested-actions--flow': {
|
|
23
|
+
flexDirection: 'row',
|
|
24
|
+
flexWrap: 'wrap',
|
|
25
|
+
justifyContent: 'flex-end'
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
'&.webchat-fluent__suggested-actions--stacked': {
|
|
29
|
+
flexDirection: 'column'
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
11
34
|
function SuggestedActionStackedOrFlowContainer(
|
|
12
35
|
props: Readonly<{
|
|
13
36
|
'aria-label'?: string | undefined;
|
|
@@ -25,11 +48,11 @@ function SuggestedActionStackedOrFlowContainer(
|
|
|
25
48
|
aria-live="polite"
|
|
26
49
|
aria-orientation="vertical"
|
|
27
50
|
className={cx(
|
|
28
|
-
classNames['
|
|
51
|
+
classNames['webchat-fluent__suggested-actions'],
|
|
29
52
|
suggestedActionsStyleSet + '',
|
|
30
53
|
{
|
|
31
|
-
|
|
32
|
-
|
|
54
|
+
'webchat-fluent__suggested-actions--flow': suggestedActionLayout === 'flow',
|
|
55
|
+
'webchat-fluent__suggested-actions--stacked': suggestedActionLayout !== 'flow'
|
|
33
56
|
},
|
|
34
57
|
props.className
|
|
35
58
|
)}
|
|
@@ -88,7 +111,7 @@ function SuggestedActions() {
|
|
|
88
111
|
return (
|
|
89
112
|
<SuggestedActionStackedOrFlowContainer
|
|
90
113
|
aria-label={localize('SUGGESTED_ACTIONS_LABEL_ALT')}
|
|
91
|
-
className={classNames['
|
|
114
|
+
className={classNames['webchat-fluent__suggested-actions']}
|
|
92
115
|
>
|
|
93
116
|
{children}
|
|
94
117
|
</SuggestedActionStackedOrFlowContainer>
|