Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ export const ElementMeasurer: React.FC<ElementMeasurerProps> = ({ children, styl
return (
<Measure
bounds
onResize={({ bounds: { width, height } }) => {
onResize={({ bounds }) => {
/**
* As a parent node, <Measure /> mounted before children mounted.
* Avoid flickering issue by filtering out the first onResize event.
*/
const { width, height } = bounds ?? { width: 0, height: 0 };
if (width === 0 && height === 0) return;
onResize(new Boundary(width, height));
}}
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
"@bfc/indexers": "*",
"@bfc/shared": "*",
"@bfc/ui-plugin-composer": "*",
"@bfc/ui-plugin-cross-trained": "*",
"@bfc/ui-plugin-dialog-schema-editor": "*",
"@bfc/ui-plugin-lg": "*",
"@bfc/ui-plugin-luis": "*",
"@bfc/ui-plugin-cross-trained": "*",
"@bfc/ui-plugin-prompts": "*",
"@bfc/ui-plugin-select-dialog": "*",
"@bfc/ui-plugin-select-skill-dialog": "*",
Expand All @@ -49,6 +49,7 @@
"office-ui-fabric-react": "^7.121.11",
"prop-types": "^15.7.2",
"query-string": "^6.8.2",
"react-measure": "^2.3.0",
"re-resizable": "^6.3.2",
"react": "16.13.0",
"react-app-polyfill": "^0.2.1",
Expand Down
56 changes: 18 additions & 38 deletions Composer/packages/client/src/components/NavTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,19 @@

/** @jsx jsx */
import { jsx, css } from '@emotion/core';
import { Resizable, ResizeCallback } from 're-resizable';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import { FontWeights, FontSizes } from 'office-ui-fabric-react/lib/Styling';
import { NeutralColors } from '@uifabric/fluent-theme';
import { IButtonStyles } from 'office-ui-fabric-react/lib/Button';
import { mergeStyleSets } from 'office-ui-fabric-react/lib/Styling';
import { useRecoilValue } from 'recoil';

import { navigateTo } from '../utils/navigation';
import { dispatcherState, userSettingsState } from '../recoilModel';

// -------------------- Styles -------------------- //

const root = css`
width: 100%;
height: 100%;
border-right: 1px solid #c4c4c4;
box-sizing: border-box;
overflow-y: auto;
overflow-x: hidden;
Expand Down Expand Up @@ -75,43 +71,27 @@ interface INavTreeProps {

const NavTree: React.FC<INavTreeProps> = (props) => {
const { navLinks, regionName } = props;
const { updateUserSettings } = useRecoilValue(dispatcherState);
const { dialogNavWidth: currentWidth } = useRecoilValue(userSettingsState);

const handleResize: ResizeCallback = (_e, _dir, _ref, d) => {
updateUserSettings({ dialogNavWidth: currentWidth + d.width });
};

return (
<Resizable
enable={{
right: true,
}}
maxWidth={500}
minWidth={180}
size={{ width: currentWidth, height: 'auto' }}
onResizeStop={handleResize}
>
<div aria-label={regionName} className="ProjectTree" css={root} data-testid="ProjectTree" role="region">
{navLinks.map((item) => {
const isSelected = location.pathname.includes(item.url);
<div aria-label={regionName} className="ProjectTree" css={root} data-testid="ProjectTree" role="region">
{navLinks.map((item) => {
const isSelected = location.pathname.includes(item.url);

return (
<DefaultButton
key={item.id}
disabled={item.disabled}
href={item.url}
styles={isSelected ? itemSelected : itemNotSelected}
text={item.name}
onClick={(e) => {
e.preventDefault();
navigateTo(item.url);
}}
/>
);
})}
</div>
</Resizable>
return (
<DefaultButton
key={item.id}
disabled={item.disabled}
href={item.url}
styles={isSelected ? itemSelected : itemNotSelected}
text={item.name}
onClick={(e) => {
e.preventDefault();
navigateTo(item.url);
}}
/>
);
})}
</div>
);
};

Expand Down
14 changes: 9 additions & 5 deletions Composer/packages/client/src/components/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { jsx, css } from '@emotion/core';
import React from 'react';
import { FontWeights, FontSizes } from 'office-ui-fabric-react/lib/Styling';

import { LeftRightSplit } from '../components/Split/LeftRightSplit';

import { Toolbar, IToolbarItem } from './Toolbar';
import { NavTree, INavTreeItem } from './NavTree';

Expand Down Expand Up @@ -72,7 +74,7 @@ export const content = css`
padding: 20px;
position: relative;
overflow: auto;

height: 100%;
label: PageContent;
`;

Expand Down Expand Up @@ -101,10 +103,12 @@ const Page: React.FC<IPageProps> = (props) => {
{onRenderHeaderContent && <div css={headerContent}>{onRenderHeaderContent()}</div>}
</div>
<div css={main} role="main">
<NavTree navLinks={navLinks} regionName={navRegionName} />
<div aria-label={mainRegionName} css={content} data-testid="PageContent" role="region">
{children}
</div>
<LeftRightSplit initialLeftGridWidth="20%" minLeftPixels={200} minRightPixels={800}>
<NavTree navLinks={navLinks} regionName={navRegionName} />
<div aria-label={mainRegionName} css={content} data-testid="PageContent" role="region">
{children}
</div>
</LeftRightSplit>
</div>
</div>
</div>
Expand Down
99 changes: 41 additions & 58 deletions Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ import { FocusZone, FocusZoneDirection } from 'office-ui-fabric-react/lib/FocusZ
import cloneDeep from 'lodash/cloneDeep';
import formatMessage from 'format-message';
import { DialogInfo, ITrigger } from '@bfc/shared';
import { Resizable, ResizeCallback } from 're-resizable';
import debounce from 'lodash/debounce';
import { useRecoilValue } from 'recoil';
import { IGroupedListStyles } from 'office-ui-fabric-react/lib/GroupedList';
import { ISearchBoxStyles } from 'office-ui-fabric-react/lib/SearchBox';

import { dispatcherState, userSettingsState } from '../../recoilModel';
import { dispatcherState } from '../../recoilModel';
import { createSelectedPath, getFriendlyName } from '../../utils/dialogUtil';
import { containUnsupportedTriggers, triggerNotSupported } from '../../utils/dialogValidator';

Expand All @@ -48,7 +47,6 @@ const searchBox: ISearchBoxStyles = {
const root = css`
width: 100%;
height: 100%;
border-right: 1px solid #c4c4c4;
box-sizing: border-box;
overflow-y: auto;
overflow-x: hidden;
Expand Down Expand Up @@ -130,8 +128,7 @@ interface IProjectTreeProps {
}

export const ProjectTree: React.FC<IProjectTreeProps> = (props) => {
const { onboardingAddCoachMarkRef, updateUserSettings } = useRecoilValue(dispatcherState);
const { dialogNavWidth: currentWidth } = useRecoilValue(userSettingsState);
const { onboardingAddCoachMarkRef } = useRecoilValue(dispatcherState);

const groupRef: React.RefObject<IGroupedList> = useRef(null);
const { dialogs, dialogId, selected, onSelect, onDeleteTrigger, onDeleteDialog } = props;
Expand Down Expand Up @@ -185,41 +182,28 @@ export const ProjectTree: React.FC<IProjectTreeProps> = (props) => {
}
};

const handleResize: ResizeCallback = (_e, _dir, _ref, d) => {
updateUserSettings({ dialogNavWidth: currentWidth + d.width });
};

const itemsAndGroups: { items: any[]; groups: IGroup[] } = createItemsAndGroups(sortedDialogs, dialogId, filter);

return (
<Resizable
enable={{
right: true,
}}
maxWidth={500}
minWidth={180}
size={{ width: currentWidth, height: 'auto' }}
onResizeStop={handleResize}
<div
aria-label={formatMessage('Navigation pane')}
className="ProjectTree"
css={root}
data-testid="ProjectTree"
role="region"
>
<div
aria-label={formatMessage('Navigation pane')}
className="ProjectTree"
css={root}
data-testid="ProjectTree"
role="region"
>
<FocusZone isCircularNavigation direction={FocusZoneDirection.vertical}>
<SearchBox
underlined
ariaLabel={formatMessage('Type dialog name')}
iconProps={{ iconName: 'Filter' }}
placeholder={formatMessage('Filter Dialog')}
styles={searchBox}
onChange={onFilter}
/>
<div
aria-label={formatMessage(
`{
<FocusZone isCircularNavigation direction={FocusZoneDirection.vertical}>
<SearchBox
underlined
ariaLabel={formatMessage('Type dialog name')}
iconProps={{ iconName: 'Filter' }}
placeholder={formatMessage('Filter Dialog')}
styles={searchBox}
onChange={onFilter}
/>
<div
aria-label={formatMessage(
`{
dialogNum, plural,
=0 {No dialogs}
=1 {One dialog}
Expand All @@ -230,27 +214,26 @@ export const ProjectTree: React.FC<IProjectTreeProps> = (props) => {
0 {}
other {Press down arrow key to navigate the search results}
}`,
{ dialogNum: itemsAndGroups.groups.length }
)}
aria-live={'polite'}
/>
<GroupedList
{...itemsAndGroups}
componentRef={groupRef}
groupProps={
{
onRenderHeader: onRenderHeader,
onRenderShowAll: onRenderShowAll,
showEmptyGroups: true,
showAllProps: false,
isAllGroupsCollapsed: true,
} as Partial<IGroupRenderProps>
}
styles={groupListStyle}
onRenderCell={onRenderCell}
/>
</FocusZone>
</div>
</Resizable>
{ dialogNum: itemsAndGroups.groups.length }
)}
aria-live={'polite'}
/>
<GroupedList
{...itemsAndGroups}
componentRef={groupRef}
groupProps={
{
onRenderHeader: onRenderHeader,
onRenderShowAll: onRenderShowAll,
showEmptyGroups: true,
showAllProps: false,
isAllGroupsCollapsed: true,
} as Partial<IGroupRenderProps>
}
styles={groupListStyle}
onRenderCell={onRenderCell}
/>
</FocusZone>
</div>
);
};
Loading