From 52b64dd346f9c606e9ec551069939f4e019cc95e Mon Sep 17 00:00:00 2001 From: Alexandru Buliga Date: Fri, 25 Jan 2019 19:53:52 +0100 Subject: [PATCH 1/6] fix(dropdown): style improvements --- src/components/Dropdown/Dropdown.tsx | 23 ++++++- .../Dropdown/DropdownSearchInput.tsx | 7 ++- .../Dropdown/dropdownSearchInputStyles.ts | 16 ++--- .../components/Dropdown/dropdownStyles.ts | 60 +++++++++---------- .../components/Dropdown/dropdownVariables.ts | 24 ++++---- .../teams/components/Input/inputStyles.ts | 3 +- .../teams/components/Input/inputVariables.ts | 12 ++-- 7 files changed, 80 insertions(+), 65 deletions(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index c0b2332a44..98d6c8c339 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import * as PropTypes from 'prop-types' import * as _ from 'lodash' +import cx from 'classnames' import { Extendable, @@ -39,6 +40,9 @@ import { screenReaderContainerStyles } from '../../lib/accessibility/Styles/acce import ListItem from '../List/ListItem' export interface DropdownProps extends UIComponentProps { + /** The initial value for the open state. */ + defaultIsOpen?: boolean + /** The initial value for the search query, if the dropdown is also a search. */ defaultSearchQuery?: string @@ -68,6 +72,9 @@ export interface DropdownProps extends UIComponentProps) => string + /** Sets the open state of the dropdown (controlled mode). */ + isOpen?: boolean + /** Array of props for generating list options (Dropdown.Item[]) and selected item labels(Dropdown.SelectedItem[]), if it's a multiple selection. */ items?: ShorthandValue[] @@ -140,6 +147,7 @@ export interface DropdownProps extends UIComponentProps) { const { search, multiple, getA11yStatusMessage, itemToString, toggleIndicator } = this.props - const { defaultHighlightedIndex, searchQuery } = this.state + const { defaultHighlightedIndex, searchQuery, isOpen } = this.state return ( { + if (changes.isOpen !== undefined) { + this.trySetState({ isOpen: changes.isOpen }) + } + if (changes.isOpen && !search) { this.listRef.current.focus() } @@ -280,9 +296,10 @@ export default class Dropdown extends AutoControlledComponent< return (
+ {/* {multiple &&
{this.renderSelectedItems()}
} */} {multiple && this.renderSelectedItems()} {search ? this.renderSearchInput( diff --git a/src/components/Dropdown/DropdownSearchInput.tsx b/src/components/Dropdown/DropdownSearchInput.tsx index bc45b9ddcd..8049256eb3 100644 --- a/src/components/Dropdown/DropdownSearchInput.tsx +++ b/src/components/Dropdown/DropdownSearchInput.tsx @@ -98,7 +98,11 @@ class DropdownSearchInput extends UIComponent) { + public renderComponent({ + classes, + unhandledProps, + styles, + }: RenderResultConfig) { const { accessibilityComboboxProps, accessibilityInputProps, @@ -107,6 +111,7 @@ class DropdownSearchInput extends UIComponent = { - input: ({ variables: { backgroundColor, comboboxPaddingInput } }): ICSSInJSStyle => ({ + input: ({ variables: v }): ICSSInJSStyle => ({ width: '100%', - backgroundColor, - padding: comboboxPaddingInput, + backgroundColor: v.backgroundColor, ':focus': { borderBottomColor: 'transparent', }, }), - combobox: ({ - variables: { comboboxFlexBasis, toggleIndicatorSize }, - props: { hasToggleButton }, - }): ICSSInJSStyle => ({ - flexBasis: comboboxFlexBasis, + combobox: ({ props: p, variables: v }): ICSSInJSStyle => ({ + flexBasis: v.comboboxFlexBasis, flexGrow: 1, - ...(hasToggleButton && { - marginRight: toggleIndicatorSize, + ...(p.hasToggleButton && { + marginRight: v.toggleIndicatorSize, }), }), } diff --git a/src/themes/teams/components/Dropdown/dropdownStyles.ts b/src/themes/teams/components/Dropdown/dropdownStyles.ts index 7e87c34b49..685a299400 100644 --- a/src/themes/teams/components/Dropdown/dropdownStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownStyles.ts @@ -1,42 +1,33 @@ import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' -import { DropdownProps } from '../../../../components/Dropdown/Dropdown' +import { DropdownProps, DropdownState } from '../../../../components/Dropdown/Dropdown' import { DropdownVariables } from './dropdownVariables' import { pxToRem } from '../../../../lib' -const dropdownStyles: ComponentSlotStylesInput = { +const dropdownStyles: ComponentSlotStylesInput = { root: (): ICSSInJSStyle => ({}), - container: ({ - props: { focused, fluid }, - variables: { - backgroundColor, - borderBottom, - borderRadius, - borderColor, - borderColorFocus, - borderRadiusFocus, - color, - width, - }, - }): ICSSInJSStyle => ({ + container: ({ props: p, variables: v }): ICSSInJSStyle => ({ display: 'flex', flexWrap: 'wrap', outline: 0, border: 0, - backgroundColor, - borderBottom, - borderColor, - borderRadius, - color, - width: fluid ? '100%' : width, + backgroundColor: v.backgroundColor, + borderBottom: v.borderBottom, + borderRadius: v.borderRadius, + color: v.color, + width: p.fluid ? '100%' : v.width, position: 'relative', - ...(focused && { - borderColor: borderColorFocus, - borderRadius: borderRadiusFocus, + ...(p.focused && { + borderColor: v.borderColorFocus, }), }), - button: ({ variables: { comboboxPaddingButton } }): ICSSInJSStyle => { + // selectedItems: (): ICSSInJSStyle => ({ + // maxHeight: '40px', // v.containerMaxHeight, + // overflowY: 'auto', + // }), + + button: ({ variables: v }): ICSSInJSStyle => { const transparentColorStyle = { backgroundColor: 'transparent', borderColor: 'transparent', @@ -45,7 +36,7 @@ const dropdownStyles: ComponentSlotStylesInput boxShadow: 'none', margin: '0', justifyContent: 'left', - padding: comboboxPaddingButton, + padding: v.comboboxPaddingButton, ...transparentColorStyle, height: pxToRem(30), ':hover': transparentColorStyle, @@ -60,17 +51,20 @@ const dropdownStyles: ComponentSlotStylesInput } }, - list: ({ - variables: { listMaxHeight, width, listBackgroundColor }, - props: { fluid }, - }): ICSSInJSStyle => ({ + list: ({ props: p, variables: v }): ICSSInJSStyle => ({ + outline: 0, position: 'absolute', + borderRadius: v.listBorderRadius, zIndex: 1000, - maxHeight: listMaxHeight, + maxHeight: v.listMaxHeight, overflowY: 'auto', - width: fluid ? '100%' : width, + width: p.fluid ? '100%' : v.width, top: 'calc(100% + 2px)', // leave room for container + its border - background: listBackgroundColor, + background: v.listBackgroundColor, + ...(p.isOpen && { + boxShadow: v.listBoxShadow, + padding: v.listPadding, + }), }), loadingMessage: ({ variables: v }): ICSSInJSStyle => ({ diff --git a/src/themes/teams/components/Dropdown/dropdownVariables.ts b/src/themes/teams/components/Dropdown/dropdownVariables.ts index 63879ae015..79b48c7ccd 100644 --- a/src/themes/teams/components/Dropdown/dropdownVariables.ts +++ b/src/themes/teams/components/Dropdown/dropdownVariables.ts @@ -1,42 +1,44 @@ import { pxToRem } from '../../../../lib' export interface DropdownVariables { backgroundColor: string - borderBottom: string - borderColor: string borderColorFocus: string borderRadius: string - borderRadiusFocus: string + borderBottom: string color: string + // containerMaxHeight: string comboboxPaddingButton: string - comboboxPaddingInput: string comboboxFlexBasis: string listBackgroundColor: string + listBorderRadius: string + listPadding: string + listBoxShadow: string + listMaxHeight: string listItemBackgroundColor: string listItemBackgroundColorActive: string listItemColorActive: string - listMaxHeight: string toggleIndicatorSize: string width: string } -const [_2px_asRem, _3px_asRem, _6px_asRem, _12px_asRem] = [2, 3, 6, 12].map(v => pxToRem(v)) +const [_2px_asRem, _3px_asRem, _12px_asRem] = [2, 3, 12].map(v => pxToRem(v)) export default (siteVars): DropdownVariables => ({ backgroundColor: siteVars.gray10, - borderRadius: _3px_asRem, + borderRadius: `${_3px_asRem} ${_3px_asRem} ${_2px_asRem} ${_2px_asRem}`, borderBottom: `${_2px_asRem} solid transparent`, - borderColor: 'transparent', borderColorFocus: siteVars.brand, - borderRadiusFocus: `${_3px_asRem} ${_3px_asRem} ${_2px_asRem} ${_2px_asRem}`, color: siteVars.bodyColor, + // containerMaxHeight: '20rem', comboboxPaddingButton: `0 ${_12px_asRem}`, - comboboxPaddingInput: `${_6px_asRem} ${_12px_asRem}`, comboboxFlexBasis: '50px', listBackgroundColor: siteVars.white, + listBorderRadius: _3px_asRem, + listPadding: `${pxToRem(8)} 0`, + listBoxShadow: `0 .2rem .6rem 0 ${siteVars.gray06}`, // rgba(37, 36, 35, .3) + listMaxHeight: '20rem', listItemBackgroundColor: siteVars.white, listItemBackgroundColorActive: siteVars.brand, listItemColorActive: siteVars.white, - listMaxHeight: '20rem', toggleIndicatorSize: pxToRem(32), width: pxToRem(356), }) diff --git a/src/themes/teams/components/Input/inputStyles.ts b/src/themes/teams/components/Input/inputStyles.ts index 36d3da94f0..2538d447df 100644 --- a/src/themes/teams/components/Input/inputStyles.ts +++ b/src/themes/teams/components/Input/inputStyles.ts @@ -14,7 +14,9 @@ const inputStyles: ComponentSlotStylesInput = { input: ({ props: p, variables: v }): ICSSInJSStyle => ({ outline: 0, + boxSizing: 'border-box', border: v.border, + borderBottom: v.borderBottom, borderRadius: v.borderRadius, color: v.fontColor, backgroundColor: v.backgroundColor, @@ -27,7 +29,6 @@ const inputStyles: ComponentSlotStylesInput = { }, ':focus': { borderBottomColor: v.inputFocusBorderBottomColor, - boxShadow: v.boxShadow, }, ...(p.clearable && { padding: v.inputPaddingWithIconAtEnd }), ...(p.icon && { diff --git a/src/themes/teams/components/Input/inputVariables.ts b/src/themes/teams/components/Input/inputVariables.ts index 565e6022e1..361119fce4 100644 --- a/src/themes/teams/components/Input/inputVariables.ts +++ b/src/themes/teams/components/Input/inputVariables.ts @@ -2,9 +2,9 @@ import { pxToRem } from '../../../../lib' export interface InputVariables { backgroundColor: string - border: string + border: string | number + borderBottom: string borderRadius: string - boxShadow: string fontColor: string fontSize: string iconColor: string @@ -20,11 +20,11 @@ export interface InputVariables { export default (siteVars): InputVariables => ({ backgroundColor: siteVars.gray10, - border: `${pxToRem(1)} solid transparent`, - borderRadius: pxToRem(3), - boxShadow: `0 ${pxToRem(1)} 0 ${siteVars.brand}`, + border: 'none', + borderBottom: `${pxToRem(2)} solid transparent`, + borderRadius: `${pxToRem(3)} ${pxToRem(3)} ${pxToRem(2)} ${pxToRem(2)}`, - fontColor: siteVars.bodyColor, + fontColor: siteVars.gray02, fontSize: siteVars.fontSizes.medium, iconPosition: 'absolute', From e5c26f6da22ea548ed7417e26139cc8dec5c7e7f Mon Sep 17 00:00:00 2001 From: Alexandru Buliga Date: Tue, 29 Jan 2019 14:52:55 +0100 Subject: [PATCH 2/6] fixed toggle indicator padding --- CHANGELOG.md | 3 ++- src/components/Dropdown/Dropdown.tsx | 26 +++++++++---------- .../Dropdown/DropdownSearchInput.tsx | 3 --- .../Dropdown/dropdownSearchInputStyles.ts | 5 +--- .../components/Dropdown/dropdownStyles.ts | 16 ++++-------- .../components/Dropdown/dropdownVariables.ts | 4 +-- 6 files changed, 21 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 993ff245e8..9a9bec9479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,7 +53,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Fixes - Make `headerMedia` visible for screen readers in `ListItem` @layershifter ([#772](https://github.com/stardust-ui/react/pull/772)) - Cleanup for `Dropdown` examples' accessibility and added localisation example. @silviuavram ([#771](https://github.com/stardust-ui/react/pull/771)) -- Fix highlighted selected option in single selection `Dropdown` when opened @silviuavram ([#726](https://github.com/stardust-ui/react/pull/726)) +- Fix highlighted selected option in single selection `Dropdown` when opened @silviuavram ([#726](https://github.com/stardust-ui/react/pull/726)) +- Improve `Dropdown` component styles @Bugaa92 ([#786](https://github.com/stardust-ui/react/pull/786)) ## [v0.18.0](https://github.com/stardust-ui/react/tree/v0.18.0) (2019-01-24) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index 98d6c8c339..f464355ecc 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -41,7 +41,7 @@ import ListItem from '../List/ListItem' export interface DropdownProps extends UIComponentProps { /** The initial value for the open state. */ - defaultIsOpen?: boolean + defaultOpen?: boolean /** The initial value for the search query, if the dropdown is also a search. */ defaultSearchQuery?: string @@ -73,7 +73,7 @@ export interface DropdownProps extends UIComponentProps) => string /** Sets the open state of the dropdown (controlled mode). */ - isOpen?: boolean + open?: boolean /** Array of props for generating list options (Dropdown.Item[]) and selected item labels(Dropdown.SelectedItem[]), if it's a multiple selection. */ items?: ShorthandValue[] @@ -147,7 +147,7 @@ export interface DropdownProps extends UIComponentProps { if (!item || React.isValidElement(item)) { @@ -226,7 +226,7 @@ export default class Dropdown extends AutoControlledComponent< toggleIndicator: {}, } - static autoControlledProps = ['isOpen', 'searchQuery', 'value'] + static autoControlledProps = ['open', 'searchQuery', 'value'] static Item = DropdownItem static SearchInput = DropdownSearchInput @@ -236,7 +236,7 @@ export default class Dropdown extends AutoControlledComponent< return { // prevent deletion of last character + last selected value at the same time on backspace. backspaceDelete: multiple, - isOpen: false, + open: false, focused: false, searchQuery: search ? '' : undefined, value: multiple ? [] : null, @@ -253,12 +253,12 @@ export default class Dropdown extends AutoControlledComponent< unhandledProps, }: RenderResultConfig) { const { search, multiple, getA11yStatusMessage, itemToString, toggleIndicator } = this.props - const { defaultHighlightedIndex, searchQuery, isOpen } = this.state + const { defaultHighlightedIndex, searchQuery, open } = this.state return ( { if (changes.isOpen !== undefined) { - this.trySetState({ isOpen: changes.isOpen }) + this.trySetState({ open: changes.isOpen }) } if (changes.isOpen && !search) { @@ -299,7 +299,6 @@ export default class Dropdown extends AutoControlledComponent< className={cx(`${Dropdown.className}__container`, classes.container)} onClick={multiple ? this.handleContainerClick.bind(this, isOpen) : undefined} > - {/* {multiple &&
{this.renderSelectedItems()}
} */} {multiple && this.renderSelectedItems()} {search ? this.renderSearchInput( @@ -376,7 +375,7 @@ export default class Dropdown extends AutoControlledComponent< ) => void, variables, ): JSX.Element { - const { searchInput, multiple, placeholder, toggleIndicator } = this.props + const { searchInput, multiple, placeholder } = this.props const { searchQuery, value } = this.state const noPlaceholder = @@ -385,7 +384,6 @@ export default class Dropdown extends AutoControlledComponent< return DropdownSearchInput.create(searchInput || {}, { defaultProps: { placeholder: noPlaceholder ? '' : placeholder, - hasToggleButton: !!toggleIndicator, variables, inputRef: this.inputRef, }, diff --git a/src/components/Dropdown/DropdownSearchInput.tsx b/src/components/Dropdown/DropdownSearchInput.tsx index 8049256eb3..dda17f298b 100644 --- a/src/components/Dropdown/DropdownSearchInput.tsx +++ b/src/components/Dropdown/DropdownSearchInput.tsx @@ -14,9 +14,6 @@ import { UIComponentProps } from '../../lib/commonPropInterfaces' import Input from '../Input/Input' export interface DropdownSearchInputProps extends UIComponentProps { - /** Informs the search input about an existing toggle button. */ - hasToggleButton?: boolean - /** Ref for input DOM node. */ inputRef?: React.Ref diff --git a/src/themes/teams/components/Dropdown/dropdownSearchInputStyles.ts b/src/themes/teams/components/Dropdown/dropdownSearchInputStyles.ts index b6b5ca9c5e..893e587a5d 100644 --- a/src/themes/teams/components/Dropdown/dropdownSearchInputStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownSearchInputStyles.ts @@ -15,12 +15,9 @@ const dropdownSearchInputStyles: ComponentSlotStylesInput< }, }), - combobox: ({ props: p, variables: v }): ICSSInJSStyle => ({ + combobox: ({ variables: v }): ICSSInJSStyle => ({ flexBasis: v.comboboxFlexBasis, flexGrow: 1, - ...(p.hasToggleButton && { - marginRight: v.toggleIndicatorSize, - }), }), } diff --git a/src/themes/teams/components/Dropdown/dropdownStyles.ts b/src/themes/teams/components/Dropdown/dropdownStyles.ts index 685a299400..5239ff9774 100644 --- a/src/themes/teams/components/Dropdown/dropdownStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownStyles.ts @@ -17,16 +17,10 @@ const dropdownStyles: ComponentSlotStylesInput ({ - // maxHeight: '40px', // v.containerMaxHeight, - // overflowY: 'auto', - // }), - button: ({ variables: v }): ICSSInJSStyle => { const transparentColorStyle = { backgroundColor: 'transparent', @@ -61,7 +55,7 @@ const dropdownStyles: ComponentSlotStylesInput ({ + toggleIndicator: ({ variables: v }): ICSSInJSStyle => ({ position: 'absolute', height: v.toggleIndicatorSize, width: v.toggleIndicatorSize, @@ -87,7 +81,7 @@ const dropdownStyles: ComponentSlotStylesInput ({ borderBottom: `${_2px_asRem} solid transparent`, borderColorFocus: siteVars.brand, color: siteVars.bodyColor, - // containerMaxHeight: '20rem', comboboxPaddingButton: `0 ${_12px_asRem}`, comboboxFlexBasis: '50px', listBackgroundColor: siteVars.white, listBorderRadius: _3px_asRem, listPadding: `${pxToRem(8)} 0`, - listBoxShadow: `0 .2rem .6rem 0 ${siteVars.gray06}`, // rgba(37, 36, 35, .3) + listBoxShadow: `0 .2rem .6rem 0 ${siteVars.gray06}`, listMaxHeight: '20rem', listItemBackgroundColor: siteVars.white, listItemBackgroundColorActive: siteVars.brand, From 645940c6bdcf45084944f3974da79c72b85c9df0 Mon Sep 17 00:00:00 2001 From: Alexandru Buliga Date: Tue, 29 Jan 2019 18:38:21 +0100 Subject: [PATCH 3/6] removed code making isOpen autocontrolled prop --- src/components/Dropdown/Dropdown.tsx | 63 +++++++++---------- .../components/Dropdown/dropdownStyles.ts | 2 +- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index f464355ecc..21ce6348e0 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -40,9 +40,6 @@ import { screenReaderContainerStyles } from '../../lib/accessibility/Styles/acce import ListItem from '../List/ListItem' export interface DropdownProps extends UIComponentProps { - /** The initial value for the open state. */ - defaultOpen?: boolean - /** The initial value for the search query, if the dropdown is also a search. */ defaultSearchQuery?: string @@ -72,9 +69,6 @@ export interface DropdownProps extends UIComponentProps) => string - /** Sets the open state of the dropdown (controlled mode). */ - open?: boolean - /** Array of props for generating list options (Dropdown.Item[]) and selected item labels(Dropdown.SelectedItem[]), if it's a multiple selection. */ items?: ShorthandValue[] @@ -147,7 +141,7 @@ export interface DropdownProps extends UIComponentProps) { const { search, multiple, getA11yStatusMessage, itemToString, toggleIndicator } = this.props - const { defaultHighlightedIndex, searchQuery, open } = this.state + const { defaultHighlightedIndex, searchQuery } = this.state return ( { - if (changes.isOpen !== undefined) { - this.trySetState({ open: changes.isOpen }) - } - - if (changes.isOpen && !search) { - this.listRef.current.focus() - } - }} + onStateChange={this.handleStateChange} > {({ getInputProps, @@ -409,14 +391,16 @@ export default class Dropdown extends AutoControlledComponent< getItemProps: (options: GetItemPropsOptions) => any, getInputProps: (options?: GetInputPropsOptions) => any, ) { + const { search } = this.props const { innerRef, ...accessibilityMenuProps } = getMenuProps( { refKey: 'innerRef' }, { suppressRefError: true }, ) - const { search } = this.props + // If it's just a selection, some attributes and listeners from Downshift input need to go on the menu list. if (!search) { const accessibilityInputProps = getInputProps() + accessibilityMenuProps['aria-activedescendant'] = accessibilityInputProps['aria-activedescendant'] accessibilityMenuProps['onKeyDown'] = e => { @@ -455,8 +439,8 @@ export default class Dropdown extends AutoControlledComponent< highlightedIndex: number, ) { const { loading, loadingMessage, noResultsMessage, renderItem } = this.props - const filteredItems = this.getItemsFilteredBySearchQuery() + const items = _.map(filteredItems, (item, index) => DropdownItem.create(item, { defaultProps: { @@ -543,6 +527,16 @@ export default class Dropdown extends AutoControlledComponent< } } + private handleStateChange = (changes: StateChangeOptions) => { + if (changes.isOpen !== undefined && changes.isOpen !== this.state.isOpen) { + this.setState({ isOpen: changes.isOpen }) + } + + if (changes.isOpen && !this.props.search) { + this.listRef.current.focus() + } + } + private getItemsFilteredBySearchQuery = (): ShorthandValue[] => { const { items, itemToString, multiple, search } = this.props const { searchQuery, value } = this.state @@ -551,10 +545,12 @@ export default class Dropdown extends AutoControlledComponent< if (multiple) { filteredItems = _.difference(filteredItems, value as ShorthandValue[]) } + if (search) { if (_.isFunction(search)) { return search(filteredItems, searchQuery) } + return filteredItems.filter( item => itemToString(item) @@ -587,9 +583,7 @@ export default class Dropdown extends AutoControlledComponent< item: ShorthandValue, index: number, getItemProps: (options: GetItemPropsOptions) => any, - ) => ({ - accessibilityItemProps: getItemProps({ item, index }), - }) + ) => ({ accessibilityItemProps: getItemProps({ item, index }) }) private handleSelectedItemOverrides = ( predefinedProps: DropdownSelectedItemProps, @@ -621,9 +615,9 @@ export default class Dropdown extends AutoControlledComponent< searchInputProps: DropdownSearchInputProps, ) => { this.setState({ focused: false }) - _.invoke(predefinedProps, 'onInputBlur', e, searchInputProps) } + const handleInputKeyDown = ( e: React.SyntheticEvent, searchInputProps: DropdownSearchInputProps, @@ -718,18 +712,18 @@ export default class Dropdown extends AutoControlledComponent< const { multiple, getA11ySelectionMessage, search } = this.props const newValue = multiple ? [...(this.state.value as ShorthandValue[]), item] : item - this.trySetState({ - value: newValue, - searchQuery: '', - }) + this.trySetState({ value: newValue, searchQuery: '' }) + if (!this.props.search && !this.props.multiple) { this.setState({ defaultHighlightedIndex: this.props.items.indexOf(item), }) } + if (getA11ySelectionMessage && getA11ySelectionMessage.onAdd) { this.setA11yStatus(getA11ySelectionMessage.onAdd(item)) } + if (!search) { this.buttonRef.current.focus() } @@ -760,9 +754,8 @@ export default class Dropdown extends AutoControlledComponent< poppedItem = value.pop() } - this.trySetState({ - value, - }) + this.trySetState({ value }) + if (getA11ySelectionMessage && getA11ySelectionMessage.onRemove) { this.setA11yStatus(getA11ySelectionMessage.onRemove(poppedItem)) } diff --git a/src/themes/teams/components/Dropdown/dropdownStyles.ts b/src/themes/teams/components/Dropdown/dropdownStyles.ts index 5239ff9774..c107364d7e 100644 --- a/src/themes/teams/components/Dropdown/dropdownStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownStyles.ts @@ -55,7 +55,7 @@ const dropdownStyles: ComponentSlotStylesInput Date: Tue, 29 Jan 2019 20:57:02 +0100 Subject: [PATCH 4/6] implemented scrolling in selected items list --- src/components/Dropdown/Dropdown.tsx | 42 ++++++++++++------- .../Dropdown/DropdownSearchInput.tsx | 7 +--- .../components/Dropdown/dropdownStyles.ts | 9 +++- .../components/Dropdown/dropdownVariables.ts | 2 + 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index 21ce6348e0..ad2c66cb4f 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -162,6 +162,7 @@ export default class Dropdown extends AutoControlledComponent< private buttonRef = React.createRef() private inputRef = React.createRef() private listRef = React.createRef() + private selectedItemsRef = React.createRef() static displayName = 'Dropdown' @@ -281,16 +282,21 @@ export default class Dropdown extends AutoControlledComponent< className={cx(`${Dropdown.className}__container`, classes.container)} onClick={multiple ? this.handleContainerClick.bind(this, isOpen) : undefined} > - {multiple && this.renderSelectedItems()} - {search - ? this.renderSearchInput( - accessibilityRootPropsRest, - getInputProps, - highlightedIndex, - selectItemAtIndex, - variables, - ) - : this.renderTriggerButton(styles, getToggleButtonProps)} +
+ {multiple && this.renderSelectedItems()} + {search + ? this.renderSearchInput( + accessibilityRootPropsRest, + getInputProps, + highlightedIndex, + selectItemAtIndex, + variables, + ) + : this.renderTriggerButton(styles, getToggleButtonProps)} +
{Indicator.create(toggleIndicator, { defaultProps: { direction: isOpen ? 'top' : 'bottom', @@ -709,14 +715,14 @@ export default class Dropdown extends AutoControlledComponent< } private handleSelectedChange = (item: ShorthandValue) => { - const { multiple, getA11ySelectionMessage, search } = this.props + const { items, multiple, getA11ySelectionMessage, search } = this.props const newValue = multiple ? [...(this.state.value as ShorthandValue[]), item] : item this.trySetState({ value: newValue, searchQuery: '' }) - if (!this.props.search && !this.props.multiple) { + if (!search && !multiple) { this.setState({ - defaultHighlightedIndex: this.props.items.indexOf(item), + defaultHighlightedIndex: items.indexOf(item), }) } @@ -724,7 +730,15 @@ export default class Dropdown extends AutoControlledComponent< this.setA11yStatus(getA11ySelectionMessage.onAdd(item)) } - if (!search) { + if (search) { + setTimeout( + () => + this.selectedItemsRef.current.scrollTo({ + top: this.selectedItemsRef.current.scrollHeight, + }), + 0, + ) + } else { this.buttonRef.current.focus() } diff --git a/src/components/Dropdown/DropdownSearchInput.tsx b/src/components/Dropdown/DropdownSearchInput.tsx index dda17f298b..c64ad6b293 100644 --- a/src/components/Dropdown/DropdownSearchInput.tsx +++ b/src/components/Dropdown/DropdownSearchInput.tsx @@ -95,11 +95,7 @@ class DropdownSearchInput extends UIComponent) { + public renderComponent({ unhandledProps, styles }: RenderResultConfig) { const { accessibilityComboboxProps, accessibilityInputProps, @@ -108,7 +104,6 @@ class DropdownSearchInput extends UIComponent ({ + display: 'flex', + flexWrap: 'wrap', + maxHeight: v.selectedItemsMaxHeight, + overflowY: 'auto', }), button: ({ variables: v }): ICSSInJSStyle => { @@ -81,6 +87,7 @@ const dropdownStyles: ComponentSlotStylesInput ({ listItemBackgroundColor: siteVars.white, listItemBackgroundColorActive: siteVars.brand, listItemColorActive: siteVars.white, + selectedItemsMaxHeight: pxToRem(80), toggleIndicatorSize: pxToRem(32), width: pxToRem(356), }) From 04083aacb617ae10a5e019d621ef2983c50044cf Mon Sep 17 00:00:00 2001 From: Alexandru Buliga Date: Wed, 30 Jan 2019 14:47:19 +0100 Subject: [PATCH 5/6] fixed toggle indicator position --- src/themes/teams/components/Dropdown/dropdownStyles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/themes/teams/components/Dropdown/dropdownStyles.ts b/src/themes/teams/components/Dropdown/dropdownStyles.ts index 8c1bcc4b4e..90e3d651d1 100644 --- a/src/themes/teams/components/Dropdown/dropdownStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownStyles.ts @@ -23,8 +23,9 @@ const dropdownStyles: ComponentSlotStylesInput ({ display: 'flex', flexWrap: 'wrap', - maxHeight: v.selectedItemsMaxHeight, overflowY: 'auto', + maxHeight: v.selectedItemsMaxHeight, + ...(p.toggleIndicator && { paddingRight: v.toggleIndicatorSize }), }), button: ({ variables: v }): ICSSInJSStyle => { @@ -87,7 +88,6 @@ const dropdownStyles: ComponentSlotStylesInput Date: Wed, 30 Jan 2019 16:14:29 +0100 Subject: [PATCH 6/6] fixed styles and scrolling in Edge --- src/components/Dropdown/Dropdown.tsx | 14 ++++++-------- .../teams/components/Dropdown/dropdownStyles.ts | 2 +- .../teams/components/Dropdown/dropdownVariables.ts | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx index ad2c66cb4f..2aed4c1bfd 100644 --- a/src/components/Dropdown/Dropdown.tsx +++ b/src/components/Dropdown/Dropdown.tsx @@ -721,24 +721,22 @@ export default class Dropdown extends AutoControlledComponent< this.trySetState({ value: newValue, searchQuery: '' }) if (!search && !multiple) { - this.setState({ - defaultHighlightedIndex: items.indexOf(item), - }) + this.setState({ defaultHighlightedIndex: items.indexOf(item) }) } if (getA11ySelectionMessage && getA11ySelectionMessage.onAdd) { this.setA11yStatus(getA11ySelectionMessage.onAdd(item)) } - if (search) { + if (multiple) { setTimeout( () => - this.selectedItemsRef.current.scrollTo({ - top: this.selectedItemsRef.current.scrollHeight, - }), + (this.selectedItemsRef.current.scrollTop = this.selectedItemsRef.current.scrollHeight), 0, ) - } else { + } + + if (!search) { this.buttonRef.current.focus() } diff --git a/src/themes/teams/components/Dropdown/dropdownStyles.ts b/src/themes/teams/components/Dropdown/dropdownStyles.ts index 90e3d651d1..df3deb428b 100644 --- a/src/themes/teams/components/Dropdown/dropdownStyles.ts +++ b/src/themes/teams/components/Dropdown/dropdownStyles.ts @@ -88,7 +88,7 @@ const dropdownStyles: ComponentSlotStylesInput ({ listItemBackgroundColor: siteVars.white, listItemBackgroundColorActive: siteVars.brand, listItemColorActive: siteVars.white, - selectedItemsMaxHeight: pxToRem(80), + selectedItemsMaxHeight: pxToRem(82), toggleIndicatorSize: pxToRem(32), width: pxToRem(356), })