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
114 changes: 46 additions & 68 deletions client/landing/gutenboarding/components/domain-picker-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
* 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
Expand All @@ -16,10 +17,7 @@ import DomainPickerPopover from '../domain-picker-popover';
import DomainPickerModal from '../domain-picker-modal';
import { FLOW_ID } 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 +40,71 @@ 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' }
/>
);

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,7 @@
@include onboarding-modal-overlay;
}

.domain-picker-modal {
.is-section-gutenboarding .domain-picker-modal {

.domain-picker__panel-row-main {

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
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
5 changes: 5 additions & 0 deletions packages/domain-picker/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const PAID_DOMAINS_TO_SHOW_WITH_CATEGORIES_MODE = 10;
export const PAID_DOMAINS_TO_SHOW_WITHOUT_CATEGORIES_MODE = 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