Skip to content

Commit d2d5ef3

Browse files
committed
Add title bar
1 parent f9ed229 commit d2d5ef3

10 files changed

Lines changed: 164 additions & 39 deletions

packages/experience-chat-launcher/src/private/private/ChatLauncherPopover.module.css

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

packages/experience-chat-launcher/src/private/private/ChatLauncherPopover.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import mergeRefs from 'merge-refs';
33
import React, { forwardRef, memo, useRef, type ForwardedRef } from 'react';
44
import { object, pipe, readonly, type InferInput } from 'valibot';
55

6-
import ChatLauncherPopoverDismissButton from './ChatLauncherPopoverDismissButton';
6+
import ChatLauncherPopoverTitleBar from './ChatLauncherPopoverTitleBar';
77

88
const chatLauncherPopoverPropsSchema = pipe(object({}), readonly());
99

@@ -15,8 +15,7 @@ function ChatLauncherPopover(_: ChatLauncherPopoverProps, ref: ForwardedRef<Elem
1515
return (
1616
// TODO: [P2] Is it correct to force-cast ref to HTMLDivElement?
1717
<PopoverPolymiddlewareProxy popover="manual" ref={mergeRefs(popoverRef, ref)} type="nonmodal">
18-
{'Hello, World!'}
19-
<ChatLauncherPopoverDismissButton popoverRef={popoverRef} />
18+
<ChatLauncherPopoverTitleBar popoverRef={popoverRef} />
2019
</PopoverPolymiddlewareProxy>
2120
);
2221
}

packages/experience-chat-launcher/src/private/private/ChatLauncherPopoverDismissButton.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,26 @@ import { object, optional, pipe, readonly, type InferInput } from 'valibot';
55

66
import Icon from './Icon';
77

8-
const chatLauncherModalDismissButtonPropsSchema = pipe(
8+
const chatLauncherPopoverDismissButtonPropsSchema = pipe(
99
object({
1010
popoverRef: optional(refObject<Element>())
1111
}),
1212
readonly()
1313
);
1414

15-
type ChatLauncherModalDismissButtonProps = InferInput<typeof chatLauncherModalDismissButtonPropsSchema>;
15+
type ChatLauncherPopoverDismissButtonProps = InferInput<typeof chatLauncherPopoverDismissButtonPropsSchema>;
1616

17-
function ChatLauncherModalDismissButton(props: ChatLauncherModalDismissButtonProps) {
18-
const { popoverRef } = validateProps(chatLauncherModalDismissButtonPropsSchema, props);
17+
function ChatLauncherPopoverDismissButton(props: ChatLauncherPopoverDismissButtonProps) {
18+
const { popoverRef } = validateProps(chatLauncherPopoverDismissButtonPropsSchema, props);
1919

2020
return (
2121
<ButtonPolymiddlewareProxy appearance="flat" popoverTargetAction="hide" popoverTargetRef={popoverRef}>
22-
<Icon appearance="text" icon="dismiss" />
22+
<Icon appearance="button" icon="dismiss" />
2323
</ButtonPolymiddlewareProxy>
2424
);
2525
}
2626

27-
ChatLauncherModalDismissButton.displayName = 'ChatLauncherModalDismissButton';
27+
ChatLauncherPopoverDismissButton.displayName = 'ChatLauncherPopoverDismissButton';
2828

29-
export default memo(ChatLauncherModalDismissButton);
29+
export default memo(ChatLauncherPopoverDismissButton);
30+
export { chatLauncherPopoverDismissButtonPropsSchema, type ChatLauncherPopoverDismissButtonProps };
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ButtonPolymiddlewareProxy } from 'botframework-webchat-api/middleware';
2+
import React, { memo } from 'react';
3+
import { object, pipe, readonly, type InferInput } from 'valibot';
4+
5+
import Icon from './Icon';
6+
7+
const chatLauncherPopoverRestartButtonPropsSchema = pipe(object({}), readonly());
8+
9+
type ChatLauncherPopoverRestartButtonProps = InferInput<typeof chatLauncherPopoverRestartButtonPropsSchema>;
10+
11+
function ChatLauncherPopoverRestartButton(_: ChatLauncherPopoverRestartButtonProps) {
12+
return (
13+
<ButtonPolymiddlewareProxy appearance="flat">
14+
<Icon appearance="button" icon="arrow-clockwise" />
15+
</ButtonPolymiddlewareProxy>
16+
);
17+
}
18+
19+
ChatLauncherPopoverRestartButton.displayName = 'ChatLauncherPopoverRestartButton';
20+
21+
export default memo(ChatLauncherPopoverRestartButton);
22+
export { chatLauncherPopoverRestartButtonPropsSchema, type ChatLauncherPopoverRestartButtonProps };
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
:global(.webchat-experience-chat-launcher) .chat-launcher-popover__title-bar {
2+
--webchat-spacingHorizontalL: var(--spacingHorizontalL, 16px);
3+
--webchat-spacingHorizontalS: var(--spacingHorizontalS, 8px);
4+
--webchat-spacingVerticalM: var(--spacingVerticalM, 12px);
5+
--webchat-spacingVerticalS: var(--spacingVerticalS, 8px);
6+
--webchat-colorNeutralStroke3: var(--colorNeutralStroke3, #f0f0f0);
7+
--webchat-strokeWidthThin: var(--strokeWidthThin, 1px);
8+
9+
--webchat-chatLauncherPopoverTitleBar-border-block-end-width: var(--webchat-strokeWidthThin);
10+
--webchat-chatLauncherPopoverTitleBar-border-block-end-color: var(--webchat-colorNeutralStroke3);
11+
--webchat-chatLauncherPopoverTitleBar-padding: var(--webchat-spacingVerticalM) var(--webchat-spacingHorizontalL);
12+
13+
align-items: center;
14+
border-block-end-color: var(--webchat-chatLauncherPopoverTitleBar-border-block-end-color);
15+
border-block-end-style: solid;
16+
border-block-end-width: var(--webchat-chatLauncherPopoverTitleBar-border-block-end-width);
17+
display: grid;
18+
grid-template-columns: 1fr auto auto;
19+
padding: var(--webchat-chatLauncherPopoverTitleBar-padding);
20+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { refObject, validateProps } from '@msinternal/botframework-webchat-react-valibot';
2+
import { useStyles } from '@msinternal/botframework-webchat-styles/react';
3+
import React, { forwardRef, memo } from 'react';
4+
import { object, optional, pipe, readonly, type InferInput } from 'valibot';
5+
6+
import ChatLauncherPopoverDismissButton from './ChatLauncherPopoverDismissButton';
7+
import ChatLauncherPopoverRestartButton from './ChatLauncherPopoverRestartButton';
8+
import styles from './ChatLauncherPopoverTitleBar.module.css';
9+
import ChatLauncherPopoverTitleText from './ChatLauncherPopoverTitleText';
10+
11+
const chatLauncherPopoverTitleBarPropsSchema = pipe(
12+
object({
13+
popoverRef: optional(refObject<Element>())
14+
}),
15+
readonly()
16+
);
17+
18+
type ChatLauncherPopoverTitleBarProps = InferInput<typeof chatLauncherPopoverTitleBarPropsSchema>;
19+
20+
function ChatLauncherPopoverTitleBar(props: ChatLauncherPopoverTitleBarProps) {
21+
const { popoverRef } = validateProps(chatLauncherPopoverTitleBarPropsSchema, props);
22+
23+
const classNames = useStyles(styles);
24+
25+
return (
26+
<div className={classNames['chat-launcher-popover__title-bar']}>
27+
<ChatLauncherPopoverTitleText>{'Contoso agent'}</ChatLauncherPopoverTitleText>
28+
<ChatLauncherPopoverRestartButton />
29+
<ChatLauncherPopoverDismissButton popoverRef={popoverRef} />
30+
</div>
31+
);
32+
}
33+
34+
ChatLauncherPopoverTitleBar.displayName = 'ChatLauncherPopoverTitleBar';
35+
36+
export default memo(forwardRef(ChatLauncherPopoverTitleBar));
37+
export { chatLauncherPopoverTitleBarPropsSchema, type ChatLauncherPopoverTitleBarProps };
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
:global(.webchat-experience-chat-launcher) .chat-launcher-popover__title-text {
2+
/* TODO: [P0] Refactor variables to global or upper layer. */
3+
--webchat-colorNeutralForeground1: var(--colorNeutralForeground1, #242424);
4+
--webchat-fontFamilyBase: var(
5+
--fontFamilyBase,
6+
'Segoe UI',
7+
'Segoe UI Web (West European)',
8+
-apple-system,
9+
BlinkMacSystemFont,
10+
Roboto,
11+
'Helvetica Neue',
12+
sans-serif
13+
);
14+
--webchat-fontSizeBase400: var(--fontSizeBase400, 16px);
15+
--webchat-fontWeightSemibold: var(--fontWeightSemibold, 600);
16+
17+
/* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
18+
--webchat-chatLauncherPopoverTitleText-color: var(--webchat-colorNeutralForeground1);
19+
--webchat-chatLauncherPopoverTitleText-fontFamily: var(--webchat-fontFamilyBase);
20+
--webchat-chatLauncherPopoverTitleText-fontSize: var(--webchat-fontSizeBase400);
21+
--webchat-chatLauncherPopoverTitleText-fontWeight: var(--webchat-fontWeightSemibold);
22+
23+
color: var(--webchat-chatLauncherPopoverTitleText-color);
24+
font-family: var(--webchat-chatLauncherPopoverTitleText-fontFamily);
25+
font-size: var(--webchat-chatLauncherPopoverTitleText-fontSize);
26+
font-weight: var(--webchat-chatLauncherPopoverTitleText-fontWeight);
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { reactNode, validateProps } from '@msinternal/botframework-webchat-react-valibot';
2+
import { useStyles } from '@msinternal/botframework-webchat-styles/react';
3+
import React, { memo } from 'react';
4+
import { object, optional, pipe, readonly, type InferInput } from 'valibot';
5+
6+
import styles from './ChatLauncherPopoverTitleText.module.css';
7+
8+
const chatLauncherPopoverTitleTextPropsSchema = pipe(
9+
object({
10+
children: optional(reactNode())
11+
}),
12+
readonly()
13+
);
14+
15+
type ChatLauncherPopoverTitleTextProps = InferInput<typeof chatLauncherPopoverTitleTextPropsSchema>;
16+
17+
function ChatLauncherPopoverTitleText(props: ChatLauncherPopoverTitleTextProps) {
18+
const { children } = validateProps(chatLauncherPopoverTitleTextPropsSchema, props);
19+
20+
const classNames = useStyles(styles);
21+
22+
return <div className={classNames['chat-launcher-popover__title-text']}>{children}</div>;
23+
}
24+
25+
ChatLauncherPopoverTitleText.displayName = 'ChatLauncherPopoverTitleText';
26+
27+
export default memo(ChatLauncherPopoverTitleText);
28+
export { chatLauncherPopoverTitleTextPropsSchema, type ChatLauncherPopoverTitleTextProps };

packages/experience-chat-launcher/src/private/private/Icon.module.css

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/experience-chat-launcher/src/private/private/NonModalPopover.module.css

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
--webchat-shadow64: var(--shadow64, 0 0 8px rgba(0, 0, 0, 0.12), 0 32px 64px rgba(0, 0, 0, 0.14));
55

66
/* TODO: [P*] Is this a good naming system? Sorry I forgot if we should still go CSS BEM-alike or not. */
7-
--webchat-chatLauncherModal-background: var(--webchat-colorNeutralBackground1);
8-
--webchat-chatLauncherModal-box-shadow: var(--webchat-shadow64);
9-
--webchat-chatLauncherModal-border-radius: 20px;
10-
--webchat-chatLauncherModal-height: 610px;
11-
--webchat-chatLauncherModal-width: 340px;
7+
--webchat-popover-background: var(--webchat-colorNeutralBackground1);
8+
--webchat-popover-box-shadow: var(--webchat-shadow64);
9+
--webchat-popover-border-radius: 20px;
10+
--webchat-popover-height: 610px;
11+
--webchat-popover-width: 340px;
1212

13-
background: var(--webchat-chatLauncherModal-background);
13+
background: var(--webchat-popover-background);
1414
border: 0;
15-
border-radius: var(--webchat-chatLauncherModal-border-radius);
16-
box-shadow: var(--webchat-chatLauncherModal-box-shadow);
17-
height: var(--webchat-chatLauncherModal-height);
18-
width: var(--webchat-chatLauncherModal-width);
15+
border-radius: var(--webchat-popover-border-radius);
16+
box-shadow: var(--webchat-popover-box-shadow);
17+
height: var(--webchat-popover-height);
18+
padding: 0;
19+
width: var(--webchat-popover-width);
1920
}

0 commit comments

Comments
 (0)