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

feat(menu): color prop #712

Closed
wants to merge 2 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
### Features
- Add `Loader` component @layershifter ([#685](https://github.com/stardust-ui/react/pull/685))
- Add `color` prop to `Label` component @Bugaa92 ([#647](https://github.com/stardust-ui/react/pull/647))
- Add `color` prop to `Menu` component @Bugaa92 ([#712](https://github.com/stardust-ui/react/pull/712))

### Fixes
- Fix focus outline visible only during keyboard navigation @kolaps33 ([#689] https://github.com/stardust-ui/react/pull/689)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from 'react'
import * as _ from 'lodash'
import { Menu, ProviderConsumer, 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 = () => (
<ProviderConsumer
render={({ siteVariables: { colorScheme } }) => {
const colorsArr = _.keys(colorScheme)
const colors = _.times(7, num => colorsArr[num % colorsArr.length])

return (
<Grid
columns="repeat(2, auto)"
styles={{ justifyContent: 'left', justifyItems: 'left', alignItems: 'center' }}
variables={{ gridGap: '10px' }}
>
<Text content={`${_.upperCase(colors[0])} DEFAULT MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[0]} items={items} />
<Text content={`${_.upperCase(colors[1])} PILLS MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[1]} pills items={items} />
<Text content={`${_.upperCase(colors[2])} POINTING MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[2]} pointing items={items} />
<Text content={`${_.upperCase(colors[3])} VERTICAL POINTING MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[3]} vertical pointing items={items} />
<Text content={`${_.upperCase(colors[4])} UNDERLINED MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[4]} underlined items={items} />
<Text content={`${_.upperCase(colors[5])} ICON MENU:`} weight="bold" />
<Menu defaultActiveIndex={0} color={colors[5]} items={iconItems} />
<Text content={`${_.upperCase(colors[6])} ICON ONLY MENU:`} weight="bold" />
<Menu
defaultActiveIndex={0}
color={colors[6]}
iconOnly
items={iconItems.map(item => _.pick(item, ['key', 'icon']))}
/>
<Text content={`UNDERLINED MENU (mutiple colors):`} weight="bold" />
<Menu
defaultActiveIndex={0}
underlined
color={{ foreground: colors[4], background: colors[6], border: colors[1] }}
items={items}
/>
</Grid>
)
}}
/>
)

export default MenuExampleColor
Copy link
Member

Choose a reason for hiding this comment

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

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

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@layershifter can you show me an example of that? I would give it a shot

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const items = [
]

const MenuExampleVerticalPointing = () => (
<Menu defaultActiveIndex={0} items={items} vertical pointing />
<Menu defaultActiveIndex={0} items={items} vertical pointing primary />
)

export default MenuExampleVerticalPointing
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const items = [
]

const MenuExampleVerticalPointingEnd = () => (
<Menu defaultActiveIndex={0} items={items} vertical pointing="end" />
<Menu defaultActiveIndex={0} items={items} vertical pointing="end" primary />
)

export default MenuExampleVerticalPointingEnd
5 changes: 5 additions & 0 deletions docs/src/examples/components/Menu/Variations/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ const Variations = () => (
description="A menu with Toolbar accessibility behavior."
examplePath="components/Menu/Variations/MenuExampleToolbar"
/>
<ComponentExample
title="Colored Menu"
description="A Menu can have different colors."
examplePath="components/Menu/Variations/MenuExampleColor"
/>
</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 @@ -12,14 +12,14 @@ import {
ContentComponentProps,
commonPropTypes,
ColorComponentProps,
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 @@ -11,6 +11,8 @@ import {
ChildrenComponentProps,
commonPropTypes,
getKindProp,
ColorComponentProps,
ComplexColorPropType,
} from '../../lib'
import MenuItem from './MenuItem'
import { menuBehavior } from '../../lib/accessibility'
Expand All @@ -22,7 +24,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 @@ -89,6 +94,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 @@ -136,6 +142,7 @@ class Menu extends AutoControlledComponent<ReactProps<MenuProps>, MenuState> {

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

return MenuItem.create(item, {
defaultProps: {
color,
iconOnly,
pills,
pointing,
Expand Down
10 changes: 7 additions & 3 deletions src/components/Menu/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
commonPropTypes,
isFromKeyboard,
EventStack,
ColorComponentProps,
ComplexColorPropType,
} from '../../lib'
import Icon from '../Icon/Icon'
import Menu from '../Menu/Menu'
Expand All @@ -28,7 +30,8 @@ import Ref from '../Ref/Ref'
export interface MenuItemProps
extends UIComponentProps,
ChildrenComponentProps,
ContentComponentProps {
ContentComponentProps,
ColorComponentProps<ComplexColorPropType> {
/**
* Accessibility behavior if overridden by the user.
* @default menuItemBehavior
Expand Down Expand Up @@ -123,7 +126,7 @@ class MenuItem extends AutoControlledComponent<ReactProps<MenuItemProps>, MenuIt
static create: Function

static propTypes = {
...commonPropTypes.createCommon(),
...commonPropTypes.createCommon({ color: 'complex' }),
accessibility: PropTypes.func,
active: PropTypes.bool,
disabled: PropTypes.bool,
Expand Down Expand Up @@ -172,7 +175,7 @@ class MenuItem extends AutoControlledComponent<ReactProps<MenuItemProps>, MenuIt
}

renderComponent({ ElementType, classes, accessibility, unhandledProps, styles }) {
const { children, content, icon, wrapper, menu, primary, secondary, active } = this.props
const { children, color, content, icon, wrapper, menu, primary, secondary, active } = this.props

const { menuOpen } = this.state

Expand Down Expand Up @@ -202,6 +205,7 @@ class MenuItem extends AutoControlledComponent<ReactProps<MenuItemProps>, MenuIt
{Menu.create(menu, {
defaultProps: {
accessibility: submenuBehavior,
color,
vertical: true,
primary,
secondary,
Expand Down
11 changes: 6 additions & 5 deletions src/lib/colorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ export const mapColorsToScheme = <T>(
typeof mapper === 'number' ? String(mapper) : (mapper as any),
) as ColorValues<T>

export const getColorSchemeFn = <T>(colorProp: string, colorScheme: ColorValues<T>) => {
const colors = _.get(colorScheme, colorProp)
return (area: keyof T, defaultColor: string) => (colors ? colors[area] : defaultColor)
}
export const getColorFromScheme = <T extends {}>(
colorScheme: T,
area: keyof T,
defaultColor: string,
) => _.get(colorScheme, area, defaultColor)

export const getColorSchemeFromObject = (
colorScheme: ColorValues<Partial<ColorScheme>>,
Expand Down Expand Up @@ -61,7 +62,7 @@ export const generateColorScheme = (
// if the color prop is not defined, but the the color scheme is defined, then we are returning
// the defaults from the color scheme if they exists
if (colorScheme) {
return colorScheme && colorScheme.default ? colorScheme.default : {}
return colorScheme.default || {}
}

// if the color scheme is not defined, then if the color prop is a scheme object we are
Expand Down
9 changes: 3 additions & 6 deletions src/lib/commonPropInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,10 @@ export type ColorValue =
| string

export type ComplexColorPropType =
| {
foreground?: ColorValue
background?: ColorValue
border?: ColorValue
shadow?: ColorValue
}
| ColorValue
| Partial<
Record<'foreground' | 'background' | 'border' | 'shadow' | 'lighterBackground', ColorValue>
>

export interface ColorComponentProps<TColor = ColorValue> {
/** A component can have a color. */
Expand Down
2 changes: 2 additions & 0 deletions src/themes/base/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,13 @@ export const colorScheme: ColorSchemeMapping = _.mapValues(
border: foreground,
shadow: foreground,
background: colorVariants[500],
lighterBackground: colorVariants[300],
default: {
foreground: colors.grey[600],
border: colors.grey[600],
shadow: colors.grey[600],
background: colors.grey[100],
lighterBackground: colors.grey[300],
},
}
},
Expand Down
2 changes: 2 additions & 0 deletions src/themes/teams/colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,13 @@ export const colorScheme: ColorSchemeMapping = _.mapValues(
border: foreground,
shadow: foreground,
background: colorVariants[500],
lighterBackground: colorVariants[300],
default: {
foreground: colors.grey[600],
border: colors.grey[600],
shadow: colors.grey[600],
background: colors.grey[100],
lighterBackground: colors.grey[300],
},
}
},
Expand Down
Loading