diff --git a/spec/pivotal-ui-react/pagination/pagination_spec.js b/spec/pivotal-ui-react/pagination/pagination_spec.js
index 0e6c185c6..13df34bd0 100644
--- a/spec/pivotal-ui-react/pagination/pagination_spec.js
+++ b/spec/pivotal-ui-react/pagination/pagination_spec.js
@@ -1,92 +1,70 @@
import '../spec_helper';
-
import {Pagination} from '../../../src/react/pagination';
describe('Pagination', () => {
- let subject;
-
const renderComponent = props => ReactDOM.render(, root);
beforeEach(() => {
- subject = renderComponent();
+ renderComponent();
});
it('renders a pagination component', () => {
expect('div.pagination').toExist();
});
- it('has the "btn-group" class', () => {
- expect('div.pagination').toHaveClass('btn-group');
- });
-
it('has the "group" role', () => {
expect('div.pagination').toHaveAttr('role', 'group');
});
- it('renders 1 button when no items are specified',() => {
- expect($('.pagination button').length).toBe(3);
- expect('.pagination button:eq(0)').toHaveText('‹');
- expect('.pagination button:eq(1)').toHaveText('1');
- expect('.pagination button:eq(2)').toHaveText('›');
- });
-
- it('renders all buttons with the btn class', () => {
- expect('.pagination button:eq(0)').toHaveClass('btn');
- expect('.pagination button:eq(1)').toHaveClass('btn');
- expect('.pagination button:eq(2)').toHaveClass('btn');
+ it('renders 1 .pui-btn when no items are specified', () => {
+ expect($('.pagination .pui-btn').length).toBe(3);
+ expect('.pagination .pui-btn:eq(0) .icon svg').toHaveClass('icon-chevron_left');
+ expect('.pagination .pui-btn:eq(1)').toHaveText('1');
+ expect('.pagination .pui-btn:eq(2) .icon svg').toHaveClass('icon-chevron_right');
});
- it('renders all buttons with the btn-default-alt class', () => {
- expect('.pagination button:eq(0)').toHaveClass('btn-default-alt');
- expect('.pagination button:eq(1)').toHaveClass('btn-default-alt');
- expect('.pagination button:eq(2)').toHaveClass('btn-default-alt');
+ it('renders all buttons with flat class', () => {
+ expect('.pagination .pui-btn:eq(0)').toHaveClass('pui-btn-default-flat');
+ expect('.pagination .pui-btn:eq(1)').toHaveClass('pui-btn-brand-flat');
+ expect('.pagination .pui-btn:eq(2)').toHaveClass('pui-btn-default-flat');
});
describe('props', () => {
it('renders the number of buttons specified in items, plus next and prev buttons', () => {
- subject = renderComponent({items: 5});
+ renderComponent({items: 5});
- expect('.pagination button:eq(0)').toHaveText('‹');
- expect('.pagination button:eq(1)').toHaveText('1');
- expect('.pagination button:eq(5)').toHaveText('5');
- expect('.pagination button:eq(6)').toHaveText('›');
- expect($('.pagination button').length).toBe(7);
+ expect('.pagination .pui-btn:eq(0) .icon svg').toHaveClass('icon-chevron_left');
+ expect('.pagination .pui-btn:eq(1)').toHaveText('1');
+ expect('.pagination .pui-btn:eq(5)').toHaveText('5');
+ expect('.pagination .pui-btn:eq(6) .icon svg').toHaveClass('icon-chevron_right');
+ expect($('.pagination .pui-btn').length).toBe(7);
});
- it('does not render next when next is false',() => {
- subject = renderComponent({next: false});
+ it('does not render next when next is false', () => {
+ renderComponent({next: false});
- expect($('.pagination button').length).toBe(2);
- expect('.pagination button:eq(0)').toHaveText('‹');
- expect('.pagination button:eq(1)').toHaveText('1');
+ expect($('.pagination .pui-btn').length).toBe(2);
+ expect('.pagination .pui-btn:eq(0) .icon svg').toHaveClass('icon-chevron_left');
+ expect('.pagination .pui-btn:eq(1)').toHaveText('1');
});
- it('does not render prev when prev is false',() => {
- subject = renderComponent({prev: false});
+ it('does not render prev when prev is false', () => {
+ renderComponent({prev: false});
- expect($('.pagination button').length).toBe(2);
- expect('.pagination button:eq(0)').toHaveText('1');
- expect('.pagination button:eq(1)').toHaveText('›');
+ expect($('.pagination .pui-btn').length).toBe(2);
+ expect('.pagination .pui-btn:eq(0)').toHaveText('1');
+ expect('.pagination .pui-btn:eq(1) .icon svg').toHaveClass('icon-chevron_right');
});
- it('renders an active button when activePage number is specified', () => {
- subject = renderComponent({activePage: 1});
- expect('.pagination button:eq(1)').toHaveClass('btn-default');
- expect('.pagination button:eq(1)').not.toHaveClass('btn-default-alt');
+ it('renders an active .pui-btn when activePage number is specified', () => {
+ renderComponent({activePage: 1});
+ expect('.pagination .pui-btn:eq(1)').toHaveClass('pui-btn-brand-flat');
+ expect('.pagination .pui-btn:eq(1)').toHaveClass('active');
});
- it('renders large buttons when large prop is true', () => {
- subject = renderComponent({large: true});
- expect('div.pagination').toHaveClass('btn-group-large');
- expect('div.pagination').not.toHaveClass('btn-group-small');
- expect('div.pagination').toHaveClass('btn-group');
- });
-
- it('renders small buttons when small prop is true', () => {
- subject = renderComponent({small: true});
- expect('div.pagination').toHaveClass('btn-group-small');
- expect('div.pagination').not.toHaveClass('btn-group-large');
- expect('div.pagination').toHaveClass('btn-group');
+ it('passes the className to the top element', () => {
+ renderComponent({className: 'my-class'});
+ expect('div.pagination').toHaveClass('my-class');
});
describe('onSelect', () => {
@@ -94,26 +72,220 @@ describe('Pagination', () => {
beforeEach(() => {
onSelect = jasmine.createSpy('onSelect');
- subject = renderComponent({onSelect, items: 5});
+ renderComponent({onSelect, items: 5, activePage: 2});
});
- it('calls on button click', () => {
- $('.pagination button:eq(4)').simulate('click');
+ it('calls on .pui-btn click', () => {
+ $('.pagination .pui-btn:eq(4)').simulate('click');
expect(onSelect).toHaveBeenCalledWith(jasmine.any(Object), {eventKey: 4});
});
it('calls on prev click', () => {
- $('.pagination button:eq(0)').simulate('click');
+ $('.pagination .pui-btn:eq(0)').simulate('click');
expect(onSelect).toHaveBeenCalledWith(jasmine.any(Object), {eventKey: 'prev'});
});
it('calls on next click', () => {
- $('.pagination button:eq(6)').simulate('click');
+ $('.pagination .pui-btn:eq(6)').simulate('click');
expect(onSelect).toHaveBeenCalledWith(jasmine.any(Object), {eventKey: 'next'});
});
});
});
+
+ describe('when the first page is active', () => {
+ beforeEach(() => {
+ renderComponent({items: 3});
+ });
+
+ it('disables the left chevron', () => {
+ expect('.pagination .pui-btn:eq(0)').toBeDisabled();
+ });
+ });
+
+ describe('when the last page is active', () => {
+ beforeEach(() => {
+ renderComponent({items: 3, activePage: 3});
+ });
+
+ it('disables the left chevron', () => {
+ expect('.pagination .pui-btn:last').toBeDisabled();
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 1', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 1, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 2, 3, 4, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('2');
+ expect('button:eq(2)').toHaveText('3');
+ expect('button:eq(3)').toHaveText('4');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 2', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 2, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 2, 3, 4, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('2');
+ expect('button:eq(2)').toHaveText('3');
+ expect('button:eq(3)').toHaveText('4');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 3', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 3, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 2, 3, 4, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('2');
+ expect('button:eq(2)').toHaveText('3');
+ expect('button:eq(3)').toHaveText('4');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 4', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 4, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 3, 4, 5, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('3');
+ expect('button:eq(2)').toHaveText('4');
+ expect('button:eq(3)').toHaveText('5');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and a page in the middle is active', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 10, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 9, 10, 11, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('9');
+ expect('button:eq(2)').toHaveText('10');
+ expect('button:eq(3)').toHaveText('11');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 17', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 17, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 16, 17, 18, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('16');
+ expect('button:eq(2)').toHaveText('17');
+ expect('button:eq(3)').toHaveText('18');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ expect('button:eq(3) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 18', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 18, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 17, 18, 19, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('17');
+ expect('button:eq(2)').toHaveText('18');
+ expect('button:eq(3)').toHaveText('19');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 19', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 19, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 17, 18, 19, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('17');
+ expect('button:eq(2)').toHaveText('18');
+ expect('button:eq(3)').toHaveText('19');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
+
+ describe('when there are more than 6 pages, and activePage = 20', () => {
+ beforeEach(() => {
+ renderComponent({items: 20, activePage: 20, prev: false, next: false});
+ });
+
+ it('renders pages for 1, 17, 18, 19, 20', () => {
+ expect($('button').length).toBe(5);
+ expect('button:eq(0)').toHaveText('1');
+ expect('button:eq(1)').toHaveText('17');
+ expect('button:eq(2)').toHaveText('18');
+ expect('button:eq(3)').toHaveText('19');
+ expect('button:eq(4)').toHaveText('20');
+ });
+
+ it('renders ellipses (…)', () => {
+ expect('button:eq(0) + span').toHaveText(String.fromCharCode(8230));
+ });
+ });
});
diff --git a/src/css/pagination/pagination.scss b/src/css/pagination/pagination.scss
index da030acf4..702259ff1 100644
--- a/src/css/pagination/pagination.scss
+++ b/src/css/pagination/pagination.scss
@@ -1,9 +1,16 @@
@import "../pui-variables";
.pagination {
- font-size: 0;
- list-style-type: none;
- margin: 0;
- padding: 0;
- box-sizing: border-box;
+ .active {
+ color: $brand-8;
+ text-decoration: underline;
+ }
+
+ .pui-btn {
+ padding: 0 $base-unit;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
}
diff --git a/src/react/pagination/pagination.js b/src/react/pagination/pagination.js
index fd826d219..e50630c13 100644
--- a/src/react/pagination/pagination.js
+++ b/src/react/pagination/pagination.js
@@ -1,6 +1,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
+import {BrandButton, DefaultButton} from '../buttons';
+import {Icon} from '../iconography';
class PaginationButton extends React.PureComponent {
static propTypes = {
@@ -19,13 +21,15 @@ class PaginationButton extends React.PureComponent {
onSelect && onSelect(e, {eventKey});
};
+
render() {
- const {content, active} = this.props;
- return ();
+ );
}
}
@@ -35,9 +39,7 @@ export class Pagination extends React.PureComponent {
next: PropTypes.bool,
prev: PropTypes.bool,
activePage: PropTypes.number,
- onSelect: PropTypes.func,
- small: PropTypes.bool,
- large: PropTypes.bool
+ onSelect: PropTypes.func
};
static defaultProps = {
@@ -45,7 +47,8 @@ export class Pagination extends React.PureComponent {
next: true,
prev: true,
onSelect: () => {
- }
+ },
+ activePage: 1
};
componentDidMount() {
@@ -53,29 +56,101 @@ export class Pagination extends React.PureComponent {
}
render() {
- const {items, next, prev, activePage, onSelect, small, large, ...props} = this.props;
- const paginationButtons = [];
- for (let i = 0; i < items; i++) {
- const isActive = (i + 1 === activePage);
- paginationButtons.push();
+ const {items, next, prev, activePage, onSelect, className, ...props} = this.props;
+
+ const elements = [];
+
+ if (items < 6) {
+ for (let i = 0; i < items; i++) {
+ elements.push();
+ }
+ } else {
+ if (activePage <= 3) {
+ for (let i = 0; i < 4; i++) {
+ elements.push();
+ }
+ } else {
+ elements.push();
+ elements.push(…);
+ }
+
+ if (activePage > 3 && activePage < items - 2) {
+ for (let i = activePage - 2; i < activePage + 1; i++) {
+ elements.push();
+ }
+ }
+
+ if (activePage >= items - 2) {
+ for (let i = items - 4; i < items; i++) {
+ elements.push();
+ }
+ } else {
+ elements.push(…);
+ elements.push();
+ }
}
+ const prevButton = (,
+ iconOnly: true
+ }}/>);
- const prevButton = ;
- const nextButton = ;
+ const nextButton = (,
+ iconOnly: true
+ }}/>);
- return (
+ return (
{prev ? prevButton : null}
- {paginationButtons}
+ {elements}
{next ? nextButton : null}
);
}