From 79e1f5ac4e5a39d5418210911a920228e4051468 Mon Sep 17 00:00:00 2001 From: Levi Thomason Date: Mon, 20 May 2019 11:07:36 -0700 Subject: [PATCH 01/13] wip --- CALLING.md | 6 ++ .../Types/ToolbarExample.shorthand.tsx | 61 +++++++++++++++++ .../Toolbar/Types/ToolbarExample.tsx | 6 ++ .../components/Toolbar/Types/index.tsx | 15 +++++ .../src/examples/components/Toolbar/index.tsx | 11 +++ .../react/src/components/Toolbar/Toolbar.tsx | 67 +++++++++++++++++++ packages/react/src/index.ts | 1 + 7 files changed, 167 insertions(+) create mode 100644 CALLING.md create mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx create mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx create mode 100644 docs/src/examples/components/Toolbar/Types/index.tsx create mode 100644 docs/src/examples/components/Toolbar/index.tsx create mode 100644 packages/react/src/components/Toolbar/Toolbar.tsx diff --git a/CALLING.md b/CALLING.md new file mode 100644 index 0000000000..768c5ba1aa --- /dev/null +++ b/CALLING.md @@ -0,0 +1,6 @@ +# Calling Screen + +Based on initial notes, the toolbar component is likely a separate component: +- The button inside is a subset of the Button +- It contains many more controls than just button + diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx new file mode 100644 index 0000000000..1b2d5f40eb --- /dev/null +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx @@ -0,0 +1,61 @@ +import * as React from 'react' +import { Toolbar, Image } from '@stardust-ui/react' + +const ToolbarExampleShorthand = () => ( +
+ + W3 Aria Toolbar + + {/* Pagination Control */}
}, + + { kind: 'button', content: 'Stop Presenting' }, + + { danger: true, icon: 'phone hang up' }, + ]} + /> + + +) + +export default ToolbarExampleShorthand diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx new file mode 100644 index 0000000000..2be5602fc3 --- /dev/null +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx @@ -0,0 +1,6 @@ +import * as React from 'react' +import { Toolbar } from '@stardust-ui/react' + +const ToolbarExampleShorthand = () => Content + +export default ToolbarExampleShorthand diff --git a/docs/src/examples/components/Toolbar/Types/index.tsx b/docs/src/examples/components/Toolbar/Types/index.tsx new file mode 100644 index 0000000000..30a06abd22 --- /dev/null +++ b/docs/src/examples/components/Toolbar/Types/index.tsx @@ -0,0 +1,15 @@ +import * as React from 'react' +import ComponentExample from 'docs/src/components/ComponentDoc/ComponentExample' +import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection' + +const Types = () => ( + + + +) + +export default Types diff --git a/docs/src/examples/components/Toolbar/index.tsx b/docs/src/examples/components/Toolbar/index.tsx new file mode 100644 index 0000000000..212985429c --- /dev/null +++ b/docs/src/examples/components/Toolbar/index.tsx @@ -0,0 +1,11 @@ +import * as React from 'react' + +import Types from './Types' + +const ToolbarExamples = () => ( + <> + + +) + +export default ToolbarExamples diff --git a/packages/react/src/components/Toolbar/Toolbar.tsx b/packages/react/src/components/Toolbar/Toolbar.tsx new file mode 100644 index 0000000000..5a35a4767a --- /dev/null +++ b/packages/react/src/components/Toolbar/Toolbar.tsx @@ -0,0 +1,67 @@ +import * as React from 'react' + +import { + childrenExist, + createShorthandFactory, + UIComponent, + UIComponentProps, + ContentComponentProps, + ChildrenComponentProps, + commonPropTypes, + ColorComponentProps, +} from '../../lib' +import { Accessibility } from '../../lib/accessibility/types' +import { defaultBehavior } from '../../lib/accessibility' +import { WithAsProp, withSafeTypeForAs } from '../../types' + +export interface ToolbarProps + extends UIComponentProps, + ContentComponentProps, + ChildrenComponentProps, + ColorComponentProps { + /** + * Accessibility behavior if overridden by the user. + * @default defaultBehavior + */ + accessibility?: Accessibility +} + +class Toolbar extends UIComponent, any> { + static create: Function + + static className = 'ui-text' + + static displayName = 'Toolbar' + + static propTypes = { + ...commonPropTypes.createCommon(), + } + + static defaultProps = { + accessibility: defaultBehavior, + as: 'span', + } + + renderComponent({ accessibility, ElementType, classes, unhandledProps }): React.ReactNode { + const { children, content } = this.props + + return ( + + {childrenExist(children) ? children : content} + + ) + } +} + +Toolbar.create = createShorthandFactory({ Component: Toolbar, mappedProp: 'content' }) + +/** + * A Toolbar component groups actions. + * @accessibility + * TODO + */ +export default withSafeTypeForAs(Toolbar) diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 666a82bc0f..b95508f566 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -140,6 +140,7 @@ export { default as Segment, SegmentProps } from './components/Segment/Segment' export { default as Status, StatusProps } from './components/Status/Status' export { default as Text, TextProps } from './components/Text/Text' +export { default as Toolbar, ToolbarProps } from './components/Toolbar/Toolbar' export { default as Animation, AnimationProps } from './components/Animation/Animation' From f15f072f3762304e3163ef3147f98b82fa330008 Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 21 May 2019 20:53:55 +0200 Subject: [PATCH 02/13] basic Toolbar components scaffolding --- .../Types/ToolbarExample.shorthand.tsx | 14 +++-- .../react/src/components/Toolbar/Toolbar.tsx | 24 ++++++-- .../src/components/Toolbar/ToolbarDivider.tsx | 45 +++++++++++++++ .../src/components/Toolbar/ToolbarGroup.tsx | 41 ++++++++++++++ .../src/components/Toolbar/ToolbarItem.tsx | 56 +++++++++++++++++++ .../components/Toolbar/renderToolbarItems.tsx | 29 ++++++++++ 6 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 packages/react/src/components/Toolbar/ToolbarDivider.tsx create mode 100644 packages/react/src/components/Toolbar/ToolbarGroup.tsx create mode 100644 packages/react/src/components/Toolbar/ToolbarItem.tsx create mode 100644 packages/react/src/components/Toolbar/renderToolbarItems.tsx diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx index 1b2d5f40eb..3847a6a5d9 100644 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx @@ -6,6 +6,7 @@ const ToolbarExampleShorthand = () => ( W3 Aria Toolbar + ( { primary: true, icon: 'video' }, { primary: true, icon: 'microphone' }, - { primary: true, icon: 'scree-share-stop' }, - { primary: true, icon: 'horizontal ellipsis' }, + { primary: true, icon: 'call-control-present-new' }, { - secondary: true, - icon: 'horizontal ellipsis', + icon: 'more', menu: [ { icon: 'list', content: 'Show meeting notes' }, // ... @@ -35,7 +34,10 @@ const ToolbarExampleShorthand = () => ( // Radios do not allow you unselect an option this way. kind: 'group', // Consider a top level 'onItemClick', easier integration with lists of items passed in - items: [{ icon: 'chat', secondary: true }, { icon: 'add user', secondary: true }], + items: [ + { icon: { name: 'chat', outline: true }, secondary: true }, + { icon: { name: 'user-friends', outline: true }, secondary: true }, + ], }, { kind: 'divider' }, @@ -48,7 +50,7 @@ const ToolbarExampleShorthand = () => ( { kind: 'button', content: 'Stop Presenting' }, - { danger: true, icon: 'phone hang up' }, + { danger: true, icon: 'call-end' }, ]} /> , any> { static create: Function - static className = 'ui-text' + static className = 'ui-toolbar' static displayName = 'Toolbar' static propTypes = { ...commonPropTypes.createCommon(), + items: collectionShorthandToolbarItem(), } static defaultProps = { accessibility: defaultBehavior, - as: 'span', } + static Item = ToolbarItem + static Divider = ToolbarDivider + renderComponent({ accessibility, ElementType, classes, unhandledProps }): React.ReactNode { - const { children, content } = this.props + const { children, items } = this.props return ( - {childrenExist(children) ? children : content} + {childrenExist(children) ? children : renderToolbarItems(items)} ) } @@ -64,4 +78,4 @@ Toolbar.create = createShorthandFactory({ Component: Toolbar, mappedProp: 'conte * @accessibility * TODO */ -export default withSafeTypeForAs(Toolbar) +export default withSafeTypeForAs(Toolbar) diff --git a/packages/react/src/components/Toolbar/ToolbarDivider.tsx b/packages/react/src/components/Toolbar/ToolbarDivider.tsx new file mode 100644 index 0000000000..ad291684b2 --- /dev/null +++ b/packages/react/src/components/Toolbar/ToolbarDivider.tsx @@ -0,0 +1,45 @@ +import * as React from 'react' +import { + ChildrenComponentProps, + ContentComponentProps, + UIComponentProps, + UIComponent, + commonPropTypes, +} from 'src/lib' +import { Accessibility } from '@stardust-ui/react' +import { WithAsProp, withSafeTypeForAs } from 'src/types' +import { createShorthandFactory } from 'src/lib/factories' + +export interface ToolbarDividerProps + extends UIComponentProps, + ChildrenComponentProps, + ContentComponentProps { + /** + * Accessibility behavior if overridden by the user. + * @default menuDividerBehavior + */ + accessibility?: Accessibility +} + +class ToolbarDivider extends UIComponent> { + static displayName = 'ToolbarDivider' + + static create: Function + + static className = 'ui-toolbar__divider' + + static propTypes = { + ...commonPropTypes.createCommon(), + } + + renderComponent({ ElementType }) { + return | + } +} + +ToolbarDivider.create = createShorthandFactory({ Component: ToolbarDivider, mappedProp: 'content' }) + +/** + * Toolbar divider + */ +export default withSafeTypeForAs(ToolbarDivider) diff --git a/packages/react/src/components/Toolbar/ToolbarGroup.tsx b/packages/react/src/components/Toolbar/ToolbarGroup.tsx new file mode 100644 index 0000000000..c4fe96b08a --- /dev/null +++ b/packages/react/src/components/Toolbar/ToolbarGroup.tsx @@ -0,0 +1,41 @@ +import * as React from 'react' + +import { + ChildrenComponentProps, + ContentComponentProps, + createShorthandFactory, + UIComponentProps, + UIComponent, + childrenExist, +} from '../../lib' +import { WithAsProp, withSafeTypeForAs } from '../../types' + +import { renderToolbarItems, ToolbarItemShorthandCollection } from './renderToolbarItems' + +export interface ToolbarGroupProps + extends UIComponentProps, + ChildrenComponentProps, + ContentComponentProps { + items?: ToolbarItemShorthandCollection +} + +class ToolbarGroup extends UIComponent> { + static displayName = 'ToolbarGroup' + + static className = 'ui-toolbar__group' + + static create: Function + + renderComponent({ ElementType }) { + const { children, items } = this.props + return ( + + {childrenExist(children) ? children : renderToolbarItems(items)} + + ) + } +} + +ToolbarGroup.create = createShorthandFactory({ Component: ToolbarGroup, mappedProp: 'content' }) + +export default withSafeTypeForAs(ToolbarGroup) diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx new file mode 100644 index 0000000000..f591656cc4 --- /dev/null +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -0,0 +1,56 @@ +import * as React from 'react' + +import { + UIComponent, + createShorthandFactory, + UIComponentProps, + ChildrenComponentProps, + ContentComponentProps, + commonPropTypes, + childrenExist, +} from '../../lib' +import { ShorthandValue, WithAsProp, withSafeTypeForAs } from '../../types' +import { Accessibility } from '../../lib/accessibility/types' +import Icon from '../Icon/Icon' +import * as customPropTypes from '@stardust-ui/react-proptypes' + +export interface ToolbarItemProps + extends UIComponentProps, + ChildrenComponentProps, + ContentComponentProps { + /** + * Accessibility behavior if overridden by the user. + * @default menuItemBehavior + * @available toolbarButtonBehavior, tabBehavior + * */ + accessibility?: Accessibility + + /** Name or shorthand for Toolbar Item Icon */ + icon?: ShorthandValue +} + +class ToolbarItem extends UIComponent> { + static displayName = 'ToolbarItem' + + static className = 'ui-toolbar__item' + + static create: Function + + static propTypes = { + ...commonPropTypes.createCommon(), + icon: customPropTypes.itemShorthand, + } + + static defaultProps = { + as: 'button', + } + + renderComponent({ ElementType }) { + const { icon, children } = this.props + return {childrenExist(children) ? children : Icon.create(icon)} + } +} + +ToolbarItem.create = createShorthandFactory({ Component: ToolbarItem, mappedProp: 'content' }) + +export default withSafeTypeForAs(ToolbarItem) diff --git a/packages/react/src/components/Toolbar/renderToolbarItems.tsx b/packages/react/src/components/Toolbar/renderToolbarItems.tsx new file mode 100644 index 0000000000..6e88c89cb1 --- /dev/null +++ b/packages/react/src/components/Toolbar/renderToolbarItems.tsx @@ -0,0 +1,29 @@ +import { ShorthandCollection } from '../../types' +import * as customPropTypes from '@stardust-ui/react-proptypes' +import * as _ from 'lodash' + +import ToolbarDivider from './ToolbarDivider' +import ToolbarItem from './ToolbarItem' +import ToolbarGroup from './ToolbarGroup' + +export type ToolbarItemShorthandKinds = 'divider' | 'item' | 'button' | 'group' + +export type ToolbarItemShorthandCollection = ShorthandCollection + +export const collectionShorthandToolbarItem = () => + customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'button', 'group']) + +export const renderToolbarItems = items => { + return _.map(items, (item, index) => { + const kind = _.get(item, 'kind', 'item') + + switch (kind) { + case 'divider': + return ToolbarDivider.create(item) + case 'group': + return ToolbarGroup.create(item) + default: + return ToolbarItem.create(item) + } + }) +} From 037d7ddb6859ab356a3e7fbc003f2b9334ba463b Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 21 May 2019 21:56:35 +0200 Subject: [PATCH 03/13] isConformant tests for Toolbar components --- .../react/src/components/Toolbar/Toolbar.tsx | 6 ++- .../src/components/Toolbar/ToolbarDivider.tsx | 24 ++++++++---- .../src/components/Toolbar/ToolbarGroup.tsx | 38 +++++++++++++++++-- .../src/components/Toolbar/ToolbarItem.tsx | 19 +++++++--- .../components/Toolbar/renderToolbarItems.tsx | 1 + packages/react/src/index.ts | 4 ++ .../specs/components/Toolbar/Toolbar-test.ts | 7 ++++ .../components/Toolbar/ToolbarDivider-test.ts | 7 ++++ .../components/Toolbar/ToolbarGroup-test.ts | 7 ++++ .../components/Toolbar/ToolbarItem-test.ts | 7 ++++ 10 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 packages/react/test/specs/components/Toolbar/Toolbar-test.ts create mode 100644 packages/react/test/specs/components/Toolbar/ToolbarDivider-test.ts create mode 100644 packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts create mode 100644 packages/react/test/specs/components/Toolbar/ToolbarItem-test.ts diff --git a/packages/react/src/components/Toolbar/Toolbar.tsx b/packages/react/src/components/Toolbar/Toolbar.tsx index 4a68fd75a2..bf0e90691b 100644 --- a/packages/react/src/components/Toolbar/Toolbar.tsx +++ b/packages/react/src/components/Toolbar/Toolbar.tsx @@ -16,6 +16,8 @@ import { WithAsProp, withSafeTypeForAs } from '../../types' import ToolbarItem from './ToolbarItem' import ToolbarDivider from './ToolbarDivider' +import ToolbarGroup from './ToolbarGroup' + import { collectionShorthandToolbarItem, renderToolbarItems, @@ -54,6 +56,7 @@ class Toolbar extends UIComponent, any> { static Item = ToolbarItem static Divider = ToolbarDivider + static Group = ToolbarGroup renderComponent({ accessibility, ElementType, classes, unhandledProps }): React.ReactNode { const { children, items } = this.props @@ -75,7 +78,6 @@ Toolbar.create = createShorthandFactory({ Component: Toolbar, mappedProp: 'conte /** * A Toolbar component groups actions. - * @accessibility - * TODO + * TODO: add meaningful description */ export default withSafeTypeForAs(Toolbar) diff --git a/packages/react/src/components/Toolbar/ToolbarDivider.tsx b/packages/react/src/components/Toolbar/ToolbarDivider.tsx index ad291684b2..b3f1e00c49 100644 --- a/packages/react/src/components/Toolbar/ToolbarDivider.tsx +++ b/packages/react/src/components/Toolbar/ToolbarDivider.tsx @@ -2,13 +2,14 @@ import * as React from 'react' import { ChildrenComponentProps, ContentComponentProps, + createShorthandFactory, UIComponentProps, UIComponent, commonPropTypes, -} from 'src/lib' -import { Accessibility } from '@stardust-ui/react' -import { WithAsProp, withSafeTypeForAs } from 'src/types' -import { createShorthandFactory } from 'src/lib/factories' +} from '../../lib' +import { Accessibility } from '../../lib/accessibility/types' +import { WithAsProp, withSafeTypeForAs } from '../../types' +import { defaultBehavior } from '../../lib/accessibility' export interface ToolbarDividerProps extends UIComponentProps, @@ -32,14 +33,23 @@ class ToolbarDivider extends UIComponent> { ...commonPropTypes.createCommon(), } - renderComponent({ ElementType }) { - return | + static defaultProps = { + accessibility: defaultBehavior as Accessibility, + } + + renderComponent({ ElementType, classes, unhandledProps, accessibility }) { + return ( + + | + + ) } } ToolbarDivider.create = createShorthandFactory({ Component: ToolbarDivider, mappedProp: 'content' }) /** - * Toolbar divider + * Toolbar divider. + * TODO: add meaningful description */ export default withSafeTypeForAs(ToolbarDivider) diff --git a/packages/react/src/components/Toolbar/ToolbarGroup.tsx b/packages/react/src/components/Toolbar/ToolbarGroup.tsx index c4fe96b08a..930bd2c0e7 100644 --- a/packages/react/src/components/Toolbar/ToolbarGroup.tsx +++ b/packages/react/src/components/Toolbar/ToolbarGroup.tsx @@ -7,29 +7,55 @@ import { UIComponentProps, UIComponent, childrenExist, + commonPropTypes, } from '../../lib' import { WithAsProp, withSafeTypeForAs } from '../../types' -import { renderToolbarItems, ToolbarItemShorthandCollection } from './renderToolbarItems' +import { + collectionShorthandToolbarItem, + renderToolbarItems, + ToolbarItemShorthandCollection, +} from './renderToolbarItems' +import { Accessibility } from '../../lib/accessibility/types' +import { defaultBehavior } from '../../lib/accessibility' export interface ToolbarGroupProps extends UIComponentProps, ChildrenComponentProps, ContentComponentProps { + /** + * Accessibility behavior if overridden by the user. + */ + accessibility?: Accessibility + items?: ToolbarItemShorthandCollection } class ToolbarGroup extends UIComponent> { static displayName = 'ToolbarGroup' - static className = 'ui-toolbar__group' + static className = 'ui-toolbars' // FIXME: required by getComponentInfo/isConformant. But this is group inside a toolbar not a group of toolbars static create: Function - renderComponent({ ElementType }) { + static propTypes = { + ...commonPropTypes.createCommon(), + items: collectionShorthandToolbarItem(), + } + + static defaultProps = { + accessibility: defaultBehavior as Accessibility, + } + + renderComponent({ ElementType, classes, accessibility, unhandledProps }) { const { children, items } = this.props return ( - + {childrenExist(children) ? children : renderToolbarItems(items)} ) @@ -38,4 +64,8 @@ class ToolbarGroup extends UIComponent> { ToolbarGroup.create = createShorthandFactory({ Component: ToolbarGroup, mappedProp: 'content' }) +/** + * Toolbar group. + * TODO: add meaningful description + */ export default withSafeTypeForAs(ToolbarGroup) diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index f591656cc4..8d98e0a2f3 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -11,6 +11,8 @@ import { } from '../../lib' import { ShorthandValue, WithAsProp, withSafeTypeForAs } from '../../types' import { Accessibility } from '../../lib/accessibility/types' +import { defaultBehavior } from '../../lib/accessibility' + import Icon from '../Icon/Icon' import * as customPropTypes from '@stardust-ui/react-proptypes' @@ -20,9 +22,7 @@ export interface ToolbarItemProps ContentComponentProps { /** * Accessibility behavior if overridden by the user. - * @default menuItemBehavior - * @available toolbarButtonBehavior, tabBehavior - * */ + */ accessibility?: Accessibility /** Name or shorthand for Toolbar Item Icon */ @@ -43,14 +43,23 @@ class ToolbarItem extends UIComponent> { static defaultProps = { as: 'button', + accessibility: defaultBehavior as Accessibility, } - renderComponent({ ElementType }) { + renderComponent({ ElementType, classes, unhandledProps, accessibility }) { const { icon, children } = this.props - return {childrenExist(children) ? children : Icon.create(icon)} + return ( + + {childrenExist(children) ? children : Icon.create(icon)} + + ) } } ToolbarItem.create = createShorthandFactory({ Component: ToolbarItem, mappedProp: 'content' }) +/** + * Toolbar item. + * TODO: add meaningful description + */ export default withSafeTypeForAs(ToolbarItem) diff --git a/packages/react/src/components/Toolbar/renderToolbarItems.tsx b/packages/react/src/components/Toolbar/renderToolbarItems.tsx index 6e88c89cb1..c174443ff7 100644 --- a/packages/react/src/components/Toolbar/renderToolbarItems.tsx +++ b/packages/react/src/components/Toolbar/renderToolbarItems.tsx @@ -13,6 +13,7 @@ export type ToolbarItemShorthandCollection = ShorthandCollection customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'button', 'group']) +// TODO: what about nested groups? Do we want to explicitly deny them? export const renderToolbarItems = items => { return _.map(items, (item, index) => { const kind = _.get(item, 'kind', 'item') diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index b95508f566..df97398b8e 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -140,7 +140,11 @@ export { default as Segment, SegmentProps } from './components/Segment/Segment' export { default as Status, StatusProps } from './components/Status/Status' export { default as Text, TextProps } from './components/Text/Text' + export { default as Toolbar, ToolbarProps } from './components/Toolbar/Toolbar' +export { default as ToolbarDivider, ToolbarDividerProps } from './components/Toolbar/ToolbarDivider' +export { default as ToolbarItem, ToolbarItemProps } from './components/Toolbar/ToolbarItem' +export { default as ToolbarGroup, ToolbarGroupProps } from './components/Toolbar/ToolbarGroup' export { default as Animation, AnimationProps } from './components/Animation/Animation' diff --git a/packages/react/test/specs/components/Toolbar/Toolbar-test.ts b/packages/react/test/specs/components/Toolbar/Toolbar-test.ts new file mode 100644 index 0000000000..6ca77e5c04 --- /dev/null +++ b/packages/react/test/specs/components/Toolbar/Toolbar-test.ts @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import Toolbar from 'src/components/Toolbar/Toolbar' + +describe('Toolbar', () => { + isConformant(Toolbar) +}) diff --git a/packages/react/test/specs/components/Toolbar/ToolbarDivider-test.ts b/packages/react/test/specs/components/Toolbar/ToolbarDivider-test.ts new file mode 100644 index 0000000000..41c32e772b --- /dev/null +++ b/packages/react/test/specs/components/Toolbar/ToolbarDivider-test.ts @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import ToolbarDivider from 'src/components/Toolbar/ToolbarDivider' + +describe('ToolbarDivider', () => { + isConformant(ToolbarDivider) +}) diff --git a/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts b/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts new file mode 100644 index 0000000000..95d12734af --- /dev/null +++ b/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import ToolbarGroup from 'src/components/Toolbar/ToolbarGroup' + +describe('ToolbarGroup', () => { + isConformant(ToolbarGroup) +}) diff --git a/packages/react/test/specs/components/Toolbar/ToolbarItem-test.ts b/packages/react/test/specs/components/Toolbar/ToolbarItem-test.ts new file mode 100644 index 0000000000..233e03a262 --- /dev/null +++ b/packages/react/test/specs/components/Toolbar/ToolbarItem-test.ts @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import ToolbarItem from 'src/components/Toolbar/ToolbarItem' + +describe('ToolbarItem', () => { + isConformant(ToolbarItem) +}) From b53537e8f1b74da471758200993dfd34a0cb4b1b Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Thu, 23 May 2019 16:39:56 +0200 Subject: [PATCH 04/13] ToolbarItem onClick --- .../Menu/Types/MenuExample.shorthand.tsx | 6 +- .../Types/ToolbarExample.shorthand.tsx | 127 ++++++++++-------- .../react/src/components/Menu/MenuItem.tsx | 11 +- .../react/src/components/Toolbar/Toolbar.tsx | 35 +++-- .../src/components/Toolbar/ToolbarGroup.tsx | 71 ---------- .../src/components/Toolbar/ToolbarItem.tsx | 52 ++++++- .../components/Toolbar/ToolbarRadioGroup.tsx | 88 ++++++++++++ .../components/Toolbar/renderToolbarItems.tsx | 30 ----- packages/react/src/index.ts | 5 +- .../components/Toolbar/ToolbarGroup-test.ts | 7 - .../Toolbar/ToolbarRadioGroup-test.ts | 7 + 11 files changed, 256 insertions(+), 183 deletions(-) delete mode 100644 packages/react/src/components/Toolbar/ToolbarGroup.tsx create mode 100644 packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx delete mode 100644 packages/react/src/components/Toolbar/renderToolbarItems.tsx delete mode 100644 packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts create mode 100644 packages/react/test/specs/components/Toolbar/ToolbarRadioGroup-test.ts diff --git a/docs/src/examples/components/Menu/Types/MenuExample.shorthand.tsx b/docs/src/examples/components/Menu/Types/MenuExample.shorthand.tsx index 9e5b4550b0..bece5a5c53 100644 --- a/docs/src/examples/components/Menu/Types/MenuExample.shorthand.tsx +++ b/docs/src/examples/components/Menu/Types/MenuExample.shorthand.tsx @@ -7,6 +7,10 @@ const items = [ { key: 'events', content: 'Upcoming Events' }, ] -const MenuExample = () => +const MenuExample = () => ( + {}}> + {}}>x + +) export default MenuExample diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx index 3847a6a5d9..51e3582f16 100644 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx @@ -1,63 +1,76 @@ import * as React from 'react' import { Toolbar, Image } from '@stardust-ui/react' -const ToolbarExampleShorthand = () => ( -
- - W3 Aria Toolbar - - - { + const videoIconEnabled = 'call-video' + const videoIconDisabled = { name: 'call-video-off', outline: true } + + const [videoEnabled, setVideoEnabled] = React.useState(true) + + return ( +
+ + W3 Aria Toolbar + + + { + setVideoEnabled(!videoEnabled) + }, + }, + { primary: true, icon: 'microphone' }, + { primary: true, icon: 'call-control-present-new' }, + { + icon: 'more', + menu: [ + { icon: 'list', content: 'Show meeting notes' }, + // ... + { kind: 'divider' }, + // ... + { icon: 'video off', content: 'Turn off incoming video' }, + ], + }, + { + // TODO: + // note that these don't act like radios exactly. + // You can unselect all options by clicking an option twice. + // Radios do not allow you unselect an option this way. + kind: 'group', + // Consider a top level 'onItemClick', easier integration with lists of items passed in + items: [ + { icon: { name: 'chat', outline: true }, secondary: true }, + { icon: { name: 'user-friends', outline: true }, secondary: true }, + ], + }, + + { kind: 'divider' }, + // TODO: - // note that these don't act like radios exactly. - // You can unselect all options by clicking an option twice. - // Radios do not allow you unselect an option this way. - kind: 'group', - // Consider a top level 'onItemClick', easier integration with lists of items passed in - items: [ - { icon: { name: 'chat', outline: true }, secondary: true }, - { icon: { name: 'user-friends', outline: true }, secondary: true }, - ], - }, - - { kind: 'divider' }, - - // TODO: - // how would FocusZone work in this area? - // should this be a "spin button"? - // should this be 3 separate controls? - { content:
{/* Pagination Control */}
}, - - { kind: 'button', content: 'Stop Presenting' }, - - { danger: true, icon: 'call-end' }, - ]} - /> - -
-) + // how would FocusZone work in this area? + // should this be a "spin button"? + // should this be 3 separate controls? + { content:
{/* Pagination Control */}
}, + + { kind: 'button', content: 'Stop Presenting' }, + + { danger: true, icon: 'call-end' }, + ]} + /> + +
+ ) +} export default ToolbarExampleShorthand diff --git a/packages/react/src/components/Menu/MenuItem.tsx b/packages/react/src/components/Menu/MenuItem.tsx index 492db4a04e..5e0d3e7ece 100644 --- a/packages/react/src/components/Menu/MenuItem.tsx +++ b/packages/react/src/components/Menu/MenuItem.tsx @@ -71,8 +71,7 @@ export interface MenuItemProps itemsCount?: number /** - * Called on click. When passed, the component will render as an `a` - * tag by default instead of a `div`. + * Called on click. * * @param {SyntheticEvent} event - React's original SyntheticEvent. * @param {object} data - All props. @@ -86,6 +85,13 @@ export interface MenuItemProps */ onFocus?: ComponentEventHandler + /** + * Called after item blur. + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props. + */ + onBlur?: ComponentEventHandler + /** A menu can adjust its appearance to de-emphasize its contents. */ pills?: boolean @@ -164,6 +170,7 @@ class MenuItem extends AutoControlledComponent, MenuIt itemsCount: PropTypes.number, onClick: PropTypes.func, onFocus: PropTypes.func, + onBlur: PropTypes.func, pills: PropTypes.bool, pointing: PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['start', 'end'])]), primary: customPropTypes.every([customPropTypes.disallow(['secondary']), PropTypes.bool]), diff --git a/packages/react/src/components/Toolbar/Toolbar.tsx b/packages/react/src/components/Toolbar/Toolbar.tsx index bf0e90691b..8111e32cc2 100644 --- a/packages/react/src/components/Toolbar/Toolbar.tsx +++ b/packages/react/src/components/Toolbar/Toolbar.tsx @@ -1,4 +1,6 @@ import * as React from 'react' +import * as _ from 'lodash' +import * as customPropTypes from '@stardust-ui/react-proptypes' import { childrenExist, @@ -12,17 +14,13 @@ import { } from '../../lib' import { Accessibility } from '../../lib/accessibility/types' import { defaultBehavior } from '../../lib/accessibility' -import { WithAsProp, withSafeTypeForAs } from '../../types' +import { ShorthandCollection, WithAsProp, withSafeTypeForAs } from '../../types' import ToolbarItem from './ToolbarItem' import ToolbarDivider from './ToolbarDivider' -import ToolbarGroup from './ToolbarGroup' +import ToolbarRadioGroup from './ToolbarRadioGroup' -import { - collectionShorthandToolbarItem, - renderToolbarItems, - ToolbarItemShorthandCollection, -} from './renderToolbarItems' +export type ToolbarItemShorthandKinds = 'divider' | 'item' | 'button' | 'group' export interface ToolbarProps extends UIComponentProps, @@ -35,7 +33,7 @@ export interface ToolbarProps */ accessibility?: Accessibility - items?: ToolbarItemShorthandCollection + items?: ShorthandCollection } class Toolbar extends UIComponent, any> { @@ -47,7 +45,7 @@ class Toolbar extends UIComponent, any> { static propTypes = { ...commonPropTypes.createCommon(), - items: collectionShorthandToolbarItem(), + items: customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'button', 'group']), } static defaultProps = { @@ -56,7 +54,22 @@ class Toolbar extends UIComponent, any> { static Item = ToolbarItem static Divider = ToolbarDivider - static Group = ToolbarGroup + static RadioGroup = ToolbarRadioGroup + + private renderItems(items) { + return _.map(items, (item, index) => { + const kind = _.get(item, 'kind', 'item') + + switch (kind) { + case 'divider': + return ToolbarDivider.create(item) + case 'group': + return ToolbarRadioGroup.create(item) + default: + return ToolbarItem.create(item) + } + }) + } renderComponent({ accessibility, ElementType, classes, unhandledProps }): React.ReactNode { const { children, items } = this.props @@ -68,7 +81,7 @@ class Toolbar extends UIComponent, any> { {...accessibility.attributes.root} {...unhandledProps} > - {childrenExist(children) ? children : renderToolbarItems(items)} + {childrenExist(children) ? children : this.renderItems(items)} ) } diff --git a/packages/react/src/components/Toolbar/ToolbarGroup.tsx b/packages/react/src/components/Toolbar/ToolbarGroup.tsx deleted file mode 100644 index 930bd2c0e7..0000000000 --- a/packages/react/src/components/Toolbar/ToolbarGroup.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import * as React from 'react' - -import { - ChildrenComponentProps, - ContentComponentProps, - createShorthandFactory, - UIComponentProps, - UIComponent, - childrenExist, - commonPropTypes, -} from '../../lib' -import { WithAsProp, withSafeTypeForAs } from '../../types' - -import { - collectionShorthandToolbarItem, - renderToolbarItems, - ToolbarItemShorthandCollection, -} from './renderToolbarItems' -import { Accessibility } from '../../lib/accessibility/types' -import { defaultBehavior } from '../../lib/accessibility' - -export interface ToolbarGroupProps - extends UIComponentProps, - ChildrenComponentProps, - ContentComponentProps { - /** - * Accessibility behavior if overridden by the user. - */ - accessibility?: Accessibility - - items?: ToolbarItemShorthandCollection -} - -class ToolbarGroup extends UIComponent> { - static displayName = 'ToolbarGroup' - - static className = 'ui-toolbars' // FIXME: required by getComponentInfo/isConformant. But this is group inside a toolbar not a group of toolbars - - static create: Function - - static propTypes = { - ...commonPropTypes.createCommon(), - items: collectionShorthandToolbarItem(), - } - - static defaultProps = { - accessibility: defaultBehavior as Accessibility, - } - - renderComponent({ ElementType, classes, accessibility, unhandledProps }) { - const { children, items } = this.props - return ( - - {childrenExist(children) ? children : renderToolbarItems(items)} - - ) - } -} - -ToolbarGroup.create = createShorthandFactory({ Component: ToolbarGroup, mappedProp: 'content' }) - -/** - * Toolbar group. - * TODO: add meaningful description - */ -export default withSafeTypeForAs(ToolbarGroup) diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index 8d98e0a2f3..1047d318f7 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -1,4 +1,7 @@ import * as React from 'react' +import * as _ from 'lodash' +import * as PropTypes from 'prop-types' +import * as customPropTypes from '@stardust-ui/react-proptypes' import { UIComponent, @@ -9,12 +12,11 @@ import { commonPropTypes, childrenExist, } from '../../lib' -import { ShorthandValue, WithAsProp, withSafeTypeForAs } from '../../types' +import { ComponentEventHandler, ShorthandValue, WithAsProp, withSafeTypeForAs } from '../../types' import { Accessibility } from '../../lib/accessibility/types' import { defaultBehavior } from '../../lib/accessibility' import Icon from '../Icon/Icon' -import * as customPropTypes from '@stardust-ui/react-proptypes' export interface ToolbarItemProps extends UIComponentProps, @@ -27,6 +29,28 @@ export interface ToolbarItemProps /** Name or shorthand for Toolbar Item Icon */ icon?: ShorthandValue + + /** + * Called on click. + * + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props. + */ + onClick?: ComponentEventHandler + + /** + * Called after user's focus. + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props. + */ + onFocus?: ComponentEventHandler + + /** + * Called after item blur. + * @param {SyntheticEvent} event - React's original SyntheticEvent. + * @param {object} data - All props. + */ + onBlur?: ComponentEventHandler } class ToolbarItem extends UIComponent> { @@ -39,6 +63,9 @@ class ToolbarItem extends UIComponent> { static propTypes = { ...commonPropTypes.createCommon(), icon: customPropTypes.itemShorthand, + onClick: PropTypes.func, + onFocus: PropTypes.func, + onBlur: PropTypes.func, } static defaultProps = { @@ -49,11 +76,30 @@ class ToolbarItem extends UIComponent> { renderComponent({ ElementType, classes, unhandledProps, accessibility }) { const { icon, children } = this.props return ( - + {childrenExist(children) ? children : Icon.create(icon)} ) } + + private handleBlur = (e: React.SyntheticEvent) => { + _.invoke(this.props, 'onBlur', e, this.props) + } + + private handleFocus = (e: React.SyntheticEvent) => { + _.invoke(this.props, 'onFocus', e, this.props) + } + + private handleClick = (e: React.SyntheticEvent) => { + _.invoke(this.props, 'onClick', e, this.props) + } } ToolbarItem.create = createShorthandFactory({ Component: ToolbarItem, mappedProp: 'content' }) diff --git a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx new file mode 100644 index 0000000000..0a144fbc67 --- /dev/null +++ b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx @@ -0,0 +1,88 @@ +import * as React from 'react' +import * as _ from 'lodash' +import * as customPropTypes from '@stardust-ui/react-proptypes' + +import { + ChildrenComponentProps, + ContentComponentProps, + createShorthandFactory, + UIComponentProps, + UIComponent, + childrenExist, + commonPropTypes, +} from '../../lib' +import { ShorthandCollection, WithAsProp, withSafeTypeForAs } from '../../types' +import { Accessibility } from '../../lib/accessibility/types' +import { defaultBehavior } from '../../lib/accessibility' + +import ToolbarDivider from 'src/components/Toolbar/ToolbarDivider' +import ToolbarItem from 'src/components/Toolbar/ToolbarItem' + +export type ToolbarRadioGroupItemShorthandKinds = 'divider' | 'item' + +export interface ToolbarRadioGroupProps + extends UIComponentProps, + ChildrenComponentProps, + ContentComponentProps { + /** + * Accessibility behavior if overridden by the user. + */ + accessibility?: Accessibility + + items?: ShorthandCollection +} + +class ToolbarRadioGroup extends UIComponent> { + static displayName = 'ToolbarRadioGroup' + + static className = 'ui-toolbars' // FIXME: required by getComponentInfo/isConformant. But this is group inside a toolbar not a group of toolbars + + static create: Function + + static propTypes = { + ...commonPropTypes.createCommon(), + items: customPropTypes.collectionShorthandWithKindProp(['divider', 'item']), + } + + static defaultProps = { + accessibility: defaultBehavior as Accessibility, + } + + private renderItems(items) { + return _.map(items, (item, index) => { + const kind = _.get(item, 'kind', 'item') + + if (kind === 'divider') { + return ToolbarDivider.create(item) + } + return ToolbarItem.create(item) + }) + } + + renderComponent({ ElementType, classes, accessibility, unhandledProps }) { + const { children, items } = this.props + return ( + + {childrenExist(children) ? children : this.renderItems(items)} + + ) + } +} + +ToolbarRadioGroup.create = createShorthandFactory({ + Component: ToolbarRadioGroup, + mappedProp: 'content', +}) + +/** + * Toolbar radiogroup. + * TODO: add meaningful description + */ +export default withSafeTypeForAs( + ToolbarRadioGroup, +) diff --git a/packages/react/src/components/Toolbar/renderToolbarItems.tsx b/packages/react/src/components/Toolbar/renderToolbarItems.tsx deleted file mode 100644 index c174443ff7..0000000000 --- a/packages/react/src/components/Toolbar/renderToolbarItems.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { ShorthandCollection } from '../../types' -import * as customPropTypes from '@stardust-ui/react-proptypes' -import * as _ from 'lodash' - -import ToolbarDivider from './ToolbarDivider' -import ToolbarItem from './ToolbarItem' -import ToolbarGroup from './ToolbarGroup' - -export type ToolbarItemShorthandKinds = 'divider' | 'item' | 'button' | 'group' - -export type ToolbarItemShorthandCollection = ShorthandCollection - -export const collectionShorthandToolbarItem = () => - customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'button', 'group']) - -// TODO: what about nested groups? Do we want to explicitly deny them? -export const renderToolbarItems = items => { - return _.map(items, (item, index) => { - const kind = _.get(item, 'kind', 'item') - - switch (kind) { - case 'divider': - return ToolbarDivider.create(item) - case 'group': - return ToolbarGroup.create(item) - default: - return ToolbarItem.create(item) - } - }) -} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index df97398b8e..ba09e70284 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -144,7 +144,10 @@ export { default as Text, TextProps } from './components/Text/Text' export { default as Toolbar, ToolbarProps } from './components/Toolbar/Toolbar' export { default as ToolbarDivider, ToolbarDividerProps } from './components/Toolbar/ToolbarDivider' export { default as ToolbarItem, ToolbarItemProps } from './components/Toolbar/ToolbarItem' -export { default as ToolbarGroup, ToolbarGroupProps } from './components/Toolbar/ToolbarGroup' +export { + default as ToolbarRadioGroup, + ToolbarRadioGroupProps, +} from './components/Toolbar/ToolbarRadioGroup' export { default as Animation, AnimationProps } from './components/Animation/Animation' diff --git a/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts b/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts deleted file mode 100644 index 95d12734af..0000000000 --- a/packages/react/test/specs/components/Toolbar/ToolbarGroup-test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { isConformant } from 'test/specs/commonTests' - -import ToolbarGroup from 'src/components/Toolbar/ToolbarGroup' - -describe('ToolbarGroup', () => { - isConformant(ToolbarGroup) -}) diff --git a/packages/react/test/specs/components/Toolbar/ToolbarRadioGroup-test.ts b/packages/react/test/specs/components/Toolbar/ToolbarRadioGroup-test.ts new file mode 100644 index 0000000000..7868c03046 --- /dev/null +++ b/packages/react/test/specs/components/Toolbar/ToolbarRadioGroup-test.ts @@ -0,0 +1,7 @@ +import { isConformant } from 'test/specs/commonTests' + +import ToolbarRadioGroup from 'src/components/Toolbar/ToolbarRadioGroup' + +describe('ToolbarRadioGroup', () => { + isConformant(ToolbarRadioGroup) +}) From 6ccdb012759e991f2881547b2a20c6dc7bb2398f Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 28 May 2019 11:05:12 +0200 Subject: [PATCH 05/13] fix imports after merging latest master --- .../src/components/Toolbar/ToolbarRadioGroup.tsx | 4 ++-- packages/react/src/index.ts | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx index 0a144fbc67..f3d78262f4 100644 --- a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx +++ b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx @@ -15,8 +15,8 @@ import { ShorthandCollection, WithAsProp, withSafeTypeForAs } from '../../types' import { Accessibility } from '../../lib/accessibility/types' import { defaultBehavior } from '../../lib/accessibility' -import ToolbarDivider from 'src/components/Toolbar/ToolbarDivider' -import ToolbarItem from 'src/components/Toolbar/ToolbarItem' +import ToolbarDivider from './ToolbarDivider' +import ToolbarItem from './ToolbarItem' export type ToolbarRadioGroupItemShorthandKinds = 'divider' | 'item' diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 8b0b4e02d5..6355a3fb90 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -147,13 +147,14 @@ export { default as Text } from './components/Text/Text' export * from './components/Animation/Animation' export { default as Animation } from './components/Animation/Animation' -export { default as Toolbar, ToolbarProps } from './components/Toolbar/Toolbar' -export { default as ToolbarDivider, ToolbarDividerProps } from './components/Toolbar/ToolbarDivider' -export { default as ToolbarItem, ToolbarItemProps } from './components/Toolbar/ToolbarItem' -export { - default as ToolbarRadioGroup, - ToolbarRadioGroupProps, -} from './components/Toolbar/ToolbarRadioGroup' +export * from './components/Toolbar/Toolbar' +export { default as Toolbar } from './components/Toolbar/Toolbar' +export * from './components/Toolbar/ToolbarDivider' +export { default as ToolbarDivider } from './components/Toolbar/ToolbarDivider' +export * from './components/Toolbar/ToolbarItem' +export { default as ToolbarItem } from './components/Toolbar/ToolbarItem' +export * from './components/Toolbar/ToolbarRadioGroup' +export { default as ToolbarRadioGroup } from './components/Toolbar/ToolbarRadioGroup' export * from './components/Tree' export { default as Tree } from './components/Tree' From 62bc4f0569c691403a6ce0145b7e61ac99c0751b Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 28 May 2019 11:24:48 +0200 Subject: [PATCH 06/13] text editor toolbar example --- .../Types/ToolbarExampleEditor.shorthand.tsx | 28 +++++++++++++++++++ .../components/Toolbar/Types/index.tsx | 5 ++++ 2 files changed, 33 insertions(+) create mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx new file mode 100644 index 0000000000..e525b30fb8 --- /dev/null +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx @@ -0,0 +1,28 @@ +import * as React from 'react' +import { Toolbar } from '@stardust-ui/react' + +const ToolbarExampleShorthand = () => ( + +) + +export default ToolbarExampleShorthand diff --git a/docs/src/examples/components/Toolbar/Types/index.tsx b/docs/src/examples/components/Toolbar/Types/index.tsx index 30a06abd22..0cc8f6fa94 100644 --- a/docs/src/examples/components/Toolbar/Types/index.tsx +++ b/docs/src/examples/components/Toolbar/Types/index.tsx @@ -9,6 +9,11 @@ const Types = () => ( description="A Toolbar component." examplePath="components/Toolbar/Types/ToolbarExample" /> + ) From 365f48c14ffbac43778145e37d95029362beef0b Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 28 May 2019 19:24:47 +0200 Subject: [PATCH 07/13] basic styles --- docs/src/app.tsx | 1 - .../Menu/Types/MenuExample.shorthand.tsx | 6 +-- .../Types/ToolbarExample.shorthand.tsx | 19 +++++---- .../Types/ToolbarExampleEditor.shorthand.tsx | 34 +++++++-------- .../react/src/components/Toolbar/Toolbar.tsx | 33 +++++++++------ .../src/components/Toolbar/ToolbarDivider.tsx | 8 ++-- .../src/components/Toolbar/ToolbarItem.tsx | 11 ++++- .../components/Toolbar/ToolbarRadioGroup.tsx | 25 ++++++----- .../react/src/themes/base/componentStyles.ts | 2 + .../base/components/Toolbar/toolbarStyles.ts | 10 +++++ .../themes/teams-dark/componentVariables.ts | 1 + .../components/Toolbar/toolbarVariables.ts | 8 ++++ .../teams-high-contrast/componentVariables.ts | 1 + .../components/Toolbar/toolbarVariables.ts | 12 ++++++ .../react/src/themes/teams/componentStyles.ts | 3 ++ .../src/themes/teams/componentVariables.ts | 2 + .../Toolbar/toolbarDividerStyles.ts | 12 ++++++ .../components/Toolbar/toolbarItemStyles.ts | 41 +++++++++++++++++++ .../components/Toolbar/toolbarVariables.ts | 31 ++++++++++++++ 19 files changed, 202 insertions(+), 58 deletions(-) create mode 100644 packages/react/src/themes/base/components/Toolbar/toolbarStyles.ts create mode 100644 packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts create mode 100644 packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts create mode 100644 packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts create mode 100644 packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts create mode 100644 packages/react/src/themes/teams/components/Toolbar/toolbarVariables.ts diff --git a/docs/src/app.tsx b/docs/src/app.tsx index 35aa4adc90..ffc41f9ef7 100644 --- a/docs/src/app.tsx +++ b/docs/src/app.tsx @@ -22,7 +22,6 @@ class App extends React.Component { ( - {}}> - {}}>x - -) +const MenuExample = () => export default MenuExample diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx index 51e3582f16..151be1a190 100644 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx @@ -16,20 +16,22 @@ const ToolbarExampleShorthand = () => { 00:01, - { kind: 'divider' }, + { key: 'divider1', kind: 'divider' }, { + key: 'video', primary: true, icon: videoEnabled ? videoIconEnabled : videoIconDisabled, onClick: () => { setVideoEnabled(!videoEnabled) }, }, - { primary: true, icon: 'microphone' }, - { primary: true, icon: 'call-control-present-new' }, + { key: 'microphone', primary: true, icon: 'microphone' }, + { key: 'sharing', primary: true, icon: 'call-control-present-new' }, { + key: 'more', icon: 'more', menu: [ { icon: 'list', content: 'Show meeting notes' }, @@ -40,6 +42,7 @@ const ToolbarExampleShorthand = () => { ], }, { + key: 'sidebar', // TODO: // note that these don't act like radios exactly. // You can unselect all options by clicking an option twice. @@ -52,17 +55,17 @@ const ToolbarExampleShorthand = () => { ], }, - { kind: 'divider' }, + { key: 'divider2', kind: 'divider' }, // TODO: // how would FocusZone work in this area? // should this be a "spin button"? // should this be 3 separate controls? - { content:
{/* Pagination Control */}
}, + { key: 'pagination', content:
{/* Pagination Control */}
}, - { kind: 'button', content: 'Stop Presenting' }, + { key: 'stop-presenting', kind: 'button', content: 'Stop Presenting' }, - { danger: true, icon: 'call-end' }, + { key: 'call-end', danger: true, icon: 'call-end' }, ]} /> ( ) diff --git a/packages/react/src/components/Toolbar/Toolbar.tsx b/packages/react/src/components/Toolbar/Toolbar.tsx index 8111e32cc2..e6ffaf793b 100644 --- a/packages/react/src/components/Toolbar/Toolbar.tsx +++ b/packages/react/src/components/Toolbar/Toolbar.tsx @@ -56,32 +56,41 @@ class Toolbar extends UIComponent, any> { static Divider = ToolbarDivider static RadioGroup = ToolbarRadioGroup - private renderItems(items) { + handleItemOverrides = variables => predefinedProps => ({ + variables: { + ...variables, + ...predefinedProps.variables, + }, + }) + + private renderItems(items, variables) { + const itemOverridesFn = this.handleItemOverrides(variables) return _.map(items, (item, index) => { const kind = _.get(item, 'kind', 'item') switch (kind) { case 'divider': - return ToolbarDivider.create(item) + return ToolbarDivider.create(item, { overrideProps: itemOverridesFn }) case 'group': - return ToolbarRadioGroup.create(item) + return ToolbarRadioGroup.create(item, { overrideProps: itemOverridesFn }) default: - return ToolbarItem.create(item) + return ToolbarItem.create(item, { overrideProps: itemOverridesFn }) } }) } - renderComponent({ accessibility, ElementType, classes, unhandledProps }): React.ReactNode { + renderComponent({ + accessibility, + ElementType, + classes, + variables, + unhandledProps, + }): React.ReactNode { const { children, items } = this.props return ( - - {childrenExist(children) ? children : this.renderItems(items)} + + {childrenExist(children) ? children : this.renderItems(items, variables)} ) } diff --git a/packages/react/src/components/Toolbar/ToolbarDivider.tsx b/packages/react/src/components/Toolbar/ToolbarDivider.tsx index b3f1e00c49..9c9a2dea27 100644 --- a/packages/react/src/components/Toolbar/ToolbarDivider.tsx +++ b/packages/react/src/components/Toolbar/ToolbarDivider.tsx @@ -39,9 +39,11 @@ class ToolbarDivider extends UIComponent> { renderComponent({ ElementType, classes, unhandledProps, accessibility }) { return ( - - | - + ) } } diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index 1047d318f7..ba5e7b4f29 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -11,6 +11,7 @@ import { ContentComponentProps, commonPropTypes, childrenExist, + isFromKeyboard, } from '../../lib' import { ComponentEventHandler, ShorthandValue, WithAsProp, withSafeTypeForAs } from '../../types' import { Accessibility } from '../../lib/accessibility/types' @@ -53,7 +54,11 @@ export interface ToolbarItemProps onBlur?: ComponentEventHandler } -class ToolbarItem extends UIComponent> { +export interface ToolbarItemState { + isFromKeyboard: boolean +} + +class ToolbarItem extends UIComponent, ToolbarItemState> { static displayName = 'ToolbarItem' static className = 'ui-toolbar__item' @@ -90,10 +95,14 @@ class ToolbarItem extends UIComponent> { } private handleBlur = (e: React.SyntheticEvent) => { + this.setState({ isFromKeyboard: false }) + _.invoke(this.props, 'onBlur', e, this.props) } private handleFocus = (e: React.SyntheticEvent) => { + this.setState({ isFromKeyboard: isFromKeyboard() }) + _.invoke(this.props, 'onFocus', e, this.props) } diff --git a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx index f3d78262f4..b72e58636e 100644 --- a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx +++ b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx @@ -48,27 +48,30 @@ class ToolbarRadioGroup extends UIComponent> accessibility: defaultBehavior as Accessibility, } - private renderItems(items) { + handleItemOverrides = variables => predefinedProps => ({ + variables: { + ...variables, + ...predefinedProps.variables, + }, + }) + + private renderItems(items, variables) { + const itemOverridesFn = this.handleItemOverrides(variables) return _.map(items, (item, index) => { const kind = _.get(item, 'kind', 'item') if (kind === 'divider') { - return ToolbarDivider.create(item) + return ToolbarDivider.create(item, { overrideProps: itemOverridesFn }) } - return ToolbarItem.create(item) + return ToolbarItem.create(item, { overrideProps: itemOverridesFn }) }) } - renderComponent({ ElementType, classes, accessibility, unhandledProps }) { + renderComponent({ ElementType, classes, variables, accessibility, unhandledProps }) { const { children, items } = this.props return ( - - {childrenExist(children) ? children : this.renderItems(items)} + + {childrenExist(children) ? children : this.renderItems(items, variables)} ) } diff --git a/packages/react/src/themes/base/componentStyles.ts b/packages/react/src/themes/base/componentStyles.ts index 9872ba513f..0a3d965ecb 100644 --- a/packages/react/src/themes/base/componentStyles.ts +++ b/packages/react/src/themes/base/componentStyles.ts @@ -13,6 +13,8 @@ export { default as ProviderBox } from './components/Provider/providerBoxStyles' export { default as Text } from './components/Text/textStyles' +export { default as Toolbar } from './components/Toolbar/toolbarStyles' + export { default as Grid } from './components/Grid/gridStyles' export { default as Image } from './components/Image/imageStyles' diff --git a/packages/react/src/themes/base/components/Toolbar/toolbarStyles.ts b/packages/react/src/themes/base/components/Toolbar/toolbarStyles.ts new file mode 100644 index 0000000000..73d4d37e0e --- /dev/null +++ b/packages/react/src/themes/base/components/Toolbar/toolbarStyles.ts @@ -0,0 +1,10 @@ +import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' + +const toolbarStyles: ComponentSlotStylesInput = { + root: (): ICSSInJSStyle => ({ + display: 'flex', + alignItems: 'center', + }), +} + +export default toolbarStyles diff --git a/packages/react/src/themes/teams-dark/componentVariables.ts b/packages/react/src/themes/teams-dark/componentVariables.ts index a9c953f87c..fef3e6e448 100644 --- a/packages/react/src/themes/teams-dark/componentVariables.ts +++ b/packages/react/src/themes/teams-dark/componentVariables.ts @@ -10,6 +10,7 @@ export { default as Input } from './components/Input/inputVariables' export { default as ListItem } from './components/List/listItemVariables' export { default as RadioGroupItem } from './components/RadioGroup/radioGroupItemVariables' export { default as Text } from './components/Text/textVariables' +export { default as Toolbar } from './components/Toolbar/toolbarVariables' export { default as TreeTitle } from './components/Tree/treeTitleVariables' export { default as Menu } from './components/Menu/menuVariables' export { default as Icon } from './components/Icon/iconVariables' diff --git a/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts new file mode 100644 index 0000000000..364e2f3758 --- /dev/null +++ b/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts @@ -0,0 +1,8 @@ +import { ToolbarVariables } from '../../../teams/components/Toolbar/toolbarVariables' + +export default (siteVars: any): Partial => ({ + foreground: siteVars.colors.grey[250], + dividerBorder: siteVars.colors.grey[450], + foregroundHover: siteVars.colors.brand[400], + borderHover: siteVars.colors.brand[400], +}) diff --git a/packages/react/src/themes/teams-high-contrast/componentVariables.ts b/packages/react/src/themes/teams-high-contrast/componentVariables.ts index 9d3000c44d..d0a745ba83 100644 --- a/packages/react/src/themes/teams-high-contrast/componentVariables.ts +++ b/packages/react/src/themes/teams-high-contrast/componentVariables.ts @@ -11,6 +11,7 @@ export { default as ListItem } from './components/List/listItemVariables' export { default as Menu } from './components/Menu/menuVariables' export { default as RadioGroupItem } from './components/RadioGroup/radioGroupItemVariables' export { default as Text } from './components/Text/textVariables' +export { default as Toolbar } from './components/Toolbar/toolbarVariables' export { default as TreeTitle } from './components/Tree/treeTitleVariables' export { default as Status } from './components/Status/statusVariables' export { default as Reaction } from './components/Reaction/reactionVariables' diff --git a/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts new file mode 100644 index 0000000000..d68151e52b --- /dev/null +++ b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts @@ -0,0 +1,12 @@ +import { ToolbarVariables } from '../../../teams/components/Toolbar/toolbarVariables' + +export default (siteVars: any): Partial => ({ + foreground: siteVars.colors.white, + dividerBorder: siteVars.colors.white, + + foregroundHover: siteVars.colors.black, + backgroundHover: siteVars.accessibleYellow, + + borderWidth: '0', + borderRadius: undefined, +}) diff --git a/packages/react/src/themes/teams/componentStyles.ts b/packages/react/src/themes/teams/componentStyles.ts index b1756bc7a7..81e8604844 100644 --- a/packages/react/src/themes/teams/componentStyles.ts +++ b/packages/react/src/themes/teams/componentStyles.ts @@ -67,6 +67,9 @@ export { default as Status } from './components/Status/statusStyles' export { default as Text } from './components/Text/textStyles' +export { default as ToolbarDivider } from './components/Toolbar/toolbarDividerStyles' +export { default as ToolbarItem } from './components/Toolbar/toolbarItemStyles' + export { default as Tree } from './components/Tree/treeStyles' export { default as TreeItem } from './components/Tree/treeItemStyles' export { default as TreeTitle } from './components/Tree/treeTitleStyles' diff --git a/packages/react/src/themes/teams/componentVariables.ts b/packages/react/src/themes/teams/componentVariables.ts index d448665c28..a51cb41363 100644 --- a/packages/react/src/themes/teams/componentVariables.ts +++ b/packages/react/src/themes/teams/componentVariables.ts @@ -63,6 +63,8 @@ export { default as Status } from './components/Status/statusVariables' export { default as Text } from './components/Text/textVariables' +export { default as Toolbar } from './components/Toolbar/toolbarVariables' + export { default as TreeTitle } from './components/Tree/treeTitleVariables' export { default as Animation } from './components/Animation/animationVariables' diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts new file mode 100644 index 0000000000..0238f2ccd9 --- /dev/null +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts @@ -0,0 +1,12 @@ +import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' +import { ToolbarVariables } from './toolbarVariables' + +const toolbarDividerStyles: ComponentSlotStylesInput<{}, ToolbarVariables> = { + root: ({ variables: v }): ICSSInJSStyle => ({ + borderLeft: `1px solid ${v.dividerBorder}`, + margin: v.dividerMargin, + alignSelf: 'stretch', + }), +} + +export default toolbarDividerStyles diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts new file mode 100644 index 0000000000..4fbaf0f3c8 --- /dev/null +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts @@ -0,0 +1,41 @@ +import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' +import { ToolbarItemProps, ToolbarItemState } from '../../../../components/Toolbar/ToolbarItem' +import { ToolbarVariables } from './toolbarVariables' +import getIconFillOrOutlineStyles from '../../getIconFillOrOutlineStyles' + +type ToolbarItemPropsAndState = ToolbarItemProps & ToolbarItemState + +const toolbarItemStyles: ComponentSlotStylesInput = { + root: ({ props: p, variables: v }): ICSSInJSStyle => { + const { isFromKeyboard } = p + return { + backgroundColor: v.background, + borderWidth: v.borderWidth, + borderStyle: 'solid', + borderColor: 'transparent', + borderRadius: v.borderRadius, + height: v.itemHeight, + minWidth: v.itemHeight, + color: v.foreground, + + ':focus': { + outline: 0, + }, + + ':hover': { + color: v.foregroundHover, + backgroundColor: v.backgroundHover, + ...getIconFillOrOutlineStyles({ outline: false }), + }, + + ...(isFromKeyboard && { + color: v.foregroundHover, + backgroundColor: v.backgroundHover, + borderColor: v.borderHover, + ...getIconFillOrOutlineStyles({ outline: false }), + }), + } + }, +} + +export default toolbarItemStyles diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarVariables.ts new file mode 100644 index 0000000000..588e51d97d --- /dev/null +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarVariables.ts @@ -0,0 +1,31 @@ +import { pxToRem } from '../../../../lib' + +export interface ToolbarVariables { + foreground: string + background: string + dividerBorder: string + + foregroundHover: string + backgroundHover: string + borderHover: string + + itemHeight: string + borderWidth: string + borderRadius: string + dividerMargin: string +} + +export default (siteVars: any): ToolbarVariables => ({ + foreground: siteVars.colors.grey[500], + background: 'transparent', + dividerBorder: siteVars.colors.grey[200], + + foregroundHover: siteVars.colors.brand[600], + backgroundHover: undefined, + borderHover: siteVars.colors.brand[600], + + itemHeight: pxToRem(32), + borderWidth: '2px', + borderRadius: '50%', + dividerMargin: `${pxToRem(10)} ${pxToRem(4)}`, +}) From cf57e02795ca091e5b0663b7038697934cdc39f1 Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Tue, 28 May 2019 21:57:10 +0200 Subject: [PATCH 08/13] active and disabled props --- .../Types/ToolbarExampleEditor.shorthand.tsx | 82 +++++++++++++------ .../src/components/Toolbar/ToolbarItem.tsx | 15 ++++ .../components/Toolbar/toolbarVariables.ts | 3 + .../components/Toolbar/toolbarVariables.ts | 4 + .../components/Toolbar/toolbarItemStyles.ts | 16 ++++ .../components/Toolbar/toolbarVariables.ts | 14 +++- 6 files changed, 110 insertions(+), 24 deletions(-) diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx index a82f9a3304..37f6480a77 100644 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx @@ -1,28 +1,64 @@ import * as React from 'react' import { Toolbar } from '@stardust-ui/react' -const ToolbarExampleShorthand = () => ( - -) +const ToolbarExampleShorthand = () => { + const [isBold, setBold] = React.useState(true) + const [isItalic, setItalic] = React.useState(false) + const [isUnderline, setUnderline] = React.useState(false) + const [isStrike, setStrike] = React.useState(false) + + return ( + { + setBold(!isBold) + }, + }, + { + key: 'italic', + active: isItalic, + icon: { name: 'italic', outline: true }, + onClick: () => { + setItalic(!isItalic) + }, + }, + { + key: 'underline', + active: isUnderline, + icon: { name: 'underline', outline: true }, + onClick: () => { + setUnderline(!isUnderline) + }, + }, + { + key: 'strike', + active: isStrike, + disabled: true, + icon: { name: 'strike', outline: true }, + onClick: () => { + setStrike(!isStrike) + }, + }, + { key: 'divider1', kind: 'divider' }, + { key: 'highlight', icon: { name: 'highlight', outline: true } }, + { key: 'font-color', icon: { name: 'font-color', outline: true } }, + { key: 'font-size', icon: { name: 'font-size', outline: true } }, + { key: 'paragraph', kind: 'button' }, + { key: 'remove-format', icon: { name: 'remove-format', outline: true } }, + { key: 'divider2', kind: 'divider' }, + { key: 'outdent', icon: { name: 'outdent', outline: true } }, + { key: 'indent', icon: { name: 'indent', outline: true } }, + { key: 'bullets', icon: { name: 'bullets', outline: true } }, + { key: 'number-list', icon: { name: 'number-list', outline: true } }, + { key: 'divider3', kind: 'divider' }, + { key: 'more', icon: { name: 'more', outline: true } }, + ]} + /> + ) +} export default ToolbarExampleShorthand diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index ba5e7b4f29..077dc5408d 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -28,6 +28,12 @@ export interface ToolbarItemProps */ accessibility?: Accessibility + /** A toolbar item can be active. */ + active?: boolean + + /** A toolbar item can show it is currently unable to be interacted with. */ + disabled?: boolean + /** Name or shorthand for Toolbar Item Icon */ icon?: ShorthandValue @@ -67,6 +73,8 @@ class ToolbarItem extends UIComponent, ToolbarItemS static propTypes = { ...commonPropTypes.createCommon(), + active: PropTypes.bool, + disabled: PropTypes.bool, icon: customPropTypes.itemShorthand, onClick: PropTypes.func, onFocus: PropTypes.func, @@ -107,6 +115,13 @@ class ToolbarItem extends UIComponent, ToolbarItemS } private handleClick = (e: React.SyntheticEvent) => { + const { disabled } = this.props + + if (disabled) { + e.preventDefault() + return + } + _.invoke(this.props, 'onClick', e, this.props) } } diff --git a/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts index 364e2f3758..505edab5f7 100644 --- a/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts +++ b/packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts @@ -1,8 +1,11 @@ import { ToolbarVariables } from '../../../teams/components/Toolbar/toolbarVariables' +import { colors } from '../../../teams/colors' export default (siteVars: any): Partial => ({ foreground: siteVars.colors.grey[250], dividerBorder: siteVars.colors.grey[450], foregroundHover: siteVars.colors.brand[400], + foregroundActive: siteVars.colors.brand[400], + foregroundDisabled: colors.grey[450], borderHover: siteVars.colors.brand[400], }) diff --git a/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts index d68151e52b..9671c372d1 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts @@ -7,6 +7,10 @@ export default (siteVars: any): Partial => ({ foregroundHover: siteVars.colors.black, backgroundHover: siteVars.accessibleYellow, + foregroundActive: siteVars.accessibleYellow, + + foregroundDisabled: siteVars.accessibleGreen, + borderWidth: '0', borderRadius: undefined, }) diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts index 4fbaf0f3c8..7d33b7c175 100644 --- a/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts @@ -17,11 +17,18 @@ const toolbarItemStyles: ComponentSlotStylesInput ({ dividerBorder: siteVars.colors.grey[200], foregroundHover: siteVars.colors.brand[600], - backgroundHover: undefined, + backgroundHover: 'transparent', borderHover: siteVars.colors.brand[600], + foregroundActive: siteVars.colors.brand[600], + backgroundActive: 'transparent', + + foregroundDisabled: siteVars.colors.grey[250], + backgroundDisabled: 'transparent', + itemHeight: pxToRem(32), borderWidth: '2px', borderRadius: '50%', From 16321b9fd6ac1fd5f7683a9980bbc8031b2c3757 Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Wed, 29 May 2019 10:31:54 +0200 Subject: [PATCH 09/13] cleanup --- .../Types/ToolbarExample.shorthand.tsx | 79 ------------------- .../Toolbar/Types/ToolbarExample.tsx | 6 -- .../Types/ToolbarExampleEditor.shorthand.tsx | 1 - .../components/Toolbar/Types/index.tsx | 5 -- .../react/src/components/Toolbar/Toolbar.tsx | 8 +- .../src/components/Toolbar/ToolbarDivider.tsx | 4 +- .../src/components/Toolbar/ToolbarItem.tsx | 2 +- .../components/Toolbar/ToolbarRadioGroup.tsx | 5 +- 8 files changed, 10 insertions(+), 100 deletions(-) delete mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx delete mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx deleted file mode 100644 index 151be1a190..0000000000 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExample.shorthand.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import * as React from 'react' -import { Toolbar, Image } from '@stardust-ui/react' - -const ToolbarExampleShorthand = () => { - const videoIconEnabled = 'call-video' - const videoIconDisabled = { name: 'call-video-off', outline: true } - - const [videoEnabled, setVideoEnabled] = React.useState(true) - - return ( - , - - { key: 'divider1', kind: 'divider' }, - - { - key: 'video', - primary: true, - icon: videoEnabled ? videoIconEnabled : videoIconDisabled, - onClick: () => { - setVideoEnabled(!videoEnabled) - }, - }, - { key: 'microphone', primary: true, icon: 'microphone' }, - { key: 'sharing', primary: true, icon: 'call-control-present-new' }, - { - key: 'more', - icon: 'more', - menu: [ - { icon: 'list', content: 'Show meeting notes' }, - // ... - { kind: 'divider' }, - // ... - { icon: 'video off', content: 'Turn off incoming video' }, - ], - }, - { - key: 'sidebar', - // TODO: - // note that these don't act like radios exactly. - // You can unselect all options by clicking an option twice. - // Radios do not allow you unselect an option this way. - kind: 'group', - // Consider a top level 'onItemClick', easier integration with lists of items passed in - items: [ - { icon: { name: 'chat', outline: true }, secondary: true }, - { icon: { name: 'user-friends', outline: true }, secondary: true }, - ], - }, - - { key: 'divider2', kind: 'divider' }, - - // TODO: - // how would FocusZone work in this area? - // should this be a "spin button"? - // should this be 3 separate controls? - { key: 'pagination', content:
{/* Pagination Control */}
}, - - { key: 'stop-presenting', kind: 'button', content: 'Stop Presenting' }, - - { key: 'call-end', danger: true, icon: 'call-end' }, - ]} - /> - - - ) -} - -export default ToolbarExampleShorthand diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx deleted file mode 100644 index 2be5602fc3..0000000000 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExample.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import * as React from 'react' -import { Toolbar } from '@stardust-ui/react' - -const ToolbarExampleShorthand = () => Content - -export default ToolbarExampleShorthand diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx index 37f6480a77..c7fa5d6ee6 100644 --- a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.tsx @@ -47,7 +47,6 @@ const ToolbarExampleShorthand = () => { { key: 'highlight', icon: { name: 'highlight', outline: true } }, { key: 'font-color', icon: { name: 'font-color', outline: true } }, { key: 'font-size', icon: { name: 'font-size', outline: true } }, - { key: 'paragraph', kind: 'button' }, { key: 'remove-format', icon: { name: 'remove-format', outline: true } }, { key: 'divider2', kind: 'divider' }, { key: 'outdent', icon: { name: 'outdent', outline: true } }, diff --git a/docs/src/examples/components/Toolbar/Types/index.tsx b/docs/src/examples/components/Toolbar/Types/index.tsx index 0cc8f6fa94..d70c19e927 100644 --- a/docs/src/examples/components/Toolbar/Types/index.tsx +++ b/docs/src/examples/components/Toolbar/Types/index.tsx @@ -4,11 +4,6 @@ import ExampleSection from 'docs/src/components/ComponentDoc/ExampleSection' const Types = () => ( - } @@ -45,7 +46,7 @@ class Toolbar extends UIComponent, any> { static propTypes = { ...commonPropTypes.createCommon(), - items: customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'button', 'group']), + items: customPropTypes.collectionShorthandWithKindProp(['divider', 'item', 'group']), } static defaultProps = { @@ -99,7 +100,6 @@ class Toolbar extends UIComponent, any> { Toolbar.create = createShorthandFactory({ Component: Toolbar, mappedProp: 'content' }) /** - * A Toolbar component groups actions. - * TODO: add meaningful description + * A Toolbar component displays grouped actions. */ export default withSafeTypeForAs(Toolbar) diff --git a/packages/react/src/components/Toolbar/ToolbarDivider.tsx b/packages/react/src/components/Toolbar/ToolbarDivider.tsx index 9c9a2dea27..db04570596 100644 --- a/packages/react/src/components/Toolbar/ToolbarDivider.tsx +++ b/packages/react/src/components/Toolbar/ToolbarDivider.tsx @@ -17,7 +17,7 @@ export interface ToolbarDividerProps ContentComponentProps { /** * Accessibility behavior if overridden by the user. - * @default menuDividerBehavior + * @default defaultBehavior */ accessibility?: Accessibility } @@ -52,6 +52,6 @@ ToolbarDivider.create = createShorthandFactory({ Component: ToolbarDivider, mapp /** * Toolbar divider. - * TODO: add meaningful description + * Adds visual non-selectable separator between items. */ export default withSafeTypeForAs(ToolbarDivider) diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index 077dc5408d..55a2eaefdb 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -130,6 +130,6 @@ ToolbarItem.create = createShorthandFactory({ Component: ToolbarItem, mappedProp /** * Toolbar item. - * TODO: add meaningful description + * The item renders as a button with an icon. */ export default withSafeTypeForAs(ToolbarItem) diff --git a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx index b72e58636e..c06d5e315e 100644 --- a/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx +++ b/packages/react/src/components/Toolbar/ToolbarRadioGroup.tsx @@ -29,6 +29,7 @@ export interface ToolbarRadioGroupProps */ accessibility?: Accessibility + /** Shorthand array of props for ToolbarRadioGroup. */ items?: ShorthandCollection } @@ -83,8 +84,8 @@ ToolbarRadioGroup.create = createShorthandFactory({ }) /** - * Toolbar radiogroup. - * TODO: add meaningful description + * Toolbar radiogroup groups items where only one item can be active. + * The radiogroup does not guarantee that, it just serves accessibility purposes. */ export default withSafeTypeForAs( ToolbarRadioGroup, From db486baa682437b3ccfa1ca18181d715ada51d6d Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Wed, 29 May 2019 10:38:18 +0200 Subject: [PATCH 10/13] screener steps --- CALLING.md | 6 ------ .../Toolbar/Types/ToolbarExampleEditor.shorthand.steps.ts | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) delete mode 100644 CALLING.md create mode 100644 docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.steps.ts diff --git a/CALLING.md b/CALLING.md deleted file mode 100644 index 768c5ba1aa..0000000000 --- a/CALLING.md +++ /dev/null @@ -1,6 +0,0 @@ -# Calling Screen - -Based on initial notes, the toolbar component is likely a separate component: -- The button inside is a subset of the Button -- It contains many more controls than just button - diff --git a/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.steps.ts b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.steps.ts new file mode 100644 index 0000000000..81b7a6894d --- /dev/null +++ b/docs/src/examples/components/Toolbar/Types/ToolbarExampleEditor.shorthand.steps.ts @@ -0,0 +1,3 @@ +const config: ScreenerTestsConfig = { themes: ['teams', 'teamsDark', 'teamsHighContrast'] } + +export default config From d3d1abb0cbbd5bcca561a6dd99f834f2d6c2a9fe Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Thu, 30 May 2019 12:25:30 +0200 Subject: [PATCH 11/13] use colorScheme --- .../src/components/Toolbar/ToolbarItem.tsx | 3 +- .../react/src/themes/teams-dark/colors.ts | 2 +- .../themes/teams-dark/componentVariables.ts | 1 - .../components/Toolbar/toolbarVariables.ts | 11 ---- .../components/Toolbar/toolbarVariables.ts | 26 +++++--- .../teams/components/Menu/menuVariables.ts | 1 - .../Toolbar/toolbarDividerStyles.ts | 14 +++-- .../components/Toolbar/toolbarItemStyles.ts | 25 ++++---- .../components/Toolbar/toolbarVariables.ts | 61 ++++++++++++++++--- 9 files changed, 94 insertions(+), 50 deletions(-) delete mode 100644 packages/react/src/themes/teams-dark/components/Toolbar/toolbarVariables.ts diff --git a/packages/react/src/components/Toolbar/ToolbarItem.tsx b/packages/react/src/components/Toolbar/ToolbarItem.tsx index 55a2eaefdb..51d1d7a8c7 100644 --- a/packages/react/src/components/Toolbar/ToolbarItem.tsx +++ b/packages/react/src/components/Toolbar/ToolbarItem.tsx @@ -87,11 +87,12 @@ class ToolbarItem extends UIComponent, ToolbarItemS } renderComponent({ ElementType, classes, unhandledProps, accessibility }) { - const { icon, children } = this.props + const { icon, children, disabled } = this.props return ( => ({ - foreground: siteVars.colors.grey[250], - dividerBorder: siteVars.colors.grey[450], - foregroundHover: siteVars.colors.brand[400], - foregroundActive: siteVars.colors.brand[400], - foregroundDisabled: colors.grey[450], - borderHover: siteVars.colors.brand[400], -}) diff --git a/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts index 9671c372d1..2cfb722d7a 100644 --- a/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts +++ b/packages/react/src/themes/teams-high-contrast/components/Toolbar/toolbarVariables.ts @@ -1,15 +1,21 @@ -import { ToolbarVariables } from '../../../teams/components/Toolbar/toolbarVariables' +import { + toolbarColorAreas, + ToolbarVariables, +} from '../../../teams/components/Toolbar/toolbarVariables' +import { extendColorScheme, pickValuesFromColorScheme } from '../../../colorUtils' export default (siteVars: any): Partial => ({ - foreground: siteVars.colors.white, - dividerBorder: siteVars.colors.white, - - foregroundHover: siteVars.colors.black, - backgroundHover: siteVars.accessibleYellow, - - foregroundActive: siteVars.accessibleYellow, - - foregroundDisabled: siteVars.accessibleGreen, + colorScheme: pickValuesFromColorScheme( + extendColorScheme(siteVars.colorScheme, { + default: { + foregroundHover: siteVars.colorScheme.brand.foregroundHover, + borderFocus: undefined, + foregroundActive: siteVars.accessibleYellow, + backgroundFocus: siteVars.colorScheme.default.backgroundHover, + }, + }), + toolbarColorAreas, + ), borderWidth: '0', borderRadius: undefined, diff --git a/packages/react/src/themes/teams/components/Menu/menuVariables.ts b/packages/react/src/themes/teams/components/Menu/menuVariables.ts index c5d63357f3..5d70a9770c 100644 --- a/packages/react/src/themes/teams/components/Menu/menuVariables.ts +++ b/packages/react/src/themes/teams/components/Menu/menuVariables.ts @@ -12,7 +12,6 @@ export const menuColorAreas = stringLiteralsArray( 'backgroundHover', 'backgroundActive', 'backgroundFocus', - 'foregroundFocus', 'foregroundDisabled', ) export type MenuColorSchemeMapping = TeamsSchemeMappingWithAreas> diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts index 0238f2ccd9..ab43ab490c 100644 --- a/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerStyles.ts @@ -1,12 +1,16 @@ import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' import { ToolbarVariables } from './toolbarVariables' +import { getColorScheme } from '../../colors' const toolbarDividerStyles: ComponentSlotStylesInput<{}, ToolbarVariables> = { - root: ({ variables: v }): ICSSInJSStyle => ({ - borderLeft: `1px solid ${v.dividerBorder}`, - margin: v.dividerMargin, - alignSelf: 'stretch', - }), + root: ({ variables: v }): ICSSInJSStyle => { + const colors = getColorScheme(v.colorScheme) + return { + borderLeft: `1px solid ${v.dividerBorder || colors.border}`, + margin: v.dividerMargin, + alignSelf: 'stretch', + } + }, } export default toolbarDividerStyles diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts index 7d33b7c175..3ec572712b 100644 --- a/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarItemStyles.ts @@ -2,12 +2,15 @@ import { ComponentSlotStylesInput, ICSSInJSStyle } from '../../../types' import { ToolbarItemProps, ToolbarItemState } from '../../../../components/Toolbar/ToolbarItem' import { ToolbarVariables } from './toolbarVariables' import getIconFillOrOutlineStyles from '../../getIconFillOrOutlineStyles' +import { getColorScheme } from '../../colors' type ToolbarItemPropsAndState = ToolbarItemProps & ToolbarItemState const toolbarItemStyles: ComponentSlotStylesInput = { root: ({ props: p, variables: v }): ICSSInJSStyle => { - const { isFromKeyboard } = p + const { active, disabled, isFromKeyboard } = p + const colors = getColorScheme(v.colorScheme) + return { backgroundColor: v.background, borderWidth: v.borderWidth, @@ -16,34 +19,34 @@ const toolbarItemStyles: ComponentSlotStylesInput +> export interface ToolbarVariables { + colorScheme: ToolbarColorSchemeMapping foreground: string background: string dividerBorder: string foregroundHover: string backgroundHover: string - borderHover: string + + foregroundFocus: string + backgroundFocus: string + borderFocus: string foregroundActive: string backgroundActive: string @@ -22,18 +49,34 @@ export interface ToolbarVariables { } export default (siteVars: any): ToolbarVariables => ({ - foreground: siteVars.colors.grey[500], + colorScheme: pickValuesFromColorScheme( + extendColorScheme(siteVars.colorScheme, { + default: { + borderFocus: siteVars.colorScheme.brand.borderFocus1, + foregroundHover: siteVars.colorScheme.brand.foregroundHover, + backgroundHover: 'transparent', + foregroundFocus: siteVars.colorScheme.brand.foregroundFocus, + backgroundFocus: 'transparent', + foregroundActive: siteVars.colorScheme.brand.foregroundActive, + }, + }), + toolbarColorAreas, + ), + foreground: undefined, background: 'transparent', - dividerBorder: siteVars.colors.grey[200], + dividerBorder: undefined, + + foregroundHover: undefined, + backgroundHover: undefined, - foregroundHover: siteVars.colors.brand[600], - backgroundHover: 'transparent', - borderHover: siteVars.colors.brand[600], + foregroundFocus: undefined, + backgroundFocus: undefined, + borderFocus: undefined, - foregroundActive: siteVars.colors.brand[600], + foregroundActive: undefined, backgroundActive: 'transparent', - foregroundDisabled: siteVars.colors.grey[250], + foregroundDisabled: undefined, backgroundDisabled: 'transparent', itemHeight: pxToRem(32), From 01937e5ee3b76540720e048da1db5b0d4b7fcb1d Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Thu, 30 May 2019 13:53:17 +0200 Subject: [PATCH 12/13] add ToolbarDivider and ToolbarItem variables --- packages/react/src/themes/teams/componentVariables.ts | 2 ++ .../themes/teams/components/Toolbar/toolbarDividerVariables.ts | 3 +++ .../themes/teams/components/Toolbar/toolbarItemVariables.ts | 3 +++ 3 files changed, 8 insertions(+) create mode 100644 packages/react/src/themes/teams/components/Toolbar/toolbarDividerVariables.ts create mode 100644 packages/react/src/themes/teams/components/Toolbar/toolbarItemVariables.ts diff --git a/packages/react/src/themes/teams/componentVariables.ts b/packages/react/src/themes/teams/componentVariables.ts index a51cb41363..2fd57c22bd 100644 --- a/packages/react/src/themes/teams/componentVariables.ts +++ b/packages/react/src/themes/teams/componentVariables.ts @@ -64,6 +64,8 @@ export { default as Status } from './components/Status/statusVariables' export { default as Text } from './components/Text/textVariables' export { default as Toolbar } from './components/Toolbar/toolbarVariables' +export { default as ToolbarItem } from './components/Toolbar/toolbarItemVariables' +export { default as ToolbarDivider } from './components/Toolbar/toolbarDividerVariables' export { default as TreeTitle } from './components/Tree/treeTitleVariables' diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarDividerVariables.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerVariables.ts new file mode 100644 index 0000000000..d0e9fa26c8 --- /dev/null +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarDividerVariables.ts @@ -0,0 +1,3 @@ +import toolbarVariables from './toolbarVariables' + +export default toolbarVariables diff --git a/packages/react/src/themes/teams/components/Toolbar/toolbarItemVariables.ts b/packages/react/src/themes/teams/components/Toolbar/toolbarItemVariables.ts new file mode 100644 index 0000000000..d0e9fa26c8 --- /dev/null +++ b/packages/react/src/themes/teams/components/Toolbar/toolbarItemVariables.ts @@ -0,0 +1,3 @@ +import toolbarVariables from './toolbarVariables' + +export default toolbarVariables From d61a8dcf0a143840e7e9e211f78dd6af4b20e9ca Mon Sep 17 00:00:00 2001 From: Miroslav Stastny Date: Mon, 3 Jun 2019 21:28:55 +0200 Subject: [PATCH 13/13] changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b82d20935..163c31c144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] + ### Features +- Add `Toolbar` component @miroslavstastny ([#1408](https://github.com/stardust-ui/react/pull/1408)) + ## [v0.32.0](https://github.com/stardust-ui/react/tree/v0.32.0) (2019-06-03) [Compare changes](https://github.com/stardust-ui/react/compare/v0.31.0...v0.32.0)