Skip to content

Commit

Permalink
Coachmark: Migrate Coachmark and associated components to function co…
Browse files Browse the repository at this point in the history
…mponents (microsoft#13626)

* Copy Coachmark code to react-next to stage migration

* Change files

* Migrate Beak to function component

* Add stub function component for PositioningContainer

* Hoist default props and contentHost ref

* Hoist several refs

* Fix lint issues

* Hoist event logic

* Update API

* Cleanup

* Hoist heightOffset logic

* Finish migration (with issues)

* Revert to LKG, fixing example import

* Hoist positionedHost ref

* Hoist target refs

* Hoist positions state

* Hoist setInitialFocus

* Hoist maxHeight

* Hoist auto-dismiss events

* Hoist heightOffset

* Complete PositioningContainer migration

* Remove extraneous shouldComponentUpdate

* Hoist generic function

* Create stub function component

* Hoist entityInnerHostElementRef

* Hoist isCollapsed state

* Hoist positioned data

* Hoist beak positioning logic

* Hoist dismiss public method

* Hoist document event logic

* Hoist proximity handlers

* Hoist aria text logic

* Cleanup unused state

* Hoist autofocus logic

* Hoist last of state

* Finish migration

* Forward ref

* Update API

* Change files

* Add Screener test

* Fix lint error

* Fix cropping of Coachmark story

* Fix case where Coahmark starts expanded

* Fix API file

* Pull from react-next

* Fix bad merge

* Duplicate Coachamrk Screener test for OUFR

* Remove headers

* Handle removed props

* Deprecate Beak componentRef

* Update packages/react-next/src/components/Coachmark/Coachmark.base.tsx

Co-authored-by: Elizabeth Craig <ecraig12345@gmail.com>

* Fix eslint deprecation errors

* Change files

* Update API

* Fix build error

* Fix build issues

* Remove rejected screener story

Co-authored-by: Elizabeth Craig <ecraig12345@gmail.com>
  • Loading branch information
2 people authored and Trip Master committed Aug 10, 2020
1 parent 8294497 commit d8fc677
Show file tree
Hide file tree
Showing 19 changed files with 987 additions and 979 deletions.
1 change: 1 addition & 0 deletions apps/vr-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@uifabric/example-data": "^7.0.21",
"@uifabric/experiments": "^7.27.16",
"@uifabric/react-cards": "^0.110.14",
"@uifabric/react-hooks": "^7.7.1",
"@uifabric/set-version": "^7.0.19",
"office-ui-fabric-react": "^7.125.0",
"react": "16.8.6",
Expand Down
65 changes: 65 additions & 0 deletions apps/vr-tests/src/stories/Coachmark.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import * as React from 'react';
import Screener from 'screener-storybook/src/screener';
import { storiesOf } from '@storybook/react';
import { FabricDecorator } from '../utilities';
import { Coachmark, DirectionalHint, TeachingBubbleContent, Fabric } from 'office-ui-fabric-react';
import { useId } from '@uifabric/react-hooks';
import { DefaultButton } from 'office-ui-fabric-react';

const CoachmarkUsage = ({ isCollapsed = true }: { isCollapsed?: boolean }) => {
const targetId = useId();
return (
<>
<div id={targetId}>
<DefaultButton text="Click me!" />
</div>
<Coachmark
target={`#${targetId}`}
positioningContainerProps={{
directionalHint: DirectionalHint.rightTopEdge,
doNotLayer: false,
}}
ariaAlertText="A Coachmark has appeared"
ariaDescribedBy={'coachmark-desc1'}
ariaLabelledBy={'coachmark-label1'}
ariaDescribedByText={'Press enter or alt + C to open the Coachmark notification'}
ariaLabelledByText={'Coachmark notification'}
isCollapsed={isCollapsed}
>
<TeachingBubbleContent
headline="Example Title"
hasCloseButton={true}
closeButtonAriaLabel="Close"
primaryButtonProps={{
text: 'Try it',
}}
secondaryButtonProps={{
text: 'Try it',
}}
ariaDescribedBy={'example-description1'}
ariaLabelledBy={'example-label1'}
>
Welcome to the land of Coachmarks!
</TeachingBubbleContent>
</Coachmark>
</>
);
};

storiesOf('Coachmark', module)
.addDecorator(FabricDecorator)
.addDecorator(story =>
// prettier-ignore
<Screener
steps={new Screener.Steps()
.snapshot('default', { cropTo: '.ms-PositioningContainer' })
.end()}
>
{story()}
</Screener>,
)
.addStory('Collapsed', () => (
<Fabric>
<CoachmarkUsage />
</Fabric>
));
70 changes: 70 additions & 0 deletions apps/vr-tests/src/stories/CoachmarkNext.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import * as React from 'react';
import Screener from 'screener-storybook/src/screener';
import { storiesOf } from '@storybook/react';
import { FabricDecorator } from '../utilities';
import { Coachmark, DirectionalHint, TeachingBubbleContent, Fabric } from '@fluentui/react-next';
import { useId } from '@uifabric/react-hooks';
import { DefaultButton } from 'office-ui-fabric-react';

const CoachmarkUsage = ({ isCollapsed = true }: { isCollapsed?: boolean }) => {
const targetId = useId();
return (
<>
<div id={targetId}>
<DefaultButton text="Click me!" />
</div>
<Coachmark
target={`#${targetId}`}
positioningContainerProps={{
directionalHint: DirectionalHint.rightTopEdge,
doNotLayer: false,
}}
ariaAlertText="A Coachmark has appeared"
ariaDescribedBy={'coachmark-desc1'}
ariaLabelledBy={'coachmark-label1'}
ariaDescribedByText={'Press enter or alt + C to open the Coachmark notification'}
ariaLabelledByText={'Coachmark notification'}
isCollapsed={isCollapsed}
>
<TeachingBubbleContent
headline="Example Title"
hasCloseButton={true}
closeButtonAriaLabel="Close"
primaryButtonProps={{
text: 'Try it',
}}
secondaryButtonProps={{
text: 'Try it',
}}
ariaDescribedBy={'example-description1'}
ariaLabelledBy={'example-label1'}
>
Welcome to the land of Coachmarks!
</TeachingBubbleContent>
</Coachmark>
</>
);
};

storiesOf('Coachmark Next', module)
.addDecorator(FabricDecorator)
.addDecorator(story =>
// prettier-ignore
<Screener
steps={new Screener.Steps()
.snapshot('default', { cropTo: '.ms-PositioningContainer' })
.end()}
>
{story()}
</Screener>,
)
.addStory('Collapsed', () => (
<Fabric>
<CoachmarkUsage />
</Fabric>
))
.addStory('Expanded', () => (
<Fabric>
<CoachmarkUsage isCollapsed={false} />
</Fabric>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "prerelease",
"comment": "Migrate Coachmark and associated components to function components",
"packageName": "@fluentui/react-next",
"email": "miclo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-06-16T19:31:01.423Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "Add deprecation notices",
"packageName": "office-ui-fabric-react",
"email": "miclo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-07-15T18:41:40.248Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2395,8 +2395,10 @@ export interface ICoachmarkStyleProps {
entityHostHeight?: string;
entityHostWidth?: string;
height?: string;
// @deprecated
isBeaconAnimating: boolean;
isCollapsed: boolean;
// @deprecated
isMeasured: boolean;
isMeasuring: boolean;
theme?: ITheme;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface IBeak {}
export interface IBeakProps extends IBaseProps<IBeak> {
/**
* All props for your component are to be defined here.
* @deprecated
*/
componentRef?: IRefObject<IBeak>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,10 @@ export function getStyles(props: ICoachmarkStyleProps): ICoachmarkStyles {
beaconColorTwo,
delayBeforeCoachmarkAnimation,
isCollapsed,
// eslint-disable-next-line deprecation/deprecation
isBeaconAnimating,
isMeasuring,
// eslint-disable-next-line deprecation/deprecation
isMeasured,
entityHostHeight,
entityHostWidth,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ export interface ICoachmarkStyleProps {

/**
* Is the beacon currently animating.
* @deprecated Property is never used
*/
isBeaconAnimating: boolean;

Expand All @@ -241,6 +242,7 @@ export interface ICoachmarkStyleProps {

/**
* Is the Coachmark finished measuring the dimensions of innerHostElement
* @deprecated Value is always the inverse of `isMeasuring`
*/
isMeasured: boolean;

Expand Down
9 changes: 9 additions & 0 deletions packages/react-next/RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Breaking changes

### Beak

- Removed empty `IBeak` interface
- Removed `componentRef` prop

### SpinButton

- Simplified props to `ISpinButtonStyles` to include only the parts of the component to bring inline with
Expand All @@ -16,6 +21,10 @@
- Deprecated `onRenderLabel`.
- Added `label`/`checkmark` slot props.

### Coachmark

- Removed `isBeaconAnimating` and `isMeasured` style props

### Pivot

- Removed deprecated and redundant props from v7, including: `initialSelectedKey` and `defaultSelectedIndex`. Use `selectedKey` or `defaultSelectedKey` to define the selected tab, and provide `itemKey` on pivot item children.
Expand Down
89 changes: 11 additions & 78 deletions packages/react-next/etc/react-next.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { IWithResponsiveModeState } from 'office-ui-fabric-react/lib/utilities/d
import { Point } from 'office-ui-fabric-react/lib/Utilities';
import { Position } from 'office-ui-fabric-react/lib/utilities/positioning';
import * as React from 'react';
import { RectangleEdge } from 'office-ui-fabric-react/lib/utilities/positioning';
import { ReactNode } from 'react';
import { Selection } from 'office-ui-fabric-react/lib/Selection';
import { SlotProp } from '@fluentui/react-compose';
import { SlotProps } from '@fluentui/react-compose';
Expand Down Expand Up @@ -115,25 +115,7 @@ export const Coachmark: React.FunctionComponent<ICoachmarkProps>;
export const COACHMARK_ATTRIBUTE_NAME = "data-coachmarkid";

// @public (undocumented)
export class CoachmarkBase extends React.Component<ICoachmarkProps, ICoachmarkState> implements ICoachmark {
constructor(props: ICoachmarkProps);
// (undocumented)
componentDidMount(): void;
// (undocumented)
componentDidUpdate(prevProps: ICoachmarkProps, prevState: ICoachmarkState): void;
// (undocumented)
componentWillUnmount(): void;
// (undocumented)
static defaultProps: Partial<ICoachmarkProps>;
// (undocumented)
dismiss: (ev?: Event | React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLElement, MouseEvent> | undefined) => void;
// (undocumented)
render(): JSX.Element;
// (undocumented)
shouldComponentUpdate(newProps: ICoachmarkProps, newState: ICoachmarkState): boolean;
// (undocumented)
UNSAFE_componentWillReceiveProps(newProps: ICoachmarkProps): void;
}
export const CoachmarkBase: React.ForwardRefExoticComponent<ICoachmarkProps & React.RefAttributes<HTMLDivElement>>;

// @public (undocumented)
export const ColorPickerGridCell: React.FunctionComponent<IColorPickerGridCellProps>;
Expand Down Expand Up @@ -415,7 +397,7 @@ export interface ICoachmark {
}

// @public
export interface ICoachmarkProps extends React.ClassAttributes<CoachmarkBase> {
export interface ICoachmarkProps {
ariaAlertText?: string;
ariaDescribedBy?: string;
ariaDescribedByText?: string;
Expand All @@ -427,6 +409,7 @@ export interface ICoachmarkProps extends React.ClassAttributes<CoachmarkBase> {
beakHeight?: number;
// @deprecated
beakWidth?: number;
children?: React.ReactNode;
className?: string;
// @deprecated
collapsed?: boolean;
Expand Down Expand Up @@ -456,24 +439,6 @@ export interface ICoachmarkProps extends React.ClassAttributes<CoachmarkBase> {
width?: number;
}

// @public (undocumented)
export interface ICoachmarkState {
alertText?: string;
beakBottom?: string;
beakLeft?: string;
beakRight?: string;
beakTop?: string;
entityInnerHostRect: IEntityRect;
isBeaconAnimating: boolean;
isCollapsed: boolean;
isMeasured: boolean;
isMeasuring: boolean;
isMouseInProximity: boolean;
targetAlignment?: RectangleEdge;
targetPosition?: RectangleEdge;
transformOrigin?: string;
}

// @public
export interface ICoachmarkStyleProps {
beaconColorOne?: string;
Expand All @@ -486,9 +451,7 @@ export interface ICoachmarkStyleProps {
entityHostHeight?: string;
entityHostWidth?: string;
height?: string;
isBeaconAnimating: boolean;
isCollapsed: boolean;
isMeasured: boolean;
isMeasuring: boolean;
theme?: ITheme;
transformOrigin?: string;
Expand Down Expand Up @@ -638,9 +601,9 @@ export interface IEditingSelectedPeopleItemStylesProps {
// @public
export interface IEntityRect {
// (undocumented)
height: number;
height?: number;
// (undocumented)
width: number;
width?: number;
}

// @public (undocumented)
Expand Down Expand Up @@ -1153,6 +1116,7 @@ export interface IPositioningContainerProps extends IBaseProps<IPositioningConta
ariaLabelledBy?: string;
backgroundColor?: string;
bounds?: IRectangle;
children?: ReactNode;
className?: string;
componentRef?: IRefObject<IPositioningContainer>;
coverTarget?: boolean;
Expand All @@ -1178,12 +1142,6 @@ export interface IPositioningContainerProps extends IBaseProps<IPositioningConta
useTargetPoint?: boolean;
}

// @public (undocumented)
export interface IPositioningContainerState {
heightOffset?: number;
positions?: IPositionedData;
}

// @public @deprecated (undocumented)
export type IPositioningContainerTypes = IPositioningContainerProps;

Expand Down Expand Up @@ -1941,35 +1899,7 @@ export namespace personaSize {
export const Popup: React.ForwardRefExoticComponent<IPopupProps & React.RefAttributes<HTMLDivElement>>;

// @public (undocumented)
export class PositioningContainer extends React.Component<IPositioningContainerProps, IPositioningContainerState> implements PositioningContainer {
constructor(props: IPositioningContainerProps);
// (undocumented)
componentDidMount(): void;
// (undocumented)
componentDidUpdate(): void;
// (undocumented)
componentWillUnmount(): void;
// (undocumented)
static defaultProps: IPositioningContainerProps;
// @deprecated
dismiss: (ev?: Event | React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLElement, MouseEvent> | undefined) => void;
// (undocumented)
protected _dismissOnLostFocus(ev: Event): void;
// (undocumented)
protected _dismissOnScroll(ev: Event): void;
// (undocumented)
protected _onComponentDidMount: () => void;
// (undocumented)
onResize: (ev?: Event | React.KeyboardEvent<HTMLElement> | React.MouseEvent<HTMLElement, MouseEvent> | undefined) => void;
// (undocumented)
render(): JSX.Element | null;
// (undocumented)
protected _setInitialFocus: () => void;
// (undocumented)
UNSAFE_componentWillMount(): void;
// (undocumented)
UNSAFE_componentWillUpdate(newProps: IPositioningContainerProps): void;
}
export const PositioningContainer: React.ForwardRefExoticComponent<IPositioningContainerProps & React.RefAttributes<HTMLDivElement>>;

// @public (undocumented)
export const presenceBoolean: (presence: PersonaPresence) => {
Expand Down Expand Up @@ -2096,6 +2026,9 @@ export const Toggle: React.FunctionComponent<IToggleProps & React.RefAttributes<
// @public (undocumented)
export const ToggleBase: import("@fluentui/react-compose").ComponentWithAs<"div", IToggleProps>;

// @public (undocumented)
export function useHeightOffset({ finalHeight }: IPositioningContainerProps, contentHost: React.RefObject<HTMLDivElement | null>): number;

// @public
export const useLink: (props: ILinkProps, forwardedRef: React.Ref<HTMLElement>) => any;

Expand Down

0 comments on commit d8fc677

Please sign in to comment.