Skip to content

Commit

Permalink
feat(reply): Address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Mingze Xiao committed May 15, 2020
1 parent 11bf610 commit 904e751
Show file tree
Hide file tree
Showing 16 changed files with 157 additions and 136 deletions.
2 changes: 1 addition & 1 deletion docs/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@
#preview-container {
width: 100vw;
height: 75vh;
}
}
File renamed without changes.
44 changes: 44 additions & 0 deletions src/components/ItemList/ItemList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { SyntheticEvent } from 'react';
import noop from 'lodash/noop';
import ItemRow from './ItemRow';
import './ItemList.scss';

export type Props<T extends { id: string }> = {
activeItemIndex?: number;
itemRowAs?: JSX.Element;
items: T[];
onActivate?: (index: number) => void;
onSelect: (index: number, event: React.SyntheticEvent) => void;
};

const ItemList = <T extends { id: string }>({
activeItemIndex = 0,
itemRowAs = <ItemRow />,
items,
onActivate = noop,
onSelect,
...rest
}: Props<T>): JSX.Element => (
<ul data-testid="ba-ItemList" role="listbox" {...rest}>
{items.map((item, index) =>
React.cloneElement(itemRowAs, {
...item,
key: item.id,
className: 'ba-ItemList-row',
isActive: index === activeItemIndex,
onClick: (event: SyntheticEvent) => {
onSelect(index, event);
},
/* preventDefault on mousedown so blur doesn't happen before click */
onMouseDown: (event: SyntheticEvent) => {
event.preventDefault();
},
onMouseEnter: () => {
onActivate(index);
},
}),
)}
</ul>
);

export default ItemList;
15 changes: 15 additions & 0 deletions src/components/ItemList/ItemRow.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@import '~box-ui-elements/es/styles/variables';

.ba-ItemRow-name {
color: $bdl-gray;
font-size: 13px;
line-height: 15px;
letter-spacing: .3px;
}

.ba-ItemRow-email {
color: $bdl-gray-62;
font-size: 11px;
line-height: 15px;
letter-spacing: .25px;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import DatalistItem from 'box-ui-elements/es/components/datalist-item';
import { UserMini, GroupMini } from '../../../@types';
import { UserMini, GroupMini } from '../../@types';
import './ItemRow.scss';

export type Props = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import ItemList, { Props } from '../ItemList';
import { Collaborator } from '../../../../@types';
import { Collaborator } from '../../../@types';

describe('components/Popups/ReplyField/ItemList', () => {
describe('components/ItemList', () => {
const defaults: Props<Collaborator> = {
items: [
{ id: 'testid1', name: 'test1' },
Expand Down Expand Up @@ -37,7 +37,7 @@ describe('components/Popups/ReplyField/ItemList', () => {
preventDefault: jest.fn(),
};

const wrapper = getWrapper({ setActiveItemIndex: mockSetIndex });
const wrapper = getWrapper({ onActivate: mockSetIndex });
const firstChild = wrapper.find('[data-testid="ba-ItemList"]').childAt(0);

firstChild.simulate('click', mockEvent);
Expand Down
1 change: 1 addition & 0 deletions src/components/ItemList/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './ItemList';
44 changes: 0 additions & 44 deletions src/components/Popups/ReplyField/ItemList.tsx

This file was deleted.

7 changes: 0 additions & 7 deletions src/components/Popups/ReplyField/ItemRow.scss

This file was deleted.

1 change: 1 addition & 0 deletions src/components/Popups/ReplyField/MentionItem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

.ba-MentionItem-link {
color: $bdl-box-blue;
font-weight: bold;
}
4 changes: 2 additions & 2 deletions src/components/Popups/ReplyField/PopupList.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
}

.ba-Popup-content {
padding-top: 10px;
padding: 10px 0;
border: solid 1px $bdl-gray-30;
border-radius: $bdl-border-radius-size;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
}

.ba-PopupList-prompt {
padding: 0 10px 10px;
padding: 0 10px;
}
}
37 changes: 16 additions & 21 deletions src/components/Popups/ReplyField/PopupList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import isEmpty from 'lodash/isEmpty';
import { FormattedMessage } from 'react-intl';
import ItemList from './ItemList';
import ItemList from '../../ItemList/ItemList';
import messages from '../messages';
import PopupBase from '../PopupBase';
import { Options, PopupReference } from '../Popper';
Expand All @@ -11,13 +11,13 @@ export type Props<T extends { id: string }> = {
activeItemIndex?: number;
itemRowAs?: JSX.Element;
items: T[];
onActivate?: (index: number) => void;
onSelect: (index: number, event: React.SyntheticEvent) => void;
options?: Partial<Options>;
reference: PopupReference;
setActiveItemIndex?: (index: number) => void;
};

const defaultOptions: Partial<Options> = {
const options: Partial<Options> = {
modifiers: [
{
name: 'offset',
Expand All @@ -35,21 +35,16 @@ const defaultOptions: Partial<Options> = {
placement: 'bottom-start',
};

export default function PopupList<T extends { id: string }>({
items,
reference,
options,
...rest
}: Props<T>): JSX.Element {
return (
<PopupBase className="ba-PopupList" options={{ ...defaultOptions, ...options }} reference={reference}>
{isEmpty(items) ? (
<div className="ba-PopupList-prompt">
<FormattedMessage {...messages.popupListPrompt} />
</div>
) : (
<ItemList items={items} {...rest} />
)}
</PopupBase>
);
}
const PopupList = <T extends { id: string }>({ items, reference, ...rest }: Props<T>): JSX.Element => (
<PopupBase className="ba-PopupList" options={options} reference={reference}>
{isEmpty(items) ? (
<div className="ba-PopupList-prompt">
<FormattedMessage {...messages.popupListPrompt} />
</div>
) : (
<ItemList items={items} {...rest} />
)}
</PopupBase>
);

export default PopupList;
4 changes: 4 additions & 0 deletions src/components/Popups/ReplyField/ReplyField.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
@import '~draft-js/dist/Draft.css';

.ba-ReplyField {
* {
font-family: Lato, sans-serif;
}

.public-DraftEditorPlaceholder-hasFocus,
.public-DraftEditorPlaceholder-root {
margin: 0;
Expand Down
52 changes: 34 additions & 18 deletions src/components/Popups/ReplyField/ReplyField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,11 @@ export default class ReplyField extends React.Component<Props, State> {
this.saveCursorPosition();
}

getCollaborators = (activeMention: Mention | null): Collaborator[] => {
getCollaborators = (): Collaborator[] => {
const { collaborators } = this.props;
const { editorState } = this.state;

const activeMention = getActiveMentionForEditorState(editorState);
if (!activeMention) {
return [];
}
Expand Down Expand Up @@ -152,7 +154,7 @@ export default class ReplyField extends React.Component<Props, State> {
const { editorState } = this.state;

const activeMention = getActiveMentionForEditorState(editorState);
const collaborators = this.getCollaborators(activeMention);
const collaborators = this.getCollaborators();
const editorStateWithLink = addMention(editorState, activeMention, collaborators[index]);

this.handleChange(editorStateWithLink);
Expand Down Expand Up @@ -193,25 +195,39 @@ export default class ReplyField extends React.Component<Props, State> {
return 'handled';
};

handleArrow = (event: React.KeyboardEvent): void => {
const { activeItemIndex, editorState, popupReference } = this.state;
const collaborators = this.getCollaborators(getActiveMentionForEditorState(editorState));
handleArrow = (event: React.KeyboardEvent): number => {
const { popupReference } = this.state;
const { length } = this.getCollaborators();

if (!popupReference || !collaborators.length) {
return;
if (!popupReference || !length) {
return 0;
}

this.stopDefaultEvent(event);

let nextIndex = 0;
return length;
};

handleUpArrow = (event: React.KeyboardEvent): void => {
const { activeItemIndex } = this.state;
const length = this.handleArrow(event);

if (event.key === 'ArrowDown') {
nextIndex = activeItemIndex === collaborators.length - 1 ? 0 : activeItemIndex + 1;
} else if (event.key === 'ArrowUp') {
nextIndex = activeItemIndex === 0 ? collaborators.length - 1 : activeItemIndex - 1;
if (!length) {
return;
}

this.setPopupListActiveItem(activeItemIndex === 0 ? length - 1 : activeItemIndex - 1);
};

handleDownArrow = (event: React.KeyboardEvent): void => {
const { activeItemIndex } = this.state;
const length = this.handleArrow(event);

if (!length) {
return;
}

this.setPopupListActiveItem(nextIndex);
this.setPopupListActiveItem(activeItemIndex === length - 1 ? 0 : activeItemIndex + 1);
};

render(): JSX.Element {
Expand All @@ -226,22 +242,22 @@ export default class ReplyField extends React.Component<Props, State> {
editorState={editorState}
handleReturn={this.handleReturn}
onChange={this.handleChange}
onDownArrow={this.handleArrow}
onUpArrow={this.handleArrow}
onDownArrow={this.handleDownArrow}
onUpArrow={this.handleUpArrow}
placeholder={placeholder}
readOnly={isDisabled}
stripPastedStyles
webDriverTestID="ba-ReplyField-editor"
/>

{popupReference && (
<PopupList<Collaborator>
<PopupList
activeItemIndex={activeItemIndex}
itemRowAs={itemRowAs}
items={this.getCollaborators(getActiveMentionForEditorState(editorState))}
items={this.getCollaborators()}
onActivate={this.setPopupListActiveItem}
onSelect={this.handleSelect}
reference={popupReference}
setActiveItemIndex={this.setPopupListActiveItem}
/>
)}
</div>
Expand Down
Loading

0 comments on commit 904e751

Please sign in to comment.