Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
2 changes: 2 additions & 0 deletions Composer/packages/client/src/components/EditableField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { mergeStyleSets } from '@fluentui/style-utilities';
import { IconButton } from '@fluentui/react/lib/Button';
import { IIconProps } from '@fluentui/react/lib/Icon';
import { Announced } from '@fluentui/react/lib/Announced';
import formatMessage from 'format-message';

import { FieldConfig, useForm } from '../hooks/useForm';
import { useAfterRender } from '../hooks/useAfterRender';
Expand Down Expand Up @@ -296,6 +297,7 @@ const EditableField: React.FC<EditableFieldProps> = (props) => {
/>
{enableIcon && (
<IconButton
aria-label={formatMessage('Remove item {name}', { name: formData.value })}
iconProps={{
iconName: iconProps?.iconName,
styles: mergeStyleSets(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const GetStarted: React.FC<GetStartedProps> = (props) => {

return (
<Panel
closeButtonAriaLabel={formatMessage('Close Get Started panel')}
customWidth="395px"
isBlocking={false}
isOpen={props.isOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
/** @jsx jsx */
import { jsx } from '@emotion/core';
import React from 'react';
import { ActionButton, DefaultButton, IButtonStyles, IconButton } from '@fluentui/react/lib/Button';
import { ActionButton, IButtonStyles, IconButton } from '@fluentui/react/lib/Button';
import { IContextualMenuProps } from '@fluentui/react/lib/ContextualMenu';
import formatMessage from 'format-message';
import { CommunicationColors, NeutralColors } from '@fluentui/theme';
import { SplitButton } from '@bfc/ui-shared';

import { RestartOption } from './types';

Expand All @@ -27,7 +28,7 @@ const customButtonStyles: IButtonStyles = {
splitButtonDivider: {
backgroundColor: `${NeutralColors.gray50}`,
width: 1,
right: 26,
right: 28,
position: 'absolute',
top: 4,
bottom: 4,
Expand Down Expand Up @@ -112,8 +113,7 @@ export const WebChatHeader: React.FC<WebChatHeaderProps> = ({
onClick={onCloseWebChat}
/>
</h4>
<DefaultButton
split
<SplitButton
aria-roledescription="split button"
ariaLabel="restart-conversation"
disabled={isRestartButtonDisabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { FontSizes } from '@fluentui/theme';
import { Resizable } from 're-resizable';
import { Label } from '@fluentui/react/lib/Label';
import { useRecoilValue } from 'recoil';
import { useId } from '@fluentui/react-hooks';

import TelemetryClient from '../../../telemetry/TelemetryClient';
import { debugPanelExpansionState, debugPanelActiveTabState, dispatcherState } from '../../../recoilModel';
Expand All @@ -37,6 +38,7 @@ export const DebugPanel: React.FC = () => {
const isPanelExpanded = useRecoilValue(debugPanelExpansionState);
const activeTab = useRecoilValue(debugPanelActiveTabState);
const pivotRef = useRef<IPivot>(null);
const contentId = useId('debug-panel-content');

useEffect(() => {
if (isPanelExpanded) {
Expand Down Expand Up @@ -170,15 +172,20 @@ export const DebugPanel: React.FC = () => {
{headerPivot}
</div>
<div
aria-controls={contentId}
aria-expanded={isPanelExpanded ? 'true' : 'false'}
aria-label={formatMessage('Toggle debug panel')}
css={{ flexGrow: 1, cursor: 'pointer', outline: 'none' }}
data-testid="header__blank"
role="button"
tabIndex={0}
tabIndex={-1}
onClick={onDebugPaneClick}
onKeyPress={onDebugPaneClick}
/>
<div css={rightBarStyle} data-testid="header__right">
<IconButton
aria-controls={contentId}
aria-expanded={isPanelExpanded ? 'true' : 'false'}
iconProps={{ iconName: isPanelExpanded ? 'ChevronDown' : 'ChevronUp' }}
styles={{ root: { height: '100%' } }}
title={isPanelExpanded ? formatMessage('Collapse Debug Panel') : formatMessage('Expand Debug Panel')}
Expand All @@ -192,7 +199,13 @@ export const DebugPanel: React.FC = () => {
/>
</div>
</div>
<div css={debugPaneContentStyle} data-testid="debug-panel__content">
<div
aria-label={formatMessage('Debug panel tab content')}
css={debugPaneContentStyle}
data-testid="debug-panel__content"
id={contentId}
role="region"
>
{debugExtensions.map((debugTabs) => {
const { ContentWidget } = debugTabs;
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export const DiagnosticsFilters: React.FC<DiagnosticsFiltersProps> = (props) =>
}}
>
<DropdownWithAllOption
aria-label={formatMessage('Select bots to display problems for')}
optionAll={optionAll}
options={projectSelectorOptions}
placeholder={formatMessage('Select bots')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ const TableView: React.FC<TableViewProps> = (props) => {
const onRenderItem = (item: IOverflowSetItemProps): JSX.Element => {
return (
<IconButton
aria-Label={formatMessage('Edit knowledge base name')}
menuIconProps={{ iconName: 'Edit' }}
styles={{
root: {
Expand Down
7 changes: 5 additions & 2 deletions Composer/packages/client/src/pages/publish/BotStatusList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ export const BotStatusList: React.FC<BotStatusListProps> = ({
onRender: (item: BotStatus) => {
return (
<Dropdown
aria-label={formatMessage('Publish target')}
options={getPublishTargetOptions(item)}
placeholder={formatMessage('Select a publish target')}
selectedKey={item.publishTarget}
Expand Down Expand Up @@ -300,7 +301,7 @@ export const BotStatusList: React.FC<BotStatusListProps> = ({
},
{
key: 'SkillManifest',
name: '',
name: formatMessage('Manifest'),
className: 'skillManifest',
fieldName: 'skillManifestUrl',
minWidth: 134,
Expand All @@ -313,7 +314,7 @@ export const BotStatusList: React.FC<BotStatusListProps> = ({
},
{
key: 'ShowPublishHistory',
name: '',
name: formatMessage('History'),
className: 'showHistory',
fieldName: 'showHistory',
minWidth: 150,
Expand All @@ -325,6 +326,8 @@ export const BotStatusList: React.FC<BotStatusListProps> = ({
onRender: (item: BotStatus) => {
return (
<IconButton
aria-expanded={expandedBotIds[item.id] ? 'true' : 'false'}
aria-label={formatMessage('Show {name} publish history', { name: item.name })}
iconProps={{ iconName: expandedBotIds[item.id] ? 'ChevronDown' : 'ChevronRight' }}
styles={{ root: { float: 'right' } }}
onClick={() => onChangeShowHistoryBots(item)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const FieldLabel = React.memo((props: Props) => {
<Stack horizontal tokens={{ childrenGap: 4 }} verticalAlign="center">
{props.defaultRender}
{props.optional ? <Text styles={{ root: { fontStyle: 'italic' } }}>({formatMessage('optional')})</Text> : null}
<HelpTooltip helpMessage={props.helpText} tooltipId={props.tooltipId} />
<HelpTooltip aria-label={props.helpText} helpMessage={props.helpText} tooltipId={props.tooltipId} />
</Stack>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,20 @@ const InternalPropertyList = React.memo((props: Props) => (

export const PropertyList = (props: Props) => {
const { kind } = props;
const helpText =
kind === 'required'
? formatMessage(
'Required properties are properties that your bot will ask the user to provide. The user must provide values for all required properties.'
)
: formatMessage('Optional properties are properties the bot accepts if given but does not ask for.');

return (
<Root horizontalAlign="center">
<Header horizontal tokens={{ childrenGap: 8 }} verticalAlign="center">
<HeaderText>
{kind === 'required' ? formatMessage('Required properties') : formatMessage('Optional properties')}
</HeaderText>
<HelpTooltip
helpMessage={
kind === 'required'
? formatMessage(
'Required properties are properties that your bot will ask the user to provide. The user must provide values for all required properties.'
)
: formatMessage('Optional properties are properties the bot accepts if given but does not ask for.')
}
tooltipId={`${kind}-tooltip`}
/>
<HelpTooltip aria-label={helpText} helpMessage={helpText} tooltipId={`${kind}-tooltip`} />
</Header>
<Droppable direction="vertical" droppableId={kind}>
{(provided, { isDraggingOver }) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const RequiredPriorityIndicator = React.memo((props: Props) => {
help: ({ children }) => (
<HelpTooltip
key={`${propertyId}-priority-tooltip`}
aria-label={children}
helpMessage={children}
tooltipId={`${propertyId}-priority-tooltip`}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const HelpIconTooltip = React.memo(
}: {
tooltipId: string;
helpMessage: string | JSX.Element | JSX.Element[];
tooltipProps?: Partial<HelpTooltipProps>;
tooltipProps: HelpTooltipProps;
}) => {
return (
<HelpTooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { HelpIconTooltip } from './HelpIconTooltip';
const containerTokens = { childrenGap: 4 };

type Props = {
'aria-label': string;
tooltipId: string;
itemText: string | JSX.Element | JSX.Element[] | React.ReactNode;
tooltipText: string | JSX.Element | JSX.Element[];
Expand All @@ -19,9 +20,18 @@ type Props = {

const defaultRender = (text: string) => <Text variant="small">{text}</Text>;

export const ItemWithTooltip = React.memo(({ tooltipId, itemText, tooltipText: helpMessage, tooltipProps }: Props) => (
<Stack horizontal tokens={containerTokens} verticalAlign="center">
{typeof itemText === 'string' ? defaultRender(itemText) : itemText}
<HelpIconTooltip helpMessage={helpMessage} tooltipId={tooltipId} tooltipProps={tooltipProps} />
</Stack>
));
export const ItemWithTooltip = React.memo(
({ tooltipId, itemText, tooltipText: helpMessage, tooltipProps, ...props }: Props) => (
<Stack horizontal tokens={containerTokens} verticalAlign="center">
{typeof itemText === 'string' ? defaultRender(itemText) : itemText}
<HelpIconTooltip
helpMessage={helpMessage}
tooltipId={tooltipId}
tooltipProps={{
...props,
...tooltipProps,
}}
/>
</Stack>
)
);
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const LgSpeechModalityToolbar = React.memo((props: Props) => {
const renderHeaderContent = React.useCallback(
(itemProps: IContextualMenuItemProps, defaultRenders: IContextualMenuItemRenderFunctions) => (
<ItemWithTooltip
aria-label={formatMessage('Learn more about SSML Tags')}
itemText={defaultRenders.renderItemName(itemProps)}
tooltipId="ssml-menu-header"
tooltipProps={ssmlHeaderTooltipProps}
Expand Down
9 changes: 8 additions & 1 deletion Composer/packages/lib/code-editor/src/lg/ModalityPivot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ export const ModalityPivot = React.memo((props: Props) => {
(itemProps: IContextualMenuItemProps, defaultRenders: IContextualMenuItemRenderFunctions) =>
itemProps.item.itemType === ContextualMenuItemType.Header ? (
<ItemWithTooltip
aria-label={formatMessage('Learn more about adding more to this response')}
itemText={defaultRenders.renderItemName(itemProps)}
tooltipId="modality-add-menu-header"
tooltipText={formatMessage.rich('To learn more, <a>visit this document</a>.', {
Expand All @@ -217,6 +218,7 @@ export const ModalityPivot = React.memo((props: Props) => {
/>
) : (
<ItemWithTooltip
aria-label={formatMessage('Learn more about {item}', { item: itemProps.item.text })}
itemText={defaultRenders.renderItemName(itemProps)}
tooltipId={itemProps.item.key}
tooltipText={getModalityTooltipText(itemProps.item.key as ModalityType)}
Expand Down Expand Up @@ -393,7 +395,12 @@ export const ModalityPivot = React.memo((props: Props) => {
))}
</Pivot>
{menuItems.filter((item) => item.itemType !== ContextualMenuItemType.Header).length && (
<IconButton iconProps={addButtonIconProps} menuProps={addMenuProps} onRenderMenuIcon={() => null} />
<IconButton
aria-label={formatMessage('Add more to this response')}
iconProps={addButtonIconProps}
menuProps={addMenuProps}
onRenderMenuIcon={() => null}
/>
)}
</Stack>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const ModalityEditorContainer: React.FC<Props> = ({
): JSX.Element | null =>
itemProps?.itemType === DropdownMenuItemType.Header ? (
<ItemWithTooltip
aria-label={formatMessage('Learn more about {option}', { option: itemProps.text })}
itemText={defaultRender?.(itemProps)}
tooltipId={itemProps?.data?.tooltipId}
tooltipText={itemProps?.data?.tooltipText}
Expand Down Expand Up @@ -193,6 +194,7 @@ export const ModalityEditorContainer: React.FC<Props> = ({
<OverflowSet
items={[]}
overflowItems={overflowMenuItems}
role="menu"
onRenderItem={() => null}
onRenderOverflowButton={onRenderOverflowButton}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import { ModalityType } from '../types';
const labelStyles = { root: { fontSize: FluentTheme.fonts.small.fontSize } };

type Props = {
title: string | JSX.Element | JSX.Element[];
title: string;
modalityType: ModalityType;
helpMessage: string | JSX.Element | JSX.Element[];
};

export const ModalityEditorTitle = React.memo(({ title, modalityType, helpMessage }: Props) => (
<ItemWithTooltip
aria-label={title}
itemText={<Label styles={labelStyles}>{title}</Label>}
tooltipId={`${modalityType}ModalityTitle`}
tooltipText={helpMessage}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ const TextViewItem = React.memo(
{onRenderDisplayText?.() ?? value.replace(/\r?\n/g, '↵')}
</Text>
</Stack>
<RemoveIcon className={removeIconClassName} iconProps={{ iconName: 'Trash' }} tabIndex={-1} onClick={remove} />
<RemoveIcon
ariaLabel={formatMessage('Remove item')}
className={removeIconClassName}
iconProps={{ iconName: 'Trash' }}
tabIndex={-1}
onClick={remove}
/>
</TextViewItemRoot>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export const DefineEntityButton = React.memo((props: Props) => {
const renderMenuItemHeader = React.useCallback(
(itemProps: IContextualMenuItemProps, defaultRenders: IContextualMenuItemRenderFunctions) => (
<ItemWithTooltip
aria-label={formatMessage('Learn more about {item}', { item: itemProps.item.text })}
itemText={defaultRenders.renderItemName(itemProps)}
tooltipId="define-entity-menu-header"
tooltipText={formatMessage.rich('Visit <a>this page</a> to learn more about entity definition.', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type HelpTooltipStyles = IStyleFunctionOrObject<
>;

export type HelpTooltipProps = Omit<ITooltipHostProps, 'styles'> & {
'aria-label': string;
iconProps?: IIconProps & { 'data-testid'?: string };
styles?: HelpTooltipStyles;
};
Expand All @@ -57,6 +58,7 @@ export const HelpTooltip: React.FC<HelpTooltipProps> = ({ iconProps, ...props })
return (
<TooltipHost {...props} styles={classNames}>
<Icon
data-is-focusable
aria-label={props['aria-label']}
className={classNames.helpIcon}
iconName="Unknown"
Expand Down
Loading