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

Enhance domain-picker package encapsulation #43045

Merged
merged 12 commits into from
Jun 10, 2020
125 changes: 56 additions & 69 deletions client/landing/gutenboarding/components/domain-picker-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,26 @@
* External dependencies
*/
import * as React from 'react';
import classnames from 'classnames';
import { Button } from '@wordpress/components';
import { Icon, chevronDown } from '@wordpress/icons';
import { useDispatch, useSelect } from '@wordpress/data';
import { useSelect, useDispatch } from '@wordpress/data';
import { useI18n } from '@automattic/react-i18n';
import classnames from 'classnames';
import type { DomainSuggestions } from '@automattic/data-stores';
import DomainPicker from '@automattic/domain-picker';

/**
* Internal dependencies
*/
import DomainPickerPopover from '../domain-picker-popover';
import DomainPickerModal from '../domain-picker-modal';
import { FLOW_ID } from '../../constants';
import {
FLOW_ID,
DOMAINS_SUGGESTION_COUNT_IN_POPOVER,
DOMAINS_SUGGESTION_COUNT_IN_MODAL,
} from '../../constants';
import { STORE_KEY } from '../../stores/onboard';
import { useDomainSuggestions } from '../../hooks/use-domain-suggestions';
import { DOMAIN_SUGGESTIONS_STORE } from '../../stores/domain-suggestions';
import { getSuggestionsVendor } from 'lib/domains/suggestions';

const DOMAIN_SUGGESTION_VENDOR = getSuggestionsVendor( true );

/**
Expand All @@ -42,91 +44,76 @@ const DomainPickerButton: React.FunctionComponent< Props > = ( {
currentDomain,
...buttonProps
} ) => {
const buttonRef = React.createRef< HTMLButtonElement >();

const domainSuggestions = useDomainSuggestions( { locale: useI18n().i18nLocale, quantity: 10 } );

const domainCategories = useSelect( ( select ) =>
select( DOMAIN_SUGGESTIONS_STORE ).getCategories()
);
const { __ } = useI18n();

const { domainSearch, domainCategory } = useSelect( ( select ) =>
Copy link

@razvanpapadopol razvanpapadopol Jun 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After moving domainCategory state into DomainPicker component, the selected domain category is no longer persisted after closing Domain Modal. Is this something we want? cc: @dubielzyk

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently in production: after I've selected a domain category and then confirm de selection, next time I open the Domain Modal, I find that category already selected.

On this branch: category selection isn't saved from one DomainModal interaction opening to another: https://cloudup.com/cgXioTPqRx6

select( STORE_KEY ).getState()
);
const { setDomainSearch, setDomainCategory } = useDispatch( STORE_KEY );
const buttonRef = React.createRef< HTMLButtonElement >();

const [ isDomainPopoverVisible, setDomainPopoverVisibility ] = React.useState( false );
const [ isDomainModalVisible, setDomainModalVisibility ] = React.useState( false );
const [ domainPickerMode, setDomainPickerMode ] = React.useState<
'popover' | 'modal' | undefined
>();

const handlePopoverClose = ( e?: React.FocusEvent ) => {
// Don't collide with button toggling
if ( e?.relatedTarget === buttonRef.current ) {
return;
}
setDomainPopoverVisibility( false );
const handlePopoverToggle = () => {
setDomainPickerMode( ( mode ) => ( mode ? undefined : 'popover' ) );
};

const handleModalClose = () => {
setDomainModalVisibility( false );
const handleClose = () => {
setDomainPickerMode( undefined );
};

const handleMoreOptions = () => {
setDomainPopoverVisibility( false );
setDomainModalVisibility( true );
const onClickMoreOptions = () => {
setDomainPickerMode( 'modal' );
};

const domainSearch = useSelect( ( select ) => select( STORE_KEY ).getDomainSearch() );
const { setDomainSearch } = useDispatch( STORE_KEY );

const domainPicker = (
<DomainPicker
analyticsFlowId={ FLOW_ID }
initialDomainSearch={ domainSearch || __( 'My new site' ) }
onSetDomainSearch={ setDomainSearch }
onMoreOptions={ onClickMoreOptions }
showDomainConnectButton={ domainPickerMode === 'modal' }
onClose={ handleClose }
showDomainCategories={ domainPickerMode === 'modal' }
currentDomain={ currentDomain }
onDomainSelect={ onDomainSelect }
domainSuggestionVendor={ DOMAIN_SUGGESTION_VENDOR }
analyticsUiAlgo={ domainPickerMode === 'modal' ? 'domain_modal' : 'domain_popover' }
quantity={
domainPickerMode === 'modal'
? DOMAINS_SUGGESTION_COUNT_IN_MODAL
: DOMAINS_SUGGESTION_COUNT_IN_POPOVER
}
/>
);

return (
<>
<Button
{ ...buttonProps }
aria-expanded={ isDomainPopoverVisible }
aria-expanded={ !! domainPickerMode }
aria-haspopup="menu"
aria-pressed={ isDomainPopoverVisible }
aria-pressed={ !! domainPickerMode }
className={ classnames( 'domain-picker-button', className, {
'is-open': isDomainPopoverVisible,
'is-modal-open': isDomainModalVisible,
'is-open': !! domainPickerMode,
'is-modal-open': domainPickerMode === 'modal',
} ) }
onClick={ () => setDomainPopoverVisibility( ( s ) => ! s ) }
onClick={ handlePopoverToggle }
ref={ buttonRef }
>
<span className="domain-picker-button__label">{ children }</span>
<Icon icon={ chevronDown } size={ 22 } />
</Button>
<DomainPickerPopover
analyticsFlowId={ FLOW_ID }
domainSuggestions={ domainSuggestions }
domainCategory={ domainCategory }
domainCategories={ domainCategories }
onSetDomainCategory={ setDomainCategory }
domainSearch={ domainSearch }
onSetDomainSearch={ setDomainSearch }
isOpen={ isDomainPopoverVisible }
showDomainConnectButton={ false }
showDomainCategories={ false }
currentDomain={ currentDomain }
onDomainSelect={ onDomainSelect }
onMoreOptions={ handleMoreOptions }
onClose={ handlePopoverClose }
domainSuggestionVendor={ DOMAIN_SUGGESTION_VENDOR }
analyticsUiAlgo="domain_popover"
/>
<DomainPickerModal
analyticsFlowId={ FLOW_ID }
domainSuggestions={ domainSuggestions }
domainCategory={ domainCategory }
domainCategories={ domainCategories }
onSetDomainCategory={ setDomainCategory }
domainSearch={ domainSearch }
onSetDomainSearch={ setDomainSearch }
isOpen={ isDomainModalVisible }
showDomainConnectButton
showDomainCategories
currentDomain={ currentDomain }
onDomainSelect={ onDomainSelect }
onClose={ handleModalClose }
domainSuggestionVendor={ DOMAIN_SUGGESTION_VENDOR }
analyticsUiAlgo="domain_modal"
/>
isOpen={ domainPickerMode === 'popover' }
onClose={ handlePopoverToggle }
>
{ domainPicker }
</DomainPickerPopover>
<DomainPickerModal isOpen={ domainPickerMode === 'modal' } onClose={ handleClose }>
{ domainPicker }
</DomainPickerModal>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import * as React from 'react';
import Modal from 'react-modal';
import { select } from '@wordpress/data';
import DomainPicker, { Props as DomainPickerProps } from '@automattic/domain-picker';

/**
* Internal dependencies
Expand All @@ -17,11 +16,13 @@ import { STORE_KEY } from '../../stores/onboard';
*/
import './style.scss';

interface Props extends DomainPickerProps {
interface Props {
onClose: Function;
isOpen: boolean;
children: any;
}

const DomainPickerModal: React.FunctionComponent< Props > = ( { isOpen, onClose, ...props } ) => {
const DomainPickerModal: React.FunctionComponent< Props > = ( { isOpen, onClose, children } ) => {
if ( ! isOpen ) {
return null;
}
Expand Down Expand Up @@ -54,13 +55,7 @@ const DomainPickerModal: React.FunctionComponent< Props > = ( { isOpen, onClose,
overlayClassName="domain-picker-modal-overlay"
bodyOpenClassName="has-domain-picker-modal"
>
<DomainPicker
showDomainConnectButton
showDomainCategories
quantity={ 10 }
onClose={ handleClose }
{ ...props }
/>
{ children }
</Modal>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import * as React from 'react';
import { Popover } from '@wordpress/components';
import { useViewportMatch } from '@wordpress/compose';
import { select } from '@wordpress/data';
import DomainPicker, { Props as DomainPickerProps } from '@automattic/domain-picker';

/**
* Internal dependencies
Expand All @@ -18,11 +17,13 @@ import { STORE_KEY } from '../../stores/onboard';
*/
import './style.scss';

interface Props extends DomainPickerProps {
interface Props {
onClose: Function;
isOpen: boolean;
children: any;
}

const DomainPickerPopover: React.FunctionComponent< Props > = ( { isOpen, onClose, ...props } ) => {
const DomainPickerPopover: React.FunctionComponent< Props > = ( { isOpen, onClose, children } ) => {
// Popover expands at medium viewport width
const isMobile = useViewportMatch( 'medium', '<' );

Expand Down Expand Up @@ -59,7 +60,7 @@ const DomainPickerPopover: React.FunctionComponent< Props > = ( { isOpen, onClos
position={ 'bottom center' }
expandOnMobile={ true }
>
<DomainPicker onClose={ handleClose } { ...props } />
{ children }
</Popover>
</div>
);
Expand Down
3 changes: 3 additions & 0 deletions client/landing/gutenboarding/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import type { ValuesType } from 'utility-types';
*/
export const FLOW_ID = 'gutenboarding';

export const DOMAINS_SUGGESTION_COUNT_IN_POPOVER = 5;
export const DOMAINS_SUGGESTION_COUNT_IN_MODAL = 10;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure these new constants are needed in Gutenboarding.

We already know we want a single free domain and there is PAID_DOMAINS_TO_SHOW defined in this file.

Then there is the bigger value (DOMAINS_SUGGESTION_COUNT_IN_MODAL) which should be handled internally by the DomainPicker package. According to latest changes, even the Modal will display 6 items by default and then just double that amount.


/**
* Debounce our input + HTTP dependent select changes
*
Expand Down
11 changes: 11 additions & 0 deletions client/landing/gutenboarding/stores/onboard/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/**
* External dependencies
*/
import { select } from '@wordpress/data';

/**
* Internal dependencies
*/
import type { State } from './reducer';
import { USER_STORE } from '../user';

export const getIsRedirecting = ( state: State ) => state.isRedirecting;
export const getState = ( state: State ) => state;
Expand All @@ -23,3 +29,8 @@ export const getSelectedFonts = ( state: State ) => state.selectedFonts;
export const getSelectedVertical = ( state: State ) => state.siteVertical;
export const getSelectedDomain = ( state: State ) => state.domain;
export const getSelectedSiteTitle = ( state: State ) => state.siteTitle;
export const getDomainSearch = ( state: State ) =>
state.domainSearch ||
getSelectedSiteTitle( state ) ||
getSelectedVertical( state )?.label.trim() ||
select( USER_STORE ).getCurrentUser()?.username;
3 changes: 2 additions & 1 deletion packages/domain-picker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"lodash": "^4.17.15",
"tslib": "^1.10.0",
"use-debounce": "^3.1.0",
"uuid": "^7.0.2"
"uuid": "^7.0.2",
"@wordpress/base-styles": "^1.8.0"
},
"peerDependencies": {
"@wordpress/data": "^4.18.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/domain-picker/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const PAID_DOMAINS_TO_SHOW = 5;
export const DOMAIN_SEARCH_DEBOUNCE_INTERVAL = 300;
export const DOMAIN_SUGGESTION_VENDOR = 'variation4_front';
export const DOMAIN_SUGGESTIONS_STORE = 'automattic/domains/suggestions';
19 changes: 11 additions & 8 deletions packages/domain-picker/src/domain-categories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,24 @@ import { Icon, chevronDown } from '@wordpress/icons';
import classNames from 'classnames';
import { useI18n } from '@automattic/react-i18n';
import { useState } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { DOMAIN_SUGGESTIONS_STORE } from '../constants';

/**
* Style dependencies
*/
import './style.scss';

type DomainCategory = import('@automattic/data-stores').DomainSuggestions.DomainCategory;

export interface Props {
onSelect: ( domainCategorySlug?: string ) => void;
selected?: string;
domainCategories: DomainCategory[];
}

const DomainPickerCategories: React.FunctionComponent< Props > = ( {
onSelect,
selected,
domainCategories,
} ) => {
const DomainPickerCategories: React.FunctionComponent< Props > = ( { onSelect, selected } ) => {
const { __ } = useI18n();

const [ isOpen, setIsOpen ] = useState( false );
Expand All @@ -35,6 +34,10 @@ const DomainPickerCategories: React.FunctionComponent< Props > = ( {
onSelect( slug );
};

const domainCategories = useSelect( ( select ) =>
select( DOMAIN_SUGGESTIONS_STORE ).getCategories()
);

return (
<div className={ classNames( 'domain-categories', { 'is-open': isOpen } ) }>
<Button
Expand Down
2 changes: 1 addition & 1 deletion packages/domain-picker/src/domain-categories/style.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import '../mixins';
@import '../styles/mixins';

.domain-categories {

Expand Down
Loading