diff --git a/Composer/packages/adaptive-form/src/components/CollapseField.tsx b/Composer/packages/adaptive-form/src/components/CollapseField.tsx index 9d6392bf63..c7427c5807 100644 --- a/Composer/packages/adaptive-form/src/components/CollapseField.tsx +++ b/Composer/packages/adaptive-form/src/components/CollapseField.tsx @@ -5,12 +5,16 @@ import { css, jsx } from '@emotion/react'; import { Fragment, useState, useEffect, useLayoutEffect, useRef } from 'react'; import { FontSizes, FontWeights } from '@fluentui/react/lib/Styling'; -import { IconButton } from '@fluentui/react/lib/Button'; import { Label } from '@fluentui/react/lib/Label'; import { NeutralColors } from '@fluentui/theme'; import formatMessage from 'format-message'; +import { Icon } from '@fluentui/react/lib/Icon'; +import styled from '@emotion/styled'; const styles = { + title: css` + font-weight: ${FontWeights.semibold}; + `, description: css` font-size: ${FontSizes.medium}; `, @@ -19,6 +23,8 @@ const styles = { overflow: hidden; `, header: css` + appearance: none; + border: none; background-color: #eff6fc; display: flex; margin: 4px -18px; @@ -26,6 +32,11 @@ const styles = { `, }; +const CollapseIcon = styled(Icon)({ + color: NeutralColors.gray150, + marginRight: '4px', +}); + interface CollapseField { defaultExpanded?: boolean; description?: string; @@ -37,28 +48,19 @@ export const CollapseField: React.FC = ({ children, description, return ( -
{ setIsOpen(!isOpen); }} > - - {title && } + + {title && } {description &&  - {description}} -
+
{children}
diff --git a/Composer/packages/client/src/components/EditableField.tsx b/Composer/packages/client/src/components/EditableField.tsx index dd06a44bd5..a40e9ae2e0 100644 --- a/Composer/packages/client/src/components/EditableField.tsx +++ b/Composer/packages/client/src/components/EditableField.tsx @@ -20,13 +20,15 @@ const allowedNavigationKeys = ['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight' const defaultContainerStyle = (hasFocus, hasErrors) => css` display: flex; width: 100%; - outline: ${hasErrors - ? `2px solid ${SharedColors.red10}` - : hasFocus - ? `2px solid ${SharedColors.cyanBlue10}` - : undefined}; - background: ${hasFocus || hasErrors ? NeutralColors.white : 'inherit'}; margin-top: 2px; + @media (forced-colors: none) { + background: ${hasFocus || hasErrors ? NeutralColors.white : 'inherit'}; + outline: ${hasErrors + ? `2px solid ${SharedColors.red10}` + : hasFocus + ? `2px solid ${SharedColors.cyanBlue10}` + : undefined}; + } :hover .ms-Button-icon, :focus-within .ms-Button-icon { visibility: visible; @@ -41,6 +43,12 @@ const defaultContainerStyle = (hasFocus, hasErrors) => css` } `; +const requiredText = css` + @media (forced-colors: none) { + color: ${SharedColors.red20}; + } +`; + // turncat to show two line. const maxCharacterNumbers = 120; @@ -270,8 +278,10 @@ const EditableField: React.FC = (props) => { ':hover': { borderColor: hasFocus ? undefined : NeutralColors.gray30, }, - '.ms-TextField-field': { - background: hasFocus || hasEditingErrors ? NeutralColors.white : 'inherit', + '@media (forced-colors: none)': { + '.ms-TextField-field': { + background: hasFocus || hasEditingErrors ? NeutralColors.white : 'inherit', + }, }, }, }, @@ -312,17 +322,17 @@ const EditableField: React.FC = (props) => { }} styles={{ root: { - background: hasFocus ? NeutralColors.white : 'inherit', + '@media (forced-colors: none)': { + background: hasFocus ? NeutralColors.white : 'inherit', + }, }, }} onClick={iconProps?.onClick || resetValue} /> )} - {hasErrors && hasBeenEdited && ( - {requiredMessage || formErrors.value} - )} - {error && {error}} + {hasErrors && hasBeenEdited && {requiredMessage || formErrors.value}} + {error && {error}} {hasErrors && hasBeenEdited && } {error && }
diff --git a/Composer/packages/client/src/components/FieldWithCustomButton.tsx b/Composer/packages/client/src/components/FieldWithCustomButton.tsx index 7c31a660c0..902455c125 100644 --- a/Composer/packages/client/src/components/FieldWithCustomButton.tsx +++ b/Composer/packages/client/src/components/FieldWithCustomButton.tsx @@ -18,10 +18,12 @@ const disabledTextFieldStyle = mergeStyleSets(customFieldLabel, { root: { selectors: { '.ms-TextField-field': { - background: '#ddf3db', - }, - '.ms-Dropdown-title': { - background: '#ddf3db', + '@media (forced-colors: none)': { + background: '#ddf3db', + }, + '.ms-Dropdown-title': { + background: '#ddf3db', + }, }, 'p > span': { width: '100%', diff --git a/Composer/packages/client/src/pages/knowledge-base/styles.ts b/Composer/packages/client/src/pages/knowledge-base/styles.ts index df6014c1ac..2e40f355c7 100644 --- a/Composer/packages/client/src/pages/knowledge-base/styles.ts +++ b/Composer/packages/client/src/pages/knowledge-base/styles.ts @@ -98,7 +98,7 @@ export const rowDetails = { background: NeutralColors.gray30, selectors: { '.ms-TextField-fieldGroup': { - background: NeutralColors.gray30, + background: 'transparent', }, '.ms-Button--icon': { visibility: 'visible', @@ -117,7 +117,7 @@ export const rowDetails = { visibility: 'visible', }, '.ms-TextField-fieldGroup': { - background: NeutralColors.gray30, + background: 'transparent', }, }, }, @@ -140,8 +140,10 @@ export const addAlternative = { fontSize: 12, paddingLeft: 0, marginLeft: -5, - color: SharedColors.cyanBlue10, display: 'none', + '@media (forced-colors: none)': { + color: SharedColors.cyanBlue10, + }, }, } as IButtonStyles; diff --git a/Composer/packages/lib/code-editor/src/components/toolbar/PropertyTreeItem.tsx b/Composer/packages/lib/code-editor/src/components/toolbar/PropertyTreeItem.tsx index aa9bbdcd08..5472b1fc99 100644 --- a/Composer/packages/lib/code-editor/src/components/toolbar/PropertyTreeItem.tsx +++ b/Composer/packages/lib/code-editor/src/components/toolbar/PropertyTreeItem.tsx @@ -4,8 +4,10 @@ import styled from '@emotion/styled'; import { NeutralColors } from '@fluentui/theme'; import { Icon, IIconStyles } from '@fluentui/react/lib/Icon'; +import { Button } from '@fluentui/react/lib/Button'; import { Stack } from '@fluentui/react/lib/Stack'; import * as React from 'react'; +import { IContextualMenuItem } from '@fluentui/react/lib/ContextualMenu'; import { PropertyItem } from '../../types'; @@ -23,7 +25,7 @@ const toggleExpandIconStyle: IIconStyles = { fontSize: 8, transition: 'background 250ms ease', selectors: { - '&:hover': { background: NeutralColors.gray50 }, + '&:hover, &:focus-within': { background: NeutralColors.gray50 }, '&:before': { content: '""', }, @@ -32,7 +34,9 @@ const toggleExpandIconStyle: IIconStyles = { }; const Root = styled(Stack)({ + width: '100%', height: DEFAULT_TREE_ITEM_HEIGHT, + border: 'none', }); const Content = styled(Stack)<{ @@ -42,6 +46,10 @@ const Content = styled(Stack)<{ })); type PropertyTreeItemProps = { + onClick?: ( + ev?: React.MouseEvent | React.KeyboardEvent, + item?: IContextualMenuItem + ) => boolean | void; item: PropertyItem; level: number; onRenderLabel: (item: PropertyItem) => React.ReactNode; @@ -50,7 +58,7 @@ type PropertyTreeItemProps = { }; export const PropertyTreeItem = React.memo((props: PropertyTreeItemProps) => { - const { expanded = false, item, level, onToggleExpand, onRenderLabel } = props; + const { expanded = false, item, level, onToggleExpand, onRenderLabel, ...rest } = props; const paddingLeft = level * DEFAULT_INDENTATION_PADDING; @@ -65,7 +73,18 @@ export const PropertyTreeItem = React.memo((props: PropertyTreeItemProps) => { const isExpandable = !!item.children?.length && onToggleExpand; return ( - + {isExpandable ? ( { setPropertyTreeExpanded({ ...propertyTreeExpanded, [itemId]: expanded }); }; - return nodes.map((node) => ({ + return nodes.map((node, index) => ({ key: node.id, text: node.name, secondaryText: paths[node.id], @@ -234,6 +234,7 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { path: paths[node.id], level: levels[node.id] - 1, onToggleExpand, + index, }, })); } @@ -266,7 +267,7 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { const { root, onSelectProperty } = propertyTreeConfig; const { nodes, paths } = getAllNodes(root, { skipRoot: true }); - return nodes.map((node) => ({ + return nodes.map((node, index) => ({ text: node.id, key: node.id, secondaryText: paths[node.id], @@ -278,6 +279,7 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { node, path: paths[node.id], level: 0, + index, }, })) as IContextualMenuItem[]; } @@ -341,9 +343,11 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { } }, [menuItems, flatPropertyListItems, flatFunctionListItems, noSearchResultMenuItem, query, payload.kind]); + const menuButtonRef = React.useRef(null); const onMenuDismissed = React.useCallback(() => { onReset(); setPropertyTreeExpanded({}); + menuButtonRef?.current?.focus(); }, []); const menuProps: IContextualMenuProps = React.useMemo(() => { @@ -378,64 +382,70 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { } as IContextualMenuProps; } case 'property': { + const renderMenuItem = (item: IContextualMenuItem) => { + const { secondaryText: path } = item; + const { onToggleExpand, level, node, index } = item.data as { + node: PropertyItem; + onToggleExpand: (itemId: string, expanded: boolean) => void; + level: number; + index: number; + }; + + const renderLabel = () => { + const pathNodes = (path ?? '').split('.'); + return ( + + {pathNodes.map((pathNode, idx) => ( + + {`${pathNode}${idx === pathNodes.length - 1 && node.children.length === 0 ? '' : '.'}`} + + ))} + + ); + }; + + const renderSearchResultLabel = () => ( + + {path} + + ); + + return ( + + ); + }; return { onMenuDismissed, - items, + items: items.map((item) => ({ + ...item, + onRender: renderMenuItem, + })), calloutProps, onRenderMenuList, - contextualMenuItemAs: (itemProps: IContextualMenuItemProps) => { - const { - item: { secondaryText: path }, - } = itemProps; - const { onToggleExpand, level, node } = itemProps.item.data as { - node: PropertyItem; - onToggleExpand: (itemId: string, expanded: boolean) => void; - level: number; - }; - - const renderLabel = () => { - const pathNodes = (path ?? '').split('.'); - return ( - - {pathNodes.map((pathNode, idx) => ( - - {`${pathNode}${idx === pathNodes.length - 1 && node.children.length === 0 ? '' : '.'}`} - - ))} - - ); - }; - - const renderSearchResultLabel = () => ( - - {path} - - ); - - return ( - - ); - }, } as IContextualMenuProps; } } @@ -449,6 +459,7 @@ export const ToolbarButtonMenu = React.memo((props: ToolbarButtonMenuProps) => { className={dismissHandlerClassName} data-testid="menuButton" disabled={disabled} + elementRef={menuButtonRef} menuProps={menuProps} styles={buttonStyles} onRenderIcon={renderIcon} diff --git a/extensions/azurePublish/src/components/azureProvisionDialog.tsx b/extensions/azurePublish/src/components/azureProvisionDialog.tsx index ef0ab9f2f8..9d56c37c3d 100644 --- a/extensions/azurePublish/src/components/azureProvisionDialog.tsx +++ b/extensions/azurePublish/src/components/azureProvisionDialog.tsx @@ -818,7 +818,7 @@ export const AzureProvisionDialog: React.FC = () => { {renderPropertyInfoIcon(formatMessage('The subscription that will be billed for the resources.'))} { {renderPropertyInfoIcon(formatMessage('The region where your resources and bot will be used.'))} {