Skip to content

Commit 64643a3

Browse files
committed
Adds <ModdableIcon>
1 parent 456b165 commit 64643a3

File tree

9 files changed

+92
-46
lines changed

9 files changed

+92
-46
lines changed
54.5 KB
Loading
51.8 KB
Loading

__tests__/html2/sendBox/previewBeforeSend/threeImages.html

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@
3333
features: [{ name: 'prefers-reduced-motion', value: '' }]
3434
});
3535

36-
if (searchParams.get('theme') === 'dark') {
37-
await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
38-
features: [{ name: 'prefers-colors-scheme', value: 'dark' }]
39-
});
40-
}
36+
await host.sendDevToolsCommand('Emulation.setEmulatedMedia', {
37+
features: [{ name: 'prefers-colors-scheme', value: searchParams.get('theme') === 'dark' ? 'dark' : '' }]
38+
});
4139

4240
const { directLine, store } = createDirectLineEmulator();
4341

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { validateProps } from 'botframework-webchat-api/internal';
2+
import classNames from 'classnames';
3+
import React, { useMemo, type CSSProperties } from 'react';
4+
import { object, optional, pipe, readonly, string, type InferInput } from 'valibot';
5+
6+
import useStyleSet from '../hooks/useStyleSet';
7+
8+
const moddableIconPropsSchema = pipe(
9+
object({
10+
className: optional(string()),
11+
color: optional(string()),
12+
imageURL: optional(string()),
13+
maskURL: optional(string()),
14+
size: optional(string())
15+
}),
16+
readonly()
17+
);
18+
19+
type ModdableIconProps = InferInput<typeof moddableIconPropsSchema>;
20+
21+
function ModdableIcon(props: ModdableIconProps) {
22+
const { className, color, imageURL, maskURL, size } = validateProps(moddableIconPropsSchema, props);
23+
24+
const [{ moddableIcon: moddableIconClassName }] = useStyleSet();
25+
26+
const style = useMemo<CSSProperties>(
27+
() =>
28+
({
29+
'--webchat__moddable-icon--color': color,
30+
'--webchat__moddable-icon--mask': maskURL && `url(${maskURL})`,
31+
'--webchat__moddable-icon--image': imageURL && `url(${imageURL})`,
32+
'--webchat__moddable-icon--size': size
33+
}) satisfies Record<`--${string}`, number | string | undefined> as any, // csstype.CSSProperties does not allow CSS custom variables yet.
34+
[color, imageURL, maskURL, size]
35+
);
36+
37+
return <div className={classNames('webchat__moddable-icon', moddableIconClassName + '', className)} style={style} />;
38+
}
39+
40+
export default ModdableIcon;
41+
export { moddableIconPropsSchema, type ModdableIconProps };
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { type StyleSet } from '../Styles/StyleSet/types/StyleSet';
2+
3+
export default function createModdableIconStyle() {
4+
return {
5+
'&.webchat__moddable-icon': {
6+
height: '100%',
7+
width: '100%',
8+
9+
// 1. Use the image as texture.
10+
backgroundImage: 'var(--webchat__moddable-icon--image, none)',
11+
backgroundPosition: 'center',
12+
backgroundRepeat: 'no-repeat',
13+
backgroundSize: 'var(--webchat__moddable-icon--size, 1em)',
14+
15+
// 2. If image is not set, fallback to solid color.
16+
backgroundColor: 'var(--webchat__moddable-icon--color, currentColor)',
17+
18+
// 3. Set the mask if any.
19+
maskImage: 'var(--webchat__moddable-icon--mask)', // TODO: Need to think about 3P customization story.
20+
maskPosition: 'center',
21+
maskRepeat: 'no-repeat',
22+
maskSize: 'var(--webchat__moddable-icon--size, 1em)'
23+
}
24+
} satisfies StyleSet;
25+
}

packages/component/src/SendBox/AttachmentBar/AttachmentBarItemStyle.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,21 @@ export default function createSendBoxAttachmentBarItemStyle(_: StrictStyleOption
3939
padding: '0',
4040
transition: 'opacity 50ms', // Assume ultra-fast.
4141

42+
'--webchat__moddable-icon--size': '20px',
43+
44+
'&.webchat__send-box-attachment-bar-item__delete-button--large': {
45+
'--webchat__moddable-icon--mask': `url(data:image/svg+xml;utf8,${encodeURIComponent('<svg fill="none" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M4.60507 5.12706L4.66061 5.06059C4.82723 4.89396 5.08588 4.87545 5.27295 5.00505L5.33943 5.06059L9.80002 9.52128L14.2606 5.06059C14.4481 4.87314 14.752 4.87314 14.9394 5.06059C15.1269 5.24804 15.1269 5.55196 14.9394 5.73941L10.4787 10.2L14.9394 14.6606C15.1061 14.8272 15.1246 15.0859 14.995 15.2729L14.9394 15.3394C14.7728 15.506 14.5142 15.5245 14.3271 15.395L14.2606 15.3394L9.80002 10.8787L5.33943 15.3394C5.15198 15.5269 4.84806 15.5269 4.66061 15.3394C4.47316 15.152 4.47316 14.848 4.66061 14.6606L9.1213 10.2L4.66061 5.73941C4.49398 5.57279 4.47547 5.31414 4.60507 5.12706L4.66061 5.06059L4.60507 5.12706Z" fill="#242424" /></svg>')})`
46+
},
47+
48+
'&.webchat__send-box-attachment-bar-item__delete-button--small': {
49+
'--webchat__moddable-icon--mask': `url(data:image/svg+xml;utf8,${encodeURIComponent('<svg fill="none" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg"><path d="M6.08859 6.21569L6.14645 6.14645C6.32001 5.97288 6.58944 5.9536 6.78431 6.08859L6.85355 6.14645L10 9.293L13.1464 6.14645C13.3417 5.95118 13.6583 5.95118 13.8536 6.14645C14.0488 6.34171 14.0488 6.65829 13.8536 6.85355L10.707 10L13.8536 13.1464C14.0271 13.32 14.0464 13.5894 13.9114 13.7843L13.8536 13.8536C13.68 14.0271 13.4106 14.0464 13.2157 13.9114L13.1464 13.8536L10 10.707L6.85355 13.8536C6.65829 14.0488 6.34171 14.0488 6.14645 13.8536C5.95118 13.6583 5.95118 13.3417 6.14645 13.1464L9.293 10L6.14645 6.85355C5.97288 6.67999 5.9536 6.41056 6.08859 6.21569L6.14645 6.14645L6.08859 6.21569Z" fill="#242424" /></svg>')})`
50+
},
51+
4252
// https://react.fluentui.dev/?path=/docs/theme-colors--docs
4353
'@media not (prefers-color-scheme: dark)': {
54+
'--webchat__moddable-icon--color': '#242424', // Background/colorNeutralForeground1
4455
backgroundColor: 'White', // Background/colorNeutralBackground1
4556
borderColor: '#D1D1D1', // Stroke/colorNeutralStroke1
46-
color: '#242424', // Background/colorNeutralForeground1
4757

4858
'&:hover': {
4959
backgroundColor: '#F5F5F5', // Background/colorNeutralBackground1Hover
@@ -56,16 +66,17 @@ export default function createSendBoxAttachmentBarItemStyle(_: StrictStyleOption
5666
},
5767

5868
'&:disabled, &[aria-diabled]': {
69+
'--webchat__moddable-icon--color': '#BDBDBD', // Stroke/colorNeutralForegroundDisabled
5970
backgroundColor: '#F0F0F0', // Background/colorNeutralBackgroundDisabled
6071
borderColor: '#E0E0E0', // Stroke/colorNeutralStrokeDisabled
6172
color: '#BDBDBD' // Stroke/colorNeutralForegroundDisabled
6273
}
6374
},
6475

6576
'@media (prefers-color-scheme: dark)': {
77+
'--webchat__moddable-icon--color': '#FFFFFF', // Background/colorNeutralBackground1
6678
backgroundColor: '#292929', // Background/colorNeutralBackground1
6779
borderColor: '#666666', // Stroke/colorNeutralStroke1
68-
color: '#FFFFFF', // Background/colorNeutralBackground1
6980

7081
'&:hover': {
7182
backgroundColor: '#3D3D3D', // Background/colorNeutralBackground1Hover
@@ -78,19 +89,14 @@ export default function createSendBoxAttachmentBarItemStyle(_: StrictStyleOption
7889
},
7990

8091
'&:disabled, &[aria-diabled]': {
92+
'--webchat__moddable-icon--color': '#5C5C5C', // Stroke/colorNeutralForegroundDisabled
8193
backgroundColor: '#141414', // Background/colorNeutralBackgroundDisabled
8294
borderColor: '#424242', // Stroke/colorNeutralStrokeDisabled
8395
color: '#5C5C5C' // Stroke/colorNeutralForegroundDisabled
8496
}
8597
}
8698
},
8799

88-
'& .webchat__send-box-attachment-bar-item__delete-icon-masker': {
89-
backgroundColor: 'currentcolor',
90-
height: '20px',
91-
width: '20px'
92-
},
93-
94100
'&.webchat__send-box-attachment-bar-item.webchat__send-box-attachment-bar-item--as-list-item .webchat__send-box-attachment-bar-item__delete-button':
95101
{
96102
border: '0',

packages/component/src/SendBox/AttachmentBar/DeleteIcon.tsx

Lines changed: 0 additions & 30 deletions
This file was deleted.

packages/component/src/SendBox/AttachmentBar/ItemDeleteButton.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { hooks } from 'botframework-webchat-api';
22
import { validateProps } from 'botframework-webchat-api/internal';
3+
import classNames from 'classnames';
34
import React, { KeyboardEventHandler, useCallback } from 'react';
45
import { function_, object, optional, picklist, pipe, readonly, string, type InferInput } from 'valibot';
56

67
import { useFocus } from '../../hooks';
8+
import ModdableIcon from '../../ModdableIcon/ModdableIcon';
79
import testIds from '../../testIds';
8-
import DeleteIcon from './DeleteIcon';
910

1011
const { useLocalizer } = hooks;
1112

@@ -40,14 +41,17 @@ function AttachmentDeleteButton(props: AttachmentDeleteButtonProps) {
4041
return (
4142
<button
4243
aria-label={localize('SEND_BOX_ATTACHMENT_BAR_DELETE_BUTTON_ALT', attachmentName)}
43-
className="webchat__send-box-attachment-bar-item__delete-button"
44+
className={classNames('webchat__send-box-attachment-bar-item__delete-button', {
45+
'webchat__send-box-attachment-bar-item__delete-button--large': size === 'large',
46+
'webchat__send-box-attachment-bar-item__delete-button--small': size !== 'large'
47+
})}
4448
data-testid={testIds.sendBoxAttachmentBarItemDeleteButton}
4549
onClick={onClick}
4650
onKeyDown={handleKeyDown}
4751
title={localize('SEND_BOX_ATTACHMENT_BAR_DELETE_BUTTON_TOOLTIP')}
4852
type="button"
4953
>
50-
<DeleteIcon size={size} />
54+
<ModdableIcon />
5155
</button>
5256
);
5357
}

packages/component/src/Styles/createStyleSet.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import createInitialsAvatarStyle from './StyleSet/InitialsAvatar';
3131
import createLinkDefinitionsStyle from './StyleSet/LinkDefinitions';
3232
import createMicrophoneButtonStyle from './StyleSet/MicrophoneButton';
3333
import createModalDialogStyle from './StyleSet/ModalDialog';
34+
import createModdableIconStyle from '../ModdableIcon/ModdableIconStyle';
3435
import createMonochromeImageMaskerStyleSet from './StyleSet/MonochromeImageMasker';
3536
import createRenderMarkdownStyle from './StyleSet/RenderMarkdown';
3637
import createRootStyle from './StyleSet/Root';
@@ -89,6 +90,7 @@ export default function createStyleSet(styleOptions: StyleOptions) {
8990
imageAvatar: createImageAvatarStyle(),
9091
initialsAvatar: createInitialsAvatarStyle(strictStyleOptions),
9192
microphoneButton: createMicrophoneButtonStyle(strictStyleOptions),
93+
moddableIcon: createModdableIconStyle(),
9294
monochromeImageMasker: createMonochromeImageMaskerStyleSet(),
9395
options: { ...strictStyleOptions }, // Cloned to make sure no additional modifications will propagate up.
9496
root: createRootStyle(strictStyleOptions),

0 commit comments

Comments
 (0)