Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"cz-lerna-changelog": "^1.2.1",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-context-patch": "^0.0.9",
"enzyme-to-json": "^3.3.3",
"fs-extra": "^6.0.1",
"glob": "^7.1.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Avatar, AvatarProps } from './Avatar';
Copy link
Contributor

Choose a reason for hiding this comment

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

thanks for adding this

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as Brand, BrandProps } from './Brand';
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as Checkbox } from './Checkbox';
export { default as Checkbox, CheckboxProps } from './Checkbox';
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
export {
default as Dropdown,
DropdownPosition,
DropdownDirection
DropdownDirection,
DropdownProps
} from './Dropdown';
export { default as DropdownItem } from './Item';
export { default as DropdownSeparator } from './Separator';
export { default as KebabToggle } from './KebabToggle';
export { default as DropdownToggle } from './DropdownToggle';
export { default as DropdownItem, ItemProps } from './Item';
export { default as DropdownSeparator, SeparatorProps } from './Separator';
export { default as KebabToggle, KebabProps } from './KebabToggle';
export { default as DropdownToggle, DropdownToggleProps } from './DropdownToggle';
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as List, ListProps } from './List';
export { default as ListItem, ListItemProps } from './ListItem';
14 changes: 14 additions & 0 deletions packages/patternfly-4/react-core/src/components/Nav/Nav.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { SFC, HTMLProps, ReactNode, FormEvent } from 'react';
import { Omit } from '../../typeUtils';

export interface NavProps extends Omit<HTMLProps<HTMLDivElement>, 'onSelect'> {
children?: ReactNode;
className?: string;
onSelect(groupId: number, itemId: number, event: FormEvent<HTMLInputElement>): void;
onToggle(groupId: number, expanded: boolean, event: FormEvent<HTMLInputElement>): void;
'aria-label': string;
}

declare const Nav: SFC<NavProps>;

export default Nav;
33 changes: 33 additions & 0 deletions packages/patternfly-4/react-core/src/components/Nav/Nav.docs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Nav, NavGroup, NavList, NavItem, NavExpandable, NavVariants } from '@patternfly/react-core';
import SimpleList from './examples/NavSimpleList';
import GroupedList from './examples/NavGroupedList';
import ExpandableList from './examples/NavExpandableList';
import ExpandableTitlesList from './examples/NavExpandableTitlesList';
import MixedList from './examples/NavMixedList';
import DefaultList from './examples/NavDefaultList';
import HorizontalList from './examples/NavHorizontalList';
import TertiaryList from './examples/NavTertiaryList';

export default {
title: 'Nav',
components: {
Nav,
NavGroup,
NavList,
NavExpandable,
NavItem
},
enumValues: {
'Object.values(NavVariants)': Object.values(NavVariants)
},
examples: [
SimpleList,
GroupedList,
DefaultList,
ExpandableList,
ExpandableTitlesList,
MixedList,
HorizontalList,
TertiaryList
]
};
70 changes: 70 additions & 0 deletions packages/patternfly-4/react-core/src/components/Nav/Nav.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import styles from '@patternfly/patternfly-next/components/Nav/styles.css';
import { css } from '@patternfly/react-styles';
import PropTypes from 'prop-types';

const propTypes = {
/** Anything that can be rendered inside of the nav */
children: PropTypes.node,
/** Additional classes added to the container */
className: PropTypes.string,
/** Callback for updating when item selection changes */
onSelect: PropTypes.func,
/** Callback for when a list is expanded or collapsed */
onToggle: PropTypes.func,
/** Accessibility label */
'aria-label': PropTypes.string.isRequired
};

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we add a warning similar to other components for the a missing aria-label.

const defaultProps = {
children: null,
className: '',
onSelect: () => undefined,
onToggle: () => undefined
};

export const NavContext = React.createContext();

class Nav extends React.Component {
// Callback from NavItem
onSelect(event, groupId, itemId) {
event.stopPropagation();
this.props.onSelect({
event,
itemId,
groupId
});
}

// Callback from NavExpandable
onToggle(event, groupId, isExpanded) {
event.stopPropagation();
this.props.onToggle({
event,
groupId,
isExpanded
});
}

render() {
const { children, className, ...props } = this.props;

return (
<NavContext.Provider
value={{
onSelect: (event, groupId, itemId) => this.onSelect(event, groupId, itemId),
onToggle: (event, groupId, expanded) => this.onToggle(event, groupId, expanded)
}}
>
<nav className={css(styles.nav, className)} {...props}>
{children}
</nav>
</NavContext.Provider>
);
}
}

Nav.propTypes = propTypes;
Nav.defaultProps = defaultProps;

export default Nav;
211 changes: 211 additions & 0 deletions packages/patternfly-4/react-core/src/components/Nav/Nav.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import React from 'react';
import { mount } from 'enzyme';
import Nav from './Nav';
import NavList from './NavList';
import NavGroup from './NavGroup';
import NavItem from './NavItem';
import NavExpandable from './NavExpandable';

const props = {
items: [
{ to: '#link1', label: 'Link 1' },
{ to: '#link2', label: 'Link 2' },
{ to: '#link3', label: 'Link 3' },
{ to: '#link4', label: 'Link 4' }
]
};

beforeEach(() => {
window.location.hash = '#link1';
});

const context = {
onSelect: () => undefined,
onToggle: () => undefined
};

test('Default Nav List', () => {
const view = mount(
<Nav aria-label="Test">
<NavList>
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Default Nav List - Trigger item active update', () => {
window.location.hash = '#link2';
const view = mount(
<Nav aria-label="Test">
<NavList>
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavList>
</Nav>,
{ context }
);
view
.find({ href: '#link2' })
.first()
.simulate('click');
expect(view).toMatchSnapshot();
});

test('Simple Nav List', () => {
const view = mount(
<Nav aria-label="Test">
<NavList variant="simple">
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Expandable Nav List', () => {
const view = mount(
<Nav aria-label="Test">
<NavList>
<NavExpandable id="grp-1" title="Section 1">
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavExpandable>
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Expandable Nav List - Trigger toggle', () => {
window.location.hash = '#link2';
const view = mount(
<Nav aria-label="Test">
<NavList>
<NavExpandable id="grp-1" title="Section 1" className="expandable-group" isExpanded>
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavExpandable>
</NavList>
</Nav>,
{ context }
);
view
.find('li.expandable-group')
.first()
.simulate('click');
expect(view).toMatchSnapshot();
});

test('Expandable Nav List with aria label', () => {
const view = mount(
<Nav aria-label="Test">
<NavList>
<NavExpandable id="grp-1" title="Section 1" srText="Section 1 - Example sub-navigation">
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavExpandable>
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Nav Grouped List', () => {
const view = mount(
<Nav aria-label="Test">
<NavGroup id="grp-1" title="Section 1">
<NavList>
{props.items.map(item => (
<NavItem to={item.to} key={`section1_${item.to}`}>
{item.label}
</NavItem>
))}
</NavList>
</NavGroup>
<NavGroup id="grp-2" title="Section 2">
<NavList>
{props.items.map(item => (
<NavItem to={item.to} key={`section2_${item.to}`}>
{item.label}
</NavItem>
))}
</NavList>
</NavGroup>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Horizontal Nav List', () => {
const view = mount(
<Nav aria-label="Test">
<NavList variant="horizontal">
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Tertiary Nav List', () => {
const view = mount(
<Nav aria-label="Test">
<NavList variant="tertiary">
{props.items.map(item => (
<NavItem to={item.to} key={item.to}>
{item.label}
</NavItem>
))}
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});

test('Nav List with custom item nodes', () => {
const CustomNode = () => <div>My custom node</div>;
const view = mount(
<Nav aria-label="Test">
<NavList variant="tertiary">
<NavItem to="/components/nav#link1">
<CustomNode />
</NavItem>
</NavList>
</Nav>,
{ context }
);
expect(view).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { SFC, HTMLProps, ReactNode } from 'react';

export interface NavExpandableProps extends HTMLProps<HTMLDivElement> {
title: string;
srText?: string;
isExpanded?: boolean;
children?: ReactNode;
className?: string;
groupId?: string | number;
isActive?: boolean;
id?: string;
}

declare const NavExpandable: SFC<NavExpandableProps>;

export default NavExpandable;
Loading