Skip to content

Commit

Permalink
refactor(home): clean up code
Browse files Browse the repository at this point in the history
refactor(home): minor improvements

refactor(home): code optimisations

refactor(home): minor style improvements
  • Loading branch information
royschut committed Oct 23, 2024
1 parent c4831d1 commit 77582c4
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
import type { PlaylistItem } from '@jwp/ott-common/types/playlist';
import type { CSSProperties } from 'react';
import type { CSSProperties, TransitionEventHandler } from 'react';

import Image from '../Image/Image';

import styles from './FeaturedShelf.module.scss';

const FeaturedBackground = ({ item, style, hidden }: { item: PlaylistItem | null; style: CSSProperties; hidden?: boolean }) => {
const FeaturedBackground = ({
id,
item,
style,
hidden,
onTransitionEnd,
}: {
id?: string;
item: PlaylistItem | null;
style: CSSProperties;
hidden?: boolean;
onTransitionEnd?: TransitionEventHandler;
}) => {
if (!item) return null;

const image = item.images.find((img) => img.width === 1920)?.src || item?.backgroundImage;

return (
<div style={style} aria-hidden={hidden ? 'true' : undefined}>
<div style={style} aria-hidden={hidden ? 'true' : undefined} id={id} onTransitionEnd={onTransitionEnd}>
<Image className={styles.image} image={image} width={1920} alt={item?.title} />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ const FeaturedMetadata = ({

if (!item) return null;

const hasVideo = item.sources.find((source) => source.file.indexOf('.m3u8') > -1 || source.file.indexOf('.mp4') > -1);

return (
<div className={styles.metadata} style={{ ...style, visibility: hidden ? 'hidden' : undefined }} aria-hidden={hidden ? 'true' : undefined}>
<h2 className={classNames(loading ? styles.loadingTitle : styles.title)}>{!loading && item?.title}</h2>
<TruncatedText text={item?.description} maximumLines={3} className={styles.description} />
<div>
<StartWatchingButton item={item} playUrl={mediaURL({ id: item.mediaid, title: item.title, playlistId, play: true })} />
{hasVideo && <StartWatchingButton item={item} playUrl={mediaURL({ id: item.mediaid, title: item.title, playlistId, play: true })} />}
<Button
label={t('common:more_info')}
onClick={() => !!item && navigate(mediaURL({ id: item.mediaid, title: item.title, playlistId }))}
Expand Down
105 changes: 38 additions & 67 deletions packages/ui-react/src/components/FeaturedShelf/FeaturedPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,32 @@ import { useMemo } from 'react';

import styles from './FeaturedShelf.module.scss';

const calculateDotSize = (direction: 'left' | 'right' | false, itemIndex: number, index: number, range: number, sizeSmall: number) => {
const isAnimatingLeft = direction === 'left';
const isAnimatingRight = direction === 'right';

const dotPosition = {
semiEdgeLeft: itemIndex === index - range + 1 && isAnimatingRight,
edgeLeft: itemIndex === index - range,
newDotLeft: itemIndex === index - range - 1,
semiEdgeRight: itemIndex === index + range - 1 && isAnimatingLeft,
edgeRight: itemIndex === index + range,
newDotRight: itemIndex === index + range + 1,
};

if (dotPosition.semiEdgeLeft || dotPosition.semiEdgeRight) return sizeSmall;
if (dotPosition.edgeLeft) return isAnimatingRight ? 0 : isAnimatingLeft ? 1 : sizeSmall;
if (dotPosition.edgeRight) return isAnimatingLeft ? 0 : isAnimatingRight ? 1 : sizeSmall;
if (dotPosition.newDotLeft) return isAnimatingLeft ? sizeSmall : 0;
if (dotPosition.newDotRight) return isAnimatingRight ? sizeSmall : 0;

return 1;
};

type Props = {
playlist: Playlist;
index: number;
animating: 'left' | 'right' | false;
direction: 'left' | 'right' | false;
nextIndex: number;
setIndex: (index: number) => void;
range?: number;
Expand All @@ -19,16 +41,15 @@ type Props = {
const FeaturedPagination = ({
playlist,
index: indexIn,
animating,
direction,
nextIndex: nextIndexIn,
setIndex,
range = 3,
animationDuration = 200,
className,
}: Props) => {
// @todo: translation
const { t } = useTranslation('common');
const placeholderCount = range + 1; // Needed to keep a stable count of dom elements
const placeholderCount = range + 1; // Placeholders are used to keep a stable amount of DOM elements
const index = indexIn + placeholderCount;
const nextIndex = nextIndexIn + placeholderCount;

Expand All @@ -38,91 +59,41 @@ const FeaturedPagination = ({
return [...placeholders, ...playlist.playlist, ...placeholders];
}, [playlist.playlist, placeholderCount]);

const movementBase = 22;

return (
<div className={classNames(styles.dots, styles.undimmed, className)}>
<div aria-live="polite" className="hidden">
{t('slide_indicator', { page: indexIn + 1, pages: playlist.playlist.length })}
</div>
{playlistWithPlaceholders.map((current, itemIndex) => {
const calculateDotSize = () => {
const isAnimatingLeft = animating === 'left';
const isAnimatingRight = animating === 'right';

const sizeSmall = 0.6;

const isSemiEdgeDotRight = itemIndex === index + range - 1;
const isEdgeDotRight = itemIndex === index + range;
const isNewDotRight = itemIndex === index + range + 1;

const isSemiEdgeDotLeft = itemIndex === index - range + 1;
const isEdgeDotLeft = itemIndex === index - range;
const isNewDotLeft = itemIndex === index - range - 1;

const isPlaceholder = current === undefined;

if (isPlaceholder) return 0;

if (isSemiEdgeDotRight) {
if (isAnimatingLeft) return 0.6;
}
if (isEdgeDotRight) {
if (isAnimatingLeft) return 0;

return isAnimatingRight ? 1 : sizeSmall;
}
if (isNewDotRight) {
return isAnimatingRight ? sizeSmall : 0;
}

if (isSemiEdgeDotLeft) {
if (isAnimatingRight) return 0.6;
}
if (isEdgeDotLeft) {
if (isAnimatingRight) return 0;

return isAnimatingLeft ? 1 : sizeSmall;
}
if (isNewDotLeft) {
return isAnimatingLeft ? sizeSmall : 0;
}

return 1;
};
if (itemIndex < index - range - 1 || itemIndex > index + range + 1) {
return null;
}
if (!current) {
return <div className={classNames(styles.dotPlaceholder)} key={itemIndex} aria-hidden="true" />;
}

// Dot container
const movementBase = 22; // dot width (10) + gap(12)
const movementTotal = Math.abs(index - nextIndex) * movementBase;
const movement = animating === 'left' ? movementTotal : animating === 'right' ? 0 - movementTotal : 0;
const movement = direction === 'left' ? movementTotal : direction === 'right' ? 0 - movementTotal : 0;
const transform = `translateX(${movement}px)`;
const transition = animating
const transition = direction
? `transform ${animationDuration}ms ease-out ${animationDuration / 3}ms, width ${animationDuration / 2}ms ease-out ${animationDuration / 3}ms`
: '';

// Dot
const size = calculateDotSize();
const transformDiv = `scale(${calculateDotSize()})`;
const transitionDiv = animating
const size = calculateDotSize(direction, itemIndex, index, range, 0.6);
const transformDiv = `scale(${size})`;
const transitionDiv = direction
? `width ${animationDuration}ms ease-out, height ${animationDuration}ms ease-out, transform ${animationDuration}ms ease-out`
: '';

if (itemIndex < index - range - 1 || itemIndex > index + range + 1) {
return null;
}

// Placeholder
if (!current) {
return <div className={classNames(styles.dot)} key={itemIndex} aria-hidden="true" />;
}

const isCurrent = itemIndex === index;
const hidden = size !== 1;
const ariaLabel = hidden ? undefined : t('slide_to', { page: itemIndex - placeholderCount + 1, pages: playlist.playlist.length });

return (
<button
key={current?.mediaid}
className={classNames(styles.dot, itemIndex === nextIndex && styles.dotActive, !animating && itemIndex === index && styles.dotActive)}
className={classNames(styles.dot, itemIndex === nextIndex && styles.dotActive, !direction && itemIndex === index && styles.dotActive)}
style={{ transform, transition }}
aria-label={ariaLabel}
aria-hidden={hidden ? 'true' : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
font-size: 18px;
line-height: 1.5em;
letter-spacing: 0.5px;
background-color:var(--featured-shelf-background-color);

&:hover .chevron:not(:disabled) {
opacity: 0.8;
Expand Down Expand Up @@ -54,7 +55,7 @@
top: 0;
right: 0;
left: 0;
z-index: -1;
z-index: 0;
display: flex;
justify-content: flex-end;
align-items: flex-end;
Expand Down Expand Up @@ -85,8 +86,8 @@
height: calc(60vh + 56px);
justify-self: flex-end;

-webkit-mask-image: linear-gradient(to right, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 80%);
mask-image: linear-gradient(to right, #0000 0, rgba(0,0,0,0.2) 50%, rgba(0,0,0,0.8) 80%);
-webkit-mask-image: linear-gradient(to right, #0000 0, rgba(0,0,0,0.15) 50%, rgba(0,0,0,0.8) 80%);
mask-image: linear-gradient(to right, #0000 0, rgba(0,0,0,0.15) 50%, rgba(0,0,0,0.8) 80%);

> div {
position: absolute;
Expand Down Expand Up @@ -117,7 +118,7 @@
right: 0;
bottom: 0;
left: 0;
background: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0.6) 95%, rgba(0, 0, 0, 1) 100%);
background: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0.8) 95%, rgba(0, 0, 0, 1) 100%);
}

.fade2 {
Expand Down Expand Up @@ -212,6 +213,11 @@
&:hover {
transform: scale(1.2);
}
&:disabled {
cursor: default;
opacity: 0;
transition: none;
}
@include responsive.mobile-and-small-tablet() {
&:not(.dimmed) {
opacity: 1;
Expand Down Expand Up @@ -262,6 +268,10 @@
outline: none;
}
}

&:disabled {
cursor: default;
}
}

.dotActive {
Expand All @@ -271,4 +281,9 @@
.dotActive > div {
background-color: var(--primary-color);
opacity: 1;
}

.dotPlaceholder {
width: 10px;
height: 10px;
}
Loading

0 comments on commit 77582c4

Please sign in to comment.