Skip to content

Commit

Permalink
fix: accessibility improvements for Hero shelf pagination and LayoutGrid
Browse files Browse the repository at this point in the history
* fix(a11y): rowindex and colindex must start from 1

* fix(a11y): hero shelf pagination list aria markup
  • Loading branch information
langemike authored Nov 25, 2024
1 parent b65f0c5 commit 9ad371d
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ exports[`<CardGrid> > renders and matches snapshot 1`] = `
role="grid"
>
<div
aria-rowindex="0"
aria-rowindex="1"
class="_row_19b484"
role="row"
>
<div
aria-colindex="0"
aria-colindex="1"
class="_cell_19b484"
id="layout_grid_0-0"
role="gridcell"
Expand Down Expand Up @@ -56,7 +56,7 @@ exports[`<CardGrid> > renders and matches snapshot 1`] = `
</a>
</div>
<div
aria-colindex="1"
aria-colindex="2"
class="_cell_19b484"
id="layout_grid_0-1"
role="gridcell"
Expand Down Expand Up @@ -98,7 +98,7 @@ exports[`<CardGrid> > renders and matches snapshot 1`] = `
</a>
</div>
<div
aria-colindex="2"
aria-colindex="3"
class="_cell_19b484"
id="layout_grid_0-2"
role="gridcell"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ exports[`<Favorites> > renders and matches snapshot 1`] = `
role="grid"
>
<div
aria-rowindex="0"
aria-rowindex="1"
class="_row_19b484"
role="row"
>
<div
aria-colindex="0"
aria-colindex="1"
class="_cell_19b484"
id="layout_grid_0-0"
role="gridcell"
Expand Down Expand Up @@ -77,7 +77,7 @@ exports[`<Favorites> > renders and matches snapshot 1`] = `
</a>
</div>
<div
aria-colindex="1"
aria-colindex="2"
class="_cell_19b484"
id="layout_grid_0-1"
role="gridcell"
Expand Down Expand Up @@ -124,7 +124,7 @@ exports[`<Favorites> > renders and matches snapshot 1`] = `
</a>
</div>
<div
aria-colindex="2"
aria-colindex="3"
class="_cell_19b484"
id="layout_grid_0-2"
role="gridcell"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ $mobile-landscape-height: 100vh;
}

&:hover {
transform: scale(1.2) translateY(-50%);;
transform: scale(1.2) translateY(-50%);
}

&:disabled {
Expand Down Expand Up @@ -361,7 +361,7 @@ $mobile-landscape-height: 100vh;
}
}

&[aria-hidden="true"] {
&[disabled] {
cursor: default;
}
}
Expand Down
82 changes: 42 additions & 40 deletions packages/ui-react/src/components/HeroShelf/HeroShelfPagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,53 +50,55 @@ const HeroShelfPagination = ({ playlist, index: indexIn, direction, nextIndex: n
}, [playlist.playlist, placeholderCount]);

return (
<nav className={styles.dots}>
<>
<div aria-live="polite" className="hidden">
{t('slide_indicator', { page: indexIn + 1, pages: playlist.playlist.length })}
</div>
<ul className={styles.dotsList}>
{playlistWithPlaceholders.map((current, itemIndex) => {
if (itemIndex < index - range - 1 || itemIndex > index + range + 1) {
return null;
}
if (!current) {
return <div className={classNames(styles.dotPlaceholder)} key={itemIndex} aria-hidden="true" />;
}
<nav className={styles.dots}>
<ul className={styles.dotsList}>
{playlistWithPlaceholders.map((current, itemIndex) => {
if (itemIndex < index - range - 1 || itemIndex > index + range + 1) {
return null;
}
if (!current) {
return <li className={classNames(styles.dotPlaceholder)} key={itemIndex} aria-hidden="true" />;
}

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

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`
: '';
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`
: '';

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

return (
<button
key={current?.mediaid}
className={classNames(styles.dot, itemIndex === nextIndex && styles.dotActive, !direction && itemIndex === index && styles.dotActive)}
style={{ transform, transition }}
aria-label={ariaLabel}
aria-hidden={hidden ? 'true' : undefined}
aria-current={isCurrent ? 'true' : undefined}
onClick={hidden || isCurrent ? undefined : () => setIndex(itemIndex - placeholderCount)}
>
<div style={{ transform: transformDiv, transition: transitionDiv }} />
</button>
);
})}
</ul>
</nav>
return (
<li key={current?.mediaid} aria-hidden={hidden || undefined} aria-current={isCurrent || undefined}>
<button
className={classNames(styles.dot, itemIndex === nextIndex && styles.dotActive, !direction && itemIndex === index && styles.dotActive)}
style={{ transform, transition }}
aria-label={ariaLabel}
disabled={hidden || undefined}
onClick={hidden || isCurrent ? undefined : () => setIndex(itemIndex - placeholderCount)}
>
<div style={{ transform: transformDiv, transition: transitionDiv }} />
</button>
</li>
);
})}
</ul>
</nav>
</>
);
};

Expand Down
4 changes: 2 additions & 2 deletions packages/ui-react/src/components/LayoutGrid/LayoutGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ const LayoutGrid = <Item extends object>({ className, columnCount, data, renderC
return (
<div role="grid" ref={gridRef} aria-rowcount={rowCount} className={className} onKeyDown={handleKeyDown}>
{Array.from({ length: rowCount }).map((_, rowIndex) => (
<div role="row" key={rowIndex} aria-rowindex={rowIndex} className={styles.row}>
<div role="row" key={rowIndex} aria-rowindex={rowIndex + 1} className={styles.row}>
{data.slice(rowIndex * columnCount, rowIndex * columnCount + columnCount).map((item, columnIndex) => (
<div
role="gridcell"
id={`layout_grid_${rowIndex}-${columnIndex}`}
key={getCellKey(item)}
aria-colindex={columnIndex}
aria-colindex={columnIndex + 1}
className={styles.cell}
style={gridCellStyle}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,12 +416,12 @@ exports[`User Component tests > Favorites Page 1`] = `
role="grid"
>
<div
aria-rowindex="0"
aria-rowindex="1"
class="_row_19b484"
role="row"
>
<div
aria-colindex="0"
aria-colindex="1"
class="_cell_19b484"
id="layout_grid_0-0"
role="gridcell"
Expand Down Expand Up @@ -463,7 +463,7 @@ exports[`User Component tests > Favorites Page 1`] = `
</a>
</div>
<div
aria-colindex="1"
aria-colindex="2"
class="_cell_19b484"
id="layout_grid_0-1"
role="gridcell"
Expand Down Expand Up @@ -505,7 +505,7 @@ exports[`User Component tests > Favorites Page 1`] = `
</a>
</div>
<div
aria-colindex="2"
aria-colindex="3"
class="_cell_19b484"
id="layout_grid_0-2"
role="gridcell"
Expand Down

0 comments on commit 9ad371d

Please sign in to comment.