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

fix: Update onboarding experience #6500

Merged
merged 4 commits into from
Mar 24, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 2 additions & 6 deletions Composer/cypress/integration/Onboarding.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,20 @@ context('Onboarding', () => {
cy.visitPage('Design');
});

// The onboarding test is disabled since we are temporarily disabling onboarding
xit('walk through product tour teaching bubbles', () => {
it('walk through product tour teaching bubbles', () => {
cy.findByTestId('onboardingNextSet').click();
cy.findByTestId('onboardingNext').click();
cy.findByTestId('onboardingNext').click();
cy.findByTestId('onboardingNext').click();
cy.findByTestId('onboardingNext').click();
cy.findByTestId('onboardingNext').click();

cy.findByTestId('onboardingNextSet').click();
cy.findByTestId('onboardingNext').click();
cy.findByTestId('onboardingNext').click();

cy.findByTestId('onboardingNextSet').click();

cy.findByTestId('onboardingNext').click();

cy.findByTestId('onboardingNextSet').click();

cy.findByTestId('onboardingNext').click();

cy.findByTestId('onboardingDone').click();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ describe('<AppSettings /> & <ElectronSettings />', () => {
});

it('should render the user settings page', () => {
const { getByText } = renderWithRecoil(<AppSettings />, ({ set }) => {
const { getByText, getAllByText } = renderWithRecoil(<AppSettings />, ({ set }) => {
set(onboardingState, {
coachMarkRefs: {},
complete: false,
});
});
// there are 2 onboarding texts
getAllByText('Onboarding');
getByText('Property editor preferences');
getByText('Application Updates');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import React from 'react';

import OnboardingContext from '../../src/Onboarding/OnboardingContext';
import TeachingBubbles from '../../src/Onboarding/TeachingBubbles/TeachingBubbles';
import TeachingBubbles from '../../src/Onboarding/TeachingBubbles';
import WelcomeModal from '../../src/Onboarding/WelcomeModal/WelcomeModal';
import { renderWithRecoil } from '../testUtils';
import { onboardingState } from '../../src/recoilModel';
import { stepSets as defaultStepSets } from '../../src/Onboarding/onboardingUtils';
import { stepSets as defaultStepSets } from '../../src/Onboarding/content';

describe('<Onboarding />', () => {
let onboardingDefaultState;
Expand Down Expand Up @@ -57,7 +57,7 @@ describe('<Onboarding />', () => {
</OnboardingContext.Provider>,
onboardingDefaultState
);
expect(rendered.baseElement).toHaveTextContent('Get started!');
expect(rendered.baseElement).toHaveTextContent('Main dialog');
});
});

Expand Down
8 changes: 4 additions & 4 deletions Composer/packages/client/src/Onboarding/Onboarding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ import { useLocation } from '../utils/hooks';
import { dispatcherState, onboardingState, botProjectIdsState, dialogsSelectorFamily } from '../recoilModel';

import OnboardingContext from './OnboardingContext';
import TeachingBubbles from './TeachingBubbles/TeachingBubbles';
import TeachingBubbles from './TeachingBubbles';
import WelcomeModal from './WelcomeModal/WelcomeModal';
import { IStepSet, stepSets as defaultStepSets } from './onboardingUtils';
import { IStepSet, stepSets as defaultStepSets } from './content';

const getCurrentSet = (stepSets) => stepSets.findIndex(({ id }) => id === onboardingStorage.getCurrentSet('setUpBot'));
const getCurrentSet = (stepSets) => stepSets.findIndex(({ id }) => id === onboardingStorage.getCurrentSet());

const Onboarding: React.FC = () => {
const didMount = useRef(false);
Expand Down Expand Up @@ -46,7 +46,7 @@ const Onboarding: React.FC = () => {
}, [rootBotProjectId, rootDialogId]);

const [currentSet, setCurrentSet] = useState<number>(getCurrentSet(stepSets));
const [currentStep, setCurrentStep] = useState<number>(0);
const [currentStep, setCurrentStep] = useState<number>(-1);
const [hideModal, setHideModal] = useState(true);
const [minimized, setMinimized] = useState<boolean>(false);
const [teachingBubble, setTeachingBubble] = useState<any>({});
Expand Down
6 changes: 4 additions & 2 deletions Composer/packages/client/src/Onboarding/OnboardingContext.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { createContext } from 'react';
import { createContext, useContext } from 'react';

import { IStep, IStepSet } from './onboardingUtils';
import { IStep, IStepSet } from './content';

interface OnboardingContext {
actions: {
Expand Down Expand Up @@ -47,4 +47,6 @@ const OnboardingContext = createContext<OnboardingContext>({
},
});

export const useOnboardingContext = () => useContext(OnboardingContext);

export default OnboardingContext;
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import React, { useContext, useEffect, useState, useRef } from 'react';
import React, { useEffect, useState, useRef } from 'react';
import formatMessage from 'format-message';
import debounce from 'lodash/debounce';
import { TeachingBubble } from 'office-ui-fabric-react/lib/TeachingBubble';
import { useRecoilValue } from 'recoil';

import { onboardingState } from '../../recoilModel';
import OnboardingContext from '../OnboardingContext';
import { getTeachingBubble } from '../onboardingUtils';

import { teachingBubbleStyles, teachingBubbleTheme } from './styles';
import { FluentTheme } from '@uifabric/fluent-theme';
import { ITeachingBubbleStyles } from 'office-ui-fabric-react/lib/TeachingBubble';

import { onboardingState } from '../recoilModel';

import { useOnboardingContext } from './OnboardingContext';
import { getTeachingBubble } from './content';

export const teachingBubbleStyles: Partial<ITeachingBubbleStyles> = {
bodyContent: {
selectors: {
a: {
color: FluentTheme.palette.white,
},
},
},
};

function getPrimaryButtonText(currentStep, setLength) {
if (setLength > 1) {
Expand All @@ -30,9 +41,9 @@ const TeachingBubbles = () => {
const {
actions: { nextStep, previousStep },
state: { currentSet, currentStep, teachingBubble },
} = useContext(OnboardingContext);
} = useOnboardingContext();

const [, forceRender] = useState();
const [, forceRender] = useState<object>();
const rerender = useRef(debounce(() => forceRender({}), 200)).current;

useEffect(() => {
Expand Down Expand Up @@ -78,8 +89,13 @@ const TeachingBubbles = () => {
<TeachingBubble
styles={teachingBubbleStyles}
target={target}
theme={teachingBubbleTheme}
{...teachingBubbleProps}
calloutProps={{
preventDismissOnLostFocus: true,
preventDismissOnResize: true,
preventDismissOnScroll: true,
...teachingBubbleProps.calloutProps,
}}
/>
);
};
Expand Down
50 changes: 0 additions & 50 deletions Composer/packages/client/src/Onboarding/TeachingBubbles/styles.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@

/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useContext } from 'react';
import formatMessage from 'format-message';
import { IconButton } from 'office-ui-fabric-react/lib/Button';
import { FluentTheme } from '@uifabric/fluent-theme';

import OnboardingContext from '../../OnboardingContext';
import { palette } from '../../palette';
import { useOnboardingContext } from '../../OnboardingContext';

import { buttonStyles, content } from './styles';

const CollapsedWelcomeModal = () => {
const {
actions: { exit, toggleMinimized },
} = useContext(OnboardingContext);
} = useOnboardingContext();

return (
<div css={content}>
Expand All @@ -29,7 +28,7 @@ const CollapsedWelcomeModal = () => {
/>
<IconButton
iconProps={{ iconName: 'ChromeClose' }}
styles={{ ...buttonStyles, icon: { color: palette.white, fontSize: '12px' } }}
styles={{ ...buttonStyles, icon: { color: FluentTheme.palette.white, fontSize: '12px' } }}
title={formatMessage('Close')}
onClick={exit}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@

import { css } from '@emotion/core';
import { IButtonStyles } from 'office-ui-fabric-react/lib/Button';

import { palette } from '../../palette';
import { FluentTheme } from '@uifabric/fluent-theme';

export const content = css`
color: ${palette.white};
color: ${FluentTheme.palette.white};
display: flex;
padding: 10px;
justify-content: space-between;
Expand All @@ -16,20 +15,20 @@ export const content = css`

export const buttonStyles: IButtonStyles = {
icon: {
color: palette.white,
color: FluentTheme.palette.white,
},
root: {
selectors: {
':hover .ms-Button-icon': {
background: palette.themeDarkAlt,
color: palette.white,
background: FluentTheme.palette.themeDarkAlt,
color: FluentTheme.palette.white,
},
':active .ms-Button-icon': {
background: palette.themeDark,
color: palette.white,
background: FluentTheme.palette.themeDark,
color: FluentTheme.palette.white,
},
},
},
rootHovered: { backgroundColor: palette.themeDarkAlt },
rootPressed: { backgroundColor: palette.themeDark },
rootHovered: { backgroundColor: FluentTheme.palette.themeDarkAlt },
rootPressed: { backgroundColor: FluentTheme.palette.themeDark },
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@

/** @jsx jsx */
import { jsx } from '@emotion/core';
import { useContext } from 'react';
import formatMessage from 'format-message';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import { IconButton, PrimaryButton } from 'office-ui-fabric-react/lib/Button';

import OnboardingContext from '../../OnboardingContext';
import { useOnboardingContext } from '../../OnboardingContext';

import {
buttonStyle,
Expand Down Expand Up @@ -38,13 +37,13 @@ const WelcomeModal = () => {
const {
actions: { exit, nextSet, onComplete, toggleMinimized },
state: { currentSet, currentStep, stepSets },
} = useContext(OnboardingContext);
} = useOnboardingContext();

return (
<div css={contentStyle}>
<div css={headerStyle}>
<div css={topBarStyle}>
<div css={titleStyle}>{formatMessage('Welcome!')}</div>
<div css={titleStyle}>{formatMessage('Welcome to Composer!')}</div>
<div css={buttonStyle}>
<IconButton
iconProps={{ iconName: 'ChromeMinimize' }}
Expand All @@ -60,7 +59,7 @@ const WelcomeModal = () => {
</div>
</div>
<img alt="Welcome" src={welcomeImage} />
<div css={subtitleStyle}>{formatMessage('Your bot creation journey on Composer')}</div>
<div css={subtitleStyle}>{formatMessage('What you need to know to get started')}</div>
</div>
<div>
{stepSets.map(({ steps: { length }, title }, index) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// Licensed under the MIT License.

import { css } from '@emotion/core';
import { NeutralColors, SharedColors } from '@uifabric/fluent-theme/lib/fluent/FluentColors';
import { NeutralColors, SharedColors } from '@uifabric/fluent-theme';

export const buttonStyle = css`
position: absolute;
right: 0px;
top: 0px;
right: -24px;
top: -24px;
`;

export const contentStyle = css`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,40 @@

import React, { useContext } from 'react';
import { Modal } from 'office-ui-fabric-react/lib/Modal';
import { FluentTheme } from '@uifabric/fluent-theme';
import { IModalStyles } from 'office-ui-fabric-react/lib/Modal';

import OnboardingContext from '../OnboardingContext';
import { useOnboardingContext } from '../OnboardingContext';

import CollapsedWelcomeModal from './Collapsed/CollapsedWelcomeModal';
import ExpandedWelcomeModal from './Expanded/ExpandedWelcomeModal';
import { collapsedStyles, expandedStyles } from './style';

const collapsedStyles: Partial<IModalStyles> = {
main: {
backgroundColor: FluentTheme.palette.themePrimary,
bottom: '30px',
minHeight: '55px',
color: 'white',
paddingLeft: '15px',
position: 'absolute',
right: '20px',
},
};

const expandedStyles: Partial<IModalStyles> = {
main: {
bottom: '30px',
padding: '15px',
position: 'absolute',
right: '30px',
},
};

const WelcomeModal = () => {
const {
actions: { exit },
state: { complete, hideModal, minimized },
} = useContext(OnboardingContext);
} = useOnboardingContext();

return !(complete || hideModal) ? (
<Modal
Expand Down
Loading