Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3f1afc2
-added variables for dark theme
May 6, 2019
97ceb67
-updated HC theme
May 7, 2019
b44665e
-fixed searable border radius when dropdown is opened
May 7, 2019
c6d815a
-fixed hover state of the HC dropdown
May 7, 2019
fe4ba01
-fixed selected items
May 7, 2019
f2dd80e
-fixed focus + active color for trigger button in HC theme
May 9, 2019
f718c5a
Merge branch 'master' into feat/dropdown-theming
May 10, 2019
255e126
-resolved color palette updates
May 10, 2019
6a0c73d
-fixing issues
May 10, 2019
7d9e869
-added selected prop on the Dropdown Item
May 10, 2019
53d6488
Merge branch 'master' into feat/dropdown-theming
May 10, 2019
149b18e
-added focus border
May 10, 2019
9a76c37
-implemented focused styles on the items
May 10, 2019
77dfafb
-added tests for different themes
May 10, 2019
2245c94
Merge branch 'master' into feat/dropdown-theming
May 10, 2019
0bfb9fe
-extracted isFromKeyboard set state in a separate function call
May 10, 2019
067071c
-added focused state
May 10, 2019
8448866
-fixed HC hover styles dependening on the open prop
May 10, 2019
051fe6d
-reverting Flex Item changes
May 10, 2019
864a046
-fixed multiple + selection scenario
May 10, 2019
366653c
-added dropdown item className on the list item element
May 10, 2019
bbb3144
-used the border focus styles inside the dropdown item
May 13, 2019
bef6128
-fixing handlers in the Dropdown's trigger button
May 13, 2019
0a9c072
-fixed focusing style on the dropdown
May 13, 2019
b40ab6a
-updated list box shadow
May 13, 2019
dd7f58d
Merge branch 'master' into feat/dropdown-theming
May 13, 2019
afdcc8a
-addressed PR comments
May 13, 2019
a1c26b6
-added shadowLevel3 in dark theme, and used this value for the list b…
May 14, 2019
9463f34
Merge branch 'master' into feat/dropdown-theming
May 14, 2019
0c26c47
-updated changelog
May 14, 2019
bac1c5e
-addressed PR comments
May 14, 2019
b039e21
-rename consts used in the renderTriggerButton method
May 14, 2019
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Restrict Typescript checks for component props @kuzhelov ([#1290](https://github.com/stardust-ui/react/pull/1290))

### Fix
- Fixed Flex.Item children prop type @mnajdova ([#1320](https://github.com/stardust-ui/react/pull/1320))
- Fixed `Flex.Item` children prop type @mnajdova ([#1320](https://github.com/stardust-ui/react/pull/1320))

### Features
- Add `selected`, `isFromKeyboard` props to `DropdownItem` @mnajdova ([#1299](https://github.com/stardust-ui/react/pull/1299))
- Add styles for the dark and high contrast Teams themes for the `Dropdown` component @mnajdova ([#1299](https://github.com/stardust-ui/react/pull/1299))

<!--------------------------------[ v0.30.0 ]------------------------------- -->
## [v0.30.0](https://github.com/stardust-ui/react/tree/v0.30.0) (2019-05-10)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const selectors = {
}

const config: ScreenerTestsConfig = {
themes: ['teams', 'teamsDark', 'teamsHighContrast'],
steps: [
builder => builder.click(selectors.triggerButton).snapshot('Shows list'),
builder =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const selectors = {
}

const config: ScreenerTestsConfig = {
themes: ['teams', 'teamsDark', 'teamsHighContrast'],
steps: [
(builder, keys) =>
builder
Expand Down
64 changes: 50 additions & 14 deletions packages/react/src/components/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
RenderResultConfig,
commonPropTypes,
UIComponentProps,
isFromKeyboard,
} from '../../lib'
import List from '../List/List'
import DropdownItem, { DropdownItemProps } from './DropdownItem'
Expand Down Expand Up @@ -208,6 +209,8 @@ export interface DropdownState {
searchQuery: string
highlightedIndex: number
value: ShorthandValue | ShorthandCollection
itemIsFromKeyboard: boolean
isFromKeyboard: boolean
}

class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, DropdownState> {
Expand Down Expand Up @@ -308,6 +311,8 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
highlightedIndex: this.props.highlightFirstItemOnOpen ? 0 : null,
searchQuery: search ? '' : undefined,
value: multiple ? [] : null,
itemIsFromKeyboard: false,
isFromKeyboard: false,
}
}

Expand Down Expand Up @@ -425,6 +430,7 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
getMenuProps,
getItemProps,
getInputProps,
value,
)}
</div>
</Ref>
Expand Down Expand Up @@ -453,6 +459,17 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
const { triggerButton } = this.props
const content = this.getSelectedItemAsString(this.state.value)

const triggerButtonProps = getToggleButtonProps({
onFocus: this.handleTriggerButtonOrListFocus,
onBlur: this.handleTriggerButtonBlur,
onKeyDown: e => {
this.handleTriggerButtonKeyDown(e, rtl)
},
'aria-label': content,
})

const { onClick, onFocus, onBlur, onKeyDown, ...restTriggerButtonProps } = triggerButtonProps

return (
<Ref innerRef={this.buttonRef}>
{Button.create(triggerButton, {
Copy link
Contributor

Choose a reason for hiding this comment

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

this is another good example of why we should refrain from blindly passing all calculated props to any slot's content - we might imagine what it would be if regular <button />, or even any other Stardust component type which is different from Button will be provided here

Expand All @@ -461,15 +478,26 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
content,
fluid: true,
styles: styles.triggerButton,
...getToggleButtonProps({
onFocus: this.handleTriggerButtonOrListFocus,
onBlur: this.handleTriggerButtonBlur,
onKeyDown: e => {
this.handleTriggerButtonKeyDown(e, rtl)
},
'aria-label': content,
}),
...restTriggerButtonProps,
},
overrideProps: (predefinedProps: IconProps) => ({
onClick: e => {
onClick(e)
_.invoke(predefinedProps, 'onClick', e, predefinedProps)
},
onFocus: e => {
onFocus(e)
_.invoke(predefinedProps, 'onFocus', e, predefinedProps)
},
onBlur: e => {
onBlur(e)
_.invoke(predefinedProps, 'onBlur', e, predefinedProps)
},
onKeyDown: e => {
onKeyDown(e)
_.invoke(predefinedProps, 'onKeyDown', e, predefinedProps)
},
}),
})}
</Ref>
)
Expand Down Expand Up @@ -522,6 +550,7 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
getMenuProps: (options?: GetMenuPropsOptions, otherOptions?: GetPropsCommonOptions) => any,
getItemProps: (options: GetItemPropsOptions<ShorthandValue>) => any,
getInputProps: (options?: GetInputPropsOptions) => any,
value: ShorthandValue | ShorthandCollection,
) {
const { search } = this.props
const { open } = this.state
Expand Down Expand Up @@ -562,7 +591,9 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
aria-hidden={!open}
onFocus={this.handleTriggerButtonOrListFocus}
onBlur={this.handleListBlur}
items={open ? this.renderItems(styles, variables, getItemProps, highlightedIndex) : []}
items={
open ? this.renderItems(styles, variables, getItemProps, highlightedIndex, value) : []
}
/>
</Ref>
)
Expand All @@ -573,6 +604,7 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
variables: ComponentVariablesInput,
getItemProps: (options: GetItemPropsOptions<ShorthandValue>) => any,
highlightedIndex: number,
value: ShorthandValue | ShorthandCollection,
) {
const { loading, loadingMessage, noResultsMessage, renderItem } = this.props
const filteredItems = this.getItemsFilteredBySearchQuery()
Expand All @@ -582,6 +614,8 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
defaultProps: {
className: Dropdown.slotClassNames.item,
active: highlightedIndex === index,
selected: !this.props.multiple && value === item,
isFromKeyboard: this.state.itemIsFromKeyboard,
variables,
...(typeof item === 'object' &&
!item.hasOwnProperty('key') && {
Expand Down Expand Up @@ -680,7 +714,9 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
}

if (this.state.open && _.isNumber(changes.highlightedIndex)) {
const itemIsFromKeyboard = changes.type !== Downshift.stateChangeTypes.itemMouseEnter
this.trySetState({ highlightedIndex: changes.highlightedIndex })
this.setState({ itemIsFromKeyboard })
}
}

Expand Down Expand Up @@ -759,7 +795,7 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
e: React.SyntheticEvent,
searchInputProps: DropdownSearchInputProps,
) => {
this.setState({ focused: false })
this.setState({ focused: false, isFromKeyboard: isFromKeyboard() })
e.nativeEvent['preventDownshiftDefault'] = true
_.invoke(predefinedProps, 'onInputBlur', e, searchInputProps)
}
Expand Down Expand Up @@ -812,7 +848,7 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
// same story as above for getRootProps.
accessibilityComboboxProps,
onFocus: (e: React.SyntheticEvent, searchInputProps: DropdownSearchInputProps) => {
this.setState({ focused: true })
this.setState({ focused: true, isFromKeyboard: isFromKeyboard() })

_.invoke(predefinedProps, 'onFocus', e, searchInputProps)
},
Expand Down Expand Up @@ -1014,18 +1050,18 @@ class Dropdown extends AutoControlledComponent<WithAsProp<DropdownProps>, Dropdo
}

private handleTriggerButtonOrListFocus = () => {
this.setState({ focused: true })
this.setState({ focused: true, isFromKeyboard: isFromKeyboard() })
}

private handleTriggerButtonBlur = e => {
if (this.listRef.current !== e.relatedTarget) {
this.setState({ focused: false })
this.setState({ focused: false, isFromKeyboard: isFromKeyboard() })
}
}

private handleListBlur = e => {
if (this.buttonRef.current !== e.relatedTarget) {
this.setState({ focused: false })
this.setState({ focused: false, isFromKeyboard: isFromKeyboard() })
}
}

Expand Down
15 changes: 12 additions & 3 deletions packages/react/src/components/Dropdown/DropdownItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,22 @@ export interface DropdownItemProps extends UIComponentProps<DropdownItemProps> {
/** Item's image. */
image?: ShorthandValue

/** Indicated whether the item has been set active by keyboard. */
isFromKeyboard?: boolean

/**
* Called on dropdown item click.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props and proposed value.
*/
onClick?: ComponentEventHandler<DropdownItemProps>

/** A dropdown item can be selected if single selection Dropdown is used. */
selected?: boolean
}

class DropdownItem extends UIComponent<WithAsProp<DropdownItemProps>, any> {
class DropdownItem extends UIComponent<WithAsProp<DropdownItemProps>> {
static displayName = 'DropdownItem'

static create: Function
Expand All @@ -62,6 +68,8 @@ class DropdownItem extends UIComponent<WithAsProp<DropdownItemProps>, any> {
header: customPropTypes.itemShorthand,
image: customPropTypes.itemShorthand,
onClick: PropTypes.func,
isFromKeyboard: PropTypes.bool,
selected: PropTypes.bool,
}

private handleClick = e => {
Expand All @@ -76,14 +84,15 @@ class DropdownItem extends UIComponent<WithAsProp<DropdownItemProps>, any> {
const { content, header, image, accessibilityItemProps } = this.props
return (
<ListItem
className={classes.root}
className={DropdownItem.className}
styles={styles.root}
onClick={this.handleClick}
header={Box.create(header, {
defaultProps: {
className: DropdownItem.slotClassNames.header,
styles: styles.header,
},
})}
onClick={this.handleClick}
media={Image.create(image, {
defaultProps: {
avatar: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export { default as Icon } from './components/Icon/iconVariables'
export { default as Reaction } from './components/Reaction/reactionVariables'
export { default as Alert } from './components/Alert/alertVariables'
export { default as ProviderBox } from './components/Provider/providerBoxVariables'
export { default as Dropdown } from './components/Dropdown/dropdownVariables'

export { default as PopupContent } from './components/Popup/popupContentVariables'
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { DropdownVariables } from '../../../teams/components/Dropdown/dropdownVariables'

export default (siteVars): Partial<DropdownVariables> => ({
backgroundColor: siteVars.colors.grey[650],
backgroundColorHover: siteVars.colors.grey[550],
borderColor: 'transparent',
borderColorFocus: siteVars.colors.brand[400],
color: siteVars.colors.grey[250],
selectedItemColor: siteVars.colors.grey[250],
listBackgroundColor: siteVars.colors.grey[650],
listItemBackgroundColor: siteVars.colors.grey[650],
listItemColorHover: siteVars.colors.white,
listItemBackgroundColorHover: siteVars.colors.grey[550],
listItemBackgroundColorActive: siteVars.colors.grey[550],
listItemColorActive: siteVars.colors.white,
selectedItemBackgroundColor: siteVars.colors.grey[650],
selectedItemColorFocus: siteVars.colors.grey[700], // check this value
listItemSelectedColor: siteVars.colors.white,
selectedItemBackgroundColorFocus: siteVars.colors.brand[200],
triggerButtonColorHover: siteVars.colors.grey[250],
})
1 change: 1 addition & 0 deletions packages/react/src/themes/teams-dark/siteVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const focusOuterBorderColor = colors.white
// SHADOW LEVELS
//
export const shadowLevel1 = '0 .2rem .4rem -.075rem rgba(0, 0, 0, .25)'
export const shadowLevel3 = '0 .8rem 1rem -0.2rem rgba(0, 0, 0, .25)'

//
// SEMANTIC ASSIGNMENTS
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { default as Attachment } from './components/Attachment/attachmentStyles'
export { default as MenuItem } from './components/Menu/menuItemStyles'
export { default as Alert } from './components/Alert/alertStyles'
export { default as Dropdown } from './components/Dropdown/dropdownStyles'
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export { default as Status } from './components/Status/statusVariables'
export { default as Reaction } from './components/Reaction/reactionVariables'
export { default as Alert } from './components/Alert/alertVariables'
export { default as ProviderBox } from './components/Provider/providerBoxVariables'
export { default as Dropdown } from './components/Dropdown/dropdownVariables'
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types'
import {
default as Dropdown,
DropdownProps,
DropdownState,
} from '../../../../components/Dropdown/Dropdown'
import { DropdownVariablesHC } from './dropdownVariables'

type DropdownPropsAndState = DropdownProps & DropdownState

const transparentColorStyle: ICSSInJSStyle = {
backgroundColor: 'transparent',
borderColor: 'transparent',
borderBottomColor: 'transparent',
}

const dropdownStyles: ComponentSlotStylesInput<DropdownPropsAndState, DropdownVariablesHC> = {
container: ({ props: p, variables: v }): ICSSInJSStyle => ({
...(!p.open && {
':hover': {
backgroundColor: v.backgroundColorHover,
borderColor: v.borderColorHover,
[`& .${Dropdown.slotClassNames.triggerButton}`]: {
color: v.triggerButtonColorHover,
},
},
}),
}),

triggerButton: ({ props: p, variables: v }): ICSSInJSStyle => ({
':hover': {
...transparentColorStyle,
color: v.triggerButtonColorHover,
},
':focus': {
color: v.color,
':active': {
color: v.color,
},
},
}),
}

export default dropdownStyles
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { DropdownVariables } from '../../../teams/components/Dropdown/dropdownVariables'
import { pxToRem } from '../../../../lib'

export interface DropdownVariablesHC extends DropdownVariables {
borderColorHover: string
}

export default (siteVars): Partial<DropdownVariablesHC> => ({
backgroundColor: siteVars.colors.black,
borderColor: siteVars.colors.white,
borderRadius: pxToRem(3),
borderWidth: `1px`,
backgroundColorHover: siteVars.colors.black,
borderColorHover: siteVars.accessibleYellow,
borderColorFocus: siteVars.accessibleCyan,
color: siteVars.colors.white,
selectedItemColor: siteVars.colors.white,
listBackgroundColor: siteVars.colors.black,
listBorderColor: siteVars.colors.white,
listBoxShadow: undefined,
listBorderWidth: '1px',
listItemBackgroundColor: siteVars.colors.black,
listItemColorHover: siteVars.colors.black,
listItemBackgroundColorHover: siteVars.accessibleYellow,
listItemBackgroundColorActive: siteVars.accessibleYellow,
listItemColorActive: siteVars.colors.black,
listItemSelectedColor: siteVars.accessibleCyan,
selectedItemBackgroundColor: siteVars.colors.black,
selectedItemColorFocus: siteVars.colors.black,
selectedItemBackgroundColorFocus: siteVars.accessibleYellow,
triggerButtonColorHover: siteVars.colors.white,
})
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export default (siteVars: any): Partial<InputVariables> => {
fontColor: siteVars.bodyColor,
iconColor: siteVars.bodyColor,
inputFocusBorderColor: `transparent transparent ${siteVars.accessibleYellow} transparent`,
placeholderColor: siteVars.colors.white,
}
}
Loading