BotFramework-WebChat icon indicating copy to clipboard operation
BotFramework-WebChat copied to clipboard

Investigate Web Chat Editor, playground, and Web Chat Designer

Open corinagum opened this issue 5 years ago • 0 comments

  • Compare the three projects and plan to bring alignment & reduce overlapping work
  • Expand scope of playground with action items for the following:
    • a demo app/playground
    • Composer extension
    • future hosting surfaces yet to be defined

Current resources:

  • https://github.com/pavolum/WebChat-Editor
  • https://webchateditor.azurewebsites.net/
  • Web Chat Designer:
import React, { useState } from 'react';
import AdaptiveForm  from '@bfc/adaptive-form';
import ReactWebChat from 'botframework-webchat';
import { JSONSchema7 } from '@bfc/extension-client';

const schema: JSONSchema7 = {
	"title": "Web Chat Designer",
	"description": "Web Chat Designer",
	"type": "object",
	"properties": {
		"accent": {
			"$role": "color",
			"type": "string"
		},
		"backgroundColor": {
				"$role": "color",
				"type": "string"
		},
		"cardEmphasisBackgroundColor": {
			"$role": "color",
			"type": "string"
		},
		"paddingRegular": {
			"oneOf":[
				{
						"type": "string"
				},
				{
					"type": "number"
				}
			]
		},
		"paddingWide": {
			"oneOf":[
				{
						"type": "string"
				},
				{
					"type": "number"
				}
			]
		},
		"subtle": {
			"$role": "color",
			"type": "string"
		},

		"messageActivityWordBreak": {
			"type": "string",
			"enum": [
				"break-word",
				"normal",
				"break-all",
				"break-word", 
				"keep-all"
			]
		},
		"fontSizeSmall": {
			"type": "string"
		},
		"monospaceFont": {
			"type": "string"
		},
		"primaryFont": {
			"type": "string"
		},
		"avatarBorderRadius": {
			"type": "string"
		},
		"avatarSize": {
			"oneOf":[
				{
						"type": "string"
				},
				{
					"type": "number"
				}
			]
		},
		"botAvatarBackgroundColor": {
			"$role": "color",
			"description": "defaults to accent color",
			"type": "string"
		},
		"botAvatarImage": {
			"description": "Data URI, blob, or Image URL",
			"type": "string"
		},
		"botAvatarInitials": {
			"description": "Empty strings means it has avatar but not initials inside.",
			"type": "string"
		},
		"userAvatarBackgroundColor": {
			"$role": "color",
			"description": "defaults to accent color",
			"type": "string"
		},
		"userAvatarImage": {
			"description": "Or a string of URL. Can be a data URI or blob.",
			"type": "string"
		},
		"userAvatarInitials": {
			"description": "Or a string. Empty strings means it has avatar but not initials inside.",
			"type": "string"
		},
		"showAvatarInGroup": {
			"oneOf": [
				{
					"type": "boolean"
				},
				{
					"type": "string",
					"enum": [
						"status",
						"sender"
					]
				}
			]
		},
		"bubbleBackground": {
			"$role": "color",
			"type": "string"
		},
		"bubbleBorderColor": {
			"$role": "color",
			"type": "string"
		},
		"bubbleBorderRadius": {
			"type": "number"
		},
		"bubbleBorderStyle": {
			"type": "string",
			"enum": [
				"dotted",
				"dashed",
				"solid",
				"double",
				"groove",
				"ridge",
				"inset",
				"outset",
				"none",
				"hidden",
				"mix"
			]
		},
		"bubbleBorderWidth": {
			"type": "number"
		},
		"bubbleFromUserBackground": {
			"$role": "color",
			"type": "string"
		},
		"bubbleFromUserBorderColor": {
			"$role": "color",
			"type": "string"
		},
		"bubbleFromUserBorderRadius": {
			"type": "number"
		},
		"bubbleFromUserBorderStyle": {
			"type": "string",
			"enum": [
				"dotted",
				"dashed",
				"solid",
				"double",
				"groove",
				"ridge",
				"inset",
				"outset",
				"none",
				"hidden",
				"mix"
			]
		},
		"bubbleFromUserBorderWidth": {
			"type": "number"
		},
		"bubbleFromUserNubOffset": {
			"oneOf": [
				{
					"type": "string",
					"const": "bottom"
				},
				{
					"type": "number"
				}
			]
		},
		"bubbleFromUserNubSize": {
			"type": "number"
		},
		"bubbleFromUserTextColor": {
			"$role": "color",
			"type": "string"
		},
		"bubbleImageHeight": {
			"type": "number"
		},
		"bubbleMaxWidth": {
			"type": "number"
		},
		"bubbleMinHeight": {
			"type": "number"
		},
		"bubbleMinWidth": {
			"type": "number"
		},
		"bubbleNubOffset": {
			"type": "number"
		},
		"bubbleNubSize": {
			"type": "number"
		},
		"bubbleTextColor": {
			"$role": "color",
			"type": "string"
		},
		"markdownRespectCRLF": {
			"type": "boolean"
		},
		"richCardWrapTitle": {
			"description": "Applies to subtitles as well",
			"type": "boolean"
		},
		"rootHeight": {
			"type": "string"
		},
		"rootWidth": {
			"type": "string"
		},
		"rootZIndex": {
			"description": "\"z-index\" for the root container of Web Chat. This will form a new stacking context so \"z-index\" used in children won't pollute.",
			"type": "number"
		}, 
		"hideScrollToEndButton": {
			"type": "boolean"
		},
		"hideSendBox": {
			"type": "boolean"
		},
		"hideUploadButton": {
			"type": "boolean"
		},
		"microphoneButtonColorOnDictate": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxBackground": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxButtonColor": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxButtonColorOnDisabled": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxButtonColorOnFocus": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxButtonColorOnHover": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxDisabledTextColor": {
			"$role": "color",
			"type": "string"
		},
		"sendBoxHeight": {
			"type": "number"
		},
		"sendBoxMaxHeight": {
			"type": "number"
		},
		"sendBoxTextColor": {
			"$role": "color",
			"type": "string"
		},
		
		"sendBoxPlaceholderColor": {
			"$role": "color",
			"description": "defaults to subtle",
			"type": "string"
		},
		"sendBoxTextWrap": {
			"type": "boolean"
		},
		"showSpokenText": {
			"description": "Visually show spoken text",
			"type": "boolean"
		},
		"suggestedActionBackground": {
			"$role": "color",
			"type": "string"
		},
		"suggestedActionBorderColor": {
			"$role": "color",
			"description": "defaults to accent",
			"type": "string"
		},
		"suggestedActionBorderRadius": {
			"type": "number"
		},
		"suggestedActionBorderStyle": {
			"type": "string",
			"enum": [
				"dotted",
				"dashed",
				"solid",
				"double",
				"groove",
				"ridge",
				"inset",
				"outset",
				"none",
				"hidden",
				"mix"
			]
		},
		"suggestedActionBorderWidth": {
			"type": "number"
		},
		"suggestedActionDisabledBackground": {
			"$role": "color",
			"description": "",
			"type": "string"
		},
		"suggestedActionDisabledBorderColor": {
			"$role": "color",
			"type": "string"
		},
		"suggestedActionDisabledBorderStyle": {
			"type": "string",
			"enum": [
				"dotted",
				"dashed",
				"solid",
				"double",
				"groove",
				"ridge",
				"inset",
				"outset",
				"none",
				"hidden",
				"mix"
			]
		},
		"suggestedActionDisabledTextColor": {
			"$role": "color",
			"description": "defaults to subtle",
			"type": "string"
		},
		"suggestedActionLayout": {
			"type": "string",
			"enum": [
				"carousel",
				"stacked"
			]
		}
    }
};

const uiOptions = {
	fieldsets: [
		{ title: 'Avatar', fields: ['avatarBorderRadius', 'avatarSize', 'botAvatarBackgroundColor', 'botAvatarImage', 'botAvatarInitials', 'userAvatarBackgroundColor', 'userAvatarImage', 'userAvatarInitials', 'showAvatarInGroup'] },
		{ title: 'Bubble', fields: ['bubbleBackground'] },
		{ title: 'Markdown', fields: ['markdownRespectCRLF'] },
		{ title: 'Send box', fields: ['hideSendBox', 'hideUploadButton'] },
		{ title: 'Suggested actions', fields: ['suggestedActionBackground', 'suggestedActionBorder'] },
		{ title: 'Other' }]
};

export const WebChatDesigner: React.FC = () => {
	const [styleOptions, setStyleOptions] = useState({});

	return (
		<div style={{ display: 'flex', height: '100%' }}>
			<div style={{ flex: 1, background: 'lightgrey', textAlign: 'center' }}>
				<ReactWebChat styleOptions={styleOptions} />
			</div>
			<div style={{ overflowY: 'auto' }}>
				<AdaptiveForm formData={styleOptions} onChange={setStyleOptions} schema={schema} uiOptions={uiOptions} />
			</div>
		</div>

	)
}

export default WebChatDesigner;

Playground to do items:

  • [ ] Reliable connection

  • [ ] Speech

  • [ ] Voice gender preference

  • [ ] Make all defaultStyleOptions configurable in the side panel

    • [ ] Color / padding / root
    • [ ] Fonts
    • [ ] Avatar
    • [ ] Bubble
    • [ ] Markdown
    • [ ] Rich cards
    • [ ] Send box
    • [ ] Show spoken text
    • [ ] Suggested actions
    • [ ] Timestamp
    • [ ] Transcript overlay buttons
    • [ ] Video
    • [ ] Connectivity
    • [x] Typing animation
    • [ ] Spinner animation
    • [ ] Upload thumbnail
    • [ ] Toast
    • [ ] Emoji
    • [x] Use fluent to intuitively group different sections/props
    • [x] Use fluent to add info icons w/ descriptions / suggested commands
    • [ ] Add a section in a side panel with a note that says 'Selecting these options will restart Web Chat':
      • [ ] Changing username
      • [ ] Changing userID
    • [ ] Set up @emotion/core properly
  • [ ] Add buttons to manually test Mock Bot commands?

  • [ ] use utils to indicate what browser we're using

  • [ ] DARK MODE

  • [ ] Middleware: Connection status always visible

  • [ ] Middleware: <ScreenReaderText> components visible

  • [ ] Store whether last token fetch was from local or official MockBot

  • [ ] Change alerts and console logs to toasts

  • [ ] Enable search

corinagum avatar Oct 02 '20 20:10 corinagum