Skip to content

Commit 484eb90

Browse files
committed
WIP: Hide Pagination Bar when not needed
1 parent f7a7958 commit 484eb90

File tree

4 files changed

+131
-104
lines changed

4 files changed

+131
-104
lines changed

packages/main/src/components/Carousel/Carousel.jss.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { fonts } from '@ui5/webcomponents-react-base';
22
import { JSSTheme } from '../../interfaces/JSSTheme';
33

4-
const styles = ({ theme, contentDensity, parameters }: JSSTheme) => ({
4+
const styles = ({ parameters }: JSSTheme) => ({
55
carousel: {
66
position: 'relative',
77
overflow: 'hidden',

packages/main/src/components/Carousel/CarouselPagination.jss.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ const styles = ({ parameters }: JSSTheme) => ({
1212
backgroundColor: parameters.sapUiPageFooterBackground
1313
},
1414
paginationTop: {
15-
borderBottom: `1px solid ${parameters.sapUiPageFooterBorderColor}`,
16-
'&$paginationArrowContent': {
17-
'& $paginationArrow': {
18-
top: 'calc(50% + 2rem) !important'
19-
}
20-
}
15+
borderBottom: `1px solid ${parameters.sapUiPageFooterBorderColor}`
2116
},
2217
paginationBottom: {
2318
borderTop: `1px solid ${parameters.sapUiPageFooterBorderColor}`
@@ -76,14 +71,33 @@ const styles = ({ parameters }: JSSTheme) => ({
7671
boxShadow: parameters.sapUiShadowLevel1,
7772
'&:first-child': {
7873
position: 'absolute',
79-
top: 'calc(50% - 2rem)',
74+
top: 'calc(50% - 2.75rem)',
75+
left: '0.5rem',
76+
opacity: 0,
77+
zIndex: ZIndex.InputModal
78+
},
79+
'&:last-child': {
80+
position: 'absolute',
81+
top: 'calc(50% - 2.75rem)',
82+
right: '0.5rem',
83+
opacity: 0,
84+
zIndex: ZIndex.InputModal
85+
}
86+
}
87+
},
88+
paginationArrowContentNoBar: {
89+
'& $paginationArrow': {
90+
boxShadow: parameters.sapUiShadowLevel1,
91+
'&:first-child': {
92+
position: 'absolute',
93+
top: 'calc(50% - 1rem)',
8094
left: '0.5rem',
8195
opacity: 0,
8296
zIndex: ZIndex.InputModal
8397
},
8498
'&:last-child': {
8599
position: 'absolute',
86-
top: 'calc(50% - 2rem)',
100+
top: 'calc(50% - 1rem)',
87101
right: '0.5rem',
88102
opacity: 0,
89103
zIndex: ZIndex.InputModal
Lines changed: 84 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
import { Event, StyleClassHelper, withStyles } from '@ui5/webcomponents-react-base';
2-
import React, { Children, Component } from 'react';
3-
import { ClassProps } from '../../interfaces/ClassProps';
1+
import { StyleClassHelper } from '@ui5/webcomponents-react-base';
2+
import React, { Children, FC, useMemo } from 'react';
3+
import { createUseStyles } from 'react-jss';
4+
import { JSSTheme } from '../../interfaces/JSSTheme';
45
import { CarouselArrowsPlacement } from '../../lib/CarouselArrowsPlacement';
56
import { Icon } from '../../lib/Icon';
67
import { Label } from '../../lib/Label';
78
import { PlacementType } from '../../lib/PlacementType';
89
import styles from './CarouselPagination.jss';
910

11+
const useStyles = createUseStyles<JSSTheme, keyof ReturnType<typeof styles>>(styles);
12+
1013
export interface CarouselPaginationPropTypes {
1114
/**
1215
* Defines where the carousel's arrows are placed.
@@ -26,78 +29,96 @@ export interface CarouselPaginationPropTypes {
2629
* The default value is PlacementType.Bottom.
2730
*/
2831
pageIndicatorPlacement?: PlacementType.Top | PlacementType.Bottom;
29-
}
3032

31-
interface CarouselPaginationInternalProps extends CarouselPaginationPropTypes, ClassProps {
32-
goToPreviousPage: (e: Event) => void;
33-
goToNextPage: (e: Event) => void;
33+
/**
34+
* Index of the active page to be displayed
35+
*/
3436
activePage?: number;
35-
}
3637

37-
@withStyles(styles)
38-
export class CarouselPagination extends Component<CarouselPaginationInternalProps> {
39-
private static TEXT_INDICATOR_THRESHOLD = 8;
38+
goToPreviousPage?: (e: any) => void;
39+
goToNextPage?: (e: any) => void;
40+
}
4041

41-
private handleGoToNextPage = (e) => {
42-
this.props.goToNextPage(Event.of(this, e));
43-
};
42+
const TEXT_INDICATOR_THRESHOLD = 8;
43+
const CarouselPagination: FC<CarouselPaginationPropTypes> = (props) => {
44+
const classes = useStyles();
4445

45-
private handleGoToPreviousPage = (e) => {
46-
this.props.goToPreviousPage(Event.of(this, e));
47-
};
46+
const {
47+
arrowsPlacement,
48+
children,
49+
showPageIndicator,
50+
pageIndicatorPlacement,
51+
activePage,
52+
goToPreviousPage,
53+
goToNextPage
54+
} = props;
4855

49-
render() {
50-
const { arrowsPlacement, children, showPageIndicator, pageIndicatorPlacement, classes, activePage } = this.props;
56+
const numberOfChildren = React.Children.count(children);
57+
const showTextIndicator = numberOfChildren >= TEXT_INDICATOR_THRESHOLD;
5158

52-
const numberOfChildren = React.Children.count(children);
53-
const showTextIndicator = numberOfChildren >= CarouselPagination.TEXT_INDICATOR_THRESHOLD;
59+
const paginationClasses = StyleClassHelper.of(classes.pagination);
60+
if (arrowsPlacement === CarouselArrowsPlacement.Content) {
61+
paginationClasses.put(classes.paginationArrowContent);
62+
}
63+
if (pageIndicatorPlacement === PlacementType.Top) {
64+
paginationClasses.put(classes.paginationTop);
65+
}
66+
if (pageIndicatorPlacement === PlacementType.Bottom) {
67+
paginationClasses.put(classes.paginationBottom);
68+
}
5469

55-
const paginationClasses = StyleClassHelper.of(classes.pagination);
56-
if (arrowsPlacement === CarouselArrowsPlacement.Content) {
57-
paginationClasses.put(classes.paginationArrowContent);
58-
}
59-
if (pageIndicatorPlacement === PlacementType.Top) {
60-
paginationClasses.put(classes.paginationTop);
61-
}
62-
if (pageIndicatorPlacement === PlacementType.Bottom) {
63-
paginationClasses.put(classes.paginationBottom);
64-
}
70+
const shouldRenderPaginationBar = useMemo(() => {
71+
return showPageIndicator || arrowsPlacement === CarouselArrowsPlacement.PageIndicator;
72+
}, [showPageIndicator, arrowsPlacement]);
6573

74+
if (!shouldRenderPaginationBar) {
6675
return (
67-
<div className={paginationClasses.valueOf()}>
68-
<div
69-
data-value={arrowsPlacement === CarouselArrowsPlacement.Content ? 'paginationArrow' : null}
70-
className={classes.paginationArrow}
71-
onClick={this.handleGoToPreviousPage}
72-
>
73-
<Icon src="slim-arrow-left" />
76+
<div className={classes.paginationArrowContentNoBar}>
77+
<div data-value="paginationArrow" className={classes.paginationArrow} onClick={goToPreviousPage}>
78+
<Icon src="sap-icon://slim-arrow-left" />
7479
</div>
75-
76-
{showPageIndicator && (
77-
<div className={classes.paginationIndicator}>
78-
{showTextIndicator && <Label>{`Showing ${activePage + 1} of ${numberOfChildren}`}</Label>}
79-
80-
{!showTextIndicator &&
81-
Children.map(children, (item, index) => (
82-
<span
83-
key={index}
84-
className={`${activePage === index ? classes.paginationIconActive : null} ${classes.paginationIcon}`}
85-
aria-label={`Item ${index + 1} of ${numberOfChildren} displayed`}
86-
>
87-
{index + 1}
88-
</span>
89-
))}
90-
</div>
91-
)}
92-
93-
<div
94-
data-value={arrowsPlacement === CarouselArrowsPlacement.Content ? 'paginationArrow' : null}
95-
className={classes.paginationArrow}
96-
onClick={this.handleGoToNextPage}
97-
>
98-
<Icon src="slim-arrow-right" />
80+
<div data-value="paginationArrow" className={classes.paginationArrow} onClick={goToNextPage}>
81+
<Icon src="sap-icon://slim-arrow-right" />
9982
</div>
10083
</div>
10184
);
10285
}
103-
}
86+
87+
return (
88+
<div className={paginationClasses.valueOf()}>
89+
<div
90+
data-value={arrowsPlacement === CarouselArrowsPlacement.Content ? 'paginationArrow' : null}
91+
className={classes.paginationArrow}
92+
onClick={goToPreviousPage}
93+
>
94+
<Icon src="sap-icon://slim-arrow-left" />
95+
</div>
96+
97+
<div className={classes.paginationIndicator}>
98+
{showPageIndicator && showTextIndicator && <Label>{`Showing ${activePage + 1} of ${numberOfChildren}`}</Label>}
99+
100+
{showPageIndicator &&
101+
!showTextIndicator &&
102+
Children.map(children, (item, index) => (
103+
<span
104+
key={index}
105+
className={`${activePage === index ? classes.paginationIconActive : null} ${classes.paginationIcon}`}
106+
aria-label={`Item ${index + 1} of ${numberOfChildren} displayed`}
107+
>
108+
{index + 1}
109+
</span>
110+
))}
111+
</div>
112+
113+
<div
114+
data-value={arrowsPlacement === CarouselArrowsPlacement.Content ? 'paginationArrow' : null}
115+
className={classes.paginationArrow}
116+
onClick={goToNextPage}
117+
>
118+
<Icon src="sap-icon://slim-arrow-right" />
119+
</div>
120+
</div>
121+
);
122+
};
123+
124+
export { CarouselPagination };

packages/main/src/components/Carousel/index.tsx

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,13 @@ import { PlacementType } from '../../lib/PlacementType';
77
import styles from './Carousel.jss';
88
import { CarouselPagination, CarouselPaginationPropTypes } from './CarouselPagination';
99

10-
export interface CarouselPropTypes extends CarouselPaginationPropTypes, CommonProps {
10+
export interface CarouselPropTypes
11+
extends Omit<CarouselPaginationPropTypes, 'goToPreviousPage' | 'goToNextPage'>,
12+
CommonProps {
1113
/**
1214
* The content which the carousel displays.
1315
*/
1416
children: ReactNode | ReactNodeArray;
15-
/**
16-
* Index of the active page to be displayed
17-
*/
18-
activePage?: number;
1917
/**
2018
* This event is fired after a carousel swipe has been completed
2119
*/
@@ -45,27 +43,6 @@ interface CarouselState {
4543
};
4644
}
4745

48-
const CarouselInner = (props) => {
49-
const { children, className, activePage } = props;
50-
51-
return (
52-
<Fragment>
53-
{Children.map(children, (item, index) => (
54-
<div
55-
key={index}
56-
className={className}
57-
style={{
58-
transform: `translateX(-${activePage * 100}%)`,
59-
visibility: [activePage - 1, activePage, activePage + 1].includes(index) ? 'visible' : 'hidden'
60-
}}
61-
>
62-
{item}
63-
</div>
64-
))}
65-
</Fragment>
66-
);
67-
};
68-
6946
@withStyles(styles)
7047
export class Carousel extends Component<CarouselPropTypes, CarouselState> {
7148
static defaultProps = {
@@ -133,7 +110,8 @@ export class Carousel extends Component<CarouselPropTypes, CarouselState> {
133110
className,
134111
style,
135112
arrowsPlacement,
136-
tooltip
113+
tooltip,
114+
showPageIndicator
137115
} = this.props as CarouselPropsInternal;
138116

139117
const { activePage } = this.state;
@@ -158,21 +136,35 @@ export class Carousel extends Component<CarouselPropTypes, CarouselState> {
158136
<div className={classNameString.toString()} style={outerStyle} title={tooltip} slot={this.props['slot']}>
159137
{Children.count(children) > 1 && pageIndicatorPlacement === PlacementType.Top && (
160138
<CarouselPagination
161-
{...this.props}
139+
arrowsPlacement={arrowsPlacement}
140+
showPageIndicator={showPageIndicator}
141+
pageIndicatorPlacement={pageIndicatorPlacement}
162142
activePage={activePage}
143+
children={children}
163144
goToPreviousPage={this.goToPreviousPage}
164145
goToNextPage={this.goToNextPage}
165146
/>
166147
)}
167148
<div className={classes.carouselInner}>
168-
<CarouselInner className={carouselItemClasses.toString()} activePage={activePage}>
169-
{children}
170-
</CarouselInner>
149+
{Children.map(children, (item, index) => (
150+
<div
151+
key={index}
152+
className={carouselItemClasses.toString()}
153+
style={{
154+
transform: `translateX(-${activePage * 100}%)`
155+
}}
156+
>
157+
{item}
158+
</div>
159+
))}
171160
</div>
172161
{Children.count(children) > 1 && pageIndicatorPlacement === PlacementType.Bottom && (
173162
<CarouselPagination
174-
{...this.props}
163+
arrowsPlacement={arrowsPlacement}
164+
showPageIndicator={showPageIndicator}
165+
pageIndicatorPlacement={pageIndicatorPlacement}
175166
activePage={activePage}
167+
children={children}
176168
goToPreviousPage={this.goToPreviousPage}
177169
goToNextPage={this.goToNextPage}
178170
/>

0 commit comments

Comments
 (0)