Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.

feat(menu): color prop and complex scheme #756

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

## [Unreleased]

### BREAKING CHANGES
- Add `color` prop to `Menu` component, change variable names for `Menu` @Bugaa92 ([#756](https://github.com/stardust-ui/react/pull/756))

### Features
- Export `triangle-down` and `triangle-right` icons in Teams theme @codepretty ([#785](https://github.com/stardust-ui/react/pull/785))
- Add rtl examples for `Button` and `Divider` components @mnajdova ([#792](https://github.com/stardust-ui/react/pull/792))
Expand Down Expand Up @@ -52,7 +55,7 @@ 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))

<!--------------------------------[ v0.18.0 ]------------------------------- -->
## [v0.18.0](https://github.com/stardust-ui/react/tree/v0.18.0) (2019-01-24)
Expand Down
3 changes: 3 additions & 0 deletions docs/src/components/Knobs/Knobs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import KnobsValue from './KnobsValue'

import KnobsBoolean from './KnobsBoolean'
import KnobsScalar from './KnobsScalar'
import KnobsSelect from './KnobsSelect'

const Knobs: any = createComponent(
() => ({
Expand All @@ -31,12 +32,14 @@ const Knobs: any = createComponent(
}),
'div',
)

Knobs.Field = KnobsField
Knobs.Control = KnobsControl
Knobs.Label = KnobsLabel
Knobs.Value = KnobsValue

Knobs.Boolean = KnobsBoolean
Knobs.Scalar = KnobsScalar
Knobs.Select = KnobsSelect

export default Knobs
2 changes: 1 addition & 1 deletion docs/src/components/Knobs/KnobsBoolean.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class KnobsBoolean extends React.Component<any, any> {

return (
<KnobsField>
<KnobsControl>
<KnobsControl textAlign="center">
<input type="checkbox" defaultChecked={booleanValue} onChange={this.handleChange} />
</KnobsControl>
<KnobsLabel value={value} name={name} />
Expand Down
5 changes: 3 additions & 2 deletions docs/src/components/Knobs/KnobsControl.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { createComponent } from 'react-fela'
import { TextAlignProperty } from 'csstype'
import { pxToRem } from 'src/lib'

const KnobsControl = createComponent(
() => ({
({ textAlign = 'initial' }: { textAlign?: TextAlignProperty }) => ({
marginRight: pxToRem(5),
verticalAlign: 'middle',
textAlign: 'center',
textAlign,
}),
'span',
)
Expand Down
5 changes: 3 additions & 2 deletions docs/src/components/Knobs/KnobsField.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createComponent } from 'react-fela'
import { pxToRem } from 'src/lib'

const KnobsField = createComponent(() => ({
const KnobsField = createComponent(({ width = 60 }: { width?: number }) => ({
display: 'grid',
gridTemplateColumns: `${pxToRem(60)} auto`,
alignItems: 'center',
gridTemplateColumns: `${pxToRem(width)} auto`,
}))

export default KnobsField
69 changes: 69 additions & 0 deletions docs/src/components/Knobs/KnobsSelect.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as PropTypes from 'prop-types'
import * as React from 'react'
import * as _ from 'lodash'

import KnobsField from './KnobsField'
import KnobsLabel from './KnobsLabel'
import KnobsControl from './KnobsControl'
import { ObjectOf } from 'types/utils'

export type KnobsSelectItem = { name: string; value: string }

export interface KnobsSelectProps {
onChange?: (data: KnobsSelectProps) => void
name?: string
items?: KnobsSelectItem[]
selectedItem?: KnobsSelectItem
}

class KnobsSelect extends React.Component<KnobsSelectProps, {}> {
private itemsMap: ObjectOf<KnobsSelectItem>

public static propTypes = {
onChange: PropTypes.func,
name: PropTypes.string.isRequired,
items: PropTypes.arrayOf(PropTypes.shape({ name: PropTypes.string, value: PropTypes.string })),
selectedItem: PropTypes.shape({ name: PropTypes.string, value: PropTypes.string }),
}

componentDidMount() {
this.itemsMap = {}
this.props.items.forEach(item => {
this.itemsMap[item.value] = item
})
}

componentWillUnmount() {
this.itemsMap = {}
}

render() {
const { name, items } = this.props
if (!items || !items.length) {
return null
}

const selectedItem = this.props.selectedItem || this.props.items[0]

return (
<KnobsField width={120}>
<KnobsControl>
<select value={selectedItem.value} onChange={this.handleChange}>
{items.map(({ name, value }) => (
<option key={value} value={value}>
{name}
</option>
))}
</select>
</KnobsControl>
<KnobsLabel value={selectedItem.name} name={name} />
</KnobsField>
)
}

private handleChange = (e: React.SyntheticEvent<HTMLElement>) => {
this.props.onChange({ selectedItem: this.itemsMap[_.get(e, 'target.value')] })
}
}

export default KnobsSelect
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react'
import * as PropTypes from 'prop-types'
import * as _ from 'lodash'
import { ProviderConsumer } from '@stardust-ui/react'

import Knobs from 'docs/src/components/Knobs/Knobs'
import { KnobsSelectItem } from 'docs/src/components/Knobs/KnobsSelect'

type MenuExampleColorKnobsProps = {
onKnobChange: () => void
overrides: { selectedItem?: KnobsSelectItem }
}

const MenuExampleColorKnobs = ({
onKnobChange,
overrides: { selectedItem },
}: MenuExampleColorKnobsProps) => {
return (
<ProviderConsumer
render={({ siteVariables: { colorScheme } }) => {
const colorsArr = _.keys(colorScheme).map(color => ({
name: _.startCase(color),
value: color,
}))

return (
<Knobs>
<Knobs.Select
name="Color"
items={colorsArr}
onChange={onKnobChange}
selectedItem={selectedItem}
/>
</Knobs>
)
}}
/>
)
}

MenuExampleColorKnobs.propTypes = {
onKnobChange: PropTypes.func.isRequired,
selectedItem: PropTypes.shape({ name: PropTypes.string, value: PropTypes.string }),
}

MenuExampleColorKnobs.defaultProps = {
selectedItem: { name: 'Primary', value: 'primary' },
}

export default MenuExampleColorKnobs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react'
import * as _ from 'lodash'
import { Menu, Grid, Text } from '@stardust-ui/react'

const items = [
{ key: 'editorials', content: 'Editorials' },
{ key: 'review', content: 'Reviews' },
{ key: 'events', content: 'Upcoming Events' },
]

const iconItems = [
{ key: 'home', content: 'Home', icon: 'home' },
{ key: 'users', content: 'Users', icon: 'users' },
{ key: 'search', icon: 'search' },
]

const MenuExampleColor = ({
knobs: {
selectedItem: { name, value },
},
}: {
knobs: { selectedItem: { name: string; value: string } }
}) => (
<Grid
columns="repeat(2, auto)"
styles={{ justifyContent: 'left', justifyItems: 'left', alignItems: 'center' }}
variables={{ gridGap: '10px' }}
>
<Text content="Default menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} items={items} />
<Text content="Pills menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} pills items={items} />
<Text content="Pointing menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} pointing items={items} />
<Text content="Vertical pointing menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} vertical pointing items={items} />
<Text content="Underlined menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} underlined items={items} />
<Text content="Icon menu:" weight="bold" />
<Menu defaultActiveIndex={0} color={value} items={iconItems} />
<Text content="Icon only menu:" weight="bold" />
<Menu
defaultActiveIndex={0}
color={value}
iconOnly
items={iconItems.map(item => _.pick(item, ['key', 'icon']))}
/>
</Grid>
)

export default MenuExampleColor
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

for tracking @layershifter 's comment in: #712 (comment)

This example looks overcomplicated to me, may be we can:

  • introduce a new Select knob
  • use it to get select an active color

will address

Copy link
Member

@levithomason levithomason Jan 22, 2019

Choose a reason for hiding this comment

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

Bare minimum examples

Reference SUIR for examples of clean Menu color examples. Let's not put so much information in a single example.

https://react.semantic-ui.com/collections/menu/#variations-colored

Definition only, avoid large permutations

The doc page should only be a "definition" of the component right now. That is a single example for each thing the menu can do, usually one example per prop.

At this point, let's not add examples for all possible permutations of what the menu can do.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@levithomason
in SUIR there are not that many versions of Menus; I just introduced a Select Knob at @layershifter 's proposal and now we have examples that look like this:

TODO - introduce screenshot

We can separate these into different example files where we reuse the knob or we can add a knob on every example for the color, but because of the way knobs are implemented we need to have a .knobs.tsx file for every example, which is a lot of duplication

what do you think?

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as React from 'react'
import * as _ from 'lodash'
import { Menu, ProviderConsumer } from '@stardust-ui/react'

const items = [
{ key: 'editorials', content: 'Editorials' },
{ key: 'review', content: 'Reviews' },
{ key: 'events', content: 'Upcoming Events' },
]

const MenuExampleColorComplex = () => (
<ProviderConsumer
render={({ siteVariables: { colorScheme } }) => {
const colors = _.keys(colorScheme)

return (
<Menu
defaultActiveIndex={0}
underlined
color={{ foreground: colors[3], background: colors[1], border: colors[0] }}
items={items}
/>
)
}}
/>
)

export default MenuExampleColorComplex
10 changes: 10 additions & 0 deletions docs/src/examples/components/Menu/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ const Variations = () => (
description="A vertical menu can be fluid which takes up the full space of its container. A horizontal menu does this by default."
examplePath="components/Menu/Variations/MenuExampleFluid"
/>
<ComponentExample
title="Colored Menu"
description="A Menu can have different colors."
examplePath="components/Menu/Variations/MenuExampleColor"
/>
<ComponentExample
title="Complex Colored Menu"
description="A Menu can have different colors for different areas (border, background, foregroung)."
examplePath="components/Menu/Variations/MenuExampleColorComplex"
/>
</ExampleSection>
)

Expand Down
2 changes: 1 addition & 1 deletion src/components/Label/Label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import {
commonPropTypes,
ColorComponentProps,
rtlTextContainer,
ComplexColorPropType,
} from '../../lib'

import Icon from '../Icon/Icon'
import Image from '../Image/Image'
import Layout from '../Layout/Layout'
import { Accessibility } from '../../lib/accessibility/types'
import { ReactProps, ShorthandValue } from '../../../types/utils'
import { ComplexColorPropType } from '../../lib/commonPropInterfaces'

export interface LabelProps
extends UIComponentProps,
Expand Down
10 changes: 9 additions & 1 deletion src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
commonPropTypes,
getKindProp,
rtlTextContainer,
ColorComponentProps,
ComplexColorPropType,
} from '../../lib'
import MenuItem from './MenuItem'
import { menuBehavior } from '../../lib/accessibility'
Expand All @@ -23,7 +25,10 @@ import MenuDivider from './MenuDivider'

export type MenuShorthandKinds = 'divider' | 'item'

export interface MenuProps extends UIComponentProps, ChildrenComponentProps {
export interface MenuProps
extends UIComponentProps,
ChildrenComponentProps,
ColorComponentProps<ComplexColorPropType> {
/**
* Accessibility behavior if overridden by the user.
* @default menuBehavior
Expand Down Expand Up @@ -93,6 +98,7 @@ class Menu extends AutoControlledComponent<ReactProps<MenuProps>, MenuState> {
static propTypes = {
...commonPropTypes.createCommon({
content: false,
color: 'complex',
}),
accessibility: PropTypes.func,
activeIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
Expand Down Expand Up @@ -141,6 +147,7 @@ class Menu extends AutoControlledComponent<ReactProps<MenuProps>, MenuState> {

renderItems = (variables: ComponentVariablesObject) => {
const {
color,
iconOnly,
items,
pills,
Expand Down Expand Up @@ -172,6 +179,7 @@ class Menu extends AutoControlledComponent<ReactProps<MenuProps>, MenuState> {

return MenuItem.create(item, {
defaultProps: {
color,
iconOnly,
pills,
pointing,
Expand Down
Loading