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] Incorporated PR comments of 4846 #4857

Merged
merged 15 commits into from Sep 15, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Resolves [#4840](https://github.com/microsoft/BotFramework-WebChat/issues/4840). Added feedback buttons in activity status, by [@compulim](https://github.com/compulim), in PR [#4846](https://github.com/microsoft/BotFramework-WebChat/pull/4846)
- Resolves [#4841](https://github.com/microsoft/BotFramework-WebChat/issues/4841). Added link definitions UI in Markdown, by [@compulim](https://github.com/compulim), in PR [#4846](https://github.com/microsoft/BotFramework-WebChat/pull/4846)
- Resolves [#4842](https://github.com/microsoft/BotFramework-WebChat/issues/4842). Added provenance in activity status, by [@compulim](https://github.com/compulim), in PR [#4846](https://github.com/microsoft/BotFramework-WebChat/pull/4846)
- Resolves [#4856](https://github.com/microsoft/BotFramework-WebChat/issues/4856). Added types for `useStyleSet`, by [@compulim](https://github.com/compulim), in PR [#4857](https://github.com/microsoft/BotFramework-WebChat/pull/4857)

## [4.15.9] - 2023-08-25

Expand Down
Expand Up @@ -25,10 +25,11 @@ import useAdaptiveCardsPackage from '../hooks/useAdaptiveCardsPackage';
import useDisabledModEffect from './AdaptiveCardHacks/useDisabledModEffect';
import usePersistValuesModEffect from './AdaptiveCardHacks/usePersistValuesModEffect';
import useRoleModEffect from './AdaptiveCardHacks/useRoleModEffect';
import useStyleSet from '../../hooks/useStyleSet';
import useValueRef from './AdaptiveCardHacks/private/useValueRef';

const { ErrorBox } = Components;
const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd, useStyleSet } = hooks;
const { useDisabled, useLocalizer, usePerformCardAction, useRenderMarkdownAsHTML, useScrollToEnd } = hooks;

const node_env = process.env.node_env || process.env.NODE_ENV;

Expand Down
@@ -1,14 +1,14 @@
/* eslint react/no-array-index-key: "off" */

import { Components, hooks } from 'botframework-webchat-component';
import { Components } from 'botframework-webchat-component';
import PropTypes from 'prop-types';
import React, { FC } from 'react';
import type { DirectLineAnimationCard } from 'botframework-webchat-core';

import CommonCard from './CommonCard';
import useStyleSet from '../../hooks/useStyleSet';
compulim marked this conversation as resolved.
Show resolved Hide resolved

const { ImageContent, VideoContent } = Components;
const { useStyleSet } = hooks;

type AnimationCardContentProps = {
actionPerformedClassName?: string;
Expand Down
@@ -1,14 +1,14 @@
/* eslint react/no-array-index-key: "off" */

import { Components, hooks } from 'botframework-webchat-component';
import { Components } from 'botframework-webchat-component';
import PropTypes from 'prop-types';
import React, { FC } from 'react';
import type { DirectLineAudioCard } from 'botframework-webchat-core';

import CommonCard from './CommonCard';
import useStyleSet from '../../hooks/useStyleSet';

const { AudioContent } = Components;
const { useStyleSet } = hooks;

type AudioCardContentProps = {
actionPerformedClassName?: string;
Expand Down
@@ -1,11 +1,9 @@
import { hooks } from 'botframework-webchat-component';
import PropTypes from 'prop-types';
import React, { FC } from 'react';
import type { DirectLineSignInCard } from 'botframework-webchat-core';

import CommonCard from './CommonCard';

const { useStyleSet } = hooks;
import useStyleSet from '../../hooks/useStyleSet';

type SignInCardContentProps = {
actionPerformedClassName?: string;
Expand Down
@@ -1,13 +1,13 @@
/* eslint react/no-array-index-key: "off" */

import { Components, hooks } from 'botframework-webchat-component';
import { Components } from 'botframework-webchat-component';
import PropTypes from 'prop-types';
import React, { FC } from 'react';
import type { DirectLineVideoCard } from 'botframework-webchat-core';

import CommonCard from './CommonCard';
import useStyleSet from '../../hooks/useStyleSet';

const { useStyleSet } = hooks;
const { VideoContent } = Components;

type VideoCardContentProps = {
Expand Down
13 changes: 13 additions & 0 deletions packages/bundle/src/hooks/useStyleSet.ts
@@ -0,0 +1,13 @@
import { hooks } from 'botframework-webchat-component';

import type AdaptiveCardsStyleSet from '../adaptiveCards/AdaptiveCardsStyleSet';

const useMinimalStyleSet = hooks.useStyleSet;

type MinimalStyleSet = ReturnType<typeof useMinimalStyleSet>[0];

export default function useStyleSet(): readonly [MinimalStyleSet & AdaptiveCardsStyleSet] {
const [styleOptions] = useMinimalStyleSet();

return Object.freeze([styleOptions as MinimalStyleSet & AdaptiveCardsStyleSet] as const);
}
4 changes: 3 additions & 1 deletion packages/bundle/src/index.ts
Expand Up @@ -28,6 +28,7 @@ import ThumbnailCardContent from './adaptiveCards/Attachment/ThumbnailCardConten
import useAdaptiveCardsHostConfig from './adaptiveCards/hooks/useAdaptiveCardsHostConfig';
import useAdaptiveCardsPackage from './adaptiveCards/hooks/useAdaptiveCardsPackage';
import useStyleOptions from './hooks/useStyleOptions';
import useStyleSet from './hooks/useStyleSet';
import VideoCardContent from './adaptiveCards/Attachment/VideoCardContent';

const renderWebChat = coreRenderWebChat.bind(null, ReactWebChat);
Expand Down Expand Up @@ -56,7 +57,8 @@ const patchedHooks = {
...hooks,
useAdaptiveCardsHostConfig,
useAdaptiveCardsPackage,
useStyleOptions
useStyleOptions,
useStyleSet
};

const AdditionalComponents = {
Expand Down
Expand Up @@ -2,9 +2,9 @@ import { type WebChatActivity } from 'botframework-webchat-core';
import classNames from 'classnames';
import React, { memo, type ReactNode, useMemo } from 'react';

import { isReplyAction, type ReplyAction } from '../types/external/SchemaOrg/ReplyAction';
import { isThing, type Thing } from '../types/external/SchemaOrg/Thing';
import { isVoteAction, type VoteAction } from '../types/external/SchemaOrg/VoteAction';
import { isReplyAction, type ReplyAction } from '../types/external/OrgSchema/ReplyAction';
import { isThing, type Thing } from '../types/external/OrgSchema/Thing';
import { isVoteAction, type VoteAction } from '../types/external/OrgSchema/VoteAction';
import { type TypeOfArray } from '../types/internal/TypeOfArray';
import Feedback from './private/Feedback/Feedback';
import Originator from './private/Originator';
Expand Down
@@ -1,8 +1,8 @@
import { hooks } from 'botframework-webchat-api';
import { useRefFrom } from 'use-ref-from';
import React, { Fragment, memo, type PropsWithChildren, useCallback, useState, useEffect } from 'react';
import React, { Fragment, memo, type PropsWithChildren, useState, useEffect } from 'react';

import { type VoteAction } from '../../../types/external/SchemaOrg/VoteAction';
import { type VoteAction } from '../../../types/external/OrgSchema/VoteAction';
import FeedbackVoteButton from './private/VoteButton';

const { usePonyfill, usePostActivity } = hooks;
Expand All @@ -15,14 +15,9 @@ const DEBOUNCE_TIMEOUT = 500;

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

const handleChange = useCallback<(voteAction: VoteAction) => void>(
voteAction => setSelectedVoteAction(voteAction),
[setSelectedVoteAction]
);

const postActivityRef = useRefFrom(postActivity);

useEffect(() => {
Expand All @@ -48,7 +43,7 @@ const Feedback = memo(({ voteActions }: Props) => {
{Array.from(voteActions).map((voteAction, index) => (
<FeedbackVoteButton
key={voteAction['@id'] || voteAction.actionOption || index}
onClick={handleChange}
onClick={setSelectedVoteAction}
pressed={selectedVoteAction === voteAction}
voteAction={voteAction}
/>
Expand Down
@@ -1,7 +1,7 @@
import React, { memo, useCallback } from 'react';
import { useRefFrom } from 'use-ref-from';

import { type VoteAction } from '../../../../types/external/SchemaOrg/VoteAction';
import { type VoteAction } from '../../../../types/external/OrgSchema/VoteAction';
import ThumbsButton from './ThumbButton';

type Props = {
Expand Down
@@ -1,13 +1,10 @@
import classNames from 'classnames';
import React, { memo } from 'react';

import { type ReplyAction } from '../../types/external/SchemaOrg/ReplyAction';
import useStyleSet from '../../hooks/useStyleSet';
import { type ReplyAction } from '../../types/external/OrgSchema/ReplyAction';

type Props = { replyAction: ReplyAction };

const Originator = memo(({ replyAction }: Props) => {
const [{ originatorActivityStatus }] = useStyleSet();
const { description, provider } = replyAction;

const text = description || provider?.name;
Expand All @@ -23,7 +20,7 @@ const Originator = memo(({ replyAction }: Props) => {
{text}
</a>
) : (
<span className={classNames('webchat__activity-status__originator', originatorActivityStatus + '')}>{text}</span>
<span className="webchat__activity-status__originator">{text}</span>
);
compulim marked this conversation as resolved.
Show resolved Hide resolved
});

Expand Down
Expand Up @@ -3,8 +3,8 @@ import { useRefFrom } from 'use-ref-from';
import classNames from 'classnames';
import React, { memo, type MouseEventHandler, useCallback, useMemo } from 'react';

import { isClaim, type Claim } from '../../../types/external/SchemaOrg/Claim';
import { isThing } from '../../../types/external/SchemaOrg/Thing';
import { isClaim, type Claim } from '../../../types/external/OrgSchema/Claim';
import { isThing } from '../../../types/external/OrgSchema/Thing';
import { type PropsOf } from '../../../types/PropsOf';
import { type WebChatActivity } from 'botframework-webchat-core';
import isHTMLButtonElement from './isHTMLButtonElement';
Expand Down
4 changes: 2 additions & 2 deletions packages/component/src/Composer.tsx
Expand Up @@ -53,14 +53,14 @@ type ComposerCoreUIProps = {
};

const ComposerCoreUI = memo(({ children }: ComposerCoreUIProps) => {
const [{ cssVariables }] = useStyleSet();
const [{ cssCustomProperties }] = useStyleSet();

const dictationOnError = useCallback(err => {
console.error(err);
}, []);

return (
<div className={classNames('webchat__css-variables', cssVariables)}>
<div className={classNames('webchat__css-custom-properties', cssCustomProperties)}>
compulim marked this conversation as resolved.
Show resolved Hide resolved
<ModalDialogComposer>
{/* When <SendBoxComposer> is finalized, it will be using an independent instance that lives inside <BasicSendBox>. */}
<SendBoxComposer>
Expand Down
21 changes: 21 additions & 0 deletions packages/component/src/Styles/CSSTokens.ts
@@ -0,0 +1,21 @@
import CustomPropertyNames from './CustomPropertyNames';

type CustomPropertyNamesType = typeof CustomPropertyNames;

type CSSTokensType<T extends Readonly<Record<string, string>>> = {
compulim marked this conversation as resolved.
Show resolved Hide resolved
[K in keyof T]: `var(${T[K]})`;
};

// To add/remove/update a token, go to `CustomPropertyName.ts`.
const CSSTokens = new Proxy(
{},
{
get(_, key: keyof CustomPropertyNamesType) {
// We already checked in the `CustomPropertyName`.
// eslint-disable-next-line security/detect-object-injection
return `var(${CustomPropertyNames[key]})`;
}
}
) as CSSTokensType<CustomPropertyNamesType>;

export default CSSTokens;
16 changes: 16 additions & 0 deletions packages/component/src/Styles/CustomPropertyNames.ts
@@ -0,0 +1,16 @@
const CustomPropertyNames = Object.freeze({
compulim marked this conversation as resolved.
Show resolved Hide resolved
// Make sure key names does not have JavaScript forbidden names.
ColorAccent: '--webchat__color--accent',
ColorTimestamp: '--webchat__color--timestamp',
FontPrimary: '--webchat__font--primary',
FontSizeSmall: '--webchat__font-size--small',
IconURLExternalLink: '--webchat__icon-url--external-link',
MaxWidthBubble: '--webchat__max-width--bubble',
MinHeightBubble: '--webchat__min-height--bubble',
PaddingRegular: '--webchat__padding--regular'
});

// This is for type-checking only to make sure the CSS custom property names is `--webchat__${string}`.
const _TypeChecking: Readonly<Record<string, `--webchat__${string}`>> = CustomPropertyNames;
compulim marked this conversation as resolved.
Show resolved Hide resolved

export default CustomPropertyNames;
45 changes: 45 additions & 0 deletions packages/component/src/Styles/StyleSet/CSSCustomProperties.ts
@@ -0,0 +1,45 @@
import { StrictStyleOptions } from 'botframework-webchat-api';

import CustomPropertyNames from '../CustomPropertyNames';

export default function createCSSCustomPropertiesStyle({
accent,
bubbleMaxWidth,
bubbleMinHeight,
fontSizeSmall,
markdownExternalLinkIconImage,
paddingRegular,
primaryFont,
subtle,
timestampColor
}: StrictStyleOptions) {
return {
'&.webchat__css-custom-properties': {
display: 'contents',

// TODO: Should we register the CSS property for inheritance, type checking, and initial value?
// Registrations need to be done on global level, and duplicate registration will throw.
// https://developer.mozilla.org/en-US/docs/Web/CSS/@property

// TODO: This is ongoing work. We are slowly adding CSS variables to ease calculations and stuff.
//
// We need to build a story to let web devs override these CSS variables.
//
// Candy points:
// - They should be able to override CSS variables for certain things (say, padding of popover) without affecting much.
//
// House rules:
// - We should put styling varibles here, e.g. paddingRegular
// - We MUST NOT put runtime variables here, e.g. sendTimeout
// - This is because we cannot programmatically know when the sendTimeout change
[CustomPropertyNames.ColorAccent]: accent,
[CustomPropertyNames.ColorTimestamp]: timestampColor || subtle, // Maybe we should not need this if we allow web devs to override CSS variables for certain components.
[CustomPropertyNames.FontPrimary]: primaryFont,
[CustomPropertyNames.FontSizeSmall]: fontSizeSmall,
[CustomPropertyNames.IconURLExternalLink]: markdownExternalLinkIconImage,
[CustomPropertyNames.MaxWidthBubble]: bubbleMaxWidth + 'px',
[CustomPropertyNames.MinHeightBubble]: bubbleMinHeight + 'px',
[CustomPropertyNames.PaddingRegular]: paddingRegular + 'px'
}
};
}
40 changes: 0 additions & 40 deletions packages/component/src/Styles/StyleSet/CSSVariables.ts

This file was deleted.

9 changes: 3 additions & 6 deletions packages/component/src/Styles/StyleSet/LinkDefinitions.ts
Expand Up @@ -5,7 +5,8 @@ import {
NOT_FORCED_COLORS_SELECTOR
} from './Constants';

// TODO: Fix CSS var.
import CSSTokens from '../CSSTokens';

export default function createLinkDefinitionsStyleSet() {
return {
'&.webchat__link-definitions': {
Expand All @@ -28,10 +29,6 @@ export default function createLinkDefinitionsStyleSet() {
}
},

// '.webchat__link-definitions__header-chevron': {
// verticalAlign: 'middle'
// },

'&:not([open]) .webchat__link-definitions__header-chevron': {
marginBottom: '-0.1em',
transform: 'rotate(-180deg)'
Expand Down Expand Up @@ -130,7 +127,7 @@ export default function createLinkDefinitionsStyleSet() {
padding: 4,

[NOT_FORCED_COLORS_SELECTOR]: {
color: 'var(--webchat__color--accent)'
color: CSSTokens.ColorAccent
}
},

Expand Down