Skip to content

Commit

Permalink
Merge pull request #1359 from multiversx/mm-add-pagination-search
Browse files Browse the repository at this point in the history
Ledger Address Table Pagination Search Tooltip
  • Loading branch information
MiroMargineanu authored Jan 15, 2025
2 parents ba5691a + dc80342 commit f229451
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 121 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- [Added search tooltip to the Ledger address table pagination](https://github.com/multiversx/mx-sdk-dapp/pull/1359)

## [[v3.1.7](https://github.com/multiversx/mx-sdk-dapp/pull/1358)] - 2025-01-14

- [Fixed double rendering](https://github.com/multiversx/mx-sdk-dapp/pull/1357)
Expand Down
14 changes: 7 additions & 7 deletions src/UI/LoadingDots/LoadingDots.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React from 'react';
import classNames from 'classnames';

import { withStyles, WithStylesImportType } from 'hocs/withStyles';
import { WithClassnameType } from 'UI/types';

const LoadingDotsComponent = ({
className,
styles
}: WithClassnameType & WithStylesImportType) => (
export type LoadingDotsPropsType = WithClassnameType & WithStylesImportType;

const LoadingDotsComponent = ({ className, styles }: LoadingDotsPropsType) => (
<div className={classNames(styles?.loadingDots, className)}>
{Array.from({ length: 3 }).map((_, index) => (
{Array.from({ length: 3 }).map((_, dotIndex) => (
<span
key={`loading-dot-${index}`}
key={`loading-dot-${dotIndex}`}
className={classNames(
styles?.loadingDot,
styles?.[`loadingDot-${index}`]
styles?.[`loadingDot-${dotIndex}`]
)}
/>
))}
Expand Down
11 changes: 6 additions & 5 deletions src/UI/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { withStyles } from 'hocs/withStyles';
import { WithClassnameType } from 'UI/types';
import { stringIsInteger } from 'utils/validation/stringIsInteger';

import { PaginationEdgeButton } from './components';
import { PaginationEdgeButton, PaginationEllipsisForm } from './components';
import { getPagination } from './helpers';

export interface PaginationPropsType
Expand Down Expand Up @@ -140,7 +140,6 @@ const PaginationComponent = ({
styles?.paginationItem,
buttonsClassNames,
{ [styles?.active]: isCurrentPageActive(paginationItem) },
{ [styles?.ellipsis]: !stringIsInteger(paginationItem) },
{ [styles?.disabled]: isDisabled },
{
[styles?.hundreds]:
Expand All @@ -154,9 +153,11 @@ const PaginationComponent = ({
</span>
</div>
) : (
<span className={styles?.paginationItemText}>
{paginationItem}
</span>
<PaginationEllipsisForm
paginationItem={paginationItem}
maxPageToSearchFor={totalPages}
onSearch={handlePageClick}
/>
)}
</div>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import React, {
ChangeEvent,
FocusEvent,
FormEvent,
KeyboardEvent,
MouseEvent,
useState
} from 'react';
import { faMagnifyingGlass } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import BigNumber from 'bignumber.js';
import classNames from 'classnames';

import { WithStylesImportType } from 'hocs/useStyles';
import { withStyles } from 'hocs/withStyles';

export interface PaginationEllipsisFormPropsType extends WithStylesImportType {
paginationItem: string;
maxPageToSearchFor: number;
onSearch: (page: number) => void;
}

const PaginationEllipsisFormComponent = ({
styles,
onSearch,
paginationItem,
maxPageToSearchFor
}: PaginationEllipsisFormPropsType) => {
const [pageValue, setPageValue] = useState('');
const [isEllipsisTooltipVisible, setIsEllipsisTooltipVisible] =
useState(false);

const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (['Equal', 'Minus', 'Period', 'KeyE', 'Comma'].includes(event.code)) {
event.preventDefault();
return;
}
};

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const valueBigNumber = new BigNumber(event.target.value);
const isBelowMax = valueBigNumber.isLessThanOrEqualTo(maxPageToSearchFor);

if (valueBigNumber.isNaN() || isBelowMax) {
setPageValue(valueBigNumber.toString());
}
};

const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
onSearch(parseInt(pageValue));
};

const handleMagnifyingGlassClick = (event: MouseEvent<HTMLDivElement>) => {
event.preventDefault();
onSearch(parseInt(pageValue));
};

const handleEllipsisClick = (event: MouseEvent<HTMLElement>) => {
event.preventDefault();
setIsEllipsisTooltipVisible(
(isEllipsisTooltipVisible) => !isEllipsisTooltipVisible
);
};

const handleBlur = (event: FocusEvent<HTMLDivElement>) => {
if (!event.currentTarget.contains(event.relatedTarget)) {
setIsEllipsisTooltipVisible(false);
}
};

return (
<div
onClick={handleEllipsisClick}
className={classNames(styles?.paginationEllipsisFormContainer, {
[styles?.active]: isEllipsisTooltipVisible
})}
>
{isEllipsisTooltipVisible && (
<div
className={styles?.paginationEllipsisFormWrapper}
onBlur={handleBlur}
tabIndex={-1}
>
<form
className={styles?.paginationEllipsisForm}
onClick={(event) => event.stopPropagation()}
onSubmit={handleSubmit}
>
<label
htmlFor='paginationSearch'
className={styles?.paginationEllipsisFormFieldLabel}
>
Page
</label>

<div className={styles?.paginationEllipsisFormField}>
<input
autoFocus
type='number'
autoComplete='off'
id='paginationSearch'
name='paginationSearch'
onChange={handleChange}
onKeyDown={handleKeyDown}
value={pageValue}
className={styles?.paginationEllipsisFormFieldInput}
/>

<div
className={styles?.paginationEllipsisFormButton}
onClick={handleMagnifyingGlassClick}
>
<FontAwesomeIcon
icon={faMagnifyingGlass}
className={styles?.paginationEllipsisFormButtonIcon}
/>
</div>
</div>
</form>
</div>
)}

<span className={styles?.paginationEllipsisFormTrigger}>
{paginationItem}
</span>
</div>
);
};

export const PaginationEllipsisForm = withStyles(
PaginationEllipsisFormComponent,
{
ssrStyles: () =>
import(
'UI/Pagination/components/PaginationEllipsisForm/paginationEllipsisFormStyles.scss'
),
clientStyles: () =>
require('UI/Pagination/components/PaginationEllipsisForm/paginationEllipsisFormStyles.scss')
.default
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './PaginationEllipsisForm';
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
.pagination-ellipsis-form-container {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
transition: all 200ms ease;
border-radius: 50%;

&:hover,
&.active {
background-color: #143736;
}

.pagination-ellipsis-form-wrapper {
left: 50%;
transform: translateX(-50%);
bottom: calc(100% + 24px);
position: absolute;

.pagination-ellipsis-form {
flex-direction: row;
text-align: left;
gap: 8px;
cursor: default;
background: #000000;
border-radius: 12px;
border: 1px solid #262626;
padding: 8px;

&:after {
width: 8px;
height: 8px;
border: 1px solid #262626;
background-color: #000000;
border-top: none;
border-right: none;
position: absolute;
content: '';
left: 50%;
transform-origin: center;
transform: translateX(calc(50% - 8px)) rotateZ(calc(45deg * -1));
bottom: calc(20px / 4 * -1);
}

.pagination-ellipsis-form-field-label {
margin-bottom: 8px;
font-size: 12px;
color: #a3a3a3;
cursor: pointer;
}

.pagination-ellipsis-form-field {
display: flex;
gap: 8px;
position: relative;

.pagination-ellipsis-form-field-input {
width: 80px;
height: calc(40px + 4px);
border-width: 1px;
box-shadow: none;
font-size: 1rem;
padding: 12px;
padding-right: calc(40px);
text-align: center;
transition: all 200ms ease;
border-color: transparent;
appearance: none;
-webkit-appearance: none;
appearance: none;
-moz-appearance: textfield;
margin: 0;

&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}

&:focus {
border-color: #23f7dd;
}
}

.pagination-ellipsis-form-button {
outline: none;
border: none;
background-color: transparent;
line-height: 1;
cursor: pointer;
position: absolute;
right: 4px;
transform: translateY(-50%);
font-size: 12px;
padding: calc(20px / 2);
top: 50%;

&:hover .pagination-ellipsis-form-button-icon {
color: #23f7dd;
}
}
}
}
}
}
1 change: 1 addition & 0 deletions src/UI/Pagination/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './PaginationEdgeButton';
export * from './PaginationEllipsisForm';
12 changes: 0 additions & 12 deletions src/UI/Pagination/paginationStyles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,6 @@
pointer-events: none;
}

&.ellipsis {
margin: 0;

&:before {
background-color: transparent;
}

&:hover:before {
background-color: #143736;
}
}

.pagination-item-text {
position: relative;
z-index: 2;
Expand Down
Loading

0 comments on commit f229451

Please sign in to comment.