Repository: medly/medly-components
Pull request #169 (2020-10-06 14:00:50)

feat(core): update pagination component as per new design
### PR Checklist

Please check if your PR fulfills the following requirements:

-   [ ] Tests for the changes have been added (for bug fixes / features)
-   [ ] Docs have been added / updated (for bug fixes / features)

### PR Type

What kind of change does this PR introduce?

<!-- Please check the one that applies to this PR using "x". -->

-   [ ] Bugfix
-   [ ] Feature
-   [ ] Code style update (formatting, local variables)
-   [ ] Refactoring (no functional changes, no api changes)
-   [ ] Build related changes
-   [ ] CI related changes
-   [ ] Performance improves
-   [ ] Adding missing tests
-   [ ] Documentation content changes
-   [ ] Other... Please describe:

### What is the current behavior?

<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->

## Fixes # (issue)

### What is the new behavior?

### Does this PR introduce a breaking change?

-   [ ] Yes
-   [ ] No

<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->

### Additional context

Add any other context or screenshots about the feature pr here.



Patch:
diff --git a/packages/core/src/components/Pagination/Pagination.stories.mdx b/packages/core/src/components/Pagination/Pagination.stories.mdx
index 9a1b1a43..afcd515c 100644
--- a/packages/core/src/components/Pagination/Pagination.stories.mdx
+++ b/packages/core/src/components/Pagination/Pagination.stories.mdx
@@ -1,7 +1,9 @@
 import { Pagination } from './Pagination';
 import { defaultTheme } from '@medly-components/theme';
+import { boolean, number } from '@storybook/addon-knobs';
 import { Preview, Story, Meta, Props } from '@storybook/addon-docs/blocks';
-import * as stories from './Pagination.stories';
+import { ThemeInterface } from './Pagination.stories';
+import { useState } from 'react';
 
 <Meta title="Core" component={Pagination} />
 
@@ -10,7 +12,20 @@ import * as stories from './Pagination.stories';
 ### Basic Pagination
 
 <Preview withToolbar>
-    <Story name="Pagination">{stories.Basic()}</Story>
+    <Story name="Pagination">
+        {() => {
+            const [activePage, setActivePage] = useState(1);
+            return (
+                <Pagination
+                    activePage={activePage}
+                    totalItems={number('Total Items', 1000)}
+                    itemsPerPage={number('Items per page', 20)}
+                    hidePrevNextLinks={boolean('Hide Prev Next Links', false)}
+                    onPageClick={setActivePage}
+                />
+            );
+        }}
+    </Story>
 </Preview>
 
 ### Props
@@ -19,4 +34,4 @@ import * as stories from './Pagination.stories';
 
 ### Theme
 
-There is no exclusive theme for pagination, it is actually using button theme.
+<Props of={ThemeInterface} />
diff --git a/packages/core/src/components/Pagination/Pagination.stories.tsx b/packages/core/src/components/Pagination/Pagination.stories.tsx
index c02d683c..ed44b02d 100644
--- a/packages/core/src/components/Pagination/Pagination.stories.tsx
+++ b/packages/core/src/components/Pagination/Pagination.stories.tsx
@@ -1,20 +1,7 @@
-import { boolean, number } from '@storybook/addon-knobs';
-import React, { useState } from 'react';
+import { defaultTheme, PaginationTheme } from '@medly-components/theme/src';
+import React from 'react';
 
-import { Pagination } from './Pagination';
-
-export const Basic = () => {
-    const [activePage, setActivePage] = useState(1);
-
-    return (
-        <Pagination
-            activePage={activePage}
-            totalItems={number('Total Items', 1000)}
-            itemsPerPage={number('Items per page', 20)}
-            pageRangeDisplayed={number('Page Range Displayed', 5)}
-            hideFirstLastLinks={boolean('Hide First Last Links', false)}
-            hidePrevNextLinks={boolean('Hide Prev Next Links', false)}
-            onPageClick={setActivePage}
-        />
-    );
+export const ThemeInterface: React.FC<PaginationTheme> = () => null;
+ThemeInterface.defaultProps = {
+    ...defaultTheme.pagination
 };
diff --git a/packages/core/src/components/Pagination/Pagination.styled.tsx b/packages/core/src/components/Pagination/Pagination.styled.tsx
new file mode 100644
index 00000000..f7a6aa05
--- /dev/null
+++ b/packages/core/src/components/Pagination/Pagination.styled.tsx
@@ -0,0 +1,86 @@
+import { ChevronLeftIcon, ChevronRightIcon, SvgIcon } from '@medly-components/icons';
+import { css, styled } from '@medly-components/utils';
+import List from '../List';
+
+export const ListWrapper = styled(List)`
+    & > li {
+        margin: 0;
+    }
+`;
+
+export const getPageNumberButtonStyleByState = (
+    itemKey: 'pageNumber' | 'overlayPageNumber',
+    state: 'default' | 'active' | 'pressed' | 'hovered'
+) => css`
+    color: ${({ theme: { pagination } }) => pagination[itemKey].color[state]};
+    background: ${({ theme: { pagination } }) => pagination[itemKey].bgColor[state]};
+`;
+
+const getPageNavButtonStyleByState = (state: 'default' | 'pressed' | 'hovered' | 'disabled') => css`
+    background: ${({ theme: { pagination } }) => pagination.pageNav.bgColor[state]};
+    ${SvgIcon} {
+        * {
+            fill: ${({ theme: { pagination } }) => pagination.pageNav.color[state]};
+        }
+    }
+`;
+
+const pageNavButtonState = css`
+    &:hover {
+        ${getPageNavButtonStyleByState('hovered')}
+    }
+
+    &:active {
+        ${getPageNavButtonStyleByState('pressed')}
+    }
+`;
+
+export const BaseButton = styled.button`
+    height: 4rem;
+    width: 4rem;
+    display: block;
+    border-radius: 50%;
+    user-select: none;
+    border: none;
+    padding: 0;
+    text-align: center;
+    transition: all 100ms ease-out;
+    ${getPageNumberButtonStyleByState('pageNumber', 'default')}
+
+    &:hover {
+        cursor: pointer;
+    }
+
+    &:focus {
+        outline: none;
+    }
+
+    &:disabled {
+        cursor: not-allowed;
+    }
+`;
+export const PageNumberButton = styled(BaseButton)<{ isActive?: boolean }>`
+    margin: 4px;
+    height: 3.2rem;
+    width: 3.2rem;
+    ${props => getPageNumberButtonStyleByState('pageNumber', props.isActive ? 'active' : 'default')};
+
+    &:hover {
+        ${props => !props.isActive && getPageNumberButtonStyleByState('pageNumber', 'hovered')};
+    }
+    &:active {
+        font-weight: ${({ theme }) => theme.font.weights.Strong};
+        ${getPageNumberButtonStyleByState('pageNumber', 'pressed')}
+    }
+`;
+
+export const PageNavButton = styled(BaseButton)<{ disabled: boolean }>`
+    & > ${ChevronLeftIcon.Style}, ${ChevronRightIcon.Style} {
+        margin: 4px;
+        padding: 4px;
+    }
+
+    ${getPageNavButtonStyleByState('default')}
+
+    ${props => (props.disabled ? getPageNavButtonStyleByState('disabled') : pageNavButtonState)};
+`;
diff --git a/packages/core/src/components/Pagination/Pagination.tsx b/packages/core/src/components/Pagination/Pagination.tsx
index 080c8b9c..924a8a86 100644
--- a/packages/core/src/components/Pagination/Pagination.tsx
+++ b/packages/core/src/components/Pagination/Pagination.tsx
@@ -1,100 +1,71 @@
+import { ChevronLeftIcon, ChevronRightIcon } from '@medly-components/icons';
 import { WithStyle } from '@medly-components/utils';
 import React, { FC, useMemo } from 'react';
-import Button from '../Button';
-import List from '../List';
+import Popover from '../Popover';
+import Text from '../Text';
 import { paginator } from './helper';
+import { ListWrapper, PageNavButton, PageNumberButton } from './Pagination.styled';
+import PaginationPopup from './PaginationPopup';
 import { PaginationProps } from './types';
 
 export const Pagination: FC<PaginationProps> & WithStyle = React.memo(
     React.forwardRef((props, ref) => {
         const links = [],
-            {
-                hideFirstLastLinks,
-                hidePrevNextLinks,
-                activePage,
-                itemsPerPage,
-                totalItems,
-                pageRangeDisplayed,
-                onPageClick,
-                ...restProps
-            } = props,
-            pagesConfig = useMemo(() => paginator(totalItems, activePage, itemsPerPage, pageRangeDisplayed), [
+            { hidePrevNextLinks, activePage, itemsPerPage, totalItems, onPageClick, ...restProps } = props,
+            { currentPage, linkItems, totalPages } = useMemo(() => paginator(totalItems, activePage, itemsPerPage), [
                 totalItems,
                 activePage,
-                itemsPerPage,
-                pageRangeDisplayed
+                itemsPerPage
             ]);
 
-        const onClickHandler = (page: number) => () => {
-            onPageClick(page);
-        };
+        const onClickHandler = (page: number | '...') => () => page !== '...' && onPageClick(page);
 
-        for (let i = pagesConfig.startPage; i <= pagesConfig.endPage; i++) {
-            links.push(
-                <Button size="S" key={i} onClick={onClickHandler(i)} variant={i === pagesConfig.currentPage ? 'solid' : 'outlined'}>
-                    {i}
-                </Button>
-            );
+        for (let i = 0; i < linkItems.length; i++) {
+            if (linkItems[i] === '...')
+                links.push(
+                    <Popover interactionType="click">
+                        <PaginationPopup
+                            prevPageNumber={linkItems[i - 1] as number}
+                            nextPageNumber={linkItems[i + 1] as number}
+                            onClickHandler={onPageClick}
+                        ></PaginationPopup>
+                    </Popover>
+                );
+            else
+                links.push(
+                    <PageNumberButton key={i} onClick={onClickHandler(linkItems[i])} isActive={linkItems[i] === currentPage}>
+                        <Text textVariant="h5" textAlign="center" textWeight={linkItems[i] === currentPage ? 'Strong' : 'Medium'}>
+                            {linkItems[i]}
+                        </Text>
+                    </PageNumberButton>
+                );
         }
 
         if (!hidePrevNextLinks) {
             links.unshift(
-                <Button
-                    size="S"
-                    key="prev"
-                    disabled={pagesConfig.currentPage < 2}
-                    onClick={onClickHandler(pagesConfig.currentPage - 1)}
-                    variant="outlined"
-                >
-                    Prev
-                </Button>
-            );
-            links.push(
-                <Button
-                    size="S"
-                    key="next"
-                    disabled={pagesConfig.currentPage === pagesConfig.totalPages}
-                    onClick={onClickHandler(pagesConfig.currentPage + 1)}
-                    variant="outlined"
-                >
-                    Next
-                </Button>
-            );
-        }
-
-        if (!hideFirstLastLinks) {
-            links.unshift(
-                <Button size="S" key="first" disabled={pagesConfig.currentPage < 2} onClick={onClickHandler(1)} variant="outlined">
-                    First
-                </Button>
+                <PageNavButton key="first" disabled={currentPage < 2} onClick={onClickHandler(currentPage - 1)}>
+                    <ChevronLeftIcon size="M" />
+                </PageNavButton>
             );
             links.push(
-                <Button
-                    size="S"
-                    key="last"
-                    disabled={pagesConfig.currentPage === pagesConfig.totalPages}
-                    onClick={onClickHandler(pagesConfig.totalPages)}
-                    variant="outlined"
-                >
-                    Last
-                </Button>
+                <PageNavButton key="last" disabled={currentPage === totalPages} onClick={onClickHandler(currentPage + 1)}>
+                    <ChevronRightIcon size="M" />
+                </PageNavButton>
             );
         }
 
         return (
-            <List ref={ref} variant="horizontal" {...restProps}>
+            <ListWrapper ref={ref} variant="horizontal" {...restProps}>
                 {links}
-            </List>
+            </ListWrapper>
         );
     })
 );
 
 Pagination.displayName = 'Pagination';
-Pagination.Style = List.Style;
+Pagination.Style = ListWrapper.Style;
 Pagination.defaultProps = {
     activePage: 1,
     itemsPerPage: 20,
-    pageRangeDisplayed: 5,
-    hideFirstLastLinks: false,
     hidePrevNextLinks: false
 };
diff --git a/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.styled.tsx b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.styled.tsx
new file mode 100644
index 00000000..8083d717
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.styled.tsx
@@ -0,0 +1,46 @@
+import { centerAligned, styled } from '@medly-components/utils';
+import Text from '../../Text';
+import { getPageNumberButtonStyleByState, PageNumberButton } from '../Pagination.styled';
+
+export const PaginationBackgroundStyled = styled('div')`
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background: transparent;
+    z-index: 1000;
+    ${centerAligned()}
+`;
+
+export const PageEllipsisOverlay = styled('div')`
+    max-height: 20rem;
+    display: flex;
+    align-items: center;
+    flex-direction: column;
+    overflow: auto;
+    background: ${({ theme }) => theme.colors.white};
+    box-shadow: 0 0.2rem 0.8rem ${({ theme }) => theme.colors.grey[400]};
+    border-radius: 0.4rem;
+
+    & > ${PageNumberButton} {
+        display: block;
+        border-radius: 0;
+        margin: 0;
+        height: 4rem;
+        width: 4rem;
+        padding: 0.4rem;
+
+        & > ${Text.Style} {
+            line-height: 3.2rem;
+        }
+
+        &:hover {
+            ${getPageNumberButtonStyleByState('overlayPageNumber', 'hovered')}
+        }
+
+        &:active {
+            ${getPageNumberButtonStyleByState('overlayPageNumber', 'hovered')}
+        }
+    }
+`;
diff --git a/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.tsx b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.tsx
new file mode 100644
index 00000000..ead839f5
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.tsx
@@ -0,0 +1,39 @@
+import React, { FC, useContext } from 'react';
+import Popover from '../../Popover';
+import Text from '../../Text';
+import { addPageItems } from '../helper';
+import { PageNumberButton } from '../Pagination.styled';
+import { PageEllipsisOverlay, PaginationBackgroundStyled } from './PaginationPopup.styled';
+import { Props } from './types';
+
+export const PaginationPopup: FC<Props> = React.memo(({ prevPageNumber, nextPageNumber, onClickHandler }) => {
+    const [isPopoverVisible, setPopoverVisibility] = useContext(Popover.Context),
+        onClickHandlerWrapper = (pageNumber: any) => () => {
+            setPopoverVisibility(false);
+            onClickHandler(pageNumber);
+        };
+    return (
+        <>
+            <PageNumberButton key={prevPageNumber + '...'}>
+                <Text textVariant="h5" textAlign="center" textWeight="Medium">
+                    ...
+                </Text>
+            </PageNumberButton>
+            {isPopoverVisible && <PaginationBackgroundStyled />}
+            <Popover.Popup>
+                <PageEllipsisOverlay>
+                    {addPageItems(prevPageNumber + 1, nextPageNumber - 1, []).map(item => {
+                        return (
+                            <PageNumberButton key={item} onClick={onClickHandlerWrapper(item)}>
+                                <Text textVariant="h5" textAlign="center" textWeight="Medium">
+                                    {item}
+                                </Text>
+                            </PageNumberButton>
+                        );
+                    })}
+                </PageEllipsisOverlay>
+            </Popover.Popup>
+        </>
+    );
+});
+PaginationPopup.displayName = 'PaginationPopup';
diff --git a/packages/core/src/components/Pagination/PaginationPopup/index.ts b/packages/core/src/components/Pagination/PaginationPopup/index.ts
new file mode 100644
index 00000000..3ef744fb
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/index.ts
@@ -0,0 +1,3 @@
+import { PaginationPopup } from './PaginationPopup';
+
+export default PaginationPopup;
diff --git a/packages/core/src/components/Pagination/PaginationPopup/types.ts b/packages/core/src/components/Pagination/PaginationPopup/types.ts
new file mode 100644
index 00000000..d2273f53
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/types.ts
@@ -0,0 +1,5 @@
+export interface Props {
+    prevPageNumber: number;
+    nextPageNumber: number;
+    onClickHandler: (page: number) => void;
+}
diff --git a/packages/core/src/components/Pagination/helper.ts b/packages/core/src/components/Pagination/helper.ts
index 7b0a8a50..8b78f236 100644
--- a/packages/core/src/components/Pagination/helper.ts
+++ b/packages/core/src/components/Pagination/helper.ts
@@ -1,31 +1,38 @@
-export const paginator = (totalItems: number, activePage = 1, itemsPerPage = 20, pageRangeDisplayed = 5) => {
+export const addPageItems = (from: number, to: number, result: (number | '...')[]) => {
+    for (let i = from; i <= to; i++) result.push(i);
+    return result;
+};
+
+export const paginator = (totalItems: number, activePage = 1, itemsPerPage = 20) => {
     const totalPages = Math.ceil(totalItems / itemsPerPage);
     const currentPage = activePage < 1 ? 1 : activePage > totalPages ? totalPages : activePage;
+    let result: (number | '...')[] = [];
 
-    let startPage: number, endPage: number;
-
-    if (totalPages <= pageRangeDisplayed) {
-        startPage = 1;
-        endPage = totalPages;
+    /* If totalPages is less than 8 then add all the page numbers*/
+    if (totalPages < 8) {
+        result = addPageItems(1, totalPages, result);
+    } else if (currentPage === 1 || currentPage === totalPages) {
+        /* In case of first and last page, six items should be displayed */
+        if (currentPage === 1) {
+            result.push(1, 2, 3, '...', totalPages);
+        } else {
+            result.push(1, '...', totalPages - 2, totalPages - 1, totalPages);
+        }
     } else {
-        const maxPagesBeforeCurrentPage = Math.floor(pageRangeDisplayed / 2);
-        const maxPagesAfterCurrentPage = Math.ceil(pageRangeDisplayed / 2) - 1;
-        if (currentPage <= maxPagesBeforeCurrentPage) {
-            startPage = 1;
-            endPage = pageRangeDisplayed;
-        } else if (currentPage + maxPagesAfterCurrentPage >= totalPages) {
-            startPage = totalPages - pageRangeDisplayed + 1;
-            endPage = totalPages;
+        /* Left side of active Page */
+        if (currentPage > 4) {
+            result.push(1, '...', currentPage - 1);
+        } else {
+            addPageItems(1, currentPage - 1, result);
+        }
+
+        /* Right side of active Page */
+        if (totalPages - currentPage >= 4) {
+            result.push(currentPage, currentPage + 1, '...', totalPages);
         } else {
-            startPage = currentPage - maxPagesBeforeCurrentPage;
-            endPage = currentPage + maxPagesAfterCurrentPage;
+            addPageItems(currentPage, totalPages, result);
         }
     }
 
-    return {
-        currentPage,
-        startPage,
-        endPage,
-        totalPages
-    };
+    return { currentPage, linkItems: result, totalPages };
 };
diff --git a/packages/core/src/components/Pagination/types.ts b/packages/core/src/components/Pagination/types.ts
index 7725cec7..4f809eea 100644
--- a/packages/core/src/components/Pagination/types.ts
+++ b/packages/core/src/components/Pagination/types.ts
@@ -9,10 +9,6 @@ export interface PaginationProps extends HTMLProps<HTMLUListElement> {
     onPageClick: (page: number) => void;
     /** Items count per page */
     itemsPerPage?: number;
-    /** Hide first and last named button */
-    hideFirstLastLinks?: boolean;
     /** Hide Next and Prev named button */
     hidePrevNextLinks?: boolean;
-    /** Number of page link to be dislayed */
-    pageRangeDisplayed?: number;
 }
diff --git a/packages/theme/src/core/index.ts b/packages/theme/src/core/index.ts
index 878e61b0..72d9eed6 100644
--- a/packages/theme/src/core/index.ts
+++ b/packages/theme/src/core/index.ts
@@ -14,6 +14,7 @@ import label from './label';
 import link from './link';
 import modal from './modal';
 import multiSelect from './multiSelect';
+import pagination from './pagination';
 import radio from './radio';
 import reactDatepicker from './reactDatepicker';
 import searchBox from './searchBox';
@@ -53,5 +54,6 @@ export const coreDefaultTheme = {
     tabs,
     textField,
     toast,
-    toggle
+    toggle,
+    pagination
 };
diff --git a/packages/theme/src/core/pagination/index.ts b/packages/theme/src/core/pagination/index.ts
new file mode 100644
index 00000000..58efb4af
--- /dev/null
+++ b/packages/theme/src/core/pagination/index.ts
@@ -0,0 +1,49 @@
+import colors from '../colors';
+import { PaginationTheme } from './types';
+
+const { grey, black, white, blue } = colors;
+
+const pagination: PaginationTheme = {
+    pageNumber: {
+        color: {
+            default: grey[800],
+            hovered: grey[900],
+            pressed: black,
+            active: blue[500]
+        },
+        bgColor: {
+            default: white,
+            hovered: grey[50],
+            pressed: grey[100],
+            active: blue[100]
+        }
+    },
+    pageNav: {
+        color: {
+            default: grey[800],
+            hovered: grey[900],
+            pressed: black,
+            disabled: grey[300]
+        },
+        bgColor: {
+            default: white,
+            hovered: grey[50],
+            pressed: grey[100],
+            disabled: white
+        }
+    },
+    overlayPageNumber: {
+        color: {
+            default: grey[100],
+            hovered: grey[800],
+            pressed: black
+        },
+        bgColor: {
+            default: white,
+            hovered: grey[50],
+            pressed: grey[100]
+        }
+    }
+};
+
+export default pagination;
diff --git a/packages/theme/src/core/pagination/types.ts b/packages/theme/src/core/pagination/types.ts
new file mode 100644
index 00000000..6ddc1d6b
--- /dev/null
+++ b/packages/theme/src/core/pagination/types.ts
@@ -0,0 +1,47 @@
+export interface PaginationTheme {
+    /** Theme for page number button */
+    pageNumber: {
+        color: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            active: string;
+        };
+        bgColor: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            active: string;
+        };
+    };
+    /** Theme for page navigation arrows */
+    pageNav: {
+        color: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            disabled?: string;
+        };
+        bgColor: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            disabled?: string;
+        };
+    };
+    /** Theme for page number in popup */
+    overlayPageNumber: {
+        color: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            active?: string;
+        };
+        bgColor: {
+            default: string;
+            hovered: string;
+            pressed: string;
+            active?: string;
+        };
+    };
+}
diff --git a/packages/theme/src/core/types.ts b/packages/theme/src/core/types.ts
index 8977e708..ebe7f318 100644
--- a/packages/theme/src/core/types.ts
+++ b/packages/theme/src/core/types.ts
@@ -14,6 +14,7 @@ export * from './label/types';
 export * from './link/types';
 export * from './modal/types';
 export * from './multiSelect/types';
+export * from './pagination/types';
 export * from './radio/types';
 export * from './searchBox/types';
 export * from './singleSelect/types';
diff --git a/packages/theme/src/types.ts b/packages/theme/src/types.ts
index 15135994..ad078789 100644
--- a/packages/theme/src/types.ts
+++ b/packages/theme/src/types.ts
@@ -30,6 +30,7 @@ export interface CoreTheme {
     tabs?: CoreThemes.TabsTheme;
     textField?: CoreThemes.TextFieldTheme;
     toast?: CoreThemes.ToastTheme;
+    pagination?: CoreThemes.PaginationTheme;
 }
 
 export interface LayoutTheme {


Test patch:
diff --git a/packages/core/src/components/Pagination/Pagination.test.tsx b/packages/core/src/components/Pagination/Pagination.test.tsx
index d50b12a9..638787a4 100644
--- a/packages/core/src/components/Pagination/Pagination.test.tsx
+++ b/packages/core/src/components/Pagination/Pagination.test.tsx
@@ -3,78 +3,65 @@ import React from 'react';
 import { Pagination } from './Pagination';
 
 describe('Pagination component', () => {
+    const renderer = (props: any = { totalItems: 0 }) => {
+        const mockOnPageClick = jest.fn();
+        return {
+            mockOnPageClick,
+            ...render(<Pagination {...props} onPageClick={mockOnPageClick} />)
+        };
+    };
+
     afterEach(cleanup);
 
     it('should render correctly with all the default props', () => {
-        const mockOnPageClick = jest.fn();
-        const { container } = render(<Pagination totalItems={150} onPageClick={mockOnPageClick} />);
+        const { container } = renderer({ totalItems: 150 });
         expect(container).toMatchSnapshot();
     });
 
     it('should render correctly when total items is 0', () => {
-        const mockOnPageClick = jest.fn();
-        const { container } = render(<Pagination totalItems={0} onPageClick={mockOnPageClick} />);
+        const { container } = renderer();
         expect(container).toMatchSnapshot();
     });
 
     it('should render correctly with all the props given', () => {
-        const mockOnPageClick = jest.fn();
-        const { container } = render(
-            <Pagination
-                totalItems={150}
-                activePage={1}
-                itemsPerPage={10}
-                pageRangeDisplayed={4}
-                hideFirstLastLinks
-                hidePrevNextLinks
-                onPageClick={mockOnPageClick}
-            />
-        );
+        const { container } = renderer({ totalItems: 150, activePage: 1, itemsPerPage: 10, hidePrevNextLinks: true });
         expect(container).toMatchSnapshot();
     });
 
     it('should call onClick handler with correct page number when any page link is clicked', () => {
-        const mockOnPageClick = jest.fn();
-        const { getByText } = render(<Pagination activePage={3} totalItems={150} onPageClick={mockOnPageClick} />);
-
+        const { getByText, mockOnPageClick } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
         fireEvent.click(getByText('4').closest('button'));
-
         expect(mockOnPageClick).toBeCalledWith(4);
     });
 
-    it('should call onClick handler with first page when first link is clicked', () => {
-        const mockOnPageClick = jest.fn();
-        const { getByText } = render(<Pagination activePage={3} totalItems={150} onPageClick={mockOnPageClick} />);
-
-        fireEvent.click(getByText('First').closest('button'));
-
+    it('should call onClick handler with first page when first page is clicked', () => {
+        const { getByText, mockOnPageClick } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
+        fireEvent.click(getByText('1').closest('button'));
         expect(mockOnPageClick).toBeCalledWith(1);
     });
 
-    it('should call onClick handler with last page when last link is clicked', () => {
-        const mockOnPageClick = jest.fn();
-        const { getByText } = render(<Pagination activePage={3} totalItems={150} onPageClick={mockOnPageClick} />);
-
-        fireEvent.click(getByText('Last').closest('button'));
-
-        expect(mockOnPageClick).toBeCalledWith(8);
+    it('should call onClick handler with last page when last page is clicked', () => {
+        const { getByText, mockOnPageClick } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
+        fireEvent.click(getByText('15').closest('button'));
+        expect(mockOnPageClick).toBeCalledWith(15);
     });
 
     it('should call onClick handler with prev page when prev link is clicked', () => {
-        const mockOnPageClick = jest.fn();
-        const { getByText } = render(<Pagination activePage={3} totalItems={150} onPageClick={mockOnPageClick} />);
-
-        fireEvent.click(getByText('Prev').closest('button'));
-
+        const { mockOnPageClick, container } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
+        fireEvent.click(container.querySelectorAll('svg')[0].closest('button'));
         expect(mockOnPageClick).toBeCalledWith(2);
     });
 
     it('should call onClick handler with next page when next link is clicked', () => {
-        const mockOnPageClick = jest.fn();
-        const { getByText } = render(<Pagination activePage={3} totalItems={150} onPageClick={mockOnPageClick} />);
-
-        fireEvent.click(getByText('Next').closest('button'));
-
+        const { mockOnPageClick, container } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
+        fireEvent.click(container.querySelectorAll('svg')[1].closest('button'));
         expect(mockOnPageClick).toBeCalledWith(4);
     });
+
+    it('should call onClick handler with expected page when selected from ellipsis popover', () => {
+        const { mockOnPageClick, getByText } = renderer({ totalItems: 150, activePage: 3, itemsPerPage: 10 });
+        fireEvent.click(getByText('...').closest('button'));
+        fireEvent.click(getByText('7').closest('button'));
+        expect(mockOnPageClick).toBeCalledWith(7);
+    });
 });
diff --git a/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.test.tsx b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.test.tsx
new file mode 100644
index 00000000..e2535098
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/PaginationPopup.test.tsx
@@ -0,0 +1,32 @@
+import { cleanup, fireEvent, render } from '@test-utils';
+import React from 'react';
+import PaginationPopup from '.';
+import Popover from '../../Popover';
+
+describe('Pagination popup component', () => {
+    const renderer = (props: any = { prevPageNumber: 1, nextPageNumber: 3 }) => {
+        const mockOnPageClick = jest.fn();
+        return {
+            mockOnPageClick,
+            ...render(
+                <Popover interactionType="click">
+                    <PaginationPopup {...props} onClickHandler={mockOnPageClick} />
+                </Popover>
+            )
+        };
+    };
+
+    afterEach(cleanup);
+
+    it('should render correctly with all the default props', () => {
+        const { container } = renderer();
+        expect(container).toMatchSnapshot();
+    });
+
+    it('should call onClick handler with expected page when selected from ellipsis popover', () => {
+        const { mockOnPageClick, getByText } = renderer();
+        fireEvent.click(getByText('...').closest('button'));
+        fireEvent.click(getByText('2').closest('button'));
+        expect(mockOnPageClick).toBeCalledWith(2);
+    });
+});
diff --git a/packages/core/src/components/Pagination/PaginationPopup/__snapshots__/PaginationPopup.test.tsx.snap b/packages/core/src/components/Pagination/PaginationPopup/__snapshots__/PaginationPopup.test.tsx.snap
new file mode 100644
index 00000000..cb7b0861
--- /dev/null
+++ b/packages/core/src/components/Pagination/PaginationPopup/__snapshots__/PaginationPopup.test.tsx.snap
@@ -0,0 +1,87 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Pagination popup component should render correctly with all the default props 1`] = `
+.c0 {
+  position: relative;
+  display: -webkit-inline-box;
+  display: -webkit-inline-flex;
+  display: -ms-inline-flexbox;
+  display: inline-flex;
+}
+
+.c2 {
+  margin: 0;
+  color: inherit;
+  font-size: 1.2rem;
+  font-weight: 600;
+  -webkit-letter-spacing: 0.12rem;
+  -moz-letter-spacing: 0.12rem;
+  -ms-letter-spacing: 0.12rem;
+  letter-spacing: 0.12rem;
+  line-height: 2.0rem;
+  text-align: center;
+}
+
+.c1 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: none;
+  padding: 0;
+  text-align: center;
+  -webkit-transition: all 100ms ease-out;
+  transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  margin: 4px;
+  height: 3.2rem;
+  width: 3.2rem;
+  color: #435465;
+  background: #ffffff;
+}
+
+.c1:hover {
+  cursor: pointer;
+}
+
+.c1:focus {
+  outline: none;
+}
+
+.c1:disabled {
+  cursor: not-allowed;
+}
+
+.c1:hover {
+  color: #303C48;
+  background: #F7F8F9;
+}
+
+.c1:active {
+  font-weight: 700;
+  color: #13181D;
+  background: #eff2f4;
+}
+
+<div>
+  <div
+    class="c0"
+    id="medly-popover-wrapper"
+  >
+    <button
+      class="sc-AxheI c1"
+    >
+      <h5
+        class="c2"
+      >
+        ...
+      </h5>
+    </button>
+  </div>
+</div>
+`;
diff --git a/packages/core/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap b/packages/core/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap
index 2aa49240..e1cc99fa 100644
--- a/packages/core/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap
+++ b/packages/core/src/components/Pagination/__snapshots__/Pagination.test.tsx.snap
@@ -1,145 +1,194 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Pagination component should render correctly when total items is 0 1`] = `
-.c3 {
-  margin: 0;
-  color: inherit;
-  font-size: 1.4rem;
-  font-weight: 600;
-  -webkit-letter-spacing: 0rem;
-  -moz-letter-spacing: 0rem;
-  -ms-letter-spacing: 0rem;
-  letter-spacing: 0rem;
-  line-height: 2.2rem;
-  text-align: initial;
-}
-
-.c1 {
-  border: none;
-  position: relative;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-  font-family: inherit;
-  -webkit-text-decoration: none;
-  text-decoration: none;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  padding: 0.8rem 2.4rem 1rem;
-  border-radius: 0.8rem;
-  background-color: transparent;
-  display: -webkit-inline-box;
-  display: -webkit-inline-flex;
-  display: -ms-inline-flexbox;
-  display: inline-flex;
-  -webkit-box-pack: center;
-  -webkit-justify-content: center;
-  -ms-flex-pack: center;
-  justify-content: center;
-  -webkit-align-items: center;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
+.c4 {
+  overflow: visible;
+  font-size: 2.4rem;
+  -webkit-transition: all 100ms linear;
+  transition: all 100ms linear;
+  cursor: inherit;
 }
 
-.c1 * {
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
+.c4 * {
+  fill-opacity: 1;
+  -webkit-transition: all 100ms linear;
+  transition: all 100ms linear;
+  fill: #607890;
 }
 
-.c1:hover {
-  cursor: pointer;
+.c0 {
+  padding: 0;
+  margin: 0;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  list-style: none;
+  -webkit-flex-direction: row;
+  -ms-flex-direction: row;
+  flex-direction: row;
 }
 
-.c1:focus {
-  outline: none;
+.c0 li {
+  margin: 0 0.4rem;
 }
 
-.c1:disabled {
-  cursor: not-allowed;
+.c0 li:last-child {
+  margin-right: 0.8rem;
 }
 
-.c1::after {
-  content: '';
-  box-sizing: border-box;
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  background-color: transparent;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  border-radius: 0.8rem;
-  border-style: solid;
+.c0 li:first-child {
+  margin-left: 0.8rem;
 }
 
-.c1:disabled {
-  color: #98A7B7;
-  background-color: transparent;
+.c1 > li {
+  margin: 0;
 }
 
-.c1:disabled::after {
-  border-width: 0.1rem;
-  border-color: #98A7B7;
+.c2 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: none;
+  padding: 0;
+  text-align: center;
+  -webkit-transition: all 100ms ease-out;
+  transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  background: #ffffff;
+  background: #ffffff;
 }
 
-.c1:disabled .sc-AxirZ * {
-  fill: #98A7B7;
+.c2:hover {
+  cursor: pointer;
 }
 
-.c1:not(:disabled):not(:hover) {
-  color: #126AFA;
-  background-color: transparent;
+.c2:focus {
+  outline: none;
 }
 
-.c1:not(:disabled):not(:hover)::after {
-  border-width: 0.1rem;
-  border-color: #126AFA;
+.c2:disabled {
+  cursor: not-allowed;
 }
 
-.c1:not(:disabled):not(:hover) .sc-AxirZ * {
-  fill: #126AFA;
+.c2 > .c3,
+.c2 .c3 {
+  margin: 4px;
+  padding: 4px;
 }
 
-.c1:not(:disabled):active {
-  color: #0D4AAF;
-  background-color: #E7F0FF;
+.c2 .c3 * {
+  fill: #435465;
 }
 
-.c1:not(:disabled):active::after {
-  border-width: 0.2rem;
-  border-color: #0D4AAF;
+.c2 .c3 * {
+  fill: #C7D0D8;
 }
 
-.c1:not(:disabled):active .sc-AxirZ * {
-  fill: #0D4AAF;
-}
+<div>
+  <ul
+    class="c0 c1"
+  >
+    <li>
+      <button
+        class="sc-AxheI c2"
+        disabled=""
+      >
+        <svg
+          class="c3 c4"
+          fill="none"
+          height="1em"
+          viewBox="0 0 24 24"
+          width="1em"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M15 6.705a.996.996 0 0 0-1.41 0L9 11.295a.996.996 0 0 0 0 1.41l4.59 4.59a.996.996 0 1 0 1.41-1.41l-3.88-3.89L15 8.115c.39-.39.38-1.03 0-1.41z"
+            fill="#000"
+            fill-opacity=".54"
+          />
+        </svg>
+      </button>
+    </li>
+    <li>
+      <button
+        class="sc-AxheI c2"
+        disabled=""
+      >
+        <svg
+          class="c3 c4"
+          fill="none"
+          height="1em"
+          viewBox="0 0 24 24"
+          width="1em"
+          xmlns="http://www.w3.org/2000/svg"
+        >
+          <path
+            d="M9 6.71a.996.996 0 0 0 0 1.41L12.88 12 9 15.88a.996.996 0 1 0 1.41 1.41L15 12.7a.996.996 0 0 0 0-1.41L10.41 6.7c-.38-.38-1.02-.38-1.41.01z"
+            fill="#000"
+            fill-opacity=".54"
+          />
+        </svg>
+      </button>
+    </li>
+  </ul>
+</div>
+`;
 
-.c1:not(:disabled):not(:active):hover {
-  color: #0F5AD5;
-  background-color: transparent;
-  box-shadow: 0 0.2rem 0.8rem rgba(15,90,213,0.35);
+exports[`Pagination component should render correctly with all the default props 1`] = `
+.c4 {
+  overflow: visible;
+  font-size: 2.4rem;
+  -webkit-transition: all 100ms linear;
+  transition: all 100ms linear;
+  cursor: inherit;
 }
 
-.c1:not(:disabled):not(:active):hover::after {
-  border-width: 0.2rem;
-  border-color: #0F5AD5;
+.c4 * {
+  fill-opacity: 1;
+  -webkit-transition: all 100ms linear;
+  transition: all 100ms linear;
+  fill: #607890;
 }
 
-.c1:not(:disabled):not(:active):hover .sc-AxirZ * {
-  fill: #0F5AD5;
+.c9 {
+  position: relative;
+  display: -webkit-inline-box;
+  display: -webkit-inline-flex;
+  display: -ms-inline-flexbox;
+  display: inline-flex;
 }
 
-.c1 .sc-AxirZ + .c2 {
-  margin-left: 0.8rem;
+.c6 {
+  margin: 0;
+  color: inherit;
+  font-size: 1.2rem;
+  font-weight: 700;
+  -webkit-letter-spacing: 0.12rem;
+  -moz-letter-spacing: 0.12rem;
+  -ms-letter-spacing: 0.12rem;
+  letter-spacing: 0.12rem;
+  line-height: 2.0rem;
+  text-align: center;
 }
 
-.c1 .c2 + .sc-AxirZ {
-  margin-left: 0.8rem;
+.c8 {
+  margin: 0;
+  color: inherit;
+  font-size: 1.2rem;
+  font-weight: 600;
+  -webkit-letter-spacing: 0.12rem;
+  -moz-letter-spacing: 0.12rem;
+  -ms-letter-spacing: 0.12rem;
+  letter-spacing: 0.12rem;
+  line-height: 2.0rem;
+  text-align: center;
 }
 
 .c0 {
@@ -167,435 +216,303 @@ exports[`Pagination component should render correctly when total items is 0 1`]
   margin-left: 0.8rem;
 }
 
-<div>
-  <ul
-    class="c0"
-  >
-    <li>
-      <button
-        class="c1"
-        disabled=""
-        type="button"
-      >
-        <span
-          class="c2 c3"
-        >
-          First
-        </span>
-      </button>
-    </li>
-    <li>
-      <button
-        class="c1"
-        disabled=""
-        type="button"
-      >
-        <span
-          class="c2 c3"
-        >
-          Prev
-        </span>
-      </button>
-    </li>
-    <li>
-      <button
-        class="c1"
-        disabled=""
-        type="button"
-      >
-        <span
-          class="c2 c3"
-        >
-          Next
-        </span>
-      </button>
-    </li>
-    <li>
-      <button
-        class="c1"
-        disabled=""
-        type="button"
-      >
-        <span
-          class="c2 c3"
-        >
-          Last
-        </span>
-      </button>
-    </li>
-  </ul>
-</div>
-`;
-
-exports[`Pagination component should render correctly with all the default props 1`] = `
-.c3 {
+.c1 > li {
   margin: 0;
-  color: inherit;
-  font-size: 1.4rem;
-  font-weight: 600;
-  -webkit-letter-spacing: 0rem;
-  -moz-letter-spacing: 0rem;
-  -ms-letter-spacing: 0rem;
-  letter-spacing: 0rem;
-  line-height: 2.2rem;
-  text-align: initial;
 }
 
-.c1 {
-  border: none;
-  position: relative;
+.c5 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   user-select: none;
-  font-family: inherit;
-  -webkit-text-decoration: none;
-  text-decoration: none;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  padding: 0.8rem 2.4rem 1rem;
-  border-radius: 0.8rem;
-  background-color: transparent;
-  display: -webkit-inline-box;
-  display: -webkit-inline-flex;
-  display: -ms-inline-flexbox;
-  display: inline-flex;
-  -webkit-box-pack: center;
-  -webkit-justify-content: center;
-  -ms-flex-pack: center;
-  justify-content: center;
-  -webkit-align-items: center;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
-}
-
-.c1 * {
+  border: none;
+  padding: 0;
+  text-align: center;
   -webkit-transition: all 100ms ease-out;
   transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  margin: 4px;
+  height: 3.2rem;
+  width: 3.2rem;
+  color: #126AFA;
+  background: #E7F0FF;
 }
 
-.c1:hover {
+.c5:hover {
   cursor: pointer;
 }
 
-.c1:focus {
+.c5:focus {
   outline: none;
 }
 
-.c1:disabled {
+.c5:disabled {
   cursor: not-allowed;
 }
 
-.c1::after {
-  content: '';
-  box-sizing: border-box;
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  background-color: transparent;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  border-radius: 0.8rem;
-  border-style: solid;
-}
-
-.c1:disabled {
-  color: #98A7B7;
-  background-color: transparent;
-}
-
-.c1:disabled::after {
-  border-width: 0.1rem;
-  border-color: #98A7B7;
-}
-
-.c1:disabled .sc-AxirZ * {
-  fill: #98A7B7;
-}
-
-.c1:not(:disabled):not(:hover) {
-  color: #126AFA;
-  background-color: transparent;
-}
-
-.c1:not(:disabled):not(:hover)::after {
-  border-width: 0.1rem;
-  border-color: #126AFA;
-}
-
-.c1:not(:disabled):not(:hover) .sc-AxirZ * {
-  fill: #126AFA;
+.c5:active {
+  font-weight: 700;
+  color: #13181D;
+  background: #eff2f4;
 }
 
-.c1:not(:disabled):active {
-  color: #0D4AAF;
-  background-color: #E7F0FF;
-}
-
-.c1:not(:disabled):active::after {
-  border-width: 0.2rem;
-  border-color: #0D4AAF;
-}
-
-.c1:not(:disabled):active .sc-AxirZ * {
-  fill: #0D4AAF;
+.c7 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: none;
+  padding: 0;
+  text-align: center;
+  -webkit-transition: all 100ms ease-out;
+  transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  margin: 4px;
+  height: 3.2rem;
+  width: 3.2rem;
+  color: #435465;
+  background: #ffffff;
 }
 
-.c1:not(:disabled):not(:active):hover {
-  color: #0F5AD5;
-  background-color: transparent;
-  box-shadow: 0 0.2rem 0.8rem rgba(15,90,213,0.35);
+.c7:hover {
+  cursor: pointer;
 }
 
-.c1:not(:disabled):not(:active):hover::after {
-  border-width: 0.2rem;
-  border-color: #0F5AD5;
+.c7:focus {
+  outline: none;
 }
 
-.c1:not(:disabled):not(:active):hover .sc-AxirZ * {
-  fill: #0F5AD5;
+.c7:disabled {
+  cursor: not-allowed;
 }
 
-.c1 .sc-AxirZ + .c2 {
-  margin-left: 0.8rem;
+.c7:hover {
+  color: #303C48;
+  background: #F7F8F9;
 }
 
-.c1 .c2 + .sc-AxirZ {
-  margin-left: 0.8rem;
+.c7:active {
+  font-weight: 700;
+  color: #13181D;
+  background: #eff2f4;
 }
 
-.c4 {
-  border: none;
-  position: relative;
+.c2 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   user-select: none;
-  font-family: inherit;
-  -webkit-text-decoration: none;
-  text-decoration: none;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  padding: 0.8rem 2.4rem 1rem;
-  border-radius: 0.8rem;
-  display: -webkit-inline-box;
-  display: -webkit-inline-flex;
-  display: -ms-inline-flexbox;
-  display: inline-flex;
-  -webkit-box-pack: center;
-  -webkit-justify-content: center;
-  -ms-flex-pack: center;
-  justify-content: center;
-  -webkit-align-items: center;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
-}
-
-.c4 * {
+  border: none;
+  padding: 0;
+  text-align: center;
   -webkit-transition: all 100ms ease-out;
   transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  background: #ffffff;
+  background: #ffffff;
 }
 
-.c4:hover {
+.c2:hover {
   cursor: pointer;
 }
 
-.c4:focus {
+.c2:focus {
   outline: none;
 }
 
-.c4:disabled {
+.c2:disabled {
   cursor: not-allowed;
 }
 
-.c4:disabled {
-  color: #98A7B7;
-  background: #dfe4e9;
+.c2 > .c3,
+.c2 .c3 {
+  margin: 4px;
+  padding: 4px;
 }
 
-.c4:disabled .sc-AxirZ * {
-  fill: #98A7B7;
+.c2 .c3 * {
+  fill: #435465;
 }
 
-.c4:not(:disabled):not(:hover) {
-  color: #ffffff;
-  background: #126AFA;
+.c2 .c3 * {
+  fill: #C7D0D8;
 }
 
-.c4:not(:disabled):not(:hover) .sc-AxirZ * {
-  fill: #ffffff;
+.c10 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: none;
+  padding: 0;
+  text-align: center;
+  -webkit-transition: all 100ms ease-out;
+  transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  background: #ffffff;
 }
 
-.c4:not(:disabled):active {
-  color: #ffffff;
-  background: #0D4AAF;
+.c10:hover {
+  cursor: pointer;
 }
 
-.c4:not(:disabled):active .sc-AxirZ * {
-  fill: #ffffff;
+.c10:focus {
+  outline: none;
 }
 
-.c4:not(:disabled):not(:active):hover {
-  color: #ffffff;
-  background: #0F5AD5;
-  box-shadow: 0 0.2rem 0.8rem rgba(15,90,213,0.35);
+.c10:disabled {
+  cursor: not-allowed;
 }
 
-.c4:not(:disabled):not(:active):hover .sc-AxirZ * {
-  fill: #ffffff;
+.c10 > .c3,
+.c10 .c3 {
+  margin: 4px;
+  padding: 4px;
 }
 
-.c4 .sc-AxirZ + .c2 {
-  margin-left: 0.8rem;
+.c10 .c3 * {
+  fill: #435465;
 }
 
-.c4 .c2 + .sc-AxirZ {
-  margin-left: 0.8rem;
+.c10:hover {
+  background: #F7F8F9;
 }
 
-.c0 {
-  padding: 0;
-  margin: 0;
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  list-style: none;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
+.c10:hover .c3 * {
+  fill: #303C48;
 }
 
-.c0 li {
-  margin: 0 0.4rem;
+.c10:active {
+  background: #eff2f4;
 }
 
-.c0 li:last-child {
-  margin-right: 0.8rem;
-}
-
-.c0 li:first-child {
-  margin-left: 0.8rem;
+.c10:active .c3 * {
+  fill: #13181D;
 }
 
 <div>
   <ul
-    class="c0"
+    class="c0 c1"
   >
     <li>
       <button
-        class="c1"
+        class="sc-AxheI c2"
         disabled=""
-        type="button"
       >
-        <span
-          class="c2 c3"
+        <svg
+          class="c3 c4"
+          fill="none"
+          height="1em"
+          viewBox="0 0 24 24"
+          width="1em"
+          xmlns="http://www.w3.org/2000/svg"
         >
-          First
-        </span>
+          <path
+            d="M15 6.705a.996.996 0 0 0-1.41 0L9 11.295a.996.996 0 0 0 0 1.41l4.59 4.59a.996.996 0 1 0 1.41-1.41l-3.88-3.89L15 8.115c.39-.39.38-1.03 0-1.41z"
+            fill="#000"
+            fill-opacity=".54"
+          />
+        </svg>
       </button>
     </li>
     <li>
       <button
-        class="c1"
-        disabled=""
-        type="button"
+        class="sc-AxheI c5"
       >
-        <span
-          class="c2 c3"
-        >
-          Prev
-        </span>
-      </button>
-    </li>
-    <li>
-      <button
-        class="c4"
-        type="button"
-      >
-        <span
-          class="c2 c3"
+        <h5
+          class="c6"
         >
           1
-        </span>
+        </h5>
       </button>
     </li>
     <li>
       <button
-        class="c1"
-        type="button"
+        class="sc-AxheI c7"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c8"
         >
           2
-        </span>
+        </h5>
       </button>
     </li>
     <li>
       <button
-        class="c1"
-        type="button"
+        class="sc-AxheI c7"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c8"
         >
           3
-        </span>
-      </button>
-    </li>
-    <li>
-      <button
-        class="c1"
-        type="button"
-      >
-        <span
-          class="c2 c3"
-        >
-          4
-        </span>
+        </h5>
       </button>
     </li>
     <li>
-      <button
-        class="c1"
-        type="button"
+      <div
+        class="c9"
+        id="medly-popover-wrapper"
       >
-        <span
-          class="c2 c3"
+        <button
+          class="sc-AxheI c7"
         >
-          5
-        </span>
-      </button>
+          <h5
+            class="c8"
+          >
+            ...
+          </h5>
+        </button>
+      </div>
     </li>
     <li>
       <button
-        class="c1"
-        type="button"
+        class="sc-AxheI c7"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c8"
         >
-          Next
-        </span>
+          8
+        </h5>
       </button>
     </li>
     <li>
       <button
-        class="c1"
-        type="button"
+        class="sc-AxheI c10"
       >
-        <span
-          class="c2 c3"
+        <svg
+          class="c3 c4"
+          fill="none"
+          height="1em"
+          viewBox="0 0 24 24"
+          width="1em"
+          xmlns="http://www.w3.org/2000/svg"
         >
-          Last
-        </span>
+          <path
+            d="M9 6.71a.996.996 0 0 0 0 1.41L12.88 12 9 15.88a.996.996 0 1 0 1.41 1.41L15 12.7a.996.996 0 0 0 0-1.41L10.41 6.7c-.38-.38-1.02-.38-1.41.01z"
+            fill="#000"
+            fill-opacity=".54"
+          />
+        </svg>
       </button>
     </li>
   </ul>
@@ -603,141 +520,131 @@ exports[`Pagination component should render correctly with all the default props
 `;
 
 exports[`Pagination component should render correctly with all the props given 1`] = `
-.c3 {
-  margin: 0;
-  color: inherit;
-  font-size: 1.4rem;
-  font-weight: 600;
-  -webkit-letter-spacing: 0rem;
-  -moz-letter-spacing: 0rem;
-  -ms-letter-spacing: 0rem;
-  letter-spacing: 0rem;
-  line-height: 2.2rem;
-  text-align: initial;
-}
-
-.c1 {
-  border: none;
+.c6 {
   position: relative;
-  -webkit-user-select: none;
-  -moz-user-select: none;
-  -ms-user-select: none;
-  user-select: none;
-  font-family: inherit;
-  -webkit-text-decoration: none;
-  text-decoration: none;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  padding: 0.8rem 2.4rem 1rem;
-  border-radius: 0.8rem;
   display: -webkit-inline-box;
   display: -webkit-inline-flex;
   display: -ms-inline-flexbox;
   display: inline-flex;
-  -webkit-box-pack: center;
-  -webkit-justify-content: center;
-  -ms-flex-pack: center;
-  justify-content: center;
-  -webkit-align-items: center;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
-}
-
-.c1 * {
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
 }
 
-.c1:hover {
-  cursor: pointer;
-}
-
-.c1:focus {
-  outline: none;
+.c3 {
+  margin: 0;
+  color: inherit;
+  font-size: 1.2rem;
+  font-weight: 700;
+  -webkit-letter-spacing: 0.12rem;
+  -moz-letter-spacing: 0.12rem;
+  -ms-letter-spacing: 0.12rem;
+  letter-spacing: 0.12rem;
+  line-height: 2.0rem;
+  text-align: center;
 }
 
-.c1:disabled {
-  cursor: not-allowed;
+.c5 {
+  margin: 0;
+  color: inherit;
+  font-size: 1.2rem;
+  font-weight: 600;
+  -webkit-letter-spacing: 0.12rem;
+  -moz-letter-spacing: 0.12rem;
+  -ms-letter-spacing: 0.12rem;
+  letter-spacing: 0.12rem;
+  line-height: 2.0rem;
+  text-align: center;
 }
 
-.c1:disabled {
-  color: #98A7B7;
-  background: #dfe4e9;
+.c0 {
+  padding: 0;
+  margin: 0;
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  list-style: none;
+  -webkit-flex-direction: row;
+  -ms-flex-direction: row;
+  flex-direction: row;
 }
 
-.c1:disabled .sc-AxirZ * {
-  fill: #98A7B7;
+.c0 li {
+  margin: 0 0.4rem;
 }
 
-.c1:not(:disabled):not(:hover) {
-  color: #ffffff;
-  background: #126AFA;
+.c0 li:last-child {
+  margin-right: 0.8rem;
 }
 
-.c1:not(:disabled):not(:hover) .sc-AxirZ * {
-  fill: #ffffff;
+.c0 li:first-child {
+  margin-left: 0.8rem;
 }
 
-.c1:not(:disabled):active {
-  color: #ffffff;
-  background: #0D4AAF;
+.c1 > li {
+  margin: 0;
 }
 
-.c1:not(:disabled):active .sc-AxirZ * {
-  fill: #ffffff;
+.c2 {
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
+  -webkit-user-select: none;
+  -moz-user-select: none;
+  -ms-user-select: none;
+  user-select: none;
+  border: none;
+  padding: 0;
+  text-align: center;
+  -webkit-transition: all 100ms ease-out;
+  transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  margin: 4px;
+  height: 3.2rem;
+  width: 3.2rem;
+  color: #126AFA;
+  background: #E7F0FF;
 }
 
-.c1:not(:disabled):not(:active):hover {
-  color: #ffffff;
-  background: #0F5AD5;
-  box-shadow: 0 0.2rem 0.8rem rgba(15,90,213,0.35);
+.c2:hover {
+  cursor: pointer;
 }
 
-.c1:not(:disabled):not(:active):hover .sc-AxirZ * {
-  fill: #ffffff;
+.c2:focus {
+  outline: none;
 }
 
-.c1 .sc-AxirZ + .c2 {
-  margin-left: 0.8rem;
+.c2:disabled {
+  cursor: not-allowed;
 }
 
-.c1 .c2 + .sc-AxirZ {
-  margin-left: 0.8rem;
+.c2:active {
+  font-weight: 700;
+  color: #13181D;
+  background: #eff2f4;
 }
 
 .c4 {
-  border: none;
-  position: relative;
+  height: 4rem;
+  width: 4rem;
+  display: block;
+  border-radius: 50%;
   -webkit-user-select: none;
   -moz-user-select: none;
   -ms-user-select: none;
   user-select: none;
-  font-family: inherit;
-  -webkit-text-decoration: none;
-  text-decoration: none;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  padding: 0.8rem 2.4rem 1rem;
-  border-radius: 0.8rem;
-  background-color: transparent;
-  display: -webkit-inline-box;
-  display: -webkit-inline-flex;
-  display: -ms-inline-flexbox;
-  display: inline-flex;
-  -webkit-box-pack: center;
-  -webkit-justify-content: center;
-  -ms-flex-pack: center;
-  justify-content: center;
-  -webkit-align-items: center;
-  -webkit-box-align: center;
-  -ms-flex-align: center;
-  align-items: center;
-}
-
-.c4 * {
+  border: none;
+  padding: 0;
+  text-align: center;
   -webkit-transition: all 100ms ease-out;
   transition: all 100ms ease-out;
+  color: #435465;
+  background: #ffffff;
+  margin: 4px;
+  height: 3.2rem;
+  width: 3.2rem;
+  color: #435465;
+  background: #ffffff;
 }
 
 .c4:hover {
@@ -752,163 +659,79 @@ exports[`Pagination component should render correctly with all the props given 1
   cursor: not-allowed;
 }
 
-.c4::after {
-  content: '';
-  box-sizing: border-box;
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  background-color: transparent;
-  -webkit-transition: all 100ms ease-out;
-  transition: all 100ms ease-out;
-  border-radius: 0.8rem;
-  border-style: solid;
-}
-
-.c4:disabled {
-  color: #98A7B7;
-  background-color: transparent;
-}
-
-.c4:disabled::after {
-  border-width: 0.1rem;
-  border-color: #98A7B7;
-}
-
-.c4:disabled .sc-AxirZ * {
-  fill: #98A7B7;
-}
-
-.c4:not(:disabled):not(:hover) {
-  color: #126AFA;
-  background-color: transparent;
-}
-
-.c4:not(:disabled):not(:hover)::after {
-  border-width: 0.1rem;
-  border-color: #126AFA;
-}
-
-.c4:not(:disabled):not(:hover) .sc-AxirZ * {
-  fill: #126AFA;
-}
-
-.c4:not(:disabled):active {
-  color: #0D4AAF;
-  background-color: #E7F0FF;
-}
-
-.c4:not(:disabled):active::after {
-  border-width: 0.2rem;
-  border-color: #0D4AAF;
-}
-
-.c4:not(:disabled):active .sc-AxirZ * {
-  fill: #0D4AAF;
-}
-
-.c4:not(:disabled):not(:active):hover {
-  color: #0F5AD5;
-  background-color: transparent;
-  box-shadow: 0 0.2rem 0.8rem rgba(15,90,213,0.35);
-}
-
-.c4:not(:disabled):not(:active):hover::after {
-  border-width: 0.2rem;
-  border-color: #0F5AD5;
-}
-
-.c4:not(:disabled):not(:active):hover .sc-AxirZ * {
-  fill: #0F5AD5;
-}
-
-.c4 .sc-AxirZ + .c2 {
-  margin-left: 0.8rem;
-}
-
-.c4 .c2 + .sc-AxirZ {
-  margin-left: 0.8rem;
-}
-
-.c0 {
-  padding: 0;
-  margin: 0;
-  display: -webkit-box;
-  display: -webkit-flex;
-  display: -ms-flexbox;
-  display: flex;
-  list-style: none;
-  -webkit-flex-direction: row;
-  -ms-flex-direction: row;
-  flex-direction: row;
-}
-
-.c0 li {
-  margin: 0 0.4rem;
+.c4:hover {
+  color: #303C48;
+  background: #F7F8F9;
 }
 
-.c0 li:last-child {
-  margin-right: 0.8rem;
-}
-
-.c0 li:first-child {
-  margin-left: 0.8rem;
+.c4:active {
+  font-weight: 700;
+  color: #13181D;
+  background: #eff2f4;
 }
 
 <div>
   <ul
-    class="c0"
+    class="c0 c1"
   >
     <li>
       <button
-        class="c1"
-        type="button"
+        class="sc-AxheI c2"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c3"
         >
           1
-        </span>
+        </h5>
       </button>
     </li>
     <li>
       <button
-        class="c4"
-        type="button"
+        class="sc-AxheI c4"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c5"
         >
           2
-        </span>
+        </h5>
       </button>
     </li>
     <li>
       <button
-        class="c4"
-        type="button"
+        class="sc-AxheI c4"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c5"
         >
           3
-        </span>
+        </h5>
       </button>
     </li>
+    <li>
+      <div
+        class="c6"
+        id="medly-popover-wrapper"
+      >
+        <button
+          class="sc-AxheI c4"
+        >
+          <h5
+            class="c5"
+          >
+            ...
+          </h5>
+        </button>
+      </div>
+    </li>
     <li>
       <button
-        class="c4"
-        type="button"
+        class="sc-AxheI c4"
       >
-        <span
-          class="c2 c3"
+        <h5
+          class="c5"
         >
-          4
-        </span>
+          15
+        </h5>
       </button>
     </li>
   </ul>
diff --git a/packages/core/src/components/Pagination/helper.test.ts b/packages/core/src/components/Pagination/helper.test.ts
index c8732777..f1366968 100644
--- a/packages/core/src/components/Pagination/helper.test.ts
+++ b/packages/core/src/components/Pagination/helper.test.ts
@@ -4,8 +4,7 @@ describe('Paginator function', () => {
     it('should return expected result when active page is less than 1', () => {
         expect(paginator(50, 0)).toEqual({
             currentPage: 1,
-            startPage: 1,
-            endPage: 3,
+            linkItems: [1, 2, 3],
             totalPages: 3
         });
     });
@@ -13,8 +12,7 @@ describe('Paginator function', () => {
     it('should return expected result when when active page is greater than total pages', () => {
         expect(paginator(50, 10)).toEqual({
             currentPage: 3,
-            startPage: 1,
-            endPage: 3,
+            linkItems: [1, 2, 3],
             totalPages: 3
         });
     });
@@ -22,36 +20,46 @@ describe('Paginator function', () => {
     it('should return expected result when only totalItems count is given', () => {
         expect(paginator(50)).toEqual({
             currentPage: 1,
-            startPage: 1,
-            endPage: 3,
+            linkItems: [1, 2, 3],
             totalPages: 3
         });
     });
 
-    it('should return expected result when currentPage plus maxPagesAfterCurrentPage is greater than or equal to totalPages', () => {
-        expect(paginator(150, 8, 20, 5)).toEqual({
-            currentPage: 8,
-            startPage: 4,
-            endPage: 8,
+    it('should return expected result when currentPage is near the middle of pageRangeDisplayed', () => {
+        expect(paginator(150, 3, 20)).toEqual({
+            currentPage: 3,
+            linkItems: [1, 2, 3, 4, '...', 8],
             totalPages: 8
         });
     });
 
-    it('should return expected result when currentPage is less than maxPagesBeforeCurrentPage', () => {
-        expect(paginator(150, 2, 20, 5)).toEqual({
-            currentPage: 2,
-            startPage: 1,
-            endPage: 5,
+    it('should return expected result when currentPage is first or last page ', () => {
+        expect(paginator(150, 1, 20)).toEqual({
+            currentPage: 1,
+            linkItems: [1, 2, 3, '...', 8],
             totalPages: 8
         });
-    });
 
-    it('should return expected result when currentPage is near the middle of pageRangeDisplayed', () => {
-        expect(paginator(150, 3, 20, 5)).toEqual({
-            currentPage: 3,
-            startPage: 1,
-            endPage: 5,
+        expect(paginator(150, 8, 20)).toEqual({
+            currentPage: 8,
+            linkItems: [1, '...', 6, 7, 8],
             totalPages: 8
         });
     });
+
+    it('should return expected result when currentPage is the middle page ', () => {
+        expect(paginator(150, 8, 10)).toEqual({
+            currentPage: 8,
+            linkItems: [1, '...', 7, 8, 9, '...', 15],
+            totalPages: 15
+        });
+    });
+
+    it('should return expected result when currentPage near by 4 pages to the last page ', () => {
+        expect(paginator(150, 12, 10)).toEqual({
+            currentPage: 12,
+            linkItems: [1, '...', 11, 12, 13, 14, 15],
+            totalPages: 15
+        });
+    });
 });
diff --git a/packages/layout/src/components/SideNav/NavItem/__snapshots__/NavItem.test.tsx.snap b/packages/layout/src/components/SideNav/NavItem/__snapshots__/NavItem.test.tsx.snap
index c9738518..26b30339 100644
--- a/packages/layout/src/components/SideNav/NavItem/__snapshots__/NavItem.test.tsx.snap
+++ b/packages/layout/src/components/SideNav/NavItem/__snapshots__/NavItem.test.tsx.snap
@@ -66,7 +66,7 @@ exports[`NavItem should render properly when it is in active state 1`] = `
   color: #13181D;
 }
 
-.c2 > .c3:first-of-type > .sc-qXRQq:first-of-type > .c0 {
+.c2 > .c3:first-of-type > .sc-pczax:first-of-type > .c0 {
   margin-top: 0.6rem;
 }
 
@@ -195,11 +195,11 @@ exports[`NavItem should render properly when it is in default state 1`] = `
   color: #13181D;
 }
 
-.c2 > .c4:first-of-type > .sc-qXRQq:first-of-type > .c0 {
+.c2 > .c4:first-of-type > .sc-pczax:first-of-type > .c0 {
   margin-top: 0.6rem;
 }
 
-.c3 > .c4:first-of-type > .sc-qXRQq:first-of-type > .c0 {
+.c3 > .c4:first-of-type > .sc-pczax:first-of-type > .c0 {
   margin-top: 0.6rem;
 }
 
@@ -328,11 +328,11 @@ exports[`NavItem should render properly when it is in hovered state 1`] = `
   color: #13181D;
 }
 
-.c2 > .c4:first-of-type > .sc-qXRQq:first-of-type > .c0 {
+.c2 > .c4:first-of-type > .sc-pczax:first-of-type > .c0 {
   margin-top: 0.6rem;
 }
 
-.c3 > .c4:first-of-type > .sc-qXRQq:first-of-type > .c0 {
+.c3 > .c4:first-of-type > .sc-pczax:first-of-type > .c0 {
   margin-top: 0.6rem;
 }
 
diff --git a/packages/layout/src/components/SideNav/ToggleSwitch/__snapshots__/ToggleSwitch.test.tsx.snap b/packages/layout/src/components/SideNav/ToggleSwitch/__snapshots__/ToggleSwitch.test.tsx.snap
index 305c8426..adcd3c53 100644
--- a/packages/layout/src/components/SideNav/ToggleSwitch/__snapshots__/ToggleSwitch.test.tsx.snap
+++ b/packages/layout/src/components/SideNav/ToggleSwitch/__snapshots__/ToggleSwitch.test.tsx.snap
@@ -163,7 +163,7 @@ exports[`NavItem should call onClick when we click on it 1`] = `
 
 <div>
   <ul
-    class="sc-qXRQq c0"
+    class="sc-pczax c0"
   >
     <li
       class="c1"
@@ -355,7 +355,7 @@ exports[`NavItem should render properly when it is showing hide option 1`] = `
 
 <div>
   <ul
-    class="sc-qXRQq c0"
+    class="sc-pczax c0"
   >
     <li
       class="c1"
@@ -547,7 +547,7 @@ exports[`NavItem should render properly when it is showing open option 1`] = `
 
 <div>
   <ul
-    class="sc-qXRQq c0"
+    class="sc-pczax c0"
   >
     <li
       class="c1"
diff --git a/packages/layout/src/components/SideNav/__snapshots__/SideNav.test.tsx.snap b/packages/layout/src/components/SideNav/__snapshots__/SideNav.test.tsx.snap
index cdc9cb60..501a76f4 100644
--- a/packages/layout/src/components/SideNav/__snapshots__/SideNav.test.tsx.snap
+++ b/packages/layout/src/components/SideNav/__snapshots__/SideNav.test.tsx.snap
@@ -352,7 +352,7 @@ exports[`SideNav should render properly with shadow 1`] = `
 
 <div>
   <aside
-    class="sc-pIjat c0"
+    class="sc-pspzH c0"
     id="medly-sidenav"
   >
     <nav
@@ -856,7 +856,7 @@ exports[`SideNav should render properly without shadow 1`] = `
 
 <div>
   <aside
-    class="sc-pIjat c0"
+    class="sc-pspzH c0"
     id="medly-sidenav"
   >
     <nav