Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HIGH] New UIs for better bot response #4846

Merged
merged 64 commits into from
Sep 11, 2023
Merged

Conversation

compulim
Copy link
Contributor

@compulim compulim commented Sep 2, 2023

Resolves #4840. Resolves #4841. Resolves #4842.

Changelog Entry

Added

Description

Adding 3 new UIs:

  • Link definitions: Markdown supports link references in footnote. This UI will render these references similar to how they appear in plain text
    • We also support citation. Citation should have URL starts with cite:. The citation text should be stored in activity.entities as Claim thing
  • Feedback buttons in activity status
    • VoteAction in activity.entities with actionOption of "upvote" and "downvote" will appear as thumbs up/down button in activity status
    • When clicked, they will send event activity with entities containing the chose VoteAction
  • Provenance in activity status
    • ReplyAction in activity.entities with provider of Project will appear in the activity status

Design

Based on Schema.org

To encourage integration across multiple chat services, this work is heavily based on Schema.org.

CSS variables

We are slowly copying some styleOptions into CSS variables. This will help when we implement dark/light theme as CSS variables can be on top of media query selector.

In <Component.Composer>, we are inserting a top-level <div style="display: contents;"> which will include all CSS variables to use under this layer. We are using display: contents to minimize impact on layout.

Markdown-it "betterLink" plug-in

We converged a lot of our custom plug-in into a betterLink plug-in. The design is not fully flush. Thus, this component remains internal for now.

When we work on customization story of Markdown, we may open this plug-in, or provide it in another way. So our web devs can enjoy customization without worrying breaking accessibility and citation dialog.

Link definitions (a.k.a. reference-style links)

Details of Markdown link definitions (a.k.a. reference-style links) can be found in this article.

Markdown:

Sure, you should override the default proxy settings[1][2], when your proxy server requires authentication[3].

[1]: https://support.microsoft.com/en-us/windows/use-a-proxy-server-in-windows-03096c53-0554-4ffe-b6ab-8b1deee8dae1
[2]: https://learn.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-proxy-server-settings "Configure proxy server settings - Windows Server"
[3]: cite:1 "Introduction Configuring proxy settings is a fundamental aspect..."

Before:

image

After:

image

For readability, links without a name (This is a link[1].) or links with same name and ID (This is a link[1][1].) will be rendered as This is a link[1]. rather than This is a link1. This is done through CSS ::before and ::after. Thus, in the future, it will be easy for us if we decided to style it as a superscripted badge.

Citation in link definitions

When clicking on a link starts with cite:, it will show a modal dialog.

image

Sample activity

{
  "entities": [
    {
      "@context": "https://schema.org",
      "@type": "Claim",
      "type": "https://schema.org/Claim",

      "@id": "cite:XXX",
      "text": "Hello, World!"
    }
  ]
}
activity.entities.find(entity => entity['@id'] === 'cite:XXX' && entity.type === 'https://schema.org/Claim).text

Design

We are using HTMLDialogElement.showModal() instead of a non-native modal for these reasons:

  • Non-native modal may conflict with keyboard help screen
  • Native modal can display out of the boundary of Web Chat, providing a wider canvas for long text content
  • Native modal has better focus trap (able to TAB into address bar while trapped)
  • Native modal supports ESCAPE key and navigational keys (UP/DOWN/PAGE UP/PAGE DOWN/HOME/END)

We added a new <ModalDialogComposer> with useShowModal() and useClose() hooks. We did not fully flush our design yet. Thus, this component remains internal for now.

Feedback buttons

Feedback buttons allows end-user to send feedback to the bot and potentially improve further conversation.

image

Sample activity

{
  "entities": [
    {
      "@context": "https://schema.org",
      "@type": "VoteAction",
      "type": "https://schema.org/VoteAction",

      "actionOption": "upvote"
    }
  ]
}
activity.entities.find(entity => entity.type === 'https://schema.org/VoteAction')

We currently only works with actionOption of "upvote" and "downvote"

Design

When clicked, Web Chat will send an event activity, excerpt:

{
  "entities": [
    {
       "@context": "https://schema.org",
       "@type": "VoteAction",
       "type": "https://schema.org/VoteAction",

       "actionOption": "downvote"
    }
  ],
  "name": "webchat:activity-status/feedback",
  "type": "event"
}

Provenance

image

The provenance helps the bot to identify where the origin of specific response come from.

Sample activity

{
  "entities": [
    {
      "@context": "https://schema.org",
      "@type": "ReplyAction",
      "type": "https://schema.org/ReplyAction",

      "provider": {
        "@context": "https://schema.org",
        "@type": "Project",

        "name": "Surfaced by Azure OpenAI",
        "url": "https://www.microsoft.com/en-us/ai/responsible-ai"
      }
    }
  ]
}
activity.entities.find(entity => entity.type === 'https://schema.org/ReplyAction').provider

Currently, the provider thing is expected to be Project with name and optional url field.

What is missing

The customization story on Markdown and activity status is weakened after this pull request. We will visit this area again immediately after this pull request is merged.

  • Markdown: we introduced citation to our Markdown-It engine. If the engine is replaced (by passing a different renderMarkdown function), it will lose citation
  • Activity status: we introduced feedback buttons and provenance as a slotted component (delimited by pipe). However, web devs are not able to add new thing as a slot or remove/replace some slots. They will need to nest another slotted container on top

What is breaking

There is a minor cosmetic issue with activity status. Previously, we did not add margin-top (or padding-top) correctly on activity status. Thus, web devs using our useCreateActivityStatusRenderer will see padding being added correctly.

We may move to gap in short future. Thus, the padding maybe removed again.

Specific Changes

-

  • I have added tests and executed them locally
  • I have updated CHANGELOG.md
  • I have updated documentation

Review Checklist

This section is for contributors to review your work.

  • Accessibility reviewed (tab order, content readability, alt text, color contrast)
  • Browser and platform compatibilities reviewed
  • CSS styles reviewed (minimal rules, no z-index)
  • Documents reviewed (docs, samples, live demo)
  • Internationalization reviewed (strings, unit formatting)
  • package.json and package-lock.json reviewed
  • Security reviewed (no data URIs, check for nonce leak)
  • Tests reviewed (coverage, legitimacy)

@compulim compulim marked this pull request as ready for review September 7, 2023 20:08
@compulim compulim changed the title New UIs for bot response [HIGH] New UIs for better bot response Sep 7, 2023
*
* @see https://schema.org/Thing
*/
export type SchemaOrgThing<T extends string = string> = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I prefer OrgThemeSchema

@@ -0,0 +1,7 @@
export type TypeOfArray<T extends unknown[] | Array<unknown> | ReadonlyArray<unknown>> = T extends (infer I)[]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to check T extends (infer I)[] and Array<infer I>. They are the same thing

aria-label={!ariaLabelledBy ? ariaLabel : undefined}
aria-labelledby={ariaLabelledBy}
className={classNames('webchat__modal-dialog', className, modalDialogStyleSet + '')}
onClose={handleClose}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don' think you need to wrap onDismissRef.current in a callback.

Suggested change
onClose={handleClose}
onClose={onDismissRef.current}

const ModalDialogComposer = memo(({ children }: Props) => {
const [renderFunctionAndDialogInit, setRenderFunctionAndDialogInit] = useState<
RenderFunctionAndDialogInit | undefined
>(undefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
>(undefined);
>();

};
}

// .webchat__thumb-button {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the plan with this commented out css?


'& .webchat__thumb-button__image': {
/* TODO: Remove "color" if we want a different hover color. */
color: 'var(--webchat__color--accent)',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Having a tokens object similar to fluent would be nice.

Suggested change
color: 'var(--webchat__color--accent)',
color: tokens.colorForegroundAccent,

width: 16,

'&:active': {
// background: 'var(--pva__palette__neutral-light)'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the variable scoped to pva? Should probably remove comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because I forget to remove it. 🤣


const Feedback = memo(({ voteActions }: Props) => {
const [{ clearTimeout, setTimeout }] = usePonyfill();
const [selectedVoteAction, setSelectedVoteAction] = useState<VoteAction | undefined>(undefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const [selectedVoteAction, setSelectedVoteAction] = useState<VoteAction | undefined>(undefined);
const [selectedVoteAction, setSelectedVoteAction] = useState<VoteAction | undefined>();

const [selectedVoteAction, setSelectedVoteAction] = useState<VoteAction | undefined>(undefined);
const postActivity = usePostActivity();

const handleChange = useCallback<(voteAction: VoteAction) => void>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use setSelectedVoteAction directly.

@compulim compulim merged commit d62393e into main Sep 11, 2023
10 checks passed
@compulim compulim deleted the feat-better-bot-response branch September 11, 2023 17:55
@SAlamuru1
Copy link

Is this feedback reactions works with CDN Bundle for vue.js project

@milind045
Copy link

@compulim I want to use VoteAction to capture user's feedback to a message response. I see that clicking upvote or downvote button sends an "event" back to the server. However, where does one find the actvityId that was liked or disliked?
There is clientActvityId in channelData, but it doesn't message the activityId of the message that was sent to the channel. Kindly advise how to correlate the the VoteAction event with the correct activty/ replyActivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants