diff --git a/packages/patternfly-4/react-core/src/components/Dropdown/Dropdown.js b/packages/patternfly-4/react-core/src/components/Dropdown/Dropdown.js index 606f96291e2..9dc0e5f0171 100644 --- a/packages/patternfly-4/react-core/src/components/Dropdown/Dropdown.js +++ b/packages/patternfly-4/react-core/src/components/Dropdown/Dropdown.js @@ -26,7 +26,7 @@ const propTypes = { isOpen: PropTypes.bool, /** Display the toggle with no border or background */ isPlain: PropTypes.bool, - /** Indicates where menu will be alligned horizontally */ + /** Indicates where menu will be aligned horizontally */ position: PropTypes.oneOf(Object.values(DropdownPosition)), /** Display menu above or below dropdown toggle */ direction: PropTypes.oneOf(Object.values(DropdownDirection)), diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.d.ts new file mode 100644 index 00000000000..fcc17a3dfde --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.d.ts @@ -0,0 +1,19 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; +import { DropdownDirection, DropdownPosition } from '../Dropdown'; +import { OneOf } from '../../helpers'; + +export interface OptionsMenuProps extends HTMLProps { + className?: string; + id: string; + menuItems: ReactNode[]; + toggle: ReactNode; + isPlain?: boolean; + isOpen?: boolean; + ariaLabelMenu?: string; + position?: OneOf; + direction?: OneOf; +} + +declare const OptionsMenu: FunctionComponent; + +export default OptionsMenu; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.js new file mode 100644 index 00000000000..7efc19af701 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.js @@ -0,0 +1,80 @@ +import React, { Children, cloneElement, Component } from 'react'; +import PropTypes from 'prop-types'; +import styles from '@patternfly/patternfly/components/OptionsMenu/options-menu.css'; +import { css, getModifier } from '@patternfly/react-styles'; +import { OptionsMenuDirection, OptionsMenuPosition } from './optionsMenuConstants'; + +const propTypes = { + /** Classes applied to root element of the Options menu */ + className: PropTypes.string, + /** Id of the root element of the Options menu */ + id: PropTypes.string.isRequired, + /** Array of OptionsMenuItem and/or OptionMenuItemGroup nodes that will be rendered in the Options menu list */ + menuItems: PropTypes.arrayOf(PropTypes.node).isRequired, + /** Either an OptionsMenuToggle or an OptionsMenuToggleWithText to use to toggle the Options menu */ + toggle: PropTypes.node.isRequired, + /** Flag to indicate if menu is open */ + isOpen: PropTypes.bool, + /** Flag to indicate the toggle has no border or background */ + isPlain: PropTypes.bool, + /** Provides an accessible name for the Options menu */ + ariaLabelMenu: PropTypes.string, + /** Display menu above or below Options menu toggle */ + direction: PropTypes.oneOf(Object.values(OptionsMenuDirection)), + /** Indicates where menu will be aligned horizontally */ + position: PropTypes.oneOf(Object.values(OptionsMenuPosition)), +}; + +const defaultProps = { + className: '', + isOpen: false, + isPlain: false, + ariaLabelMenu: '', + direction: OptionsMenuDirection.down, + position: OptionsMenuPosition.left, +}; + +class OptionsMenu extends Component { + + render() { + const { + className, + direction, + position, + id, + isOpen, + isPlain, + ariaLabelMenu, + menuItems, + toggle } = this.props; + return ( +
+ {Children.map(toggle, oneToggle => + cloneElement(oneToggle, { + parentId: id, + isOpen, + isPlain, + }))} + {isOpen && +
    + {menuItems.map((item) => { + return item; + })} +
} +
+ ) + } +} + +OptionsMenu.propTypes = propTypes; +OptionsMenu.defaultProps = defaultProps; + +export default OptionsMenu; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.md b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.md new file mode 100644 index 00000000000..26ceded5ced --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.md @@ -0,0 +1,374 @@ +--- +title: "Options menu" +cssPrefix: "pf-c-options-menu" +--- +import React from 'react'; +import { + OptionsMenu, + OptionsMenuItem, + OptionsMenuToggle, + OptionsMenuItemGroup, + OptionsMenuDirection, + OptionsMenuPosition, + OptionsMenuSeparator, + OptionsMenuToggleWithText +} from '@patternfly/react-core'; +import { CaretDownIcon, SortAmountDownIcon } from '@patternfly/react-icons'; + +## Options menu - single option +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuToggle } from '@patternfly/react-core'; + +class SingleOption extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + toggleTemplateProps: { + text: "Options menu" + }, + selectedOption: "singleOption1" + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelect = event => { + const id = event.target.id; + this.setState(() => { + return { selectedOption: id }; + }); + }; + + this.toggleTemplate = ({toggleTemplateProps}) => { + const { text } = toggleTemplateProps; + return {text} + }; + } + + render() { + const { isOpen, toggleTemplateProps } = this.state; + const menuItems = [ + Option 1, + Option 2, + Option 3 + ]; + const toggle = + + return ( + + ); + } +} +``` + +## Options menu - multiple options +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuSeparator, OptionsMenuItemGroup, OptionsMenuToggle} from '@patternfly/react-core'; + +class MultipleOptions extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + toggleTemplateProps: { + text: "Sort by" + }, + sortColumn: "date", + sortDirection: "ascending" + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelectColumn = event => { + const id = event.target.id; + this.setState(() => { + return { sortColumn: id }; + }); + }; + + this.onSelectDirection = event => { + const id = event.target.id; + this.setState(() => { + return { sortDirection: id }; + }); + }; + + this.toggleTemplate = ({toggleTemplateProps}) => { + const { text } = toggleTemplateProps; + return {text} + }; + } + + render() { + const { isOpen, toggleTemplateProps } = this.state; + const menuItems = [ + + Name + Date + Disabled + Size + , + , + + Ascending + Descending + + ]; + const toggle = + + return ( + + ); + } +} +``` + +## Options menu - plain +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuToggle } from '@patternfly/react-core'; +import { SortAmountDownIcon } from '@patternfly/react-icons'; + +class Plain extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + plainOption1: true, + plainOption2: false, + plainOption3: false + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelect = event => { + const id = event.target.id; + this.setState((prevState) => { + return { [id]: !prevState[id] }; + }); + }; + + this.toggleTemplate = () => { + return + ; + } + } + + render() { + const { isOpen } = this.state; + const menuItems = [ + Option 1, + Option 2, + Option 3 + ]; + const toggle = + + return ( + + ); + } +} +``` + +## Options menu - top +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuDirection, OptionsMenuToggle } from '@patternfly/react-core'; + +class Top extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + toggleTemplateProps: { + text: "Options menu" + }, + topOption1: false, + topOption2: false, + topOption3: false + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelect = event => { + const id = event.target.id; + this.setState((prevState) => { + return { [id]: !prevState[id] }; + }); + }; + + this.toggleTemplate = ({toggleTemplateProps}) => { + const { text } = toggleTemplateProps; + return {text} + }; + } + + render() { + const { toggleTemplateProps, isOpen } = this.state; + const menuItems = [ + Option 1, + Option 2, + Option 3 + ]; + const toggle = + + return ( + + ); + } +} +``` + +## Options menu - align right +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuPosition, OptionsMenuToggle } from '@patternfly/react-core'; + +class AlignRight extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + toggleTemplateProps: { + text: "Align right" + }, + rightOption1: true, + rightOption2: false, + rightOption3: false + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelect = event => { + const id = event.target.id; + this.setState((prevState) => { + return { [id]: !prevState[id] }; + }); + }; + + this.toggleTemplate = ({toggleTemplateProps}) => { + const { text } = toggleTemplateProps; + return {text} + }; + } + + render() { + const { toggleTemplateProps, isOpen } = this.state; + const menuItems = [ + Right option 1, + Right option 2, + Right option 3 + ]; + const toggle = + + return ( + + ); + } +} +``` + +## Options menu - plain with text +```js +import React from 'react'; +import { OptionsMenu, OptionsMenuItem, OptionsMenuToggleWithText } from '@patternfly/react-core'; +import { CaretDownIcon } from '@patternfly/react-icons'; + +class PlainWithText extends React.Component { + constructor(props) { + super(props); + this.state = { + isOpen: false, + toggleText: Custom text, + buttonContents: , + customOption1: true, + customOption2: false, + customOption3: false + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + + this.onSelect = event => { + const id = event.target.id; + this.setState((prevState) => { + return { [id]: !prevState[id] }; + }); + }; + + this.onToggle = () => { + this.setState({ + isOpen: !this.state.isOpen + }); + }; + } + + render() { + const { isOpen, toggleText, buttonContents } = this.state; + const menuItems = [ + Option 1, + Option 2, + Option 3 + ]; + const toggle = ; + + return ( + + ); + } +} +``` diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.test.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.test.js new file mode 100644 index 00000000000..dfe31f4ed2c --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenu.test.js @@ -0,0 +1,101 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import OptionsMenu from './OptionsMenu'; +import OptionsMenuToggle from './OptionsMenuToggle'; +import OptionsMenuItemGroup from './OptionsMenuItemGroup'; +import OptionsMenuItem from './OptionsMenuItem'; +import OptionsMenuSeparator from './OptionsMenuSeparator'; +import { OptionsMenuDirection, OptionsMenuPosition } from './optionsMenuConstants'; +import OptionsMenuToggleWithText from './OptionsMenuToggleWithText'; + +const menuItems = [ + + Name + Date + Disabled + Size + , + , + + Ascending + Descending + +]; + +describe('optionsMenu', () => { + test('regular', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('right aligned', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('open up', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('right aligned + open up', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('expanded', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('plain', () => { + const view = mount( + Options Menu} + /> + ); + expect(view).toMatchSnapshot(); + }); + + test('text', () => { + const view = mount( + Test} toggleText="Test" />} + /> + ); + expect(view).toMatchSnapshot(); + }); +}); diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.d.ts new file mode 100644 index 00000000000..f17888ba8c5 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.d.ts @@ -0,0 +1,14 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; + +export interface OptionsMenuItemProps extends HTMLProps { + children?: ReactNode; + className?: string; + isSelected?: boolean; + isDisabled?: boolean; + onSelect?(event: React.SyntheticEvent): void; + id?: string; +} + +declare const OptionsMenuItem: FunctionComponent; + +export default OptionsMenuItem; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.js new file mode 100644 index 00000000000..37e686d7e78 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItem.js @@ -0,0 +1,65 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { css, getModifier } from '@patternfly/react-styles'; +import styles from '@patternfly/patternfly/components/OptionsMenu/options-menu.css'; +import { CheckIcon } from '@patternfly/react-icons'; +import { KEY_CODES } from '../../helpers'; + +const propTypes = { + /** Anything which can be rendered as an Options menu item */ + children: PropTypes.node, + /** Classes applied to root element of an Options menu item */ + className: PropTypes.string, + /** Render Options menu item as selected */ + isSelected: PropTypes.bool, + /** Render Options menu item as disabled option */ + isDisabled: PropTypes.bool, + /** Callback for when this Options menu item is selected */ + onSelect: PropTypes.func, + /** Unique id of this Options menu item */ + id: PropTypes.string, +}; + +const defaultProps = { + children: null, + className: '', + isSelected: false, + isDisabled: false, + onSelect: Function.prototype, + id: '', +}; + +class OptionsMenuItem extends React.Component { + + onKeyDown = event => { + // Detected key press on this item, notify the menu parent so that the appropriate + // item can be focused + if (event.keyCode === KEY_CODES.TAB) return; + event.preventDefault(); + if (event.keyCode === KEY_CODES.ENTER) { + this.props.onSelect(event); + } + }; + + render() { + const { onSelect, isDisabled, isSelected, className, children, id, ...props } = this.props; + return
  • + +
  • + } +} + +OptionsMenuItem.propTypes = propTypes; +OptionsMenuItem.defaultProps = defaultProps; + +export default OptionsMenuItem; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.d.ts new file mode 100644 index 00000000000..e1741b8249a --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.d.ts @@ -0,0 +1,11 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; + +export interface OptionsMenuItemGroupProps extends HTMLProps { + children?: ReactNode; + className?: string; + ariaLabel?: string; +} + +declare const OptionsMenuItemGroup: FunctionComponent; + +export default OptionsMenuItemGroup; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.js new file mode 100644 index 00000000000..df0dbcea50e --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuItemGroup.js @@ -0,0 +1,31 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const OptionsMenuItemsGroup = ({ + children, + className, + ariaLabel, +}) => ( +
  • +
      + {children} +
    +
  • +); + +OptionsMenuItemsGroup.propTypes = { + /** Content to be rendered in the Options menu items component */ + children: PropTypes.node, + /** Classes applied to root element of the Options menu items group */ + className: PropTypes.string, + /** Provides an accessible name for the Options menu items group */ + ariaLabel: PropTypes.string, +}; + +OptionsMenuItemsGroup.defaultValues = { + children: null, + className: '', + ariaLabel: '', +}; + +export default OptionsMenuItemsGroup; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.d.ts new file mode 100644 index 00000000000..de9de8a8ce0 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.d.ts @@ -0,0 +1,9 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; + +export interface OptionsMenuSeparatorProps extends HTMLProps { + children?: ReactNode; +} + +declare const OptionsMenuSeparator: FunctionComponent; + +export default OptionsMenuSeparator; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.js new file mode 100644 index 00000000000..e700849d7e9 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuSeparator.js @@ -0,0 +1,23 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { css } from '@patternfly/react-styles'; +import styles from '@patternfly/patternfly/components/OptionsMenu/options-menu.css'; + +const OptionsMenuSeparator = ({ className, ...props}) => ( +
  • +); + +OptionsMenuSeparator.propTypes = { + /** Classes applied to root element of Options menu separator item */ + className: PropTypes.string, +}; + +OptionsMenuSeparator.defaultProps = { + className: '', +}; + +export default OptionsMenuSeparator; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.d.ts new file mode 100644 index 00000000000..7ffd14d4007 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.d.ts @@ -0,0 +1,19 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; + +export interface OptionsMenuToggleButtonProps extends HTMLProps { + parentId?: string; + onToggle?: Function; + isOpen?: boolean; + isPlain?: boolean; + isFocused?: boolean; + isHovered?: boolean; + isActive?: boolean; + hideCaret?: boolean; + "aria-label"?: string; + toggleTemplate?: ReactNode; + toggleTemplateProps?: object; +} + +declare const OptionsMenuToggleButton: FunctionComponent; + +export default OptionsMenuToggleButton; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.js new file mode 100644 index 00000000000..6160e545151 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggle.js @@ -0,0 +1,84 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { CaretDownIcon } from '@patternfly/react-icons'; +import styles from '@patternfly/patternfly/components/OptionsMenu/options-menu.css'; +import { css, getModifier } from '@patternfly/react-styles'; +import { fillTemplate } from '../../helpers/util'; + +const OptionsMenuToggle = ({ + parentId, + onToggle, + isOpen, + isPlain, + isHovered, + isActive, + isFocused, + hideCaret, + "aria-label": ariaLabel, + toggleTemplate: ToggleTemplate, + toggleTemplateProps }) => { + + const template = ToggleTemplate && typeof ToggleTemplate === 'string' + ? (fillTemplate(ToggleTemplate, toggleTemplateProps)) + : (); + + return +}; + +OptionsMenuToggle.propTypes = { + /** Id of the parent Options menu component */ + parentId: PropTypes.string, + /** Callback for when this Options menu is toggled */ + onToggle: PropTypes.func, + /** Flag to indicate if menu is open */ + isOpen: PropTypes.bool, + /** Flag to indicate if the button is plain */ + isPlain: PropTypes.bool, + /** Forces display of the hover state of the Options menu */ + isHovered: PropTypes.bool, + /** Forces display of the active state of the Options menu */ + isActive: PropTypes.bool, + /** Forces display of the hover state of the Options menu */ + isFocused: PropTypes.bool, + /** Content to be rendered in the Options menu toggle button */ + toggleTemplate: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + /** Props to be passed to the Options menu toggle button template */ + toggleTemplateProps: PropTypes.object, + /** hide the toggle caret */ + hideCaret: PropTypes.bool, + /** Provides an accessible name for the button when an icon is used instead of text*/ + "aria-label": PropTypes.string, +}; + +OptionsMenuToggle.defaultProps = { + parentId: '', + onToggle: Function.prototype, + isOpen: false, + isPlain: false, + isHovered: false, + isActive: false, + isFocused: false, + toggleTemplate: '', + toggleTemplateProps: undefined, + hideCaret: false, + "aria-label": 'Options menu', +}; + +export default OptionsMenuToggle; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.d.ts new file mode 100644 index 00000000000..633e62f17f9 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.d.ts @@ -0,0 +1,20 @@ +import { FunctionComponent, HTMLProps, ReactNode } from 'react'; + +export interface OptionsMenuToggleWithTextProps extends HTMLProps { + parentId?: string; + toggleText: ReactNode; + toggleTextClassName?: string; + toggleButtonContents: ReactNode; + toggleButtonContentsClassName?: string; + onToggle?: Function; + isOpen?: boolean; + isPlain?: boolean; + isFocused?: boolean; + isHovered?: boolean; + isActive?: boolean; + "aria-label"?: string; +} + +declare const OptionsMenuToggleWithText: FunctionComponent; + +export default OptionsMenuToggleWithText; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.js new file mode 100644 index 00000000000..c9eabb8afec --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/OptionsMenuToggleWithText.js @@ -0,0 +1,78 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { css, getModifier } from '@patternfly/react-styles'; +import styles from '@patternfly/patternfly/components/OptionsMenu/options-menu.css'; + +const OptionsMenuToggleWithText = ({ + parentId, + toggleText, + toggleTextClassName, + toggleButtonContents, + toggleButtonContentsClassName, + onToggle, + isOpen, + isPlain, + isHovered, + isActive, + isFocused, + "aria-label": ariaLabel + }) => ( +
    + {toggleText} + +
    +); + +OptionsMenuToggleWithText.propTypes = { + /** Id of the parent Options menu component */ + parentId: PropTypes.string, + /** Content to be rendered inside the Options menu toggle as text or another non-interactive element*/ + toggleText: PropTypes.node.isRequired, + /** classes to be added to the Options menu toggle text*/ + toggleTextClassName: PropTypes.string, + /** Content to be rendered inside the Options menu toggle button */ + toggleButtonContents: PropTypes.node.isRequired, + /** Classes to be added to the Options menu toggle button */ + toggleButtonContentsClassName: PropTypes.string, + /** Callback for when this Options menu is toggled */ + onToggle: PropTypes.func, + /** Flag to indicate if menu is open */ + isOpen: PropTypes.bool, + /** Flag to indicate if the button is plain */ + isPlain: PropTypes.bool, + /** Forces display of the hover state of the Options menu button */ + isHovered: PropTypes.bool, + /** Forces display of the active state of the Options menu button */ + isActive: PropTypes.bool, + /** Forces display of the hover state of the Options menu button */ + isFocused: PropTypes.bool, + /** Provides an accessible name for the button when an icon is used instead of text */ + "aria-label": PropTypes.string, +}; + +OptionsMenuToggleWithText.defaultProps = { + parentId: '', + toggleTextClassName: '', + toggleButtonContentsClassName: '', + onToggle: Function.prototype, + isOpen: false, + isPlain: false, + isHovered: false, + isActive: false, + isFocused: false, + "aria-label": 'Options menu', +}; + +export default OptionsMenuToggleWithText; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/__snapshots__/OptionsMenu.test.js.snap b/packages/patternfly-4/react-core/src/components/OptionsMenu/__snapshots__/OptionsMenu.test.js.snap new file mode 100644 index 00000000000..ded2c5413ce --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/__snapshots__/OptionsMenu.test.js.snap @@ -0,0 +1,1385 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`optionsMenu expanded 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="left" + toggle={ + + Options Menu + + } +> +
    + + + +
      + +
    • +
        + +
      • + +
      • +
        + +
      • + +
      • +
        + +
      • + +
      • +
        + +
      • + +
      • +
        +
      +
    • +
      + +
    • + + +
    • +
        + +
      • + +
      • +
        + +
      • + +
      • +
        +
      +
    • + +
    +
    +
    +`; + +exports[`optionsMenu open up 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="left" + toggle={ + + Options Menu + + } +> +
    + + + +
    +
    +`; + +exports[`optionsMenu plain 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="left" + toggle={ + + Options Menu + + } +> +
    + + + +
    +
    +`; + +exports[`optionsMenu regular 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="left" + toggle={ + + Options Menu + + } +> +
    + + + +
    +
    +`; + +exports[`optionsMenu right aligned + open up 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="right" + toggle={ + + Options Menu + + } +> +
    + + + +
    +
    +`; + +exports[`optionsMenu right aligned 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="right" + toggle={ + + Options Menu + + } +> +
    + + + +
    +
    +`; + +exports[`optionsMenu text 1`] = ` + + + Name + + + Date + + + Disabled + + + Size + + , + , + + + Ascending + + + Descending + + , + ] + } + position="left" + toggle={ + + Test + + } + toggleButtonContentsClassName="" + toggleText="Test" + toggleTextClassName="" + /> + } +> +
    + + Test + + } + toggleButtonContentsClassName="" + toggleText="Test" + toggleTextClassName="" + > +
    + + Test + + +
    +
    +
    +
    +`; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/index.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/index.d.ts new file mode 100644 index 00000000000..1fa818f2b4e --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/index.d.ts @@ -0,0 +1,7 @@ +export { default as OptionsMenu } from './OptionsMenu'; +export { default as OptionsMenuItem } from './OptionsMenuItem'; +export { default as OptionsMenuItemGroup } from './OptionsMenuItemGroup'; +export { default as OptionsMenuSeparator } from './OptionsMenuSeparator'; +export { default as OptionsMenuToggle } from './OptionsMenuToggle'; +export { default as OptionsMenuToggleWithText } from './OptionsMenuToggleWithText'; +export { OptionsMenuDirection, OptionsMenuPosition } from './optionsMenuConstants'; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/index.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/index.js new file mode 100644 index 00000000000..8666324b692 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/index.js @@ -0,0 +1,9 @@ +export { default as OptionsMenu } from './OptionsMenu'; +export { default as OptionsMenuItem } from './OptionsMenuItem'; +export { default as OptionsMenuItemGroup } from './OptionsMenuItemGroup'; +export { default as OptionsMenuSeparator } from './OptionsMenuSeparator'; +export { default as OptionsMenuToggle } from './OptionsMenuToggle'; +export { default as OptionsMenuToggleWithText } from './OptionsMenuToggleWithText'; +export { OptionsMenuDirection, OptionsMenuPosition } from './optionsMenuConstants'; + + diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.d.ts b/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.d.ts new file mode 100644 index 00000000000..26fad95880e --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.d.ts @@ -0,0 +1,9 @@ +export const OptionsMenuPosition: { + right: 'right'; + left: 'left'; +}; + +export const OptionsMenuDirection: { + up: 'up'; + down: 'down'; +}; diff --git a/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.js b/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.js new file mode 100644 index 00000000000..6234cdcbfc3 --- /dev/null +++ b/packages/patternfly-4/react-core/src/components/OptionsMenu/optionsMenuConstants.js @@ -0,0 +1,9 @@ +export const OptionsMenuPosition = { + right: 'right', + left: 'left' +}; + +export const OptionsMenuDirection = { + up: 'up', + down: 'down' +}; diff --git a/packages/patternfly-4/react-core/src/components/Pagination/Pagination.js b/packages/patternfly-4/react-core/src/components/Pagination/Pagination.js index 30d50e5d876..0d6e83ff9c0 100644 --- a/packages/patternfly-4/react-core/src/components/Pagination/Pagination.js +++ b/packages/patternfly-4/react-core/src/components/Pagination/Pagination.js @@ -3,9 +3,9 @@ import PropTypes from 'prop-types'; import styles from '@patternfly/patternfly/components/Pagination/pagination.css'; import { css } from '@patternfly/react-styles'; import { DropdownDirection } from '../Dropdown'; -import ToggleTamplate from './ToggleTemplate'; +import ToggleTemplate from './ToggleTemplate'; import Navigation from './Navigation'; -import OptionsMenu from './OptionsMenu'; +import PaginationOptionsMenu from './PaginationOptionsMenu'; const perPageOptions = [ { @@ -107,7 +107,7 @@ const defaultProps = { perPageOptions, dropDirection: DropdownDirection.down, widgetId: 'pagination-options-menu', - toggleTemplate: ToggleTamplate, + toggleTemplate: ToggleTemplate, onSetPage: () => undefined, onPerPageSelect: () => undefined, onFirstClick: () => undefined, @@ -155,7 +155,7 @@ const Pagination = ({ {`${itemCount} ${titles.items}`} } - ( +const ToggleTemplate = ({ firstIndex, lastIndex, itemCount, itemsTitle }) => ( {firstIndex} - {lastIndex} of {itemCount} {itemsTitle} ); -ToggleTamplate.propTypes = propTypes; -ToggleTamplate.defaultProps = defaultProps; +ToggleTemplate.propTypes = propTypes; +ToggleTemplate.defaultProps = defaultProps; -export default ToggleTamplate; +export default ToggleTemplate; diff --git a/packages/patternfly-4/react-core/src/components/Pagination/__snapshots__/Pagination.test.js.snap b/packages/patternfly-4/react-core/src/components/Pagination/__snapshots__/Pagination.test.js.snap index dc40721a4df..46856f0a072 100644 --- a/packages/patternfly-4/react-core/src/components/Pagination/__snapshots__/Pagination.test.js.snap +++ b/packages/patternfly-4/react-core/src/components/Pagination/__snapshots__/Pagination.test.js.snap @@ -60,7 +60,7 @@ exports[`component render custom pagination toggle 1`] = ` > 40 items - - + 40 items - - items - +